diff -pruN 24.0.1+9-1/.jcheck/conf 24.0.2+12-1/.jcheck/conf
--- 24.0.1+9-1/.jcheck/conf	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/.jcheck/conf	2025-06-27 08:03:14.000000000 +0000
@@ -1,7 +1,7 @@
 [general]
 project=jdk-updates
 jbs=JDK
-version=24.0.1
+version=24.0.2
 
 [checks]
 error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists
diff -pruN 24.0.1+9-1/debian/changelog 24.0.2+12-1/debian/changelog
--- 24.0.1+9-1/debian/changelog	2025-04-23 11:56:34.000000000 +0000
+++ 24.0.2+12-1/debian/changelog	2025-07-18 13:57:39.000000000 +0000
@@ -1,6 +1,16 @@
+openjdk-24 (24.0.2+12-1) unstable; urgency=medium
+
+  * OpenJDK 24 24.0.2 release.
+    - Addresses CVE-2025-5010, CVE-2025-50059, CVE-2025-30754, CVE-2025-30749.
+
+  [ Vladimir Petko ]
+  * d/p/jdk-8359735-proposed.patch: Fix process tests failing in Ubuntu 25.10.
+
+ -- Matthias Klose <doko@ubuntu.com>  Fri, 18 Jul 2025 15:57:39 +0200
+
 openjdk-24 (24.0.1+9-1) unstable; urgency=high
 
-  * OpenJDK 24 24.1.0 release.
+  * OpenJDK 24 24.0.1 release.
     - Addresses CVE-2025-30698, CVE-2025-30691, CVE-2025-21587.
 
   [ Vladimir Petko ]
diff -pruN 24.0.1+9-1/debian/patches/jdk-8359735.patch 24.0.2+12-1/debian/patches/jdk-8359735.patch
--- 24.0.1+9-1/debian/patches/jdk-8359735.patch	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/debian/patches/jdk-8359735.patch	2025-07-18 13:57:39.000000000 +0000
@@ -0,0 +1,63 @@
+Description: Process tests fail due to rust-coreutils
+ To accommodate systems like Ubuntu 25.10 that use Rust coreutils,
+ this PR updates tests that previously assumed busybox was the only
+ environment to use symlinks for core utilities.
+ - java/lang/ProcessBuilder/Basic.java: The test is updated to simply
+   verify that /bin/true and /bin/false are symlinks,
+   removing the hardcoded check for a /bin/busybox target.
+ - java/lang/ProcessHandle/InfoTest.java: The test logic is relaxed.
+   It now confirms that /bin/sleep is a symlink and then uses the
+   symlink's target as the expected executable name.
+Author: Vladimir Petko <vladimir.petko@canonical.com>
+Origin: upstream, https://github.com/openjdk/jdk/pull/25838
+Bug: https://bugs.openjdk.org/browse/JDK-8359735
+Reviewed-by: Roger Riggs <roger.riggs@oracle.com>
+Last-Update: 2025-06-19
+---
+
+--- a/test/jdk/java/lang/ProcessBuilder/Basic.java
++++ b/test/jdk/java/lang/ProcessBuilder/Basic.java
+@@ -696,7 +696,7 @@
+         public static String path() { return path; }
+         private static final String path = path0();
+         private static String path0(){
+-            if (!Platform.isBusybox("/bin/true")) {
++            if (!Files.isSymbolicLink(Paths.get("/bin/true"))) {
+                 return "/bin/true";
+             } else {
+                 File trueExe = new File("true");
+@@ -711,7 +711,7 @@
+         public static String path() { return path; }
+         private static final String path = path0();
+         private static String path0(){
+-            if (!Platform.isBusybox("/bin/false")) {
++            if (!Files.isSymbolicLink(Paths.get("/bin/false"))) {
+                 return "/bin/false";
+             } else {
+                 File falseExe = new File("false");
+--- a/test/jdk/java/lang/ProcessHandle/InfoTest.java
++++ b/test/jdk/java/lang/ProcessHandle/InfoTest.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2014, 2023, 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
+@@ -295,10 +295,12 @@
+                     String expected = "sleep";
+                     if (Platform.isWindows()) {
+                         expected = "sleep.exe";
+-                    } else if (Platform.isBusybox("/bin/sleep")) {
+-                        // With busybox sleep is just a sym link to busybox.
+-                        // The busbox executable is seen as ProcessHandle.Info command.
+-                        expected = "busybox";
++                    } else if (Files.isSymbolicLink(Paths.get("/bin/sleep"))) {
++                        // Busybox sleep is a symbolic link to /bin/busybox.
++                        // Rust coreutils sleep is a symbolic link to coreutils
++                        // The busbox/coreutils executables are seen as ProcessHandle.Info command.
++                        Path executable = Files.readSymbolicLink(Paths.get("/bin/sleep"));
++                        expected = executable.getFileName().toString();
+                     }
+                     Assert.assertTrue(command.endsWith(expected), "Command: expected: \'" +
+                             expected + "\', actual: " + command);
diff -pruN 24.0.1+9-1/debian/patches/series 24.0.2+12-1/debian/patches/series
--- 24.0.1+9-1/debian/patches/series	2025-01-25 16:32:39.000000000 +0000
+++ 24.0.2+12-1/debian/patches/series	2025-07-18 13:57:39.000000000 +0000
@@ -39,3 +39,4 @@ jdk-8335238-workaround.patch
 # FIXME: which one of these two?
 zero-alpha-workaround.diff
 #jdk-8347014-proposed.patch
+jdk-8359735.patch
diff -pruN 24.0.1+9-1/debian/patches/test-use-ip-address.patch 24.0.2+12-1/debian/patches/test-use-ip-address.patch
--- 24.0.1+9-1/debian/patches/test-use-ip-address.patch	2023-06-09 15:48:10.000000000 +0000
+++ 24.0.2+12-1/debian/patches/test-use-ip-address.patch	2025-07-18 13:57:39.000000000 +0000
@@ -4,25 +4,14 @@ Description: Use IP address in tests
 Author: Vladimir Petko <vladimir.petko@canonical.com>
 Forwarded: not-needed
 Last-Update: 2023-03-27
---- a/test/jdk/java/net/InetAddress/IsReachableViaLoopbackTest.java
-+++ b/test/jdk/java/net/InetAddress/IsReachableViaLoopbackTest.java
-@@ -36,7 +36,7 @@
-     public static void main(String[] args) {
-         try {
-             InetAddress addr = InetAddress.getByName("localhost");
--            InetAddress remoteAddr = InetAddress.getByName("bugs.openjdk.org");
-+            InetAddress remoteAddr = InetAddress.getByName("8.8.8.8");
-             if (!addr.isReachable(10000))
-                 throw new RuntimeException("Localhost should always be reachable");
-             NetworkInterface inf = NetworkInterface.getByInetAddress(addr);
 --- a/test/jdk/java/net/InetAddress/getOriginalHostName.java
 +++ b/test/jdk/java/net/InetAddress/getOriginalHostName.java
-@@ -39,7 +39,7 @@
+@@ -39,7 +39,7 @@ public class getOriginalHostName {
          SharedSecrets.getJavaNetInetAddressAccess();
  
      public static void main(String[] args) throws Exception {
 -        final String HOST = "dummyserver.java.net";
 +        final String HOST = "localhost";
          InetAddress ia = null;
-         ia = InetAddress.getByName(HOST);
-         testInetAddress(ia, HOST);
+         ia = getInetAddress(HOST);
+         if (ia != null) testInetAddress(ia, HOST);
diff -pruN 24.0.1+9-1/debian/rules 24.0.2+12-1/debian/rules
--- 24.0.1+9-1/debian/rules	2025-04-23 10:09:30.000000000 +0000
+++ 24.0.2+12-1/debian/rules	2025-07-18 13:57:39.000000000 +0000
@@ -2059,7 +2059,7 @@ endif
 	dh_builddeb -a $(nodemo) $(nojrez) #$(bd_options)
 
 git_project		= jdk24u
-git_tag			= jdk-24.0.1+9
+git_tag			= jdk-24.0.2+12
 package_version		= $(shell echo $(PKGVERSION) | sed 's/-[^-][^-]*$$//')
 ifneq ($(is_upstream_release),yes)
   package_version	:= $(subst +,~,$(package_version))
diff -pruN 24.0.1+9-1/make/Bundles.gmk 24.0.2+12-1/make/Bundles.gmk
--- 24.0.1+9-1/make/Bundles.gmk	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/make/Bundles.gmk	2025-06-27 08:03:14.000000000 +0000
@@ -245,7 +245,10 @@ ifneq ($(filter product-bundles% legacy-
       )
 
   JDK_SYMBOLS_BUNDLE_FILES := \
-      $(call FindFiles, $(SYMBOLS_IMAGE_DIR))
+      $(filter-out \
+          %.stripped.pdb, \
+          $(call FindFiles, $(SYMBOLS_IMAGE_DIR)) \
+      )
 
   TEST_DEMOS_BUNDLE_FILES := $(filter $(JDK_DEMOS_IMAGE_HOMEDIR)/demo/%, \
       $(ALL_JDK_DEMOS_FILES))
diff -pruN 24.0.1+9-1/make/Docs.gmk 24.0.2+12-1/make/Docs.gmk
--- 24.0.1+9-1/make/Docs.gmk	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/make/Docs.gmk	2025-06-27 08:03:14.000000000 +0000
@@ -680,7 +680,7 @@ ifeq ($(ENABLE_PANDOC), true)
 
   $(foreach m, $(ALL_MODULES), \
     $(eval MAN_$m := $(call ApplySpecFilter, $(filter %.md, $(call FindFiles, \
-          $(call FindModuleManDirs, $m))))) \
+          $(call FindModuleManDirsForDocs, $m))))) \
     $(if $(MAN_$m), \
       $(eval $(call SetupProcessMarkdown, MAN_TO_HTML_$m, \
         FILES := $(MAN_$m), \
diff -pruN 24.0.1+9-1/make/Main.gmk 24.0.2+12-1/make/Main.gmk
--- 24.0.1+9-1/make/Main.gmk	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/make/Main.gmk	2025-06-27 08:03:14.000000000 +0000
@@ -1310,7 +1310,10 @@ endif
 ################################################################################
 
 # all-images builds all our deliverables as images.
-all-images: product-images static-jdk-image test-image all-docs-images
+all-images: product-images test-image all-docs-images
+ifeq ($(call isTargetOs, linux macosx windows), true)
+  all-images: static-jdk-image
+endif
 
 # all-bundles packages all our deliverables as tar.gz bundles.
 all-bundles: product-bundles test-bundles docs-bundles static-libs-bundles
diff -pruN 24.0.1+9-1/make/autoconf/build-aux/config.guess 24.0.2+12-1/make/autoconf/build-aux/config.guess
--- 24.0.1+9-1/make/autoconf/build-aux/config.guess	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/make/autoconf/build-aux/config.guess	2025-06-27 08:03:14.000000000 +0000
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
 # Copyright (c) 2021, Azul Systems, Inc. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
@@ -53,10 +53,10 @@ if [ "x$OUT" = x ]; then
   fi
 fi
 
-# Test and fix cygwin on x86_64
-echo $OUT | grep 86-pc-cygwin > /dev/null 2> /dev/null
+# Test and fix cygwin/msys CPUs
+echo $OUT | grep -e "-pc-cygwin" > /dev/null 2> /dev/null
 if test $? != 0; then
-  echo $OUT | grep 86-pc-mingw > /dev/null 2> /dev/null
+  echo $OUT | grep -e "-pc-mingw" > /dev/null 2> /dev/null
 fi
 if test $? = 0; then
   case `echo $PROCESSOR_IDENTIFIER | cut -f1 -d' '` in
@@ -64,6 +64,10 @@ if test $? = 0; then
       REAL_CPU=x86_64
       OUT=$REAL_CPU`echo $OUT | sed -e 's/[^-]*//'`
       ;;
+    ARMv8)
+      REAL_CPU=aarch64
+      OUT=$REAL_CPU`echo $OUT | sed -e 's/[^-]*//'`
+      ;;
   esac
 fi
 
diff -pruN 24.0.1+9-1/make/autoconf/flags-cflags.m4 24.0.2+12-1/make/autoconf/flags-cflags.m4
--- 24.0.1+9-1/make/autoconf/flags-cflags.m4	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/make/autoconf/flags-cflags.m4	2025-06-27 08:03:14.000000000 +0000
@@ -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
@@ -277,7 +277,7 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS],
 AC_DEFUN([FLAGS_SETUP_QUALITY_CHECKS],
 [
   # bounds, memory and behavior checking options
-  if test "x$TOOLCHAIN_TYPE" = xgcc; then
+  if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang; then
     case $DEBUG_LEVEL in
     release )
       # no adjustment
@@ -354,7 +354,7 @@ AC_DEFUN([FLAGS_SETUP_OPTIMIZATION],
     C_O_FLAG_DEBUG="-Od"
     C_O_FLAG_DEBUG_JVM=""
     C_O_FLAG_NONE="-Od"
-    C_O_FLAG_SIZE="-Os"
+    C_O_FLAG_SIZE="-O1"
   fi
 
   # Now copy to C++ flags
@@ -524,12 +524,6 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER],
         -fvisibility=hidden -fno-strict-aliasing -fno-omit-frame-pointer"
   fi
 
-  if test "x$TOOLCHAIN_TYPE" = xclang && test "x$OPENJDK_TARGET_OS" = xaix; then
-    # clang compiler on aix needs -ffunction-sections
-    TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -ffunction-sections -ftls-model -fno-math-errno -fstack-protector"
-    TOOLCHAIN_CFLAGS_JDK="-ffunction-sections -fsigned-char -fstack-protector"
-  fi
-
   if test "x$TOOLCHAIN_TYPE" = xgcc; then
     TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -fstack-protector"
     TOOLCHAIN_CFLAGS_JDK="-fvisibility=hidden -pipe -fstack-protector"
@@ -549,7 +543,7 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER],
     # Restrict the debug information created by Clang to avoid
     # too big object files and speed the build up a little bit
     # (see http://llvm.org/bugs/show_bug.cgi?id=7554)
-    TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -flimit-debug-info"
+    TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -flimit-debug-info -fstack-protector"
 
     # In principle the stack alignment below is cpu- and ABI-dependent and
     # should agree with values of StackAlignmentInBytes in various
@@ -567,7 +561,13 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER],
       TOOLCHAIN_CFLAGS_JDK="-pipe"
       TOOLCHAIN_CFLAGS_JDK_CONLY="-fno-strict-aliasing" # technically NOT for CXX
     fi
-    TOOLCHAIN_CFLAGS_JDK="$TOOLCHAIN_CFLAGS_JDK -fvisibility=hidden"
+
+    if test "x$OPENJDK_TARGET_OS" = xaix; then
+      TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -ffunction-sections -ftls-model -fno-math-errno"
+      TOOLCHAIN_CFLAGS_JDK="-ffunction-sections -fsigned-char"
+    fi
+
+    TOOLCHAIN_CFLAGS_JDK="$TOOLCHAIN_CFLAGS_JDK -fvisibility=hidden -fstack-protector"
 
   elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
     # The -utf-8 option sets source and execution character sets to UTF-8 to enable correct
@@ -743,7 +743,7 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
       elif test "x$FLAGS_CPU" = xppc64le; then
         # Little endian machine uses ELFv2 ABI.
         # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI.
-        $1_CFLAGS_CPU_JVM="${$1_CFLAGS_CPU_JVM} -DABI_ELFv2 -mcpu=power8 -mtune=power8"
+        $1_CFLAGS_CPU_JVM="${$1_CFLAGS_CPU_JVM} -DABI_ELFv2 -mcpu=power8 -mtune=power10"
       fi
     elif test "x$FLAGS_CPU" = xs390x; then
       $1_CFLAGS_CPU="-mbackchain -march=z10"
@@ -761,6 +761,11 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
         # for all archs except arm and ppc, prevent gcc to omit frame pointer
         $1_CFLAGS_CPU_JDK="${$1_CFLAGS_CPU_JDK} -fno-omit-frame-pointer"
       fi
+      if test "x$FLAGS_CPU" = xppc64le; then
+        # Little endian machine uses ELFv2 ABI.
+        # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI.
+        $1_CFLAGS_CPU_JVM="${$1_CFLAGS_CPU_JVM} -DABI_ELFv2 -mcpu=power8 -mtune=power10"
+      fi
     fi
     if test "x$OPENJDK_TARGET_OS" = xaix; then
       $1_CFLAGS_CPU="-mcpu=pwr8"
diff -pruN 24.0.1+9-1/make/autoconf/toolchain_microsoft.m4 24.0.2+12-1/make/autoconf/toolchain_microsoft.m4
--- 24.0.1+9-1/make/autoconf/toolchain_microsoft.m4	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/make/autoconf/toolchain_microsoft.m4	2025-06-27 08:03:14.000000000 +0000
@@ -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
@@ -87,7 +87,7 @@ AC_DEFUN([TOOLCHAIN_CHECK_POSSIBLE_VISUA
       elif test "x$TARGET_CPU" = xaarch64; then
         # for host x86-64, target aarch64
         # aarch64 requires Visual Studio 16.8 or higher
-        VCVARSFILES="vcvarsamd64_arm64.bat vcvarsx86_arm64.bat"
+        VCVARSFILES="vcvarsarm64.bat vcvarsamd64_arm64.bat vcvarsx86_arm64.bat"
       fi
 
       for VCVARSFILE in $VCVARSFILES; do
diff -pruN 24.0.1+9-1/make/common/Modules.gmk 24.0.2+12-1/make/common/Modules.gmk
--- 24.0.1+9-1/make/common/Modules.gmk	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/make/common/Modules.gmk	2025-06-27 08:03:14.000000000 +0000
@@ -92,7 +92,10 @@ SRC_SUBDIRS += share/classes
 
 SPEC_SUBDIRS += share/specs
 
-MAN_SUBDIRS += share/man windows/man
+MAN_SUBDIRS += share/man $(TARGET_OS)/man
+
+# The docs should include the sum of all man pages for all platforms
+MAN_DOCS_SUBDIRS += share/man windows/man
 
 # Find all module-info.java files for the current build target platform and
 # configuration.
@@ -158,6 +161,10 @@ FindModuleManDirs = \
     $(strip $(wildcard \
         $(foreach sub, $(MAN_SUBDIRS), $(addsuffix /$(strip $1)/$(sub), $(TOP_SRC_DIRS)))))
 
+FindModuleManDirsForDocs = \
+    $(strip $(wildcard \
+        $(foreach sub, $(MAN_DOCS_SUBDIRS), $(addsuffix /$(strip $1)/$(sub), $(TOP_SRC_DIRS)))))
+
 # Construct the complete module source path
 GetModuleSrcPath = \
     $(call PathList, \
diff -pruN 24.0.1+9-1/make/conf/version-numbers.conf 24.0.2+12-1/make/conf/version-numbers.conf
--- 24.0.1+9-1/make/conf/version-numbers.conf	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/make/conf/version-numbers.conf	2025-06-27 08:03:14.000000000 +0000
@@ -28,12 +28,12 @@
 
 DEFAULT_VERSION_FEATURE=24
 DEFAULT_VERSION_INTERIM=0
-DEFAULT_VERSION_UPDATE=1
+DEFAULT_VERSION_UPDATE=2
 DEFAULT_VERSION_PATCH=0
 DEFAULT_VERSION_EXTRA1=0
 DEFAULT_VERSION_EXTRA2=0
 DEFAULT_VERSION_EXTRA3=0
-DEFAULT_VERSION_DATE=2025-04-15
+DEFAULT_VERSION_DATE=2025-07-15
 DEFAULT_VERSION_CLASSFILE_MAJOR=68  # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`"
 DEFAULT_VERSION_CLASSFILE_MINOR=0
 DEFAULT_VERSION_DOCS_API_SINCE=11
diff -pruN 24.0.1+9-1/make/hotspot/lib/CompileJvm.gmk 24.0.2+12-1/make/hotspot/lib/CompileJvm.gmk
--- 24.0.1+9-1/make/hotspot/lib/CompileJvm.gmk	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/make/hotspot/lib/CompileJvm.gmk	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 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
@@ -125,9 +125,7 @@ else ifeq ($(call And, $(call isTargetOs
   endif
 endif
 
-ifeq ($(call isTargetOs, linux macosx windows), true)
-  JVM_PRECOMPILED_HEADER := $(TOPDIR)/src/hotspot/share/precompiled/precompiled.hpp
-endif
+JVM_PRECOMPILED_HEADER := $(TOPDIR)/src/hotspot/share/precompiled/precompiled.hpp
 
 ifeq ($(call isTargetCpu, x86), true)
   JVM_EXCLUDE_PATTERNS += x86_64
diff -pruN 24.0.1+9-1/make/hotspot/lib/JvmOverrideFiles.gmk 24.0.2+12-1/make/hotspot/lib/JvmOverrideFiles.gmk
--- 24.0.1+9-1/make/hotspot/lib/JvmOverrideFiles.gmk	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/make/hotspot/lib/JvmOverrideFiles.gmk	2025-06-27 08:03:14.000000000 +0000
@@ -110,11 +110,7 @@ else ifeq ($(call isTargetOs, macosx), t
   endif
 
 else ifeq ($(call isTargetOs, aix), true)
-  ifeq ($(TOOLCHAIN_TYPE), clang)
-    BUILD_LIBJVM_synchronizer.cpp_CXXFLAGS := -fno-inline
-  else
-    BUILD_LIBJVM_synchronizer.cpp_CXXFLAGS := -qnoinline
-  endif
+  BUILD_LIBJVM_synchronizer.cpp_CXXFLAGS := -fno-inline
   BUILD_LIBJVM_sharedRuntimeTrans.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE)
   # Disable aggressive optimizations for functions in sharedRuntimeTrig.cpp
   # and sharedRuntimeTrans.cpp on ppc64.
@@ -128,16 +124,16 @@ else ifeq ($(call isTargetOs, aix), true
   # mode, so don't optimize sharedRuntimeTrig.cpp at all.
   BUILD_LIBJVM_sharedRuntimeTrig.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE)
 
-  ifneq ($(DEBUG_LEVEL), slowdebug)
-    # Compiling jvmtiEnterTrace.cpp with full optimization needs more than 30min
-    # (mostly because of '-qhot=level=1' and the more than 1300 'log_trace' calls
-    # which cause a lot of template expansion).
-    BUILD_LIBJVM_jvmtiEnterTrace.cpp_OPTIMIZATION := LOW
-  endif
-
   # Disable ELF decoder on AIX (AIX uses XCOFF).
   JVM_EXCLUDE_PATTERNS += elf
 
+  JVM_PRECOMPILED_HEADER_EXCLUDE := \
+      sharedRuntimeTrig.cpp \
+      sharedRuntimeTrans.cpp \
+      synchronizer.cpp \
+      $(OPT_SPEED_SRC) \
+      #
+
 else ifeq ($(call isTargetOs, windows), true)
   JVM_PRECOMPILED_HEADER_EXCLUDE := \
       bytecodeInterpreter.cpp \
diff -pruN 24.0.1+9-1/make/modules/java.desktop/lib/AwtLibraries.gmk 24.0.2+12-1/make/modules/java.desktop/lib/AwtLibraries.gmk
--- 24.0.1+9-1/make/modules/java.desktop/lib/AwtLibraries.gmk	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/make/modules/java.desktop/lib/AwtLibraries.gmk	2025-06-27 08:03:14.000000000 +0000
@@ -216,10 +216,14 @@ ifeq ($(call isTargetOs, windows macosx)
       common/font \
       common/java2d/opengl \
       common/java2d/x11 \
-      libpipewire/include \
       java.base:libjvm \
       #
 
+  # exclude pipewire from the AIX build, no Wayland support
+  ifeq ($(call isTargetOs, aix), false)
+    LIBAWT_XAWT_EXTRA_HEADER_DIRS += libpipewire/include
+  endif
+
   ifeq ($(call isTargetOs, linux), true)
     ifeq ($(DISABLE_XRENDER), true)
       LIBAWT_XAWT_CFLAGS += -DDISABLE_XRENDER_BY_DEFAULT=true
diff -pruN 24.0.1+9-1/make/modules/java.desktop/lib/ClientLibraries.gmk 24.0.2+12-1/make/modules/java.desktop/lib/ClientLibraries.gmk
--- 24.0.1+9-1/make/modules/java.desktop/lib/ClientLibraries.gmk	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/make/modules/java.desktop/lib/ClientLibraries.gmk	2025-06-27 08:03:14.000000000 +0000
@@ -222,7 +222,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false)
       EXCLUDE_SRC_PATTERNS := $(LIBSPLASHSCREEN_EXCLUDE_SRC_PATTERNS), \
       EXCLUDE_FILES := imageioJPEG.c jpegdecoder.c pngtest.c, \
       EXCLUDES := $(LIBSPLASHSCREEN_EXCLUDES), \
-      OPTIMIZATION := LOW, \
+      OPTIMIZATION := SIZE, \
       CFLAGS := $(LIBSPLASHSCREEN_CFLAGS) \
           $(GIFLIB_CFLAGS) $(LIBJPEG_CFLAGS) $(PNG_CFLAGS) $(LIBZ_CFLAGS), \
       CXXFLAGS := $(LIBSPLASHSCREEN_CFLAGS) \
@@ -231,7 +231,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false)
       DISABLED_WARNINGS_gcc_dgif_lib.c := sign-compare, \
       DISABLED_WARNINGS_gcc_jcmaster.c := implicit-fallthrough, \
       DISABLED_WARNINGS_gcc_jdphuff.c := shift-negative-value, \
-      DISABLED_WARNINGS_gcc_png.c := maybe-uninitialized, \
+      DISABLED_WARNINGS_gcc_png.c := maybe-uninitialized unused-function, \
       DISABLED_WARNINGS_gcc_pngerror.c := maybe-uninitialized, \
       DISABLED_WARNINGS_gcc_splashscreen_gfx_impl.c := implicit-fallthrough \
           maybe-uninitialized, \
@@ -242,6 +242,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false)
       DISABLED_WARNINGS_clang := deprecated-non-prototype, \
       DISABLED_WARNINGS_clang_dgif_lib.c := sign-compare, \
       DISABLED_WARNINGS_clang_gzwrite.c := format-nonliteral, \
+      DISABLED_WARNINGS_clang_png.c := unused-function, \
       DISABLED_WARNINGS_clang_splashscreen_impl.c := sign-compare \
           unused-but-set-variable unused-function, \
       DISABLED_WARNINGS_clang_splashscreen_png.c := \
@@ -327,7 +328,7 @@ else
 
   HARFBUZZ_DISABLED_WARNINGS_gcc := missing-field-initializers \
       strict-aliasing unused-result array-bounds parentheses \
-       unused-variable
+       unused-variable dangling-pointer
   # noexcept-type required for GCC 7 builds. Not required for GCC 8+.
   # expansion-to-defined required for GCC 9 builds. Not required for GCC 10+.
   # maybe-uninitialized required for GCC 8 builds. Not required for GCC 9+.
diff -pruN 24.0.1+9-1/make/modules/jdk.jlink/Java.gmk 24.0.2+12-1/make/modules/jdk.jlink/Java.gmk
--- 24.0.1+9-1/make/modules/jdk.jlink/Java.gmk	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/make/modules/jdk.jlink/Java.gmk	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 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
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+################################################################################
+
+# Instruct SetupJavaCompilation for the jdk.jlink module to include
+# upgrade_files_<module-name>.conf files
+COPY += .conf
+
+################################################################################
diff -pruN 24.0.1+9-1/src/hotspot/cpu/aarch64/abstractInterpreter_aarch64.cpp 24.0.2+12-1/src/hotspot/cpu/aarch64/abstractInterpreter_aarch64.cpp
--- 24.0.1+9-1/src/hotspot/cpu/aarch64/abstractInterpreter_aarch64.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/cpu/aarch64/abstractInterpreter_aarch64.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -150,7 +150,8 @@ void AbstractInterpreter::layout_activat
 
 #ifdef ASSERT
   if (caller->is_interpreted_frame()) {
-    assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement");
+    assert(locals <= caller->interpreter_frame_expression_stack(), "bad placement");
+    assert(locals >= interpreter_frame->sender_sp() + max_locals - 1, "bad placement");
   }
 #endif
 
diff -pruN 24.0.1+9-1/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp 24.0.2+12-1/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
--- 24.0.1+9-1/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -158,6 +158,13 @@ void VM_Version::initialize() {
     if (FLAG_IS_DEFAULT(OnSpinWaitInstCount)) {
       FLAG_SET_DEFAULT(OnSpinWaitInstCount, 2);
     }
+    if (FLAG_IS_DEFAULT(CodeEntryAlignment) &&
+        (_model == CPU_MODEL_AMPERE_1A || _model == CPU_MODEL_AMPERE_1B)) {
+      FLAG_SET_DEFAULT(CodeEntryAlignment, 32);
+    }
+    if (FLAG_IS_DEFAULT(UseSignumIntrinsic)) {
+      FLAG_SET_DEFAULT(UseSignumIntrinsic, true);
+    }
   }
 
   // ThunderX
diff -pruN 24.0.1+9-1/src/hotspot/cpu/arm/abstractInterpreter_arm.cpp 24.0.2+12-1/src/hotspot/cpu/arm/abstractInterpreter_arm.cpp
--- 24.0.1+9-1/src/hotspot/cpu/arm/abstractInterpreter_arm.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/cpu/arm/abstractInterpreter_arm.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -132,6 +132,15 @@ void AbstractInterpreter::layout_activat
 
   intptr_t* locals = interpreter_frame->sender_sp() + max_locals - 1;
 
+#ifdef ASSERT
+  if (caller->is_interpreted_frame()) {
+    // Test exact placement on top of caller args
+    intptr_t* l2 = caller->interpreter_frame_last_sp() + caller_actual_parameters - 1;
+    assert(l2 <= caller->interpreter_frame_expression_stack(), "bad placement");
+    assert(l2 >= locals, "bad placement");
+  }
+#endif
+
   interpreter_frame->interpreter_frame_set_locals(locals);
   BasicObjectLock* montop = interpreter_frame->interpreter_frame_monitor_begin();
   BasicObjectLock* monbot = montop - moncount;
diff -pruN 24.0.1+9-1/src/hotspot/cpu/ppc/abstractInterpreter_ppc.cpp 24.0.2+12-1/src/hotspot/cpu/ppc/abstractInterpreter_ppc.cpp
--- 24.0.1+9-1/src/hotspot/cpu/ppc/abstractInterpreter_ppc.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/cpu/ppc/abstractInterpreter_ppc.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -129,6 +129,15 @@ void AbstractInterpreter::layout_activat
     caller->interpreter_frame_esp() + caller_actual_parameters :
     caller->sp() + method->max_locals() - 1 + (frame::java_abi_size / Interpreter::stackElementSize);
 
+#ifdef ASSERT
+  if (caller->is_interpreted_frame()) {
+    assert(locals_base <= caller->interpreter_frame_expression_stack(), "bad placement");
+    const int caller_abi_bytesize = (is_bottom_frame ? frame::top_ijava_frame_abi_size : frame::parent_ijava_frame_abi_size);
+    intptr_t* l2 = caller->sp() + method->max_locals() - 1 + (caller_abi_bytesize / Interpreter::stackElementSize);
+    assert(locals_base >= l2, "bad placement");
+  }
+#endif
+
   intptr_t* monitor_base = caller->sp() - frame::ijava_state_size / Interpreter::stackElementSize;
   intptr_t* monitor      = monitor_base - (moncount * frame::interpreter_frame_monitor_size());
   intptr_t* esp_base     = monitor - 1;
diff -pruN 24.0.1+9-1/src/hotspot/cpu/ppc/compiledIC_ppc.cpp 24.0.2+12-1/src/hotspot/cpu/ppc/compiledIC_ppc.cpp
--- 24.0.1+9-1/src/hotspot/cpu/ppc/compiledIC_ppc.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/cpu/ppc/compiledIC_ppc.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -30,9 +30,6 @@
 #include "memory/resourceArea.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/safepoint.hpp"
-#ifdef COMPILER2
-#include "opto/matcher.hpp"
-#endif
 
 // ----------------------------------------------------------------------------
 
@@ -79,7 +76,6 @@
 const int IC_pos_in_java_to_interp_stub = 8;
 #define __ masm->
 address CompiledDirectCall::emit_to_interp_stub(MacroAssembler *masm, address mark/* = nullptr*/) {
-#ifdef COMPILER2
   if (mark == nullptr) {
     // Get the mark within main instrs section which is set to the address of the call.
     mark = __ inst_mark();
@@ -109,7 +105,7 @@ address CompiledDirectCall::emit_to_inte
   // - call
   __ calculate_address_from_global_toc(reg_scratch, __ method_toc());
   AddressLiteral ic = __ allocate_metadata_address((Metadata *)nullptr);
-  bool success = __ load_const_from_method_toc(as_Register(Matcher::inline_cache_reg_encode()),
+  bool success = __ load_const_from_method_toc(R19_inline_cache_reg,
                                                ic, reg_scratch, /*fixed_size*/ true);
   if (!success) {
     return nullptr; // CodeCache is full
@@ -135,13 +131,9 @@ address CompiledDirectCall::emit_to_inte
   assert(!is_NativeCallTrampolineStub_at(__ addr_at(stub_start_offset)),
          "must not confuse java_to_interp with trampoline stubs");
 
- // End the stub.
+  // End the stub.
   __ end_a_stub();
   return stub;
-#else
-  ShouldNotReachHere();
-  return nullptr;
-#endif
 }
 #undef __
 
diff -pruN 24.0.1+9-1/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp 24.0.2+12-1/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp
--- 24.0.1+9-1/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1285,13 +1285,7 @@ int MacroAssembler::ic_check(int end_ali
     if (use_trap_based_null_check) {
       trap_null_check(receiver);
     }
-    if (UseCompactObjectHeaders) {
-      load_narrow_klass_compact(tmp1, receiver);
-    } else if (UseCompressedClassPointers) {
-      lwz(tmp1, oopDesc::klass_offset_in_bytes(), receiver);
-    } else {
-      ld(tmp1, oopDesc::klass_offset_in_bytes(), receiver);
-    }
+    load_klass_no_decode(tmp1, receiver); // 2 instructions with UseCompactObjectHeaders
     ld(tmp2, in_bytes(CompiledICData::speculated_klass_offset()), data);
     trap_ic_miss_check(tmp1, tmp2);
 
@@ -1307,11 +1301,7 @@ int MacroAssembler::ic_check(int end_ali
       cmpdi(CCR0, receiver, 0);
       beqctr(CCR0);
     }
-    if (UseCompressedClassPointers) {
-      lwz(tmp1, oopDesc::klass_offset_in_bytes(), receiver);
-    } else {
-      ld(tmp1, oopDesc::klass_offset_in_bytes(), receiver);
-    }
+    load_klass_no_decode(tmp1, receiver); // 2 instructions with UseCompactObjectHeaders
     ld(tmp2, in_bytes(CompiledICData::speculated_klass_offset()), data);
     cmpd(CCR0, tmp1, tmp2);
     bnectr(CCR0);
@@ -3365,18 +3355,23 @@ void MacroAssembler::decode_klass_not_nu
   }
 }
 
-void MacroAssembler::load_klass(Register dst, Register src) {
+void MacroAssembler::load_klass_no_decode(Register dst, Register src) {
   if (UseCompactObjectHeaders) {
     load_narrow_klass_compact(dst, src);
-    decode_klass_not_null(dst);
   } else if (UseCompressedClassPointers) {
     lwz(dst, oopDesc::klass_offset_in_bytes(), src);
-    decode_klass_not_null(dst);
   } else {
     ld(dst, oopDesc::klass_offset_in_bytes(), src);
   }
 }
 
+void MacroAssembler::load_klass(Register dst, Register src) {
+  load_klass_no_decode(dst, src);
+  if (UseCompressedClassPointers) { // also true for UseCompactObjectHeaders
+    decode_klass_not_null(dst);
+  }
+}
+
 // Loads the obj's Klass* into dst.
 // Preserves all registers (incl src, rscratch1 and rscratch2).
 // Input:
diff -pruN 24.0.1+9-1/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp 24.0.2+12-1/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp
--- 24.0.1+9-1/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp	2025-06-27 08:03:14.000000000 +0000
@@ -769,6 +769,7 @@ class MacroAssembler: public Assembler {
   inline void decode_heap_oop(Register d);
 
   // Load/Store klass oop from klass field. Compress.
+  void load_klass_no_decode(Register dst, Register src);
   void load_klass(Register dst, Register src);
   void load_narrow_klass_compact(Register dst, Register src);
   void cmp_klass(ConditionRegister dst, Register obj, Register klass, Register tmp, Register tmp2);
diff -pruN 24.0.1+9-1/src/hotspot/cpu/riscv/abstractInterpreter_riscv.cpp 24.0.2+12-1/src/hotspot/cpu/riscv/abstractInterpreter_riscv.cpp
--- 24.0.1+9-1/src/hotspot/cpu/riscv/abstractInterpreter_riscv.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/cpu/riscv/abstractInterpreter_riscv.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -142,7 +142,8 @@ void AbstractInterpreter::layout_activat
 
 #ifdef ASSERT
   if (caller->is_interpreted_frame()) {
-    assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement");
+    assert(locals <= caller->interpreter_frame_expression_stack(), "bad placement");
+    assert(locals >= interpreter_frame->sender_sp() + max_locals - 1, "bad placement");
   }
 #endif
 
diff -pruN 24.0.1+9-1/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp 24.0.2+12-1/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp
--- 24.0.1+9-1/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -2201,7 +2201,7 @@ void C2_MacroAssembler::float16_to_float
   mv(t0, 0x7c00);
   andr(tmp, src, t0);
   // jump to stub processing NaN and Inf cases.
-  beq(t0, tmp, stub->entry());
+  beq(t0, tmp, stub->entry(), true);
 
   // non-NaN or non-Inf cases, just use built-in instructions.
   fmv_h_x(dst, src);
@@ -2244,7 +2244,7 @@ void C2_MacroAssembler::float_to_float16
   // replace fclass with feq as performance optimization.
   feq_s(t0, src, src);
   // jump to stub processing NaN cases.
-  beqz(t0, stub->entry());
+  beqz(t0, stub->entry(), true);
 
   // non-NaN cases, just use built-in instructions.
   fcvt_h_s(ftmp, src);
@@ -2305,7 +2305,7 @@ void C2_MacroAssembler::float16_to_float
   vfwcvt_f_f_v(dst, src);
 
   // jump to stub processing NaN and Inf cases if there is any of them in the vector-wide.
-  bnez(t0, stub->entry());
+  bnez(t0, stub->entry(), true);
 
   bind(stub->continuation());
 }
@@ -2359,7 +2359,7 @@ void C2_MacroAssembler::float_to_float16
   vfncvt_f_f_w(dst, src);
 
   // jump to stub processing NaN cases.
-  bnez(t0, stub->entry());
+  bnez(t0, stub->entry(), true);
 
   bind(stub->continuation());
 }
diff -pruN 24.0.1+9-1/src/hotspot/cpu/riscv/compressedKlass_riscv.cpp 24.0.2+12-1/src/hotspot/cpu/riscv/compressedKlass_riscv.cpp
--- 24.0.1+9-1/src/hotspot/cpu/riscv/compressedKlass_riscv.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/cpu/riscv/compressedKlass_riscv.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -31,7 +31,7 @@ char* CompressedKlassPointers::reserve_a
 
   char* result = nullptr;
 
-  // RiscV loads a 64-bit immediate in up to four separate steps, splitting it into four different sections
+  // RISC-V loads a 64-bit immediate in up to four separate steps, splitting it into four different sections
   // (two 32-bit sections, each split into two subsections of 20/12 bits).
   //
   // 63 ....... 44 43 ... 32 31 ....... 12 11 ... 0
@@ -51,11 +51,6 @@ char* CompressedKlassPointers::reserve_a
   //   with one instruction (2)
   result = reserve_address_space_for_unscaled_encoding(size, aslr);
 
-  // Failing that, attempt to reserve for base=zero shift>0
-  if (result == nullptr && optimize_for_zero_base) {
-    result = reserve_address_space_for_zerobased_encoding(size, aslr);
-  }
-
   // Failing that, optimize for case (3) - a base with only bits set between [32-44)
   if (result == nullptr) {
     const uintptr_t from = nth_bit(32);
diff -pruN 24.0.1+9-1/src/hotspot/cpu/s390/abstractInterpreter_s390.cpp 24.0.2+12-1/src/hotspot/cpu/s390/abstractInterpreter_s390.cpp
--- 24.0.1+9-1/src/hotspot/cpu/s390/abstractInterpreter_s390.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/cpu/s390/abstractInterpreter_s390.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -183,6 +183,13 @@ void AbstractInterpreter::layout_activat
   intptr_t* sender_sp;
   if (caller->is_interpreted_frame()) {
     sender_sp = caller->interpreter_frame_top_frame_sp();
+#ifdef ASSERT
+    assert(locals_base <= caller->interpreter_frame_expression_stack(), "bad placement");
+    // Test caller-aligned placement vs callee-aligned
+    intptr_t* l2 = (caller->sp() + method->max_locals() - 1 +
+      frame::z_parent_ijava_frame_abi_size / Interpreter::stackElementSize);
+    assert(locals_base >= l2, "bad placement");
+#endif
   } else if (caller->is_compiled_frame()) {
     sender_sp = caller->fp() - caller->cb()->frame_size();
     // The bottom frame's sender_sp is its caller's unextended_sp.
diff -pruN 24.0.1+9-1/src/hotspot/cpu/x86/abstractInterpreter_x86.cpp 24.0.2+12-1/src/hotspot/cpu/x86/abstractInterpreter_x86.cpp
--- 24.0.1+9-1/src/hotspot/cpu/x86/abstractInterpreter_x86.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/cpu/x86/abstractInterpreter_x86.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -88,7 +88,10 @@ void AbstractInterpreter::layout_activat
 
 #ifdef ASSERT
   if (caller->is_interpreted_frame()) {
-    assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement");
+    // Test exact placement on top of caller args
+    intptr_t* l2 = caller->interpreter_frame_last_sp() + caller_actual_parameters - 1;
+    assert(l2 <= caller->interpreter_frame_expression_stack(), "bad placement");
+    assert(l2 >= locals, "bad placement");
   }
 #endif
 
diff -pruN 24.0.1+9-1/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp 24.0.2+12-1/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
--- 24.0.1+9-1/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -6220,15 +6220,21 @@ void C2_MacroAssembler::vector_count_lea
   // Since IEEE 754 floating point format represents mantissa in 1.0 format
   // hence biased exponent can be used to compute leading zero count as per
   // following formula:-
-  // LZCNT = 32 - (biased_exp - 127)
+  // LZCNT = 31 - (biased_exp - 127)
   // Special handling has been introduced for Zero, Max_Int and -ve source values.
 
   // Broadcast 0xFF
   vpcmpeqd(xtmp1, xtmp1, xtmp1, vec_enc);
   vpsrld(xtmp1, xtmp1, 24, vec_enc);
 
+  // Remove the bit to the right of the highest set bit ensuring that the conversion to float cannot round up to a higher
+  // power of 2, which has a higher exponent than the input. This transformation is valid as only the highest set bit
+  // contributes to the leading number of zeros.
+  vpsrld(xtmp2, src, 1, vec_enc);
+  vpandn(xtmp3, xtmp2, src, vec_enc);
+
   // Extract biased exponent.
-  vcvtdq2ps(dst, src, vec_enc);
+  vcvtdq2ps(dst, xtmp3, vec_enc);
   vpsrld(dst, dst, 23, vec_enc);
   vpand(dst, dst, xtmp1, vec_enc);
 
@@ -6237,7 +6243,7 @@ void C2_MacroAssembler::vector_count_lea
   // Exponent = biased_exp - 127
   vpsubd(dst, dst, xtmp1, vec_enc);
 
-  // Exponent = Exponent  + 1
+  // Exponent_plus_one = Exponent + 1
   vpsrld(xtmp3, xtmp1, 6, vec_enc);
   vpaddd(dst, dst, xtmp3, vec_enc);
 
@@ -6250,7 +6256,7 @@ void C2_MacroAssembler::vector_count_lea
   vpslld(xtmp1, xtmp3, 5, vec_enc);
   // Exponent is 32 if corresponding source lane contains max_int value.
   vpcmpeqd(xtmp2, dst, xtmp1, vec_enc);
-  // LZCNT = 32 - exponent
+  // LZCNT = 32 - exponent_plus_one
   vpsubd(dst, xtmp1, dst, vec_enc);
 
   // Replace LZCNT with a value 1 if corresponding source lane
diff -pruN 24.0.1+9-1/src/hotspot/os/aix/os_aix.cpp 24.0.2+12-1/src/hotspot/os/aix/os_aix.cpp
--- 24.0.1+9-1/src/hotspot/os/aix/os_aix.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/os/aix/os_aix.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -828,13 +828,6 @@ bool os::create_attached_thread(JavaThre
 
   thread->set_osthread(osthread);
 
-  if (UseNUMA) {
-    int lgrp_id = os::numa_get_group_id();
-    if (lgrp_id != -1) {
-      thread->set_lgrp_id(lgrp_id);
-    }
-  }
-
   // initialize signal mask for this thread
   // and save the caller's signal mask
   PosixSignals::hotspot_sigmask(thread);
diff -pruN 24.0.1+9-1/src/hotspot/os/linux/cgroupUtil_linux.cpp 24.0.2+12-1/src/hotspot/os/linux/cgroupUtil_linux.cpp
--- 24.0.1+9-1/src/hotspot/os/linux/cgroupUtil_linux.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/os/linux/cgroupUtil_linux.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Red Hat, Inc.
+ * Copyright (c) 2024, 2025, Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,12 +49,18 @@ int CgroupUtil::processor_count(CgroupCp
 }
 
 void CgroupUtil::adjust_controller(CgroupMemoryController* mem) {
+  assert(mem->cgroup_path() != nullptr, "invariant");
+  if (strstr(mem->cgroup_path(), "../") != nullptr) {
+    log_warning(os, container)("Cgroup memory controller path at '%s' seems to have moved to '%s', detected limits won't be accurate",
+      mem->mount_point(), mem->cgroup_path());
+    mem->set_subsystem_path("/");
+    return;
+  }
   if (!mem->needs_hierarchy_adjustment()) {
     // nothing to do
     return;
   }
   log_trace(os, container)("Adjusting controller path for memory: %s", mem->subsystem_path());
-  assert(mem->cgroup_path() != nullptr, "invariant");
   char* orig = os::strdup(mem->cgroup_path());
   char* cg_path = os::strdup(orig);
   char* last_slash;
@@ -62,7 +68,8 @@ void CgroupUtil::adjust_controller(Cgrou
   julong phys_mem = os::Linux::physical_memory();
   char* limit_cg_path = nullptr;
   jlong limit = mem->read_memory_limit_in_bytes(phys_mem);
-  jlong lowest_limit = phys_mem;
+  jlong lowest_limit = limit < 0 ? phys_mem : limit;
+  julong orig_limit = ((julong)lowest_limit) != phys_mem ? lowest_limit : phys_mem;
   while ((last_slash = strrchr(cg_path, '/')) != cg_path) {
     *last_slash = '\0'; // strip path
     // update to shortened path and try again
@@ -83,7 +90,7 @@ void CgroupUtil::adjust_controller(Cgrou
     limit_cg_path = os::strdup("/");
   }
   assert(lowest_limit >= 0, "limit must be positive");
-  if ((julong)lowest_limit != phys_mem) {
+  if ((julong)lowest_limit != orig_limit) {
     // we've found a lower limit anywhere in the hierarchy,
     // set the path to the limit path
     assert(limit_cg_path != nullptr, "limit path must be set");
@@ -93,6 +100,7 @@ void CgroupUtil::adjust_controller(Cgrou
                              mem->subsystem_path(),
                              lowest_limit);
   } else {
+    log_trace(os, container)("Lowest limit was: " JLONG_FORMAT, lowest_limit);
     log_trace(os, container)("No lower limit found for memory in hierarchy %s, "
                              "adjusting to original path %s",
                               mem->mount_point(), orig);
@@ -104,19 +112,26 @@ void CgroupUtil::adjust_controller(Cgrou
 }
 
 void CgroupUtil::adjust_controller(CgroupCpuController* cpu) {
+  assert(cpu->cgroup_path() != nullptr, "invariant");
+  if (strstr(cpu->cgroup_path(), "../") != nullptr) {
+    log_warning(os, container)("Cgroup cpu controller path at '%s' seems to have moved to '%s', detected limits won't be accurate",
+      cpu->mount_point(), cpu->cgroup_path());
+    cpu->set_subsystem_path("/");
+    return;
+  }
   if (!cpu->needs_hierarchy_adjustment()) {
     // nothing to do
     return;
   }
   log_trace(os, container)("Adjusting controller path for cpu: %s", cpu->subsystem_path());
-  assert(cpu->cgroup_path() != nullptr, "invariant");
   char* orig = os::strdup(cpu->cgroup_path());
   char* cg_path = os::strdup(orig);
   char* last_slash;
   assert(cg_path[0] == '/', "cgroup path must start with '/'");
   int host_cpus = os::Linux::active_processor_count();
   int cpus = CgroupUtil::processor_count(cpu, host_cpus);
-  int lowest_limit = host_cpus;
+  int lowest_limit = cpus < host_cpus ? cpus: host_cpus;
+  int orig_limit = lowest_limit != host_cpus ? lowest_limit : host_cpus;
   char* limit_cg_path = nullptr;
   while ((last_slash = strrchr(cg_path, '/')) != cg_path) {
     *last_slash = '\0'; // strip path
@@ -138,7 +153,7 @@ void CgroupUtil::adjust_controller(Cgrou
     limit_cg_path = os::strdup(cg_path);
   }
   assert(lowest_limit >= 0, "limit must be positive");
-  if (lowest_limit != host_cpus) {
+  if (lowest_limit != orig_limit) {
     // we've found a lower limit anywhere in the hierarchy,
     // set the path to the limit path
     assert(limit_cg_path != nullptr, "limit path must be set");
@@ -148,6 +163,7 @@ void CgroupUtil::adjust_controller(Cgrou
                              cpu->subsystem_path(),
                              lowest_limit);
   } else {
+    log_trace(os, container)("Lowest limit was: %d", lowest_limit);
     log_trace(os, container)("No lower limit found for cpu in hierarchy %s, "
                              "adjusting to original path %s",
                               cpu->mount_point(), orig);
diff -pruN 24.0.1+9-1/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp 24.0.2+12-1/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp
--- 24.0.1+9-1/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 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
@@ -37,6 +37,47 @@
 /*
  * Set directory to subsystem specific files based
  * on the contents of the mountinfo and cgroup files.
+ *
+ * The method determines whether it runs in
+ * - host mode
+ * - container mode
+ *
+ * In the host mode, _root is equal to "/" and
+ * the subsystem path is equal to the _mount_point path
+ * joined with cgroup_path.
+ *
+ * In the container mode, it can be two possibilities:
+ * - private namespace (cgroupns=private)
+ * - host namespace (cgroupns=host, default mode in cgroup V1 hosts)
+ *
+ * Private namespace is equivalent to the host mode, i.e.
+ * the subsystem path is set by concatenating
+ * _mount_point and cgroup_path.
+ *
+ * In the host namespace, _root is equal to host's cgroup path
+ * of the control group to which the containerized process
+ * belongs to at the moment of creation. The mountinfo and
+ * cgroup files are mirrored from the host, while the subsystem
+ * specific files are mapped directly at _mount_point, i.e.
+ * at /sys/fs/cgroup/<controller>/, the subsystem path is
+ * then set equal to _mount_point.
+ *
+ * A special case of the subsystem path is when a cgroup path
+ * includes a subgroup, when a containerized process was associated
+ * with an existing cgroup, that is different from cgroup
+ * in which the process has been created.
+ * Here, the _root is equal to the host's initial cgroup path,
+ * cgroup_path will be equal to host's new cgroup path.
+ * As host cgroup hierarchies are not accessible in the container,
+ * it needs to be determined which part of cgroup path
+ * is accessible inside container, i.e. mapped under
+ * /sys/fs/cgroup/<controller>/<subgroup>.
+ * In Docker default setup, host's cgroup path can be
+ * of the form: /docker/<CONTAINER_ID>/<subgroup>,
+ * from which only <subgroup> is mapped.
+ * The method trims cgroup path from left, until the subgroup
+ * component is found. The subsystem path will be set to
+ * the _mount_point joined with the subgroup path.
  */
 void CgroupV1Controller::set_subsystem_path(const char* cgroup_path) {
   if (_cgroup_path != nullptr) {
@@ -49,28 +90,36 @@ void CgroupV1Controller::set_subsystem_p
   _cgroup_path = os::strdup(cgroup_path);
   stringStream ss;
   if (_root != nullptr && cgroup_path != nullptr) {
+    ss.print_raw(_mount_point);
     if (strcmp(_root, "/") == 0) {
-      ss.print_raw(_mount_point);
+      // host processes and containers with cgroupns=private
       if (strcmp(cgroup_path,"/") != 0) {
         ss.print_raw(cgroup_path);
       }
-      _path = os::strdup(ss.base());
     } else {
-      if (strcmp(_root, cgroup_path) == 0) {
-        ss.print_raw(_mount_point);
-        _path = os::strdup(ss.base());
-      } else {
-        char *p = strstr((char*)cgroup_path, _root);
-        if (p != nullptr && p == _root) {
-          if (strlen(cgroup_path) > strlen(_root)) {
-            ss.print_raw(_mount_point);
-            const char* cg_path_sub = cgroup_path + strlen(_root);
-            ss.print_raw(cg_path_sub);
-            _path = os::strdup(ss.base());
+      // containers with cgroupns=host, default setting is _root==cgroup_path
+      if (strcmp(_root, cgroup_path) != 0) {
+        if (*cgroup_path != '\0' && strcmp(cgroup_path, "/") != 0) {
+          // When moved to a subgroup, between subgroups, the path suffix will change.
+          const char *suffix = cgroup_path;
+          while (suffix != nullptr) {
+            stringStream pp;
+            pp.print_raw(_mount_point);
+            pp.print_raw(suffix);
+            if (os::file_exists(pp.base())) {
+              ss.print_raw(suffix);
+              if (suffix != cgroup_path) {
+                log_trace(os, container)("set_subsystem_path: cgroup v1 path reduced to: %s.", suffix);
+              }
+              break;
+            }
+            log_trace(os, container)("set_subsystem_path: skipped non-existent directory: %s.", suffix);
+            suffix = strchr(suffix + 1, '/');
           }
         }
       }
     }
+    _path = os::strdup(ss.base());
   }
 }
 
diff -pruN 24.0.1+9-1/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp 24.0.2+12-1/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp
--- 24.0.1+9-1/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, 2022, Red Hat Inc.
+ * Copyright (c) 2020, 2025, Red Hat Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -292,6 +292,10 @@ jlong memory_swap_limit_value(CgroupV2Co
 }
 
 void CgroupV2Controller::set_subsystem_path(const char* cgroup_path) {
+  if (_cgroup_path != nullptr) {
+    os::free(_cgroup_path);
+  }
+  _cgroup_path = os::strdup(cgroup_path);
   if (_path != nullptr) {
     os::free(_path);
   }
diff -pruN 24.0.1+9-1/src/hotspot/os/posix/signals_posix.cpp 24.0.2+12-1/src/hotspot/os/posix/signals_posix.cpp
--- 24.0.1+9-1/src/hotspot/os/posix/signals_posix.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/os/posix/signals_posix.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -50,6 +50,9 @@
 
 #include <signal.h>
 
+#if !defined(SEGV_BNDERR)
+#define SEGV_BNDERR 3
+#endif
 
 static const char* get_signal_name(int sig, char* out, size_t outlen);
 
@@ -970,6 +973,9 @@ static bool get_signal_code_description(
     { SIGFPE,  FPE_FLTSUB,   "FPE_FLTSUB",   "Subscript out of range." },
     { SIGSEGV, SEGV_MAPERR,  "SEGV_MAPERR",  "Address not mapped to object." },
     { SIGSEGV, SEGV_ACCERR,  "SEGV_ACCERR",  "Invalid permissions for mapped object." },
+#if defined(LINUX)
+    { SIGSEGV, SEGV_BNDERR,  "SEGV_BNDERR",  "Failed address bound checks." },
+#endif
 #if defined(AIX)
     // no explanation found what keyerr would be
     { SIGSEGV, SEGV_KEYERR,  "SEGV_KEYERR",  "key error" },
diff -pruN 24.0.1+9-1/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp 24.0.2+12-1/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp
--- 24.0.1+9-1/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -448,7 +448,7 @@ void os::print_context(outputStream *st,
 }
 
 void os::print_register_info(outputStream *st, const void *context, int& continuation) {
-  const int register_count = 32 /* r0-r32 */ + 3 /* pc, lr, sp */;
+  const int register_count = 32 /* r0-r31 */ + 3 /* pc, lr, sp */;
   int n = continuation;
   assert(n >= 0 && n <= register_count, "Invalid continuation value");
   if (context == nullptr || n == register_count) {
diff -pruN 24.0.1+9-1/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp 24.0.2+12-1/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp
--- 24.0.1+9-1/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -355,7 +355,7 @@ void os::print_context(outputStream *st,
 }
 
 void os::print_register_info(outputStream *st, const void *context, int& continuation) {
-  const int register_count = 32 /* r0-r31 */;
+  const int register_count = 31 /* r0-r30 */;
   int n = continuation;
   assert(n >= 0 && n <= register_count, "Invalid continuation value");
   if (context == nullptr || n == register_count) {
diff -pruN 24.0.1+9-1/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp 24.0.2+12-1/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
--- 24.0.1+9-1/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -468,7 +468,7 @@ void os::print_context(outputStream *st,
 }
 
 void os::print_register_info(outputStream *st, const void *context, int& continuation) {
-  const int register_count = 32 /* r0-r32 */ + 3 /* pc, lr, ctr */;
+  const int register_count = 32 /* r0-r31 */ + 3 /* pc, lr, ctr */;
   int n = continuation;
   assert(n >= 0 && n <= register_count, "Invalid continuation value");
   if (context == nullptr || n == register_count) {
diff -pruN 24.0.1+9-1/src/hotspot/share/cds/filemap.cpp 24.0.2+12-1/src/hotspot/share/cds/filemap.cpp
--- 24.0.1+9-1/src/hotspot/share/cds/filemap.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/cds/filemap.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -2219,7 +2219,7 @@ address FileMapInfo::heap_region_dumptim
   assert(CDSConfig::is_using_archive(), "runtime only");
   assert(is_aligned(r->mapping_offset(), sizeof(HeapWord)), "must be");
   if (UseCompressedOops) {
-    return /*dumptime*/ narrow_oop_base() + r->mapping_offset();
+    return /*dumptime*/ (address)((uintptr_t)narrow_oop_base() + r->mapping_offset());
   } else {
     return heap_region_requested_address();
   }
@@ -2245,7 +2245,7 @@ address FileMapInfo::heap_region_request
     // Runtime base = 0x4000 and shift is also 0. If we map this region at 0x5000, then
     // the value P can remain 0x1200. The decoded address = (0x4000 + (0x1200 << 0)) = 0x5200,
     // which is the runtime location of the referenced object.
-    return /*runtime*/ CompressedOops::base() + r->mapping_offset();
+    return /*runtime*/ (address)((uintptr_t)CompressedOops::base() + r->mapping_offset());
   } else {
     // This was the hard-coded requested base address used at dump time. With uncompressed oops,
     // the heap range is assigned by the OS so we will most likely have to relocate anyway, no matter
diff -pruN 24.0.1+9-1/src/hotspot/share/classfile/verifier.cpp 24.0.2+12-1/src/hotspot/share/classfile/verifier.cpp
--- 24.0.1+9-1/src/hotspot/share/classfile/verifier.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/classfile/verifier.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -32,7 +32,6 @@
 #include "classfile/stackMapTableFormat.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
-#include "classfile/systemDictionaryShared.hpp"
 #include "classfile/verifier.hpp"
 #include "classfile/vmClasses.hpp"
 #include "classfile/vmSymbols.hpp"
@@ -61,6 +60,9 @@
 #include "services/threadService.hpp"
 #include "utilities/align.hpp"
 #include "utilities/bytes.hpp"
+#if INCLUDE_CDS
+#include "classfile/systemDictionaryShared.hpp"
+#endif
 
 #define NOFAILOVER_MAJOR_VERSION                       51
 #define NONZERO_PADDING_BYTES_IN_SWITCH_MAJOR_VERSION  51
@@ -235,11 +237,13 @@ bool Verifier::verify(InstanceKlass* kla
          exception_name == vmSymbols::java_lang_ClassFormatError())) {
       log_info(verification)("Fail over class verification to old verifier for: %s", klass->external_name());
       log_info(class, init)("Fail over class verification to old verifier for: %s", klass->external_name());
+#if INCLUDE_CDS
       // Exclude any classes that fail over during dynamic dumping
       if (CDSConfig::is_dumping_dynamic_archive()) {
         SystemDictionaryShared::warn_excluded(klass, "Failed over class verification while dynamic dumping");
         SystemDictionaryShared::set_excluded(klass);
       }
+#endif
       message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len);
       exception_message = message_buffer;
       exception_name = inference_verify(
diff -pruN 24.0.1+9-1/src/hotspot/share/code/codeBlob.cpp 24.0.2+12-1/src/hotspot/share/code/codeBlob.cpp
--- 24.0.1+9-1/src/hotspot/share/code/codeBlob.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/code/codeBlob.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -657,7 +657,7 @@ void CodeBlob::print_value_on(outputStre
 }
 
 void CodeBlob::dump_for_addr(address addr, outputStream* st, bool verbose) const {
-  if (is_buffer_blob()) {
+  if (is_buffer_blob() || is_adapter_blob() || is_vtable_blob() || is_method_handles_adapter_blob()) {
     // the interpreter is generated into a buffer blob
     InterpreterCodelet* i = Interpreter::codelet_containing(addr);
     if (i != nullptr) {
diff -pruN 24.0.1+9-1/src/hotspot/share/code/codeCache.cpp 24.0.2+12-1/src/hotspot/share/code/codeCache.cpp
--- 24.0.1+9-1/src/hotspot/share/code/codeCache.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/code/codeCache.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1515,9 +1515,14 @@ void CodeCache::print_trace(const char*
 void CodeCache::print_internals() {
   int nmethodCount = 0;
   int runtimeStubCount = 0;
+  int upcallStubCount = 0;
   int adapterCount = 0;
+  int mhAdapterCount = 0;
+  int vtableBlobCount = 0;
   int deoptimizationStubCount = 0;
   int uncommonTrapStubCount = 0;
+  int exceptionStubCount = 0;
+  int safepointStubCount = 0;
   int bufferBlobCount = 0;
   int total = 0;
   int nmethodNotEntrant = 0;
@@ -1554,12 +1559,22 @@ void CodeCache::print_internals() {
         }
       } else if (cb->is_runtime_stub()) {
         runtimeStubCount++;
+      } else if (cb->is_upcall_stub()) {
+        upcallStubCount++;
       } else if (cb->is_deoptimization_stub()) {
         deoptimizationStubCount++;
       } else if (cb->is_uncommon_trap_stub()) {
         uncommonTrapStubCount++;
+      } else if (cb->is_exception_stub()) {
+        exceptionStubCount++;
+      } else if (cb->is_safepoint_stub()) {
+        safepointStubCount++;
       } else if (cb->is_adapter_blob()) {
         adapterCount++;
+      } else if (cb->is_method_handles_adapter_blob()) {
+        mhAdapterCount++;
+      } else if (cb->is_vtable_blob()) {
+        vtableBlobCount++;
       } else if (cb->is_buffer_blob()) {
         bufferBlobCount++;
       }
@@ -1586,10 +1601,15 @@ void CodeCache::print_internals() {
   tty->print_cr("\tjava: %d",nmethodJava);
   tty->print_cr("\tnative: %d",nmethodNative);
   tty->print_cr("runtime_stubs: %d",runtimeStubCount);
+  tty->print_cr("upcall_stubs: %d",upcallStubCount);
   tty->print_cr("adapters: %d",adapterCount);
+  tty->print_cr("MH adapters: %d",mhAdapterCount);
+  tty->print_cr("VTables: %d",vtableBlobCount);
   tty->print_cr("buffer blobs: %d",bufferBlobCount);
   tty->print_cr("deoptimization_stubs: %d",deoptimizationStubCount);
   tty->print_cr("uncommon_traps: %d",uncommonTrapStubCount);
+  tty->print_cr("exception_stubs: %d",exceptionStubCount);
+  tty->print_cr("safepoint_stubs: %d",safepointStubCount);
   tty->print_cr("\nnmethod size distribution");
   tty->print_cr("-------------------------------------------------");
 
@@ -1615,9 +1635,14 @@ void CodeCache::print() {
 
   CodeBlob_sizes live[CompLevel_full_optimization + 1];
   CodeBlob_sizes runtimeStub;
+  CodeBlob_sizes upcallStub;
   CodeBlob_sizes uncommonTrapStub;
   CodeBlob_sizes deoptimizationStub;
+  CodeBlob_sizes exceptionStub;
+  CodeBlob_sizes safepointStub;
   CodeBlob_sizes adapter;
+  CodeBlob_sizes mhAdapter;
+  CodeBlob_sizes vtableBlob;
   CodeBlob_sizes bufferBlob;
   CodeBlob_sizes other;
 
@@ -1629,12 +1654,22 @@ void CodeCache::print() {
         live[level].add(cb);
       } else if (cb->is_runtime_stub()) {
         runtimeStub.add(cb);
+      } else if (cb->is_upcall_stub()) {
+        upcallStub.add(cb);
       } else if (cb->is_deoptimization_stub()) {
         deoptimizationStub.add(cb);
       } else if (cb->is_uncommon_trap_stub()) {
         uncommonTrapStub.add(cb);
+      } else if (cb->is_exception_stub()) {
+        exceptionStub.add(cb);
+      } else if (cb->is_safepoint_stub()) {
+        safepointStub.add(cb);
       } else if (cb->is_adapter_blob()) {
         adapter.add(cb);
+      } else if (cb->is_method_handles_adapter_blob()) {
+        mhAdapter.add(cb);
+      } else if (cb->is_vtable_blob()) {
+        vtableBlob.add(cb);
       } else if (cb->is_buffer_blob()) {
         bufferBlob.add(cb);
       } else {
@@ -1665,9 +1700,14 @@ void CodeCache::print() {
     const CodeBlob_sizes* sizes;
   } non_nmethod_blobs[] = {
     { "runtime",        &runtimeStub },
+    { "upcall",         &upcallStub },
     { "uncommon trap",  &uncommonTrapStub },
     { "deoptimization", &deoptimizationStub },
+    { "exception",      &exceptionStub },
+    { "safepoint",      &safepointStub },
     { "adapter",        &adapter },
+    { "mh_adapter",     &mhAdapter },
+    { "vtable",         &vtableBlob },
     { "buffer blob",    &bufferBlob },
     { "other",          &other },
   };
diff -pruN 24.0.1+9-1/src/hotspot/share/compiler/compileBroker.cpp 24.0.2+12-1/src/hotspot/share/compiler/compileBroker.cpp
--- 24.0.1+9-1/src/hotspot/share/compiler/compileBroker.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/compiler/compileBroker.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -2532,6 +2532,11 @@ void CompileBroker::collect_statistics(C
   // C1 and C2 counters are counting both successful and unsuccessful compiles
   _t_total_compilation.add(time);
 
+  // Update compilation times. Used by the implementation of JFR CompilerStatistics
+  // and java.lang.management.CompilationMXBean.
+  _perf_total_compilation->inc(time.ticks());
+  _peak_compilation_time = MAX2(time.milliseconds(), _peak_compilation_time);
+
   if (!success) {
     _total_bailout_count++;
     if (UsePerfData) {
@@ -2550,12 +2555,6 @@ void CompileBroker::collect_statistics(C
     _t_invalidated_compilation.add(time);
   } else {
     // Compilation succeeded
-
-    // update compilation ticks - used by the implementation of
-    // java.lang.management.CompilationMXBean
-    _perf_total_compilation->inc(time.ticks());
-    _peak_compilation_time = time.milliseconds() > _peak_compilation_time ? time.milliseconds() : _peak_compilation_time;
-
     if (CITime) {
       int bytes_compiled = method->code_size() + task->num_inlined_bytecodes();
       if (is_osr) {
diff -pruN 24.0.1+9-1/src/hotspot/share/gc/g1/g1Allocator.cpp 24.0.2+12-1/src/hotspot/share/gc/g1/g1Allocator.cpp
--- 24.0.1+9-1/src/hotspot/share/gc/g1/g1Allocator.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/gc/g1/g1Allocator.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -213,10 +213,10 @@ size_t G1Allocator::used_in_alloc_region
 
 
 HeapWord* G1Allocator::par_allocate_during_gc(G1HeapRegionAttr dest,
-                                              size_t word_size,
-                                              uint node_index) {
+                                              uint node_index,
+                                              size_t word_size) {
   size_t temp = 0;
-  HeapWord* result = par_allocate_during_gc(dest, word_size, word_size, &temp, node_index);
+  HeapWord* result = par_allocate_during_gc(dest, node_index, word_size, word_size, &temp);
   assert(result == nullptr || temp == word_size,
          "Requested " SIZE_FORMAT " words, but got " SIZE_FORMAT " at " PTR_FORMAT,
          word_size, temp, p2i(result));
@@ -224,13 +224,13 @@ HeapWord* G1Allocator::par_allocate_duri
 }
 
 HeapWord* G1Allocator::par_allocate_during_gc(G1HeapRegionAttr dest,
+                                              uint node_index,
                                               size_t min_word_size,
                                               size_t desired_word_size,
-                                              size_t* actual_word_size,
-                                              uint node_index) {
+                                              size_t* actual_word_size) {
   switch (dest.type()) {
     case G1HeapRegionAttr::Young:
-      return survivor_attempt_allocation(min_word_size, desired_word_size, actual_word_size, node_index);
+      return survivor_attempt_allocation(node_index, min_word_size, desired_word_size, actual_word_size);
     case G1HeapRegionAttr::Old:
       return old_attempt_allocation(min_word_size, desired_word_size, actual_word_size);
     default:
@@ -239,10 +239,10 @@ HeapWord* G1Allocator::par_allocate_duri
   }
 }
 
-HeapWord* G1Allocator::survivor_attempt_allocation(size_t min_word_size,
+HeapWord* G1Allocator::survivor_attempt_allocation(uint node_index,
+                                                   size_t min_word_size,
                                                    size_t desired_word_size,
-                                                   size_t* actual_word_size,
-                                                   uint node_index) {
+                                                   size_t* actual_word_size) {
   assert(!_g1h->is_humongous(desired_word_size),
          "we should not be seeing humongous-size allocations in this path");
 
@@ -398,10 +398,10 @@ HeapWord* G1PLABAllocator::allocate_dire
 
     size_t actual_plab_size = 0;
     HeapWord* buf = _allocator->par_allocate_during_gc(dest,
+                                                       node_index,
                                                        required_in_plab,
                                                        plab_word_size,
-                                                       &actual_plab_size,
-                                                       node_index);
+                                                       &actual_plab_size);
 
     assert(buf == nullptr || ((actual_plab_size >= required_in_plab) && (actual_plab_size <= plab_word_size)),
            "Requested at minimum %zu, desired %zu words, but got %zu at " PTR_FORMAT,
@@ -420,7 +420,7 @@ HeapWord* G1PLABAllocator::allocate_dire
     *plab_refill_failed = true;
   }
   // Try direct allocation.
-  HeapWord* result = _allocator->par_allocate_during_gc(dest, word_sz, node_index);
+  HeapWord* result = _allocator->par_allocate_during_gc(dest, node_index, word_sz);
   if (result != nullptr) {
     plab_data->_direct_allocated += word_sz;
     plab_data->_num_direct_allocations++;
diff -pruN 24.0.1+9-1/src/hotspot/share/gc/g1/g1Allocator.hpp 24.0.2+12-1/src/hotspot/share/gc/g1/g1Allocator.hpp
--- 24.0.1+9-1/src/hotspot/share/gc/g1/g1Allocator.hpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/gc/g1/g1Allocator.hpp	2025-06-27 08:03:14.000000000 +0000
@@ -78,19 +78,16 @@ private:
   inline OldGCAllocRegion* old_gc_alloc_region();
 
   // Allocation attempt during GC for a survivor object / PLAB.
-  HeapWord* survivor_attempt_allocation(size_t min_word_size,
+  HeapWord* survivor_attempt_allocation(uint node_index,
+                                        size_t min_word_size,
                                         size_t desired_word_size,
-                                        size_t* actual_word_size,
-                                        uint node_index);
+                                        size_t* actual_word_size);
 
   // Allocation attempt during GC for an old object / PLAB.
   HeapWord* old_attempt_allocation(size_t min_word_size,
                                    size_t desired_word_size,
                                    size_t* actual_word_size);
 
-  // Node index of current thread.
-  inline uint current_node_index() const;
-
 public:
   G1Allocator(G1CollectedHeap* heap);
   ~G1Allocator();
@@ -110,16 +107,20 @@ public:
   void abandon_gc_alloc_regions();
   bool is_retained_old_region(G1HeapRegion* hr);
 
+  // Node index of current thread.
+  inline uint current_node_index() const;
+
   // Allocate blocks of memory during mutator time.
 
   // Attempt allocation in the current alloc region.
-  inline HeapWord* attempt_allocation(size_t min_word_size,
+  inline HeapWord* attempt_allocation(uint node_index,
+                                      size_t min_word_size,
                                       size_t desired_word_size,
                                       size_t* actual_word_size);
 
   // This is to be called when holding an appropriate lock. It first tries in the
   // current allocation region, and then attempts an allocation using a new region.
-  inline HeapWord* attempt_allocation_locked(size_t word_size);
+  inline HeapWord* attempt_allocation_locked(uint node_index, size_t word_size);
 
   size_t unsafe_max_tlab_alloc();
   size_t used_in_alloc_regions();
@@ -129,14 +130,15 @@ public:
   // heap, and then allocate a block of the given size. The block
   // may not be a humongous - it must fit into a single heap region.
   HeapWord* par_allocate_during_gc(G1HeapRegionAttr dest,
-                                   size_t word_size,
-                                   uint node_index);
+                                   uint node_index,
+                                   size_t word_size
+                                   );
 
   HeapWord* par_allocate_during_gc(G1HeapRegionAttr dest,
+                                   uint node_index,
                                    size_t min_word_size,
                                    size_t desired_word_size,
-                                   size_t* actual_word_size,
-                                   uint node_index);
+                                   size_t* actual_word_size);
 };
 
 // Manages the PLABs used during garbage collection. Interface for allocation from PLABs.
diff -pruN 24.0.1+9-1/src/hotspot/share/gc/g1/g1Allocator.inline.hpp 24.0.2+12-1/src/hotspot/share/gc/g1/g1Allocator.inline.hpp
--- 24.0.1+9-1/src/hotspot/share/gc/g1/g1Allocator.inline.hpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/gc/g1/g1Allocator.inline.hpp	2025-06-27 08:03:14.000000000 +0000
@@ -49,11 +49,10 @@ inline OldGCAllocRegion* G1Allocator::ol
   return &_old_gc_alloc_region;
 }
 
-inline HeapWord* G1Allocator::attempt_allocation(size_t min_word_size,
+inline HeapWord* G1Allocator::attempt_allocation(uint node_index,
+                                                 size_t min_word_size,
                                                  size_t desired_word_size,
                                                  size_t* actual_word_size) {
-  uint node_index = current_node_index();
-
   HeapWord* result = mutator_alloc_region(node_index)->attempt_retained_allocation(min_word_size, desired_word_size, actual_word_size);
   if (result != nullptr) {
     return result;
@@ -62,8 +61,7 @@ inline HeapWord* G1Allocator::attempt_al
   return mutator_alloc_region(node_index)->attempt_allocation(min_word_size, desired_word_size, actual_word_size);
 }
 
-inline HeapWord* G1Allocator::attempt_allocation_locked(size_t word_size) {
-  uint node_index = current_node_index();
+inline HeapWord* G1Allocator::attempt_allocation_locked(uint node_index, size_t word_size) {
   HeapWord* result = mutator_alloc_region(node_index)->attempt_allocation_locked(word_size);
 
   assert(result != nullptr || mutator_alloc_region(node_index)->get() == nullptr,
diff -pruN 24.0.1+9-1/src/hotspot/share/gc/g1/g1CollectedHeap.cpp 24.0.2+12-1/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
--- 24.0.1+9-1/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -401,7 +401,7 @@ G1CollectedHeap::mem_allocate(size_t wor
   return attempt_allocation(word_size, word_size, &dummy);
 }
 
-HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size) {
+HeapWord* G1CollectedHeap::attempt_allocation_slow(uint node_index, size_t word_size) {
   ResourceMark rm; // For retrieving the thread names in log messages.
 
   // Make sure you read the note in attempt_allocation_humongous().
@@ -425,7 +425,7 @@ HeapWord* G1CollectedHeap::attempt_alloc
 
       // Now that we have the lock, we first retry the allocation in case another
       // thread changed the region while we were waiting to acquire the lock.
-      result = _allocator->attempt_allocation_locked(word_size);
+      result = _allocator->attempt_allocation_locked(node_index, word_size);
       if (result != nullptr) {
         return result;
       }
@@ -452,7 +452,7 @@ HeapWord* G1CollectedHeap::attempt_alloc
     // here and the follow-on attempt will be at the start of the next loop
     // iteration (after taking the Heap_lock).
     size_t dummy = 0;
-    result = _allocator->attempt_allocation(word_size, word_size, &dummy);
+    result = _allocator->attempt_allocation(node_index, word_size, word_size, &dummy);
     if (result != nullptr) {
       return result;
     }
@@ -586,11 +586,14 @@ inline HeapWord* G1CollectedHeap::attemp
   assert(!is_humongous(desired_word_size), "attempt_allocation() should not "
          "be called for humongous allocation requests");
 
-  HeapWord* result = _allocator->attempt_allocation(min_word_size, desired_word_size, actual_word_size);
+  // Fix NUMA node association for the duration of this allocation
+  const uint node_index = _allocator->current_node_index();
+
+  HeapWord* result = _allocator->attempt_allocation(node_index, min_word_size, desired_word_size, actual_word_size);
 
   if (result == nullptr) {
     *actual_word_size = desired_word_size;
-    result = attempt_allocation_slow(desired_word_size);
+    result = attempt_allocation_slow(node_index, desired_word_size);
   }
 
   assert_heap_not_locked();
@@ -697,8 +700,11 @@ HeapWord* G1CollectedHeap::attempt_alloc
   assert(!_allocator->has_mutator_alloc_region() || !expect_null_mutator_alloc_region,
          "the current alloc region was unexpectedly found to be non-null");
 
+  // Fix NUMA node association for the duration of this allocation
+  const uint node_index = _allocator->current_node_index();
+
   if (!is_humongous(word_size)) {
-    return _allocator->attempt_allocation_locked(word_size);
+    return _allocator->attempt_allocation_locked(node_index, word_size);
   } else {
     HeapWord* result = humongous_obj_allocate(word_size);
     if (result != nullptr && policy()->need_to_start_conc_mark("STW humongous allocation")) {
diff -pruN 24.0.1+9-1/src/hotspot/share/gc/g1/g1CollectedHeap.hpp 24.0.2+12-1/src/hotspot/share/gc/g1/g1CollectedHeap.hpp
--- 24.0.1+9-1/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	2025-06-27 08:03:14.000000000 +0000
@@ -449,7 +449,7 @@ private:
   // Second-level mutator allocation attempt: take the Heap_lock and
   // retry the allocation attempt, potentially scheduling a GC
   // pause. This should only be used for non-humongous allocations.
-  HeapWord* attempt_allocation_slow(size_t word_size);
+  HeapWord* attempt_allocation_slow(uint node_index, size_t word_size);
 
   // Takes the Heap_lock and attempts a humongous allocation. It can
   // potentially schedule a GC pause.
diff -pruN 24.0.1+9-1/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp 24.0.2+12-1/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp
--- 24.0.1+9-1/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1274,7 +1274,8 @@ class G1UpdateRegionLivenessAndSelectFor
         // The liveness of this humongous obj decided by either its allocation
         // time (allocated after conc-mark-start, i.e. live) or conc-marking.
         const bool is_live = _cm->top_at_mark_start(hr) == hr->bottom()
-                             || _cm->contains_live_object(hr->hrm_index());
+                          || _cm->contains_live_object(hr->hrm_index())
+                          || hr->has_pinned_objects();
         if (is_live) {
           const bool selected_for_rebuild = tracker->update_humongous_before_rebuild(hr);
           auto on_humongous_region = [&] (G1HeapRegion* hr) {
@@ -1291,7 +1292,9 @@ class G1UpdateRegionLivenessAndSelectFor
       } else if (hr->is_old()) {
         hr->note_end_of_marking(_cm->top_at_mark_start(hr), _cm->live_bytes(hr->hrm_index()));
 
-        if (hr->live_bytes() != 0) {
+        const bool is_live = hr->live_bytes() != 0
+                          || hr->has_pinned_objects();
+        if (is_live) {
           if (tracker->update_old_before_rebuild(hr)) {
             _num_selected_for_rebuild++;
           }
diff -pruN 24.0.1+9-1/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp 24.0.2+12-1/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp
--- 24.0.1+9-1/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -653,6 +653,12 @@ void G1ParScanThreadStateSet::record_unu
   }
 }
 
+void G1ParScanThreadState::record_evacuation_failed_region(G1HeapRegion* r, uint worker_id, bool cause_pinned) {
+  if (_evac_failure_regions->record(worker_id, r->hrm_index(), cause_pinned)) {
+    G1HeapRegionPrinter::evac_failure(r);
+  }
+}
+
 NOINLINE
 oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markWord m, size_t word_sz, bool cause_pinned) {
   assert(_g1h->is_in_cset(old), "Object " PTR_FORMAT " should be in the CSet", p2i(old));
@@ -662,9 +668,7 @@ oop G1ParScanThreadState::handle_evacuat
     // Forward-to-self succeeded. We are the "owner" of the object.
     G1HeapRegion* r = _g1h->heap_region_containing(old);
 
-    if (_evac_failure_regions->record(_worker_id, r->hrm_index(), cause_pinned)) {
-      G1HeapRegionPrinter::evac_failure(r);
-    }
+    record_evacuation_failed_region(r, _worker_id, cause_pinned);
 
     // Mark the failing object in the marking bitmap and later use the bitmap to handle
     // evacuation failure recovery.
diff -pruN 24.0.1+9-1/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp 24.0.2+12-1/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp
--- 24.0.1+9-1/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp	2025-06-27 08:03:14.000000000 +0000
@@ -226,6 +226,7 @@ public:
   Tickspan trim_ticks() const;
   void reset_trim_ticks();
 
+  void record_evacuation_failed_region(G1HeapRegion* r, uint worker_id, bool cause_pinned);
   // An attempt to evacuate "obj" has failed; take necessary steps.
   oop handle_evacuation_failure_par(oop obj, markWord m, size_t word_sz, bool cause_pinned);
 
diff -pruN 24.0.1+9-1/src/hotspot/share/gc/g1/g1Policy.cpp 24.0.2+12-1/src/hotspot/share/gc/g1/g1Policy.cpp
--- 24.0.1+9-1/src/hotspot/share/gc/g1/g1Policy.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/gc/g1/g1Policy.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -661,13 +661,6 @@ void G1Policy::record_concurrent_refinem
 
 bool G1Policy::should_retain_evac_failed_region(uint index) const {
   size_t live_bytes = _g1h->region_at(index)->live_bytes();
-
-#ifdef ASSERT
-  G1HeapRegion* r = _g1h->region_at(index);
-  assert(live_bytes != 0,
-         "live bytes not set for %u used %zu garbage %zu cm-live %zu pinned %d",
-         index, r->used(), r->garbage_bytes(), live_bytes, r->has_pinned_objects());
-#endif
   size_t threshold = G1RetainRegionLiveThresholdPercent * G1HeapRegion::GrainBytes / 100;
   return live_bytes < threshold;
 }
diff -pruN 24.0.1+9-1/src/hotspot/share/gc/g1/g1RemSet.cpp 24.0.2+12-1/src/hotspot/share/gc/g1/g1RemSet.cpp
--- 24.0.1+9-1/src/hotspot/share/gc/g1/g1RemSet.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/gc/g1/g1RemSet.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1161,22 +1161,6 @@ class G1MergeHeapRootsTask : public Work
     }
   };
 
-  // Helper to allow two closure to be applied when
-  // iterating through the collection set.
-  class G1CombinedClosure : public G1HeapRegionClosure {
-    G1HeapRegionClosure* _closure1;
-    G1HeapRegionClosure* _closure2;
-  public:
-    G1CombinedClosure(G1HeapRegionClosure* cl1, G1HeapRegionClosure* cl2) :
-      _closure1(cl1),
-      _closure2(cl2) { }
-
-    bool do_heap_region(G1HeapRegion* hr) {
-      return _closure1->do_heap_region(hr) ||
-             _closure2->do_heap_region(hr);
-    }
-  };
-
   // Visitor for the remembered sets of humongous candidate regions to merge their
   // remembered set into the card table.
   class G1FlushHumongousCandidateRemSets : public G1HeapRegionIndexClosure {
@@ -1277,6 +1261,7 @@ class G1MergeHeapRootsTask : public Work
   };
 
   uint _num_workers;
+  G1HeapRegionClaimer _hr_claimer;
   G1RemSetScanState* _scan_state;
 
   // To mitigate contention due multiple threads accessing and popping BufferNodes from a shared
@@ -1306,6 +1291,7 @@ public:
   G1MergeHeapRootsTask(G1RemSetScanState* scan_state, uint num_workers, bool initial_evacuation) :
     WorkerTask("G1 Merge Heap Roots"),
     _num_workers(num_workers),
+    _hr_claimer(num_workers),
     _scan_state(scan_state),
     _dirty_card_buffers(nullptr),
     _initial_evacuation(initial_evacuation),
@@ -1395,14 +1381,13 @@ public:
       {
         // 2. collection set
         G1MergeCardSetClosure merge(_scan_state);
-        G1ClearBitmapClosure clear(g1h);
-        G1CombinedClosure combined(&merge, &clear);
 
         if (_initial_evacuation) {
           G1HeapRegionRemSet::iterate_for_merge(g1h->young_regions_cardset(), merge);
         }
 
-        g1h->collection_set_iterate_increment_from(&combined, nullptr, worker_id);
+        g1h->collection_set_iterate_increment_from(&merge, worker_id);
+
         G1MergeCardSetStats stats = merge.stats();
 
         for (uint i = 0; i < G1GCPhaseTimes::MergeRSContainersSentinel; i++) {
@@ -1411,6 +1396,12 @@ public:
       }
     }
 
+    // Preparation for evacuation failure handling.
+    {
+      G1ClearBitmapClosure clear(g1h);
+      g1h->collection_set_iterate_increment_from(&clear, &_hr_claimer, worker_id);
+    }
+
     // Now apply the closure to all remaining log entries.
     if (_initial_evacuation) {
       assert(merge_remset_phase == G1GCPhaseTimes::MergeRS, "Wrong merge phase");
diff -pruN 24.0.1+9-1/src/hotspot/share/gc/g1/g1YoungCollector.cpp 24.0.2+12-1/src/hotspot/share/gc/g1/g1YoungCollector.cpp
--- 24.0.1+9-1/src/hotspot/share/gc/g1/g1YoungCollector.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/gc/g1/g1YoungCollector.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -588,6 +588,30 @@ public:
 };
 
 class G1EvacuateRegionsBaseTask : public WorkerTask {
+
+  // All pinned regions in the collection set must be registered as failed
+  // regions as there is no guarantee that there is a reference reachable by
+  // Java code (i.e. only by native code) that adds it to the evacuation failed
+  // regions.
+  void record_pinned_regions(G1ParScanThreadState* pss, uint worker_id) {
+    class RecordPinnedRegionClosure : public G1HeapRegionClosure {
+      G1ParScanThreadState* _pss;
+      uint _worker_id;
+
+    public:
+      RecordPinnedRegionClosure(G1ParScanThreadState* pss, uint worker_id) : _pss(pss), _worker_id(worker_id) { }
+
+      bool do_heap_region(G1HeapRegion* r) {
+        if (r->has_pinned_objects()) {
+          _pss->record_evacuation_failed_region(r, _worker_id, true /* cause_pinned */);
+        }
+        return false;
+      }
+    } cl(pss, worker_id);
+
+    _g1h->collection_set_iterate_increment_from(&cl, worker_id);
+  }
+
 protected:
   G1CollectedHeap* _g1h;
   G1ParScanThreadStateSet* _per_thread_states;
@@ -595,8 +619,6 @@ protected:
   G1ScannerTasksQueueSet* _task_queues;
   TaskTerminator _terminator;
 
-  uint _num_workers;
-
   void evacuate_live_objects(G1ParScanThreadState* pss,
                              uint worker_id,
                              G1GCPhaseTimes::GCParPhases objcopy_phase,
@@ -632,6 +654,9 @@ protected:
 
   virtual void evacuate_live_objects(G1ParScanThreadState* pss, uint worker_id) = 0;
 
+private:
+  volatile bool _pinned_regions_recorded;
+
 public:
   G1EvacuateRegionsBaseTask(const char* name,
                             G1ParScanThreadStateSet* per_thread_states,
@@ -642,7 +667,7 @@ public:
     _per_thread_states(per_thread_states),
     _task_queues(task_queues),
     _terminator(num_workers, _task_queues),
-    _num_workers(num_workers)
+    _pinned_regions_recorded(false)
   { }
 
   void work(uint worker_id) {
@@ -654,6 +679,9 @@ public:
       G1ParScanThreadState* pss = _per_thread_states->state_for_worker(worker_id);
       pss->set_ref_discoverer(_g1h->ref_processor_stw());
 
+      if (!Atomic::cmpxchg(&_pinned_regions_recorded, false, true)) {
+        record_pinned_regions(pss, worker_id);
+      }
       scan_roots(pss, worker_id);
       evacuate_live_objects(pss, worker_id);
     }
diff -pruN 24.0.1+9-1/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp 24.0.2+12-1/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp
--- 24.0.1+9-1/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1149,8 +1149,9 @@ void ShenandoahBarrierC2Support::pin_and
         }
       }
     }
+    // Load barrier on the control output of a call
     if ((ctrl->is_Proj() && ctrl->in(0)->is_CallJava()) || ctrl->is_CallJava()) {
-      CallNode* call = ctrl->is_Proj() ? ctrl->in(0)->as_CallJava() : ctrl->as_CallJava();
+      CallJavaNode* call = ctrl->is_Proj() ? ctrl->in(0)->as_CallJava() : ctrl->as_CallJava();
       if (call->entry_point() == OptoRuntime::rethrow_stub()) {
         // The rethrow call may have too many projections to be
         // properly handled here. Given there's no reason for a
@@ -1186,6 +1187,14 @@ void ShenandoahBarrierC2Support::pin_and
       CallProjections projs;
       call->extract_projections(&projs, false, false);
 
+      // If this is a runtime call, it doesn't have an exception handling path
+      if (projs.fallthrough_catchproj == nullptr) {
+        assert(call->method() == nullptr, "should be runtime call");
+        assert(projs.catchall_catchproj == nullptr, "runtime call should not have catch all projection");
+        continue;
+      }
+
+      // Otherwise, clone the barrier so there's one for the fallthrough and one for the exception handling path
 #ifdef ASSERT
       VectorSet cloned;
 #endif
diff -pruN 24.0.1+9-1/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp 24.0.2+12-1/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp
--- 24.0.1+9-1/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -332,6 +332,8 @@ void ShenandoahGenerationalControlThread
     }
   }
 
+  set_gc_mode(stopped);
+
   // Wait for the actual stop(), can't leave run_service() earlier.
   while (!should_terminate()) {
     os::naked_short_sleep(ShenandoahControlIntervalMin);
@@ -827,6 +829,7 @@ const char* ShenandoahGenerationalContro
     case stw_full:          return "full";
     case servicing_old:     return "old";
     case bootstrapping_old: return "bootstrap";
+    case stopped:           return "stopped";
     default:                return "unknown";
   }
 }
diff -pruN 24.0.1+9-1/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp 24.0.2+12-1/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp
--- 24.0.1+9-1/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp	2025-06-27 08:03:14.000000000 +0000
@@ -48,7 +48,8 @@ public:
     stw_degenerated,
     stw_full,
     bootstrapping_old,
-    servicing_old
+    servicing_old,
+    stopped
   } GCMode;
 
 private:
diff -pruN 24.0.1+9-1/src/hotspot/share/interpreter/bytecode.hpp 24.0.2+12-1/src/hotspot/share/interpreter/bytecode.hpp
--- 24.0.1+9-1/src/hotspot/share/interpreter/bytecode.hpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/interpreter/bytecode.hpp	2025-06-27 08:03:14.000000000 +0000
@@ -226,6 +226,8 @@ class Bytecode_invoke: public Bytecode_m
 
   bool has_appendix();
 
+  bool has_member_arg() const;
+
   int size_of_parameters() const;
 
  private:
diff -pruN 24.0.1+9-1/src/hotspot/share/interpreter/bytecode.inline.hpp 24.0.2+12-1/src/hotspot/share/interpreter/bytecode.inline.hpp
--- 24.0.1+9-1/src/hotspot/share/interpreter/bytecode.inline.hpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/interpreter/bytecode.inline.hpp	2025-06-27 08:03:14.000000000 +0000
@@ -28,6 +28,7 @@
 #include "interpreter/bytecode.hpp"
 
 #include "oops/cpCache.inline.hpp"
+#include "prims/methodHandles.hpp"
 
 inline bool Bytecode_invoke::has_appendix() {
   if (invoke_code() == Bytecodes::_invokedynamic) {
@@ -37,4 +38,13 @@ inline bool Bytecode_invoke::has_appendi
   }
 }
 
+inline bool Bytecode_invoke::has_member_arg() const {
+  // NOTE: We could resolve the call and use the resolved adapter method here, but this function
+  // is used by deoptimization, where resolving could lead to problems, so we avoid that here
+  // by doing things symbolically.
+  //
+  // invokedynamic instructions don't have a class but obviously don't have a MemberName appendix.
+  return !is_invokedynamic() && MethodHandles::has_member_arg(klass(), name());
+}
+
 #endif // SHARE_INTERPRETER_BYTECODE_INLINE_HPP
diff -pruN 24.0.1+9-1/src/hotspot/share/logging/logDecorators.cpp 24.0.2+12-1/src/hotspot/share/logging/logDecorators.cpp
--- 24.0.1+9-1/src/hotspot/share/logging/logDecorators.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/logging/logDecorators.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -100,7 +100,9 @@ bool LogDecorators::parse(const char* de
       break;
     }
     tmp_decorators |= mask(d);
-    token = comma_pos + 1;
+    if (comma_pos != nullptr) {
+      token = comma_pos + 1;
+    }
   } while (comma_pos != nullptr);
   os::free(args_copy);
   if (result) {
diff -pruN 24.0.1+9-1/src/hotspot/share/logging/logOutput.cpp 24.0.2+12-1/src/hotspot/share/logging/logOutput.cpp
--- 24.0.1+9-1/src/hotspot/share/logging/logOutput.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/logging/logOutput.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -354,7 +354,9 @@ bool LogOutput::parse_options(const char
       }
       break;
     }
-    pos = comma_pos + 1;
+    if (comma_pos != nullptr) {
+      pos = comma_pos + 1;
+    }
   } while (comma_pos != nullptr);
 
   os::free(opts);
diff -pruN 24.0.1+9-1/src/hotspot/share/logging/logSelection.cpp 24.0.2+12-1/src/hotspot/share/logging/logSelection.cpp
--- 24.0.1+9-1/src/hotspot/share/logging/logSelection.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/logging/logSelection.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -151,7 +151,9 @@ static LogSelection parse_internal(char
       return LogSelection::Invalid;
     }
     tags[ntags++] = tag;
-    cur_tag = plus_pos + 1;
+    if (plus_pos != nullptr) {
+      cur_tag = plus_pos + 1;
+    }
   } while (plus_pos != nullptr);
 
   for (size_t i = 0; i < ntags; i++) {
diff -pruN 24.0.1+9-1/src/hotspot/share/logging/logSelectionList.cpp 24.0.2+12-1/src/hotspot/share/logging/logSelectionList.cpp
--- 24.0.1+9-1/src/hotspot/share/logging/logSelectionList.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/logging/logSelectionList.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -69,7 +69,7 @@ bool LogSelectionList::parse(const char*
   }
   char* copy = os::strdup_check_oom(str, mtLogging);
   // Split string on commas
-  for (char *comma_pos = copy, *cur = copy; success && comma_pos != nullptr; cur = comma_pos + 1) {
+  for (char *comma_pos = copy, *cur = copy; success; cur = comma_pos + 1) {
     if (_nselections == MaxSelections) {
       if (errstream != nullptr) {
         errstream->print_cr("Can not have more than " SIZE_FORMAT " log selections in a single configuration.",
@@ -90,6 +90,10 @@ bool LogSelectionList::parse(const char*
       break;
     }
     _selections[_nselections++] = selection;
+
+    if (comma_pos == nullptr) {
+      break;
+    }
   }
 
   os::free(copy);
diff -pruN 24.0.1+9-1/src/hotspot/share/memory/virtualspace.cpp 24.0.2+12-1/src/hotspot/share/memory/virtualspace.cpp
--- 24.0.1+9-1/src/hotspot/share/memory/virtualspace.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/memory/virtualspace.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -457,7 +457,7 @@ void ReservedHeapSpace::try_reserve_rang
   while (attach_point >= lowest_start  &&
          attach_point <= highest_start &&  // Avoid wrap around.
          ((_base == nullptr) ||
-          (_base < aligned_heap_base_min_address || _base + size > upper_bound))) {
+          (_base < aligned_heap_base_min_address || size > (uintptr_t)(upper_bound - _base)))) {
     try_reserve_heap(size, alignment, page_size, attach_point);
     attach_point -= stepsize;
   }
diff -pruN 24.0.1+9-1/src/hotspot/share/opto/block.cpp 24.0.2+12-1/src/hotspot/share/opto/block.cpp
--- 24.0.1+9-1/src/hotspot/share/opto/block.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/opto/block.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1611,7 +1611,8 @@ void PhaseBlockLayout::find_edges() {
           Block *target = b->non_connector_successor(j);
           float freq = b->_freq * b->succ_prob(j);
           int from_pct = (int) ((100 * freq) / b->_freq);
-          int to_pct = (int) ((100 * freq) / target->_freq);
+          float f_to_pct = (100 * freq) / target->_freq;
+          int to_pct = (f_to_pct < 100.0) ? (int)f_to_pct : 100;
           edges->append(new CFGEdge(b, target, freq, from_pct, to_pct));
         }
       }
diff -pruN 24.0.1+9-1/src/hotspot/share/opto/escape.cpp 24.0.2+12-1/src/hotspot/share/opto/escape.cpp
--- 24.0.1+9-1/src/hotspot/share/opto/escape.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/opto/escape.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -982,10 +982,11 @@ void ConnectionGraph::reduce_phi_on_cmp(
 
   Node* other = cmp->in(1)->is_Con() ? cmp->in(1) : cmp->in(2);
   Node* zero = _igvn->intcon(0);
+  Node* one = _igvn->intcon(1);
   BoolTest::mask mask = cmp->unique_out()->as_Bool()->_test._test;
 
   // This Phi will merge the result of the Cmps split through the Phi
-  Node* res_phi  = _igvn->transform(PhiNode::make(ophi->in(0), zero, TypeInt::INT));
+  Node* res_phi = PhiNode::make(ophi->in(0), zero, TypeInt::INT);
 
   for (uint i=1; i<ophi->req(); i++) {
     Node* ophi_input = ophi->in(i);
@@ -993,7 +994,12 @@ void ConnectionGraph::reduce_phi_on_cmp(
 
     const TypeInt* tcmp = optimize_ptr_compare(ophi_input, other);
     if (tcmp->singleton()) {
-      res_phi_input = _igvn->makecon(tcmp);
+      if ((mask == BoolTest::mask::eq && tcmp == TypeInt::CC_EQ) ||
+          (mask == BoolTest::mask::ne && tcmp == TypeInt::CC_GT)) {
+        res_phi_input = one;
+      } else {
+        res_phi_input = zero;
+      }
     } else {
       Node* ncmp = _igvn->transform(cmp->clone());
       ncmp->set_req(1, ophi_input);
@@ -1005,7 +1011,8 @@ void ConnectionGraph::reduce_phi_on_cmp(
     res_phi->set_req(i, res_phi_input);
   }
 
-  Node* new_cmp = _igvn->transform(new CmpINode(res_phi, zero));
+  // This CMP always compares whether the output of "res_phi" is TRUE as far as the "mask".
+  Node* new_cmp = _igvn->transform(new CmpINode(_igvn->transform(res_phi), (mask == BoolTest::mask::eq) ? one : zero));
   _igvn->replace_node(cmp, new_cmp);
 }
 
@@ -4699,13 +4706,21 @@ void ConnectionGraph::split_unique_types
       if (n == nullptr) {
         continue;
       }
+    } else if (n->Opcode() == Op_StrInflatedCopy) {
+      // Check direct uses of StrInflatedCopy.
+      // It is memory type Node - no special SCMemProj node.
     } else if (n->Opcode() == Op_StrCompressedCopy ||
                n->Opcode() == Op_EncodeISOArray) {
       // get the memory projection
       n = n->find_out_with(Op_SCMemProj);
       assert(n != nullptr && n->Opcode() == Op_SCMemProj, "memory projection required");
     } else {
+#ifdef ASSERT
+      if (!n->is_Mem()) {
+        n->dump();
+      }
       assert(n->is_Mem(), "memory node required.");
+#endif
       Node *addr = n->in(MemNode::Address);
       const Type *addr_t = igvn->type(addr);
       if (addr_t == Type::TOP) {
diff -pruN 24.0.1+9-1/src/hotspot/share/opto/library_call.cpp 24.0.2+12-1/src/hotspot/share/opto/library_call.cpp
--- 24.0.1+9-1/src/hotspot/share/opto/library_call.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/opto/library_call.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -3778,6 +3778,20 @@ bool LibraryCallKit::inline_native_Conti
   Node* test_pin_count_over_underflow = _gvn.transform(new BoolNode(pin_count_cmp, BoolTest::eq));
   IfNode* iff_pin_count_over_underflow = create_and_map_if(control(), test_pin_count_over_underflow, PROB_MIN, COUNT_UNKNOWN);
 
+  // True branch, pin count over/underflow.
+  Node* pin_count_over_underflow = _gvn.transform(new IfTrueNode(iff_pin_count_over_underflow));
+  {
+    // Trap (but not deoptimize (Action_none)) and continue in the interpreter
+    // which will throw IllegalStateException for pin count over/underflow.
+    // No memory changed so far - we can use memory create by reset_memory()
+    // at the beginning of this intrinsic. No need to call reset_memory() again.
+    PreserveJVMState pjvms(this);
+    set_control(pin_count_over_underflow);
+    uncommon_trap(Deoptimization::Reason_intrinsic,
+                  Deoptimization::Action_none);
+    assert(stopped(), "invariant");
+  }
+
   // False branch, no pin count over/underflow. Increment or decrement pin count and store back.
   Node* valid_pin_count = _gvn.transform(new IfFalseNode(iff_pin_count_over_underflow));
   set_control(valid_pin_count);
@@ -3789,20 +3803,7 @@ bool LibraryCallKit::inline_native_Conti
     next_pin_count = _gvn.transform(new AddINode(pin_count, _gvn.intcon(1)));
   }
 
-  Node* updated_pin_count_memory = store_to_memory(control(), pin_count_offset, next_pin_count, T_INT, MemNode::unordered);
-
-  // True branch, pin count over/underflow.
-  Node* pin_count_over_underflow = _gvn.transform(new IfTrueNode(iff_pin_count_over_underflow));
-  {
-    // Trap (but not deoptimize (Action_none)) and continue in the interpreter
-    // which will throw IllegalStateException for pin count over/underflow.
-    PreserveJVMState pjvms(this);
-    set_control(pin_count_over_underflow);
-    set_all_memory(input_memory_state);
-    uncommon_trap_exact(Deoptimization::Reason_intrinsic,
-                        Deoptimization::Action_none);
-    assert(stopped(), "invariant");
-  }
+  store_to_memory(control(), pin_count_offset, next_pin_count, T_INT, MemNode::unordered);
 
   // Result of top level CFG and Memory.
   RegionNode* result_rgn = new RegionNode(PATH_LIMIT);
@@ -3812,7 +3813,7 @@ bool LibraryCallKit::inline_native_Conti
 
   result_rgn->init_req(_true_path, _gvn.transform(valid_pin_count));
   result_rgn->init_req(_false_path, _gvn.transform(continuation_is_null));
-  result_mem->init_req(_true_path, _gvn.transform(updated_pin_count_memory));
+  result_mem->init_req(_true_path, _gvn.transform(reset_memory()));
   result_mem->init_req(_false_path, _gvn.transform(input_memory_state));
 
   // Set output state.
diff -pruN 24.0.1+9-1/src/hotspot/share/opto/loopTransform.cpp 24.0.2+12-1/src/hotspot/share/opto/loopTransform.cpp
--- 24.0.1+9-1/src/hotspot/share/opto/loopTransform.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/opto/loopTransform.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -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
@@ -1428,11 +1428,13 @@ void PhaseIdealLoop::insert_pre_post_loo
   _igvn.hash_delete(outer_main_head);
   outer_main_head->set_req(LoopNode::EntryControl, min_taken);
   set_idom(outer_main_head, min_taken, dd_main_head);
+  assert(post_head->in(1)->is_IfProj(), "must be zero-trip guard If node projection of the post loop");
 
   VectorSet visited;
   Node_Stack clones(main_head->back_control()->outcnt());
   // Step B3: Make the fall-in values to the main-loop come from the
   // fall-out values of the pre-loop.
+  const uint last_node_index_in_pre_loop_body = Compile::current()->unique() - 1;
   for (DUIterator i2 = main_head->outs(); main_head->has_out(i2); i2++) {
     Node* main_phi = main_head->out(i2);
     if (main_phi->is_Phi() && main_phi->in(0) == main_head && main_phi->outcnt() > 0) {
@@ -1445,21 +1447,13 @@ void PhaseIdealLoop::insert_pre_post_loo
       main_phi->set_req(LoopNode::EntryControl, fallpre);
     }
   }
+  DEBUG_ONLY(const uint last_node_index_from_backedge_goo = Compile::current()->unique() - 1);
 
-  // Nodes inside the loop may be control dependent on a predicate
-  // that was moved before the preloop. If the back branch of the main
-  // or post loops becomes dead, those nodes won't be dependent on the
-  // test that guards that loop nest anymore which could lead to an
-  // incorrect array access because it executes independently of the
-  // test that was guarding the loop nest. We add a special CastII on
-  // the if branch that enters the loop, between the input induction
-  // variable value and the induction variable Phi to preserve correct
-  // dependencies.
-
-  assert(post_head->in(1)->is_IfProj(), "must be zero-trip guard If node projection of the post loop");
   DEBUG_ONLY(ensure_zero_trip_guard_proj(outer_main_head->in(LoopNode::EntryControl), true);)
   if (UseLoopPredicate) {
-    initialize_assertion_predicates_for_main_loop(pre_head, main_head, first_node_index_in_pre_loop_body, old_new);
+    initialize_assertion_predicates_for_main_loop(pre_head, main_head, first_node_index_in_pre_loop_body,
+                                                  last_node_index_in_pre_loop_body,
+                                                  DEBUG_ONLY(last_node_index_from_backedge_goo COMMA) old_new);
   }
 
   // Step B4: Shorten the pre-loop to run only 1 iteration (for now).
@@ -1734,10 +1728,15 @@ void PhaseIdealLoop::initialize_assertio
 // Target Loop: Original - main_loop_head
 void PhaseIdealLoop::initialize_assertion_predicates_for_main_loop(CountedLoopNode* pre_loop_head,
                                                                    CountedLoopNode* main_loop_head,
-                                                                   const uint first_node_index_in_cloned_loop_body,
+                                                                   const uint first_node_index_in_pre_loop_body,
+                                                                   const uint last_node_index_in_pre_loop_body,
+                                                                   DEBUG_ONLY(const uint last_node_index_from_backedge_goo COMMA)
                                                                    const Node_List& old_new) {
-  const NodeInOriginalLoopBody node_in_original_loop_body(first_node_index_in_cloned_loop_body, old_new);
-  create_assertion_predicates_at_loop(pre_loop_head, main_loop_head, node_in_original_loop_body, true);
+  assert(first_node_index_in_pre_loop_body < last_node_index_in_pre_loop_body, "cloned some nodes");
+  const NodeInMainLoopBody node_in_main_loop_body(first_node_index_in_pre_loop_body,
+                                                  last_node_index_in_pre_loop_body,
+                                                  DEBUG_ONLY(last_node_index_from_backedge_goo COMMA) old_new);
+  create_assertion_predicates_at_main_or_post_loop(pre_loop_head, main_loop_head, node_in_main_loop_body, true);
 }
 
 // Source Loop: Original - main_loop_head
@@ -1746,7 +1745,7 @@ void PhaseIdealLoop::initialize_assertio
                                                                    CountedLoopNode* post_loop_head,
                                                                    const uint first_node_index_in_cloned_loop_body) {
   const NodeInClonedLoopBody node_in_cloned_loop_body(first_node_index_in_cloned_loop_body);
-  create_assertion_predicates_at_loop(main_loop_head, post_loop_head, node_in_cloned_loop_body, false);
+  create_assertion_predicates_at_main_or_post_loop(main_loop_head, post_loop_head, node_in_cloned_loop_body, false);
 }
 
 void PhaseIdealLoop::create_assertion_predicates_at_loop(CountedLoopNode* source_loop_head,
@@ -1768,6 +1767,47 @@ void PhaseIdealLoop::create_assertion_pr
     set_idom(target_outer_loop_head, last_created_predicate_success_proj, dom_depth(target_outer_loop_head));
   }
 }
+
+void PhaseIdealLoop::create_assertion_predicates_at_main_or_post_loop(CountedLoopNode* source_loop_head,
+                                                                      CountedLoopNode* target_loop_head,
+                                                                      const NodeInLoopBody& _node_in_loop_body,
+                                                                      bool clone_template) {
+  Node* old_target_loop_head_entry = target_loop_head->skip_strip_mined()->in(LoopNode::EntryControl);
+  const uint node_index_before_new_assertion_predicate_nodes = C->unique();
+  const bool need_to_rewire_old_target_loop_entry_dependencies = old_target_loop_head_entry->outcnt() > 1;
+  create_assertion_predicates_at_loop(source_loop_head, target_loop_head, _node_in_loop_body, clone_template);
+  if (need_to_rewire_old_target_loop_entry_dependencies) {
+    rewire_old_target_loop_entry_dependency_to_new_entry(target_loop_head, old_target_loop_head_entry,
+                                                         node_index_before_new_assertion_predicate_nodes);
+  }
+}
+
+// Rewire any control dependent nodes on the old target loop entry before adding Assertion Predicate related nodes.
+// These have been added by PhaseIdealLoop::clone_up_backedge_goo() and assume to be ending up at the target loop entry
+// which is no longer the case when adding additional Assertion Predicates. Fix this by rewiring these nodes to the new
+// target loop entry which corresponds to the tail of the last Assertion Predicate before the target loop. This is safe
+// to do because these control dependent nodes on the old target loop entry created by clone_up_backedge_goo() were
+// pinned on the loop backedge before. The Assertion Predicates are not control dependent on these nodes in any way.
+void PhaseIdealLoop::rewire_old_target_loop_entry_dependency_to_new_entry(
+    LoopNode* target_loop_head, const Node* old_target_loop_entry,
+    const uint node_index_before_new_assertion_predicate_nodes) {
+  Node* new_main_loop_entry = target_loop_head->skip_strip_mined()->in(LoopNode::EntryControl);
+  if (new_main_loop_entry == old_target_loop_entry) {
+    // No Assertion Predicates added.
+    return;
+  }
+
+  for (DUIterator_Fast imax, i = old_target_loop_entry->fast_outs(imax); i < imax; i++) {
+    Node* out = old_target_loop_entry->fast_out(i);
+    if (!out->is_CFG() && out->_idx < node_index_before_new_assertion_predicate_nodes) {
+      _igvn.replace_input_of(out, 0, new_main_loop_entry);
+      set_ctrl(out, new_main_loop_entry);
+      --i;
+      --imax;
+    }
+  }
+}
+
 //------------------------------do_unroll--------------------------------------
 // Unroll the loop body one step - make each trip do 2 iterations.
 void PhaseIdealLoop::do_unroll(IdealLoopTree *loop, Node_List &old_new, bool adjust_min_trip) {
diff -pruN 24.0.1+9-1/src/hotspot/share/opto/loopnode.hpp 24.0.2+12-1/src/hotspot/share/opto/loopnode.hpp
--- 24.0.1+9-1/src/hotspot/share/opto/loopnode.hpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/opto/loopnode.hpp	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -950,12 +950,20 @@ private:
                                                        const Node_List& old_new);
   void initialize_assertion_predicates_for_main_loop(CountedLoopNode* pre_loop_head,
                                                      CountedLoopNode* main_loop_head,
-                                                     uint first_node_index_in_cloned_loop_body,
+                                                     uint first_node_index_in_pre_loop_body,
+                                                     uint last_node_index_in_pre_loop_body,
+                                                     DEBUG_ONLY(uint last_node_index_from_backedge_goo COMMA)
                                                      const Node_List& old_new);
   void initialize_assertion_predicates_for_post_loop(CountedLoopNode* main_loop_head, CountedLoopNode* post_loop_head,
                                                      uint first_node_index_in_cloned_loop_body);
   void create_assertion_predicates_at_loop(CountedLoopNode* source_loop_head, CountedLoopNode* target_loop_head,
                                            const NodeInLoopBody& _node_in_loop_body, bool clone_template);
+  void create_assertion_predicates_at_main_or_post_loop(CountedLoopNode* source_loop_head,
+                                                        CountedLoopNode* target_loop_head,
+                                                        const NodeInLoopBody& _node_in_loop_body, bool clone_template);
+  void rewire_old_target_loop_entry_dependency_to_new_entry(LoopNode* target_loop_head,
+                                                            const Node* old_target_loop_entry,
+                                                            uint node_index_before_new_assertion_predicate_nodes);
   void insert_loop_limit_check_predicate(ParsePredicateSuccessProj* loop_limit_check_parse_proj, Node* cmp_limit,
                                          Node* bol);
   void log_loop_tree();
diff -pruN 24.0.1+9-1/src/hotspot/share/opto/phaseX.cpp 24.0.2+12-1/src/hotspot/share/opto/phaseX.cpp
--- 24.0.1+9-1/src/hotspot/share/opto/phaseX.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/opto/phaseX.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1900,6 +1900,7 @@ void PhaseCCP::push_more_uses(Unique_Nod
   push_and(worklist, parent, use);
   push_cast_ii(worklist, parent, use);
   push_opaque_zero_trip_guard(worklist, use);
+  push_bool_with_cmpu_and_mask(worklist, use);
 }
 
 
@@ -1945,6 +1946,57 @@ void PhaseCCP::push_cmpu(Unique_Node_Lis
     }
   }
 }
+
+// Look for the following shape, which can be optimized by BoolNode::Value_cmpu_and_mask() (i.e. corresponds to case
+// (1b): "(m & x) <u (m + 1))".
+// If any of the inputs on the level (%%) change, we need to revisit Bool because we could have prematurely found that
+// the Bool is constant (i.e. case (1b) can be applied) which could become invalid with new type information during CCP.
+//
+//  m    x  m    1  (%%)
+//   \  /    \  /
+//   AndI    AddI
+//      \    /
+//       CmpU
+//        |
+//       Bool
+//
+void PhaseCCP::push_bool_with_cmpu_and_mask(Unique_Node_List& worklist, const Node* use) const {
+  uint use_op = use->Opcode();
+  if (use_op != Op_AndI && (use_op != Op_AddI || use->in(2)->find_int_con(0) != 1)) {
+    // Not "m & x" or "m + 1"
+    return;
+  }
+  for (DUIterator_Fast imax, i = use->fast_outs(imax); i < imax; i++) {
+    Node* cmpu = use->fast_out(i);
+    if (cmpu->Opcode() == Op_CmpU) {
+      push_bool_matching_case1b(worklist, cmpu);
+    }
+  }
+}
+
+// Push any Bool below 'cmpu' that matches case (1b) of BoolNode::Value_cmpu_and_mask().
+void PhaseCCP::push_bool_matching_case1b(Unique_Node_List& worklist, const Node* cmpu) const {
+  assert(cmpu->Opcode() == Op_CmpU, "must be");
+  for (DUIterator_Fast imax, i = cmpu->fast_outs(imax); i < imax; i++) {
+    Node* bol = cmpu->fast_out(i);
+    if (!bol->is_Bool() || bol->as_Bool()->_test._test != BoolTest::lt) {
+      // Not a Bool with "<u"
+      continue;
+    }
+    Node* andI = cmpu->in(1);
+    Node* addI = cmpu->in(2);
+    if (andI->Opcode() != Op_AndI || addI->Opcode() != Op_AddI || addI->in(2)->find_int_con(0) != 1) {
+      // Not "m & x" and "m + 1"
+      continue;
+    }
+
+    Node* m = addI->in(1);
+    if (m == andI->in(1) || m == andI->in(2)) {
+      // Is "m" shared? Matched (1b) and thus we revisit Bool.
+      push_if_not_bottom_type(worklist, bol);
+    }
+  }
+}
 
 // If n is used in a counted loop exit condition, then the type of the counted loop's Phi depends on the type of 'n'.
 // Seem PhiNode::Value().
diff -pruN 24.0.1+9-1/src/hotspot/share/opto/phaseX.hpp 24.0.2+12-1/src/hotspot/share/opto/phaseX.hpp
--- 24.0.1+9-1/src/hotspot/share/opto/phaseX.hpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/opto/phaseX.hpp	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -626,6 +626,8 @@ class PhaseCCP : public PhaseIterGVN {
   void push_and(Unique_Node_List& worklist, const Node* parent, const Node* use) const;
   void push_cast_ii(Unique_Node_List& worklist, const Node* parent, const Node* use) const;
   void push_opaque_zero_trip_guard(Unique_Node_List& worklist, const Node* use) const;
+  void push_bool_with_cmpu_and_mask(Unique_Node_List& worklist, const Node* use) const;
+  void push_bool_matching_case1b(Unique_Node_List& worklist, const Node* cmpu) const;
 
  public:
   PhaseCCP( PhaseIterGVN *igvn ); // Compute conditional constants
diff -pruN 24.0.1+9-1/src/hotspot/share/opto/predicates.cpp 24.0.2+12-1/src/hotspot/share/opto/predicates.cpp
--- 24.0.1+9-1/src/hotspot/share/opto/predicates.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/opto/predicates.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -135,7 +135,7 @@ void TemplateAssertionPredicate::rewire_
                                                                PhaseIdealLoop* phase) const {
   for (DUIterator i = _success_proj->outs(); _success_proj->has_out(i); i++) {
     Node* output = _success_proj->out(i);
-    if (!output->is_CFG() && data_in_loop_body.check(output)) {
+    if (!output->is_CFG() && data_in_loop_body.check_node_in_loop_body(output)) {
       phase->igvn().replace_input_of(output, 0, target_predicate);
       --i; // account for the just deleted output
     }
diff -pruN 24.0.1+9-1/src/hotspot/share/opto/predicates.hpp 24.0.2+12-1/src/hotspot/share/opto/predicates.hpp
--- 24.0.1+9-1/src/hotspot/share/opto/predicates.hpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/opto/predicates.hpp	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 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
@@ -249,7 +249,7 @@ class PredicateVisitor : StackObj {
 // Interface to check whether a node is in a loop body or not.
 class NodeInLoopBody : public StackObj {
  public:
-  virtual bool check(Node* node) const = 0;
+  virtual bool check_node_in_loop_body(Node* node) const = 0;
 };
 
 // Class to represent Assertion Predicates (i.e. either Initialized and/or Template Assertion Predicates).
@@ -952,13 +952,52 @@ class NodeInOriginalLoopBody : public No
 
   // Check if 'node' is not a cloned node (i.e. "< _first_node_index_in_cloned_loop_body") and if we've created a
   // clone from 'node' (i.e. _old_new entry is non-null). Then we know that 'node' belongs to the original loop body.
-  bool check(Node* node) const override {
+  bool check_node_in_loop_body(Node* node) const override {
     if (node->_idx < _first_node_index_in_cloned_loop_body) {
       Node* cloned_node = _old_new[node->_idx];
+      // Check that the clone is actually part of the cloned loop body and not from some earlier cloning.
       return cloned_node != nullptr && cloned_node->_idx >= _first_node_index_in_cloned_loop_body;
-    } else {
-      return false;
     }
+    return false;
+  }
+};
+
+// This class checks whether a node is in the main loop body and not the pre loop body. We cannot use the
+// NodeInOriginalLoopBody class because PhaseIdealLoop::clone_up_backedge_goo() could clone additional nodes that
+// should be pinned at the main loop body entry. The check in NodeInOriginalLoopBody will ignore these.
+class NodeInMainLoopBody : public NodeInLoopBody {
+  const uint _first_node_index_in_pre_loop_body;
+  const uint _last_node_index_in_pre_loop_body;
+  DEBUG_ONLY(const uint _last_node_index_from_backedge_goo;)
+  const Node_List& _old_new;
+
+  public:
+  NodeInMainLoopBody(const uint first_node_index_in_pre_loop_body, const uint last_node_index_in_pre_loop_body,
+                     DEBUG_ONLY(const uint last_node_index_from_backedge_goo COMMA) const Node_List& old_new)
+      : _first_node_index_in_pre_loop_body(first_node_index_in_pre_loop_body),
+        _last_node_index_in_pre_loop_body(last_node_index_in_pre_loop_body),
+        DEBUG_ONLY(_last_node_index_from_backedge_goo(last_node_index_from_backedge_goo) COMMA)
+        _old_new(old_new) {}
+  NONCOPYABLE(NodeInMainLoopBody);
+
+  // Check if 'node' is not a cloned node (i.e. "< _first_node_index_in_cloned_loop_body") and if we've created a
+  // clone from 'node' (i.e. _old_new entry is non-null). Then we know that 'node' belongs to the original loop body.
+  // Additionally check if a node was cloned after the pre loop was created. This indicates that it was created by
+  // PhaseIdealLoop::clone_up_backedge_goo(). These nodes should also be pinned at the main loop entry.
+  bool check_node_in_loop_body(Node* node) const override {
+    if (node->_idx < _first_node_index_in_pre_loop_body) {
+      Node* cloned_node = _old_new[node->_idx];
+      // Check that the clone is actually part of the cloned loop body and not from some earlier cloning.
+      bool cloned_node_in_pre_loop_body = cloned_node != nullptr && cloned_node->_idx >= _first_node_index_in_pre_loop_body;
+      assert(!cloned_node_in_pre_loop_body || cloned_node->_idx <= _last_node_index_in_pre_loop_body,
+             "clone must be part of pre loop body");
+      return cloned_node_in_pre_loop_body;
+    }
+    // Created in PhaseIdealLoop::clone_up_backedge_goo()?
+    bool node_created_by_backedge_goo = node->_idx > _last_node_index_in_pre_loop_body;
+    assert(!node_created_by_backedge_goo || node->_idx <= _last_node_index_from_backedge_goo,
+           "cloned node must have been created in PhaseIdealLoop::clone_up_backedge_goo()");
+    return node_created_by_backedge_goo;
   }
 };
 
@@ -973,7 +1012,7 @@ class NodeInClonedLoopBody : public Node
 
   // Check if 'node' is a clone. This can easily be achieved by comparing its node index to the first node index
   // inside the cloned loop body (all of them are clones).
-  bool check(Node* node) const override {
+  bool check_node_in_loop_body(Node* node) const override {
     return node->_idx >= _first_node_index_in_cloned_loop_body;
   }
 };
diff -pruN 24.0.1+9-1/src/hotspot/share/opto/subnode.cpp 24.0.2+12-1/src/hotspot/share/opto/subnode.cpp
--- 24.0.1+9-1/src/hotspot/share/opto/subnode.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/opto/subnode.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1865,7 +1865,7 @@ const Type* BoolNode::Value_cmpu_and_mas
         // (1b) "(x & m) <u m + 1" and "(m & x) <u m + 1", cmp2 = m + 1
         Node* rhs_m = cmp2->in(1);
         const TypeInt* rhs_m_type = phase->type(rhs_m)->isa_int();
-        if (rhs_m_type->_lo > -1 || rhs_m_type->_hi < -1) {
+        if (rhs_m_type != nullptr && (rhs_m_type->_lo > -1 || rhs_m_type->_hi < -1)) {
           // Exclude any case where m == -1 is possible.
           m = rhs_m;
         }
@@ -1883,12 +1883,16 @@ const Type* BoolNode::Value_cmpu_and_mas
 // Simplify a Bool (convert condition codes to boolean (1 or 0)) node,
 // based on local information.   If the input is constant, do it.
 const Type* BoolNode::Value(PhaseGVN* phase) const {
+  const Type* input_type = phase->type(in(1));
+  if (input_type == Type::TOP) {
+    return Type::TOP;
+  }
   const Type* t = Value_cmpu_and_mask(phase);
   if (t != nullptr) {
     return t;
   }
 
-  return _test.cc2logical( phase->type( in(1) ) );
+  return _test.cc2logical(input_type);
 }
 
 #ifndef PRODUCT
diff -pruN 24.0.1+9-1/src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp 24.0.2+12-1/src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp
--- 24.0.1+9-1/src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -125,7 +125,7 @@ void CodeBlobCollector::do_blob(CodeBlob
     return;
   }
   // exclude VtableStubs, which are processed separately
-  if (cb->is_buffer_blob() && strcmp(cb->name(), "vtable chunks") == 0) {
+  if (cb->is_vtable_blob()) {
     return;
   }
 
diff -pruN 24.0.1+9-1/src/hotspot/share/runtime/deoptimization.cpp 24.0.2+12-1/src/hotspot/share/runtime/deoptimization.cpp
--- 24.0.1+9-1/src/hotspot/share/runtime/deoptimization.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/runtime/deoptimization.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -37,6 +37,7 @@
 #include "gc/shared/collectedHeap.hpp"
 #include "gc/shared/memAllocator.hpp"
 #include "interpreter/bytecode.hpp"
+#include "interpreter/bytecode.inline.hpp"
 #include "interpreter/bytecodeStream.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/oopMapCache.hpp"
@@ -642,11 +643,12 @@ Deoptimization::UnrollBlock* Deoptimizat
   bool caller_was_method_handle = false;
   if (deopt_sender.is_interpreted_frame()) {
     methodHandle method(current, deopt_sender.interpreter_frame_method());
-    Bytecode_invoke cur = Bytecode_invoke_check(method, deopt_sender.interpreter_frame_bci());
-    if (cur.is_invokedynamic() || cur.is_invokehandle()) {
-      // Method handle invokes may involve fairly arbitrary chains of
-      // calls so it's impossible to know how much actual space the
-      // caller has for locals.
+    Bytecode_invoke cur(method, deopt_sender.interpreter_frame_bci());
+    if (cur.has_member_arg()) {
+      // This should cover all real-world cases.  One exception is a pathological chain of
+      // MH.linkToXXX() linker calls, which only trusted code could do anyway.  To handle that case, we
+      // would need to get the size from the resolved method entry.  Another exception would
+      // be an invokedynamic with an adapter that is really a MethodHandle linker.
       caller_was_method_handle = true;
     }
   }
@@ -749,9 +751,14 @@ Deoptimization::UnrollBlock* Deoptimizat
   }
 #endif
 
+  int caller_actual_parameters = -1; // value not used except for interpreted frames, see below
+  if (deopt_sender.is_interpreted_frame()) {
+    caller_actual_parameters = callee_parameters + (caller_was_method_handle ? 1 : 0);
+  }
+
   UnrollBlock* info = new UnrollBlock(array->frame_size() * BytesPerWord,
                                       caller_adjustment * BytesPerWord,
-                                      caller_was_method_handle ? 0 : callee_parameters,
+                                      caller_actual_parameters,
                                       number_of_frames,
                                       frame_sizes,
                                       frame_pcs,
@@ -940,7 +947,7 @@ JRT_LEAF(BasicType, Deoptimization::unpa
       if (Bytecodes::is_invoke(cur_code)) {
         Bytecode_invoke invoke(mh, iframe->interpreter_frame_bci());
         cur_invoke_parameter_size = invoke.size_of_parameters();
-        if (i != 0 && !invoke.is_invokedynamic() && MethodHandles::has_member_arg(invoke.klass(), invoke.name())) {
+        if (i != 0 && invoke.has_member_arg()) {
           callee_size_of_parameters++;
         }
       }
diff -pruN 24.0.1+9-1/src/hotspot/share/runtime/os.cpp 24.0.2+12-1/src/hotspot/share/runtime/os.cpp
--- 24.0.1+9-1/src/hotspot/share/runtime/os.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/runtime/os.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1213,8 +1213,7 @@ void os::print_date_and_time(outputStrea
   if (localtime_pd(&tloc, &tz) != nullptr) {
     wchar_t w_buf[80];
     size_t n = ::wcsftime(w_buf, 80, L"%Z", &tz);
-    if (n > 0) {
-      ::wcstombs(buf, w_buf, buflen);
+    if (n > 0 && ::wcstombs(buf, w_buf, buflen) != (size_t)-1) {
       st->print("Time: %s %s", timestring, buf);
     } else {
       st->print("Time: %s", timestring);
@@ -2533,7 +2532,7 @@ char* os::build_agent_function_name(cons
       if ((start = strrchr(lib_name, *os::file_separator())) != nullptr) {
         lib_name = ++start;
       }
-#ifdef WINDOWS
+#ifdef _WINDOWS
       else { // Need to check for drive prefix e.g. C:L.dll
         if ((start = strchr(lib_name, ':')) != nullptr) {
           lib_name = ++start;
diff -pruN 24.0.1+9-1/src/hotspot/share/runtime/safepoint.cpp 24.0.2+12-1/src/hotspot/share/runtime/safepoint.cpp
--- 24.0.1+9-1/src/hotspot/share/runtime/safepoint.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/runtime/safepoint.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -472,6 +472,8 @@ void SafepointSynchronize::disarm_safepo
 // operation has been carried out
 void SafepointSynchronize::end() {
   assert(Threads_lock->owned_by_self(), "must hold Threads_lock");
+  SafepointTracing::leave();
+
   EventSafepointEnd event;
   assert(Thread::current()->is_VM_thread(), "Only VM thread can execute a safepoint");
 
@@ -866,6 +868,7 @@ void ThreadSafepointState::handle_pollin
 
 jlong SafepointTracing::_last_safepoint_begin_time_ns = 0;
 jlong SafepointTracing::_last_safepoint_sync_time_ns = 0;
+jlong SafepointTracing::_last_safepoint_leave_time_ns = 0;
 jlong SafepointTracing::_last_safepoint_end_time_ns = 0;
 jlong SafepointTracing::_last_app_time_ns = 0;
 int SafepointTracing::_nof_threads = 0;
@@ -967,6 +970,10 @@ void SafepointTracing::synchronized(int
   RuntimeService::record_safepoint_synchronized(_last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns);
 }
 
+void SafepointTracing::leave() {
+  _last_safepoint_leave_time_ns = os::javaTimeNanos();
+}
+
 void SafepointTracing::end() {
   _last_safepoint_end_time_ns = os::javaTimeNanos();
 
@@ -985,12 +992,14 @@ void SafepointTracing::end() {
      "Time since last: " JLONG_FORMAT " ns, "
      "Reaching safepoint: " JLONG_FORMAT " ns, "
      "At safepoint: " JLONG_FORMAT " ns, "
+     "Leaving safepoint: " JLONG_FORMAT " ns, "
      "Total: " JLONG_FORMAT " ns",
       VM_Operation::name(_current_type),
       _last_app_time_ns,
-      _last_safepoint_sync_time_ns    - _last_safepoint_begin_time_ns,
-      _last_safepoint_end_time_ns     - _last_safepoint_sync_time_ns,
-      _last_safepoint_end_time_ns     - _last_safepoint_begin_time_ns
+      _last_safepoint_sync_time_ns  - _last_safepoint_begin_time_ns,
+      _last_safepoint_leave_time_ns - _last_safepoint_sync_time_ns,
+      _last_safepoint_end_time_ns   - _last_safepoint_leave_time_ns,
+      _last_safepoint_end_time_ns   - _last_safepoint_begin_time_ns
      );
 
   RuntimeService::record_safepoint_end(_last_safepoint_end_time_ns - _last_safepoint_sync_time_ns);
diff -pruN 24.0.1+9-1/src/hotspot/share/runtime/safepoint.hpp 24.0.2+12-1/src/hotspot/share/runtime/safepoint.hpp
--- 24.0.1+9-1/src/hotspot/share/runtime/safepoint.hpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/runtime/safepoint.hpp	2025-06-27 08:03:14.000000000 +0000
@@ -230,6 +230,7 @@ private:
   // Absolute
   static jlong _last_safepoint_begin_time_ns;
   static jlong _last_safepoint_sync_time_ns;
+  static jlong _last_safepoint_leave_time_ns;
   static jlong _last_safepoint_end_time_ns;
 
   // Relative
@@ -251,6 +252,7 @@ public:
 
   static void begin(VM_Operation::VMOp_Type type);
   static void synchronized(int nof_threads, int nof_running, int traps);
+  static void leave();
   static void end();
 
   static void statistics_exit_log();
diff -pruN 24.0.1+9-1/src/hotspot/share/runtime/vframeArray.cpp 24.0.2+12-1/src/hotspot/share/runtime/vframeArray.cpp
--- 24.0.1+9-1/src/hotspot/share/runtime/vframeArray.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/runtime/vframeArray.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -26,6 +26,7 @@
 #include "classfile/vmSymbols.hpp"
 #include "code/vmreg.inline.hpp"
 #include "interpreter/bytecode.hpp"
+#include "interpreter/bytecode.inline.hpp"
 #include "interpreter/interpreter.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
@@ -614,10 +615,7 @@ void vframeArray::unpack_to_stack(frame
       methodHandle caller(current, elem->method());
       methodHandle callee(current, element(index - 1)->method());
       Bytecode_invoke inv(caller, elem->bci());
-      // invokedynamic instructions don't have a class but obviously don't have a MemberName appendix.
-      // NOTE:  Use machinery here that avoids resolving of any kind.
-      const bool has_member_arg =
-          !inv.is_invokedynamic() && MethodHandles::has_member_arg(inv.klass(), inv.name());
+      const bool has_member_arg = inv.has_member_arg();
       callee_parameters = callee->size_of_parameters() + (has_member_arg ? 1 : 0);
       callee_locals     = callee->max_locals();
     }
diff -pruN 24.0.1+9-1/src/hotspot/share/utilities/growableArray.cpp 24.0.2+12-1/src/hotspot/share/utilities/growableArray.cpp
--- 24.0.1+9-1/src/hotspot/share/utilities/growableArray.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/utilities/growableArray.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -44,6 +44,11 @@ void* GrowableArrayArenaAllocator::alloc
 
 void* GrowableArrayCHeapAllocator::allocate(int max, int element_size, MemTag mem_tag) {
   assert(max >= 0, "integer overflow");
+
+  if (max == 0) {
+    return nullptr;
+  }
+
   size_t byte_size = element_size * (size_t) max;
 
   // memory tag has to be specified for C heap allocation
diff -pruN 24.0.1+9-1/src/hotspot/share/utilities/growableArray.hpp 24.0.2+12-1/src/hotspot/share/utilities/growableArray.hpp
--- 24.0.1+9-1/src/hotspot/share/utilities/growableArray.hpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/hotspot/share/utilities/growableArray.hpp	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -811,10 +811,6 @@ class GrowableArrayCHeap : public Growab
   STATIC_ASSERT(MT != mtNone);
 
   static E* allocate(int max, MemTag mem_tag) {
-    if (max == 0) {
-      return nullptr;
-    }
-
     return (E*)GrowableArrayCHeapAllocator::allocate(max, sizeof(E), mem_tag);
   }
 
diff -pruN 24.0.1+9-1/src/java.base/aix/classes/sun/nio/fs/AixFileStore.java 24.0.2+12-1/src/java.base/aix/classes/sun/nio/fs/AixFileStore.java
--- 24.0.1+9-1/src/java.base/aix/classes/sun/nio/fs/AixFileStore.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/aix/classes/sun/nio/fs/AixFileStore.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2013 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -89,17 +89,31 @@ class AixFileStore
     }
 
     @Override
-    protected boolean isExtendedAttributesEnabled(UnixPath path) {
-        return false;
-    }
-
-    @Override
     public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
+        // support UserDefinedAttributeView if extended attributes enabled
+        if (type == UserDefinedFileAttributeView.class) {
+            // lookup fstypes.properties
+            FeatureStatus status = checkIfFeaturePresent("user_xattr");
+            if (status == FeatureStatus.PRESENT)
+                return true;
+            if (status == FeatureStatus.NOT_PRESENT)
+                return false;
+
+            // typical AIX file system types that support xattr (JFS2 with EA enabled)
+            String fstype = entry().fstype();
+            if ("jfs2".equals(fstype)) {
+                UnixPath dir = new UnixPath(file().getFileSystem(), entry().dir());
+                return isExtendedAttributesEnabled(dir);
+            }
+        }
         return super.supportsFileAttributeView(type);
     }
 
     @Override
     public boolean supportsFileAttributeView(String name) {
+        if (name.equals("user"))
+            return supportsFileAttributeView(UserDefinedFileAttributeView.class);
         return super.supportsFileAttributeView(name);
     }
+
 }
diff -pruN 24.0.1+9-1/src/java.base/aix/classes/sun/nio/fs/AixFileSystem.java 24.0.2+12-1/src/java.base/aix/classes/sun/nio/fs/AixFileSystem.java
--- 24.0.1+9-1/src/java.base/aix/classes/sun/nio/fs/AixFileSystem.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/aix/classes/sun/nio/fs/AixFileSystem.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2013 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -56,6 +56,7 @@ class AixFileSystem extends UnixFileSyst
         private static Set<String> supportedFileAttributeViews() {
             Set<String> result = new HashSet<String>();
             result.addAll(UnixFileSystem.standardFileAttributeViews());
+            result.add("user");
             return Collections.unmodifiableSet(result);
         }
     }
diff -pruN 24.0.1+9-1/src/java.base/aix/classes/sun/nio/fs/AixFileSystemProvider.java 24.0.2+12-1/src/java.base/aix/classes/sun/nio/fs/AixFileSystemProvider.java
--- 24.0.1+9-1/src/java.base/aix/classes/sun/nio/fs/AixFileSystemProvider.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/aix/classes/sun/nio/fs/AixFileSystemProvider.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2013 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -26,6 +26,8 @@
 
 package sun.nio.fs;
 
+import java.nio.file.*;
+import java.nio.file.attribute.*;
 import java.io.IOException;
 
 /**
@@ -49,4 +51,29 @@ class AixFileSystemProvider extends Unix
     AixFileStore getFileStore(UnixPath path) throws IOException {
         return new AixFileStore(path);
     }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <V extends FileAttributeView> V getFileAttributeView(Path obj,
+                                                                Class<V> type,
+                                                                LinkOption... options)
+    {
+        if (type == UserDefinedFileAttributeView.class) {
+            return (V) new AixUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
+                    Util.followLinks(options));
+        }
+        return super.getFileAttributeView(obj, type, options);
+    }
+
+    @Override
+    public DynamicFileAttributeView getFileAttributeView(Path obj,
+                                                         String name,
+                                                         LinkOption... options)
+    {
+        if (name.equals("user")) {
+            return new AixUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
+                    Util.followLinks(options));
+        }
+        return super.getFileAttributeView(obj, name, options);
+    }
 }
diff -pruN 24.0.1+9-1/src/java.base/aix/classes/sun/nio/fs/AixUserDefinedFileAttributeView.java 24.0.2+12-1/src/java.base/aix/classes/sun/nio/fs/AixUserDefinedFileAttributeView.java
--- 24.0.1+9-1/src/java.base/aix/classes/sun/nio/fs/AixUserDefinedFileAttributeView.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.base/aix/classes/sun/nio/fs/AixUserDefinedFileAttributeView.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.fs;
+
+class AixUserDefinedFileAttributeView
+    extends UnixUserDefinedFileAttributeView
+{
+
+    AixUserDefinedFileAttributeView(UnixPath file, boolean followLinks) {
+        super(file, followLinks);
+    }
+
+    @Override
+    protected int maxNameLength() {
+        return 255;
+    }
+
+}
diff -pruN 24.0.1+9-1/src/java.base/aix/native/libjava/ProcessHandleImpl_aix.c 24.0.2+12-1/src/java.base/aix/native/libjava/ProcessHandleImpl_aix.c
--- 24.0.1+9-1/src/java.base/aix/native/libjava/ProcessHandleImpl_aix.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/aix/native/libjava/ProcessHandleImpl_aix.c	2025-06-27 08:03:14.000000000 +0000
@@ -162,7 +162,24 @@ jint os_getChildren(JNIEnv *env, jlong j
 }
 
 pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t pid, jlong *total, jlong *start) {
-    return unix_getParentPidAndTimings(env, pid, total, start);
+    pid_t the_pid = pid;
+    struct procentry64 ProcessBuffer;
+
+    if (getprocs64(&ProcessBuffer, sizeof(ProcessBuffer), NULL, sizeof(struct fdsinfo64), &the_pid, 1) <= 0) {
+        return -1;
+    }
+
+    // Validate the pid before returning the info
+    if (kill(pid, 0) < 0) {
+        return -1;
+    }
+
+    *total = ((ProcessBuffer.pi_ru.ru_utime.tv_sec + ProcessBuffer.pi_ru.ru_stime.tv_sec) * 1000000000L) +
+             ((ProcessBuffer.pi_ru.ru_utime.tv_usec + ProcessBuffer.pi_ru.ru_stime.tv_usec));
+
+    *start = ProcessBuffer.pi_start * (jlong)1000;
+
+    return (pid_t) ProcessBuffer.pi_ppid;
 }
 
 void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
diff -pruN 24.0.1+9-1/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1SubsystemController.java 24.0.2+12-1/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1SubsystemController.java
--- 24.0.1+9-1/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1SubsystemController.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1SubsystemController.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -25,6 +25,9 @@
 
 package jdk.internal.platform.cgroupv1;
 
+import java.lang.System.Logger.Level;
+import java.nio.file.Path;
+import java.nio.file.Files;
 import jdk.internal.platform.CgroupSubsystem;
 import jdk.internal.platform.CgroupSubsystemController;
 
@@ -44,27 +47,36 @@ public class CgroupV1SubsystemController
 
     public void setPath(String cgroupPath) {
         if (root != null && cgroupPath != null) {
+            String path = mountPoint;
             if (root.equals("/")) {
+                // host processes and containers with cgroupns=private
                 if (!cgroupPath.equals("/")) {
-                    path = mountPoint + cgroupPath;
+                    path += cgroupPath;
                 }
-                else {
-                    path = mountPoint;
-                }
-            }
-            else {
-                if (root.equals(cgroupPath)) {
-                    path = mountPoint;
-                }
-                else {
-                    if (cgroupPath.startsWith(root)) {
-                        if (cgroupPath.length() > root.length()) {
-                            String cgroupSubstr = cgroupPath.substring(root.length());
-                            path = mountPoint + cgroupSubstr;
+            } else {
+                // containers with cgroupns=host, default setting is _root==cgroup_path
+                if (!cgroupPath.equals(root)) {
+                    if (!cgroupPath.equals("") && !cgroupPath.equals("/")) {
+                        // When moved to a subgroup, between subgroups, the path suffix will change.
+                        Path cgp = Path.of(cgroupPath);
+                        int nameCount = cgp.getNameCount();
+                        for (int i=0; i < nameCount; i++) {
+                            Path dir = Path.of(mountPoint, cgp.toString());
+                            if (Files.isDirectory(dir)) {
+                                path = dir.toString();
+                                if (i > 0) {
+                                    System.getLogger("jdk.internal.platform").log(Level.DEBUG, String.format(
+                                            "Cgroup v1 path reduced to: %s.", cgp));
+                                }
+                                break;
+                            }
+                            int currentNameCount = cgp.getNameCount();
+                            cgp = (currentNameCount > 1) ? cgp.subpath(1, currentNameCount) : Path.of("");
                         }
                     }
                 }
             }
+            this.path = path;
         }
     }
 
diff -pruN 24.0.1+9-1/src/java.base/linux/native/libsimdsort/avx2-emu-funcs.hpp 24.0.2+12-1/src/java.base/linux/native/libsimdsort/avx2-emu-funcs.hpp
--- 24.0.1+9-1/src/java.base/linux/native/libsimdsort/avx2-emu-funcs.hpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/linux/native/libsimdsort/avx2-emu-funcs.hpp	2025-06-27 08:03:14.000000000 +0000
@@ -127,9 +127,9 @@ void avx2_emu_mask_compressstoreu32(void
     T *leftStore = (T *)base_addr;
 
     int32_t shortMask = convert_avx2_mask_to_int(k);
-    const __m256i &perm = _mm256_loadu_si256(
+    const __m256i perm = _mm256_loadu_si256(
         (const __m256i *)avx2_compressstore_lut32_perm[shortMask].data());
-    const __m256i &left = _mm256_loadu_si256(
+    const __m256i left = _mm256_loadu_si256(
         (const __m256i *)avx2_compressstore_lut32_left[shortMask].data());
 
     typename vtype::reg_t temp = vtype::permutevar(reg, perm);
@@ -148,7 +148,7 @@ int avx2_double_compressstore32(void *le
     T *rightStore = (T *)right_addr;
 
     int32_t shortMask = convert_avx2_mask_to_int(k);
-    const __m256i &perm = _mm256_loadu_si256(
+    const __m256i perm = _mm256_loadu_si256(
         (const __m256i *)avx2_compressstore_lut32_perm[shortMask].data());
 
     typename vtype::reg_t temp = vtype::permutevar(reg, perm);
diff -pruN 24.0.1+9-1/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java 24.0.2+12-1/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
--- 24.0.1+9-1/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	2025-06-27 08:03:14.000000000 +0000
@@ -2077,7 +2077,8 @@ public class ForkJoinPool extends Abstra
         else if (deadline - System.currentTimeMillis() >= TIMEOUT_SLOP)
             stat = 0;                       // spurious wakeup
         else if (!compareAndSetCtl(
-                     c, nc = (w.stackPred & LMASK) | (UMASK & (c - TC_UNIT))))
+                     c, nc = ((w.stackPred & LMASK) | (RC_MASK & c) |
+                               (TC_MASK & (c - TC_UNIT)))))
             stat = -1;                      // lost race to signaller
         else {
             stat = 1;
diff -pruN 24.0.1+9-1/src/java.base/share/classes/java/util/jar/Attributes.java 24.0.2+12-1/src/java.base/share/classes/java/util/jar/Attributes.java
--- 24.0.1+9-1/src/java.base/share/classes/java/util/jar/Attributes.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/java/util/jar/Attributes.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -727,6 +727,7 @@ public class Attributes implements Map<O
                 addName(names, new Name("Created-By"));
                 addName(names, new Name("SHA1-Digest"));
                 addName(names, new Name("SHA-256-Digest"));
+                addName(names, new Name("SHA-384-Digest"));
                 KNOWN_NAMES = Map.copyOf(names);
             } else {
                 // Even if KNOWN_NAMES was read from archive, we still need
diff -pruN 24.0.1+9-1/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java 24.0.2+12-1/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java
--- 24.0.1+9-1/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -24,8 +24,6 @@
  */
 package sun.net.ftp.impl;
 
-
-
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
@@ -61,6 +59,7 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import javax.net.ssl.SSLSocket;
 import javax.net.ssl.SSLSocketFactory;
+
 import sun.net.ftp.FtpDirEntry;
 import sun.net.ftp.FtpDirParser;
 import sun.net.ftp.FtpProtocolException;
@@ -68,6 +67,7 @@ import sun.net.ftp.FtpReplyCode;
 import sun.net.util.IPAddressUtil;
 import sun.util.logging.PlatformLogger;
 
+import static sun.net.util.ProxyUtil.copyProxy;
 
 public class FtpClient extends sun.net.ftp.FtpClient {
 
@@ -954,7 +954,7 @@ public class FtpClient extends sun.net.f
     }
 
     public sun.net.ftp.FtpClient setProxy(Proxy p) {
-        proxy = p;
+        proxy = copyProxy(p);
         return this;
     }
 
@@ -2238,3 +2238,4 @@ public class FtpClient extends sun.net.f
         return this;
     }
 }
+
diff -pruN 24.0.1+9-1/src/java.base/share/classes/sun/net/util/ProxyUtil.java 24.0.2+12-1/src/java.base/share/classes/sun/net/util/ProxyUtil.java
--- 24.0.1+9-1/src/java.base/share/classes/sun/net/util/ProxyUtil.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/sun/net/util/ProxyUtil.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.net.util;
+
+import sun.net.ApplicationProxy;
+
+import java.net.Proxy;
+
+public final class ProxyUtil {
+
+    private ProxyUtil() {}
+
+    /**
+     * Creates a new {@link Proxy} instance for the given proxy iff it is
+     * neither null, {@link Proxy#NO_PROXY Proxy.NO_PROXY}, an
+     * {@link ApplicationProxy} instance, nor already a {@code Proxy} instance.
+     */
+    public static Proxy copyProxy(Proxy proxy) {
+        return proxy == null
+                || proxy.getClass() == Proxy.class
+                || proxy instanceof ApplicationProxy
+                ? proxy
+                : new Proxy(proxy.type(), proxy.address());
+    }
+
+}
diff -pruN 24.0.1+9-1/src/java.base/share/classes/sun/net/www/http/HttpClient.java 24.0.2+12-1/src/java.base/share/classes/sun/net/www/http/HttpClient.java
--- 24.0.1+9-1/src/java.base/share/classes/sun/net/www/http/HttpClient.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/sun/net/www/http/HttpClient.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -41,6 +41,8 @@ import sun.net.www.ParseUtil;
 import sun.net.www.protocol.http.AuthCacheImpl;
 import sun.net.www.protocol.http.HttpURLConnection;
 import sun.util.logging.PlatformLogger;
+
+import static sun.net.util.ProxyUtil.copyProxy;
 import static sun.net.www.protocol.http.HttpURLConnection.TunnelState.*;
 
 /**
@@ -261,7 +263,7 @@ public class HttpClient extends NetworkC
     }
 
     protected HttpClient(URL url, Proxy p, int to) throws IOException {
-        proxy = (p == null) ? Proxy.NO_PROXY : p;
+        proxy = p == null ? Proxy.NO_PROXY : copyProxy(p);
         this.host = url.getHost();
         this.url = url;
         port = url.getPort();
@@ -326,9 +328,7 @@ public class HttpClient extends NetworkC
     public static HttpClient New(URL url, Proxy p, int to, boolean useCache,
         HttpURLConnection httpuc) throws IOException
     {
-        if (p == null) {
-            p = Proxy.NO_PROXY;
-        }
+        p = p == null ? Proxy.NO_PROXY : copyProxy(p);
         HttpClient ret = null;
         /* see if one's already around */
         if (useCache) {
@@ -1142,3 +1142,4 @@ public class HttpClient extends NetworkC
         clientLock.unlock();
     }
 }
+
diff -pruN 24.0.1+9-1/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java 24.0.2+12-1/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java
--- 24.0.1+9-1/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -43,6 +43,7 @@ import java.net.ProxySelector;
 import java.util.List;
 import java.util.StringTokenizer;
 import java.security.Permission;
+
 import sun.net.NetworkClient;
 import sun.net.util.IPAddressUtil;
 import sun.net.www.MessageHeader;
@@ -53,6 +54,7 @@ import sun.net.ftp.FtpClient;
 import sun.net.ftp.FtpProtocolException;
 import sun.net.www.ParseUtil;
 
+import static sun.net.util.ProxyUtil.copyProxy;
 
 /**
  * This class Opens an FTP input (or output) stream given a URL.
@@ -234,7 +236,7 @@ public class FtpURLConnection extends UR
                     throw new IOException("Failed to select a proxy", iae);
                 }
                 for (Proxy proxy : proxies) {
-                    p = proxy;
+                    p = copyProxy(proxy);
                     if (p == null || p == Proxy.NO_PROXY ||
                         p.type() == Proxy.Type.SOCKS) {
                         break;
@@ -657,3 +659,4 @@ public class FtpURLConnection extends UR
         return readTimeout < 0 ? 0 : readTimeout;
     }
 }
+
diff -pruN 24.0.1+9-1/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java 24.0.2+12-1/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java
--- 24.0.1+9-1/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -33,11 +33,9 @@ import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.Proxy;
-import java.util.Map;
-import java.util.HashMap;
 import java.util.Objects;
-import sun.net.ftp.FtpClient;
-import sun.net.www.protocol.http.HttpURLConnection;
+
+import static sun.net.util.ProxyUtil.copyProxy;
 
 /** open an ftp connection given a URL */
 public class Handler extends java.net.URLStreamHandler {
@@ -57,11 +55,11 @@ public class Handler extends java.net.UR
         return openConnection(u, null);
     }
 
-    protected java.net.URLConnection openConnection(URL u, Proxy p)
+    protected java.net.URLConnection openConnection(URL u, Proxy proxy)
         throws IOException {
-        FtpURLConnection connection = null;
+        FtpURLConnection connection;
         try {
-            connection = new FtpURLConnection(u, p);
+            connection = new FtpURLConnection(u, copyProxy(proxy));
         } catch (IllegalArgumentException e) {
             var mfue = new MalformedURLException(e.getMessage());
             mfue.initCause(e);
@@ -70,3 +68,4 @@ public class Handler extends java.net.UR
         return connection;
     }
 }
+
diff -pruN 24.0.1+9-1/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java 24.0.2+12-1/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
--- 24.0.1+9-1/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -77,6 +77,7 @@ import java.nio.ByteBuffer;
 import java.util.Objects;
 import java.util.concurrent.locks.ReentrantLock;
 
+import static sun.net.util.ProxyUtil.copyProxy;
 import static sun.net.www.protocol.http.AuthScheme.BASIC;
 import static sun.net.www.protocol.http.AuthScheme.DIGEST;
 import static sun.net.www.protocol.http.AuthScheme.NTLM;
@@ -854,7 +855,7 @@ public class HttpURLConnection extends j
         responses = new MessageHeader(maxHeaderSize);
         userHeaders = new MessageHeader();
         this.handler = handler;
-        instProxy = p;
+        instProxy = copyProxy(p);
         cookieHandler = CookieHandler.getDefault();
         cacheHandler = ResponseCache.getDefault();
     }
@@ -956,7 +957,7 @@ public class HttpURLConnection extends j
                     final Iterator<Proxy> it = proxies.iterator();
                     Proxy p;
                     while (it.hasNext()) {
-                        p = it.next();
+                        p = copyProxy(it.next());
                         try {
                             if (!failedOnce) {
                                 http = getNewHttpClient(url, p, connectTimeout);
@@ -3679,3 +3680,4 @@ class EmptyInputStream extends InputStre
         return -1;
     }
 }
+
diff -pruN 24.0.1+9-1/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java 24.0.2+12-1/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java
--- 24.0.1+9-1/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -1137,6 +1137,15 @@ final class CertificateMessage {
 
             // clean up this consumer
             hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE.id);
+
+            // Ensure that the Certificate message has not been sent w/o
+            // an EncryptedExtensions preceding
+            if (hc.handshakeConsumers.containsKey(
+                    SSLHandshake.ENCRYPTED_EXTENSIONS.id)) {
+                throw hc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
+                                           "Unexpected Certificate handshake message");
+            }
+
             T13CertificateMessage cm = new T13CertificateMessage(hc, message);
             if (hc.sslConfig.isClientMode) {
                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
diff -pruN 24.0.1+9-1/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java 24.0.2+12-1/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java
--- 24.0.1+9-1/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -1163,6 +1163,14 @@ final class CertificateVerify {
             // Clean up this consumer
             hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id);
 
+            // Ensure that the Certificate Verify message has not been sent w/o
+            // a Certificate message preceding
+            if (hc.handshakeConsumers.containsKey(
+                    SSLHandshake.CERTIFICATE.id)) {
+                throw hc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
+                                  "Unexpected Certificate Verify handshake message");
+            }
+
             T13CertificateVerifyMessage cvm =
                     new T13CertificateVerifyMessage(hc, message);
             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
diff -pruN 24.0.1+9-1/src/java.base/share/classes/sun/security/ssl/Finished.java 24.0.2+12-1/src/java.base/share/classes/sun/security/ssl/Finished.java
--- 24.0.1+9-1/src/java.base/share/classes/sun/security/ssl/Finished.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/sun/security/ssl/Finished.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -900,6 +900,14 @@ final class Finished {
 
         private void onConsumeFinished(ClientHandshakeContext chc,
                 ByteBuffer message) throws IOException {
+            // Ensure that the Finished message has not been sent w/o
+            // an EncryptedExtensions preceding
+            if (chc.handshakeConsumers.containsKey(
+                    SSLHandshake.ENCRYPTED_EXTENSIONS.id)) {
+                throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
+                                           "Unexpected Finished handshake message");
+            }
+
             // Make sure that any expected CertificateVerify message
             // has been received and processed.
             if (!chc.isResumption) {
diff -pruN 24.0.1+9-1/src/java.base/share/classes/sun/security/tools/keytool/Resources_de.java 24.0.2+12-1/src/java.base/share/classes/sun/security/tools/keytool/Resources_de.java
--- 24.0.1+9-1/src/java.base/share/classes/sun/security/tools/keytool/Resources_de.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/sun/security/tools/keytool/Resources_de.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2022, 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
@@ -304,10 +304,12 @@ public class Resources_de extends java.u
                 "Das Angeben von -keysize zum Generieren von EC-Schl\u00FCsseln ist veraltet. Verwenden Sie stattdessen \"-groupname %s\"."},
         {"Key.pair.not.generated.alias.alias.already.exists",
                 "Schl\u00FCsselpaar wurde nicht generiert. Alias <{0}> ist bereits vorhanden"},
-        {"Generating.keysize.bit.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.validality.days.for",
-                "Generieren von Schl\u00FCsselpaar (Typ {1}, {0} Bit) und selbst signiertem Zertifikat ({2}) mit einer G\u00FCltigkeit von {3} Tagen\n\tf\u00FCr: {4}"},
-        {"Generating.keysize.bit.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.validality.days.for",
-                "Generieren von Schl\u00FCsselpaar (Typ {1}, {0} Bit) und Zertifikat ({2}), ausgestellt von <{3}>, mit einer G\u00FCltigkeit von {4} Tagen\n\tf\u00FCr: {5}"},
+        {"size.bit.alg",
+                "%1$d-Bit %2$s"},
+        {"Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for",
+                "Schl\u00FCsselpaar {0} und selbstsigniertes Zertifikat ({1}) werden mit einer G\u00FCltigkeit von {2} Tagen generiert\n\tf\u00FCr: {3}"},
+        {"Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for",
+                "Schl\u00FCsselpaar {0} und Zertifikat ({1}) werden generiert, das von <{2}> mit einer G\u00FCltigkeit von {3} Tagen ausgestellt wurde\n\tf\u00FCr: {4}"},
         {"Enter.key.password.for.alias.", "Schl\u00FCsselkennwort f\u00FCr <{0}> eingeben"},
         {".RETURN.if.same.as.keystore.password.",
                 "\t(RETURN, wenn identisch mit Keystore-Kennwort):  "},
@@ -472,10 +474,9 @@ public class Resources_de extends java.u
         {"alias.in.keystore", "Aussteller <%s>"},
         {"with.weak", "%s (schwach)"},
         {"with.disabled", "%s (deaktiviert)"},
-        {"key.bit", "%1$d-Bit-%2$s-Schl\u00FCssel"},
-        {"key.bit.weak", "%1$d-Bit-%2$s-Schl\u00FCssel (schwach)"},
-        {"key.bit.disabled", "%1$d-Bit-%2$s-Schl\u00FCssel (deaktiviert)"},
-        {"unknown.size.1", "%s-Schl\u00FCssel mit unbekannter Gr\u00F6\u00DFe"},
+        {"key.bit", "%s-Schl\u00FCssel"},
+        {"key.bit.weak", "%s Schl\u00FCssel (schwach)"},
+        {"key.bit.disabled", "%s Schl\u00FCssel (deaktiviert)"},
         {".PATTERN.printX509Cert.with.weak",
                 "Eigent\u00FCmer: {0}\nAussteller: {1}\nSeriennummer: {2}\nG\u00FCltig von: {3} bis: {4}\nZertifikatsfingerprints:\n\t SHA1: {5}\n\t SHA256: {6}\nSignaturalgorithmusname: {7}\nPublic-Key-Algorithmus von Subject: {8}\nVersion: {9}"},
         {"PKCS.10.with.weak",
@@ -486,7 +487,7 @@ public class Resources_de extends java.u
         {"Unable.to.parse.denyAfter.string.in.exception.message", "denyAfter-Datumszeichenfolge in Ausnahmemeldung kann nicht geparst werden"},
         {"whose.sigalg.weak", "%1$s verwendet den Signaturalgorithmus %2$s. Dies gilt als Sicherheitsrisiko."},
         {"whose.key.disabled", "%1$s verwendet %2$s. Dies gilt als Sicherheitsrisiko und ist deaktiviert."},
-        {"whose.key.weak", "%1$s verwendet %2$s. Dies gilt als Sicherheitsrisiko. Diese Schl\u00FCsselgr\u00F6\u00DFe wird in einem zuk\u00FCnftigen Update deaktiviert."},
+        {"whose.key.weak", "%1$s verwendet %2$s. Dies gilt als Sicherheitsrisiko. Wird in einem zuk\u00FCnftigen Update deaktiviert."},
         {"jks.storetype.warning", "Der %1$s-Keystore verwendet ein propriet\u00E4res Format. Es wird empfohlen, auf PKCS12 zu migrieren, das ein Industriestandardformat mit \"keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12\" ist."},
         {"migrate.keystore.warning", "\"%1$s\" zu %4$s migriert. Der %2$s-Keystore wurde als \"%3$s\" gesichert."},
         {"backup.keystore.warning", "Der urspr\u00FCngliche Keystore \"%1$s\" wird als \"%3$s\" gesichert..."},
diff -pruN 24.0.1+9-1/src/java.base/share/classes/sun/security/tools/keytool/Resources_ja.java 24.0.2+12-1/src/java.base/share/classes/sun/security/tools/keytool/Resources_ja.java
--- 24.0.1+9-1/src/java.base/share/classes/sun/security/tools/keytool/Resources_ja.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/sun/security/tools/keytool/Resources_ja.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2022, 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
@@ -304,10 +304,12 @@ public class Resources_ja extends java.u
                 "-keysize\u306E\u6307\u5B9A\u306B\u3088\u308BEC\u30AD\u30FC\u306E\u751F\u6210\u306F\u975E\u63A8\u5968\u3067\u3059\u3002\u304B\u308F\u308A\u306B\"-groupname %s\"\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002"},
         {"Key.pair.not.generated.alias.alias.already.exists",
                 "\u30AD\u30FC\u30FB\u30DA\u30A2\u306F\u751F\u6210\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u5225\u540D<{0}>\u306F\u3059\u3067\u306B\u5B58\u5728\u3057\u307E\u3059"},
-        {"Generating.keysize.bit.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.validality.days.for",
-                "{3}\u65E5\u9593\u6709\u52B9\u306A{0}\u30D3\u30C3\u30C8\u306E{1}\u306E\u30AD\u30FC\u30FB\u30DA\u30A2\u3068\u81EA\u5DF1\u7F72\u540D\u578B\u8A3C\u660E\u66F8({2})\u3092\u751F\u6210\u3057\u3066\u3044\u307E\u3059\n\t\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u540D: {4}"},
-        {"Generating.keysize.bit.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.validality.days.for",
-                "{4}\u65E5\u9593\u6709\u52B9\u306A{0}\u30D3\u30C3\u30C8\u306E{1}\u30AD\u30FC\u30FB\u30DA\u30A2\u3068<{3}>\u306B\u3088\u3063\u3066\u767A\u884C\u3055\u308C\u308B\u8A3C\u660E\u66F8({2})\u3092\u751F\u6210\u3057\u3066\u3044\u307E\u3059\n\t\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u540D: {5}"},
+        {"size.bit.alg",
+                "%1$d\u30D3\u30C3\u30C8%2$s"},
+        {"Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for",
+                "{0}\u30AD\u30FC\u30FB\u30DA\u30A2\u304A\u3088\u3073\u81EA\u5DF1\u7F72\u540D\u8A3C\u660E\u66F8({1})\u3092{2}\u65E5\u306E\u6709\u52B9\u6027\u3067\u751F\u6210\u3057\u3066\u3044\u307E\u3059\n\t\u5BFE\u8C61: {3}"},
+        {"Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for",
+                "{0}\u30AD\u30FC\u30FB\u30DA\u30A2\u3068\u003C\u007B\u0032\u007D\u003E\u306B\u3088\u3063\u3066\u767A\u884C\u3055\u308C\u305F\u8A3C\u660E\u66F8({1})\u3092{3}\u65E5\u9593\u306E\u6709\u52B9\u6027\u3067\u751F\u6210\u3057\u3066\u3044\u307E\u3059\n\t\u5BFE\u8C61: {4}"},
         {"Enter.key.password.for.alias.", "<{0}>\u306E\u30AD\u30FC\u30FB\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044"},
         {".RETURN.if.same.as.keystore.password.",
                 "\t(\u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u3068\u540C\u3058\u5834\u5408\u306FRETURN\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044):  "},
@@ -472,10 +474,9 @@ public class Resources_ja extends java.u
         {"alias.in.keystore", "\u767A\u884C\u8005<%s>"},
         {"with.weak", "%s (\u5F31)"},
         {"with.disabled", "%s (\u7121\u52B9)"},
-        {"key.bit", "%1$d\u30D3\u30C3\u30C8%2$s\u30AD\u30FC"},
-        {"key.bit.weak", "%1$d\u30D3\u30C3\u30C8%2$s\u30AD\u30FC(\u5F31)"},
-        {"key.bit.disabled", "%1$d-bit %2$s key (\u7121\u52B9)"},
-        {"unknown.size.1", "\u4E0D\u660E\u306A\u30B5\u30A4\u30BA\u306E%s\u30AD\u30FC"},
+        {"key.bit", "%s\u30AD\u30FC"},
+        {"key.bit.weak", "%s\u30AD\u30FC(\u5F31\u3044)"},
+        {"key.bit.disabled", "%s\u30AD\u30FC(\u7121\u52B9)"},
         {".PATTERN.printX509Cert.with.weak",
                 "\u6240\u6709\u8005: {0}\n\u767A\u884C\u8005: {1}\n\u30B7\u30EA\u30A2\u30EB\u756A\u53F7: {2}\n\u6709\u52B9\u671F\u9593\u306E\u958B\u59CB\u65E5: {3}\u7D42\u4E86\u65E5: {4}\n\u8A3C\u660E\u66F8\u306E\u30D5\u30A3\u30F3\u30AC\u30D7\u30EA\u30F3\u30C8:\n\t SHA1: {5}\n\t SHA256: {6}\n\u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u540D: {7}\n\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\u516C\u958B\u30AD\u30FC\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: {8}\n\u30D0\u30FC\u30B8\u30E7\u30F3: {9}"},
         {"PKCS.10.with.weak",
@@ -486,7 +487,7 @@ public class Resources_ja extends java.u
         {"Unable.to.parse.denyAfter.string.in.exception.message", "\u4F8B\u5916\u30E1\u30C3\u30BB\u30FC\u30B8\u306EdenyAfter\u65E5\u4ED8\u6587\u5B57\u5217\u3092\u89E3\u6790\u3067\u304D\u307E\u305B\u3093"},
         {"whose.sigalg.weak", "%1$s\u306F%2$s\u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u3092\u4F7F\u7528\u3057\u3066\u304A\u308A\u3001\u3053\u308C\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u307E\u3059\u3002"},
         {"whose.key.disabled", "%1$s\u306F%2$s\u3092\u4F7F\u7528\u3057\u3066\u304A\u308A\u3001\u3053\u308C\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u3001\u7121\u52B9\u5316\u3055\u308C\u3066\u3044\u307E\u3059\u3002"},
-        {"whose.key.weak", "%1$s\u306F%2$s\u3092\u4F7F\u7528\u3057\u3066\u304A\u308A\u3001\u3053\u308C\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u307E\u3059\u3002\u3053\u306E\u30AD\u30FC\u30FB\u30B5\u30A4\u30BA\u306F\u5C06\u6765\u306E\u66F4\u65B0\u3067\u7121\u52B9\u5316\u3055\u308C\u307E\u3059\u3002"},
+        {"whose.key.weak", "%1$s\u306F%2$s\u3092\u4F7F\u7528\u3057\u3066\u304A\u308A\u3001\u3053\u308C\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u307E\u3059\u3002\u4ECA\u5F8C\u306E\u66F4\u65B0\u3067\u306F\u7121\u52B9\u306B\u306A\u308A\u307E\u3059\u3002"},
         {"jks.storetype.warning", "%1$s\u30AD\u30FC\u30B9\u30C8\u30A2\u306F\u72EC\u81EA\u306E\u5F62\u5F0F\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002\"keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12\"\u3092\u4F7F\u7528\u3059\u308B\u696D\u754C\u6A19\u6E96\u306E\u5F62\u5F0F\u3067\u3042\u308BPKCS12\u306B\u79FB\u884C\u3059\u308B\u3053\u3068\u3092\u304A\u85A6\u3081\u3057\u307E\u3059\u3002"},
         {"migrate.keystore.warning", "\"%1$s\"\u304C%4$s\u306B\u79FB\u884C\u3055\u308C\u307E\u3057\u305F\u3002%2$s\u30AD\u30FC\u30B9\u30C8\u30A2\u306F\"%3$s\"\u3068\u3057\u3066\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u3055\u308C\u307E\u3059\u3002"},
         {"backup.keystore.warning", "\u5143\u306E\u30AD\u30FC\u30B9\u30C8\u30A2\"%1$s\"\u306F\"%3$s\"\u3068\u3057\u3066\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u3055\u308C\u307E\u3059..."},
diff -pruN 24.0.1+9-1/src/java.base/share/classes/sun/security/tools/keytool/Resources_zh_CN.java 24.0.2+12-1/src/java.base/share/classes/sun/security/tools/keytool/Resources_zh_CN.java
--- 24.0.1+9-1/src/java.base/share/classes/sun/security/tools/keytool/Resources_zh_CN.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/sun/security/tools/keytool/Resources_zh_CN.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2022, 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
@@ -304,10 +304,12 @@ public class Resources_zh_CN extends jav
                 "\u4E3A\u751F\u6210 EC \u5BC6\u94A5\u6307\u5B9A -keysize \u5DF2\u8FC7\u65F6\uFF0C\u8BF7\u6539\u4E3A\u4F7F\u7528 \"-groupname %s\"\u3002"},
         {"Key.pair.not.generated.alias.alias.already.exists",
                 "\u672A\u751F\u6210\u5BC6\u94A5\u5BF9, \u522B\u540D <{0}> \u5DF2\u7ECF\u5B58\u5728"},
-        {"Generating.keysize.bit.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.validality.days.for",
-                "\u6B63\u5728\u4E3A\u4EE5\u4E0B\u5BF9\u8C61\u751F\u6210 {0} \u4F4D{1}\u5BC6\u94A5\u5BF9\u548C\u81EA\u7B7E\u540D\u8BC1\u4E66 ({2}) (\u6709\u6548\u671F\u4E3A {3} \u5929):\n\t {4}"},
-        {"Generating.keysize.bit.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.validality.days.for",
-                "\u6B63\u5728\u4E3A\u4EE5\u4E0B\u5BF9\u8C61\u751F\u6210 {0} \u4F4D {1} \u5BC6\u94A5\u5BF9\u548C\u7531 <{3}> \u9881\u53D1\u7684\u8BC1\u4E66 ({2})\uFF08\u6709\u6548\u671F\u4E3A {4} \u5929\uFF09\uFF1A\n\t {5}"},
+        {"size.bit.alg",
+                "%1$d \u4F4D %2$s"},
+        {"Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for",
+                "\u6B63\u5728\u4E3A {3} \u751F\u6210\u6709\u6548\u671F\u4E3A {2} \u5929\u7684 {0} \u5BC6\u94A5\u5BF9\u548C\u81EA\u7B7E\u540D\u8BC1\u4E66 ({1})\n"},
+        {"Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for",
+                "\u751F\u6210 {0} \u5BC6\u94A5\u5BF9\u548C <{2}> \u9881\u53D1\u7684\u8BC1\u4E66 ({1})\uFF0C\u6709\u6548\u671F\u4E3A {3} \u5929 \n\t \u5BF9\u4E8E\uFF1A{4}"},
         {"Enter.key.password.for.alias.", "\u8F93\u5165 <{0}> \u7684\u5BC6\u94A5\u53E3\u4EE4"},
         {".RETURN.if.same.as.keystore.password.",
                 "\t(\u5982\u679C\u548C\u5BC6\u94A5\u5E93\u53E3\u4EE4\u76F8\u540C, \u6309\u56DE\u8F66):  "},
@@ -472,10 +474,9 @@ public class Resources_zh_CN extends jav
         {"alias.in.keystore", "\u53D1\u5E03\u8005 <%s>"},
         {"with.weak", "%s (\u5F31)"},
         {"with.disabled", "%s\uFF08\u7981\u7528\uFF09"},
-        {"key.bit", "%1$d \u4F4D %2$s \u5BC6\u94A5"},
-        {"key.bit.weak", "%1$d \u4F4D %2$s \u5BC6\u94A5 (\u5F31)"},
-        {"key.bit.disabled", "%1$d \u4F4D %2$s \u5BC6\u94A5\uFF08\u7981\u7528\uFF09"},
-        {"unknown.size.1", "\u672A\u77E5\u5927\u5C0F\u7684 %s \u5BC6\u94A5"},
+        {"key.bit", "%s \u5BC6\u94A5"},
+        {"key.bit.weak", "%s \u5BC6\u94A5\uFF08\u5F31\uFF09"},
+        {"key.bit.disabled", "%s \u5BC6\u94A5\uFF08\u5DF2\u7981\u7528\uFF09"},
         {".PATTERN.printX509Cert.with.weak",
                 "\u6240\u6709\u8005: {0}\n\u53D1\u5E03\u8005: {1}\n\u5E8F\u5217\u53F7: {2}\n\u751F\u6548\u65F6\u95F4: {3}, \u5931\u6548\u65F6\u95F4: {4}\n\u8BC1\u4E66\u6307\u7EB9:\n\t SHA1: {5}\n\t SHA256: {6}\n\u7B7E\u540D\u7B97\u6CD5\u540D\u79F0: {7}\n\u4E3B\u4F53\u516C\u5171\u5BC6\u94A5\u7B97\u6CD5: {8}\n\u7248\u672C: {9}"},
         {"PKCS.10.with.weak",
@@ -486,7 +487,7 @@ public class Resources_zh_CN extends jav
         {"Unable.to.parse.denyAfter.string.in.exception.message", "\u65E0\u6CD5\u89E3\u6790\u5F02\u5E38\u9519\u8BEF\u6D88\u606F\u4E2D\u7684 denyAfter \u65E5\u671F\u5B57\u7B26\u4E32"},
         {"whose.sigalg.weak", "%1$s \u4F7F\u7528\u7684 %2$s \u7B7E\u540D\u7B97\u6CD5\u5B58\u5728\u5B89\u5168\u98CE\u9669\u3002"},
         {"whose.key.disabled", "%1$s \u4F7F\u7528\u7684 %2$s \u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\u800C\u4E14\u88AB\u7981\u7528\u3002"},
-        {"whose.key.weak", "%1$s \u4F7F\u7528\u7684 %2$s \u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\u3002\u6B64\u5BC6\u94A5\u5927\u5C0F\u5C06\u5728\u672A\u6765\u7684\u66F4\u65B0\u4E2D\u88AB\u7981\u7528\u3002"},
+        {"whose.key.weak", "%1$s \u4F7F\u7528\u7684 %2$s \u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\u3002\u5728\u5C06\u6765\u7684\u66F4\u65B0\u4E2D\u5C06\u7981\u7528\u5B83\u3002"},
         {"jks.storetype.warning", "%1$s \u5BC6\u94A5\u5E93\u4F7F\u7528\u4E13\u7528\u683C\u5F0F\u3002\u5EFA\u8BAE\u4F7F\u7528 \"keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12\" \u8FC1\u79FB\u5230\u884C\u4E1A\u6807\u51C6\u683C\u5F0F PKCS12\u3002"},
         {"migrate.keystore.warning", "\u5DF2\u5C06 \"%1$s\" \u8FC1\u79FB\u5230 %4$s\u3002\u5C06 %2$s \u5BC6\u94A5\u5E93\u4F5C\u4E3A \"%3$s\" \u8FDB\u884C\u4E86\u5907\u4EFD\u3002"},
         {"backup.keystore.warning", "\u5DF2\u5C06\u539F\u59CB\u5BC6\u94A5\u5E93 \"%1$s\" \u5907\u4EFD\u4E3A \"%3$s\"..."},
diff -pruN 24.0.1+9-1/src/java.base/share/classes/sun/security/validator/CamerfirmaTLSPolicy.java 24.0.2+12-1/src/java.base/share/classes/sun/security/validator/CamerfirmaTLSPolicy.java
--- 24.0.1+9-1/src/java.base/share/classes/sun/security/validator/CamerfirmaTLSPolicy.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/sun/security/validator/CamerfirmaTLSPolicy.java	2025-06-27 08:03:14.000000000 +0000
@@ -43,26 +43,14 @@ final class CamerfirmaTLSPolicy {
 
     private static final Debug debug = Debug.getInstance("certpath");
 
-    // SHA-256 certificate fingerprints of distrusted roots
-    private static final Set<String> FINGERPRINTS = Set.of(
-        // cacerts alias: camerfirmachamberscommerceca
-        // DN: CN=Chambers of Commerce Root,
-        //     OU=http://www.chambersign.org,
-        //     O=AC Camerfirma SA CIF A82743287, C=EU
-        "0C258A12A5674AEF25F28BA7DCFAECEEA348E541E6F5CC4EE63B71B361606AC3",
-        // cacerts alias: camerfirmachambersca
-        // DN: CN=Chambers of Commerce Root - 2008,
-        //     O=AC Camerfirma S.A., SERIALNUMBER=A82743287,
-        //     L=Madrid (see current address at www.camerfirma.com/address),
-        //     C=EU
-        "063E4AFAC491DFD332F3089B8542E94617D893D7FE944E10A7937EE29D9693C0",
-        // cacerts alias: camerfirmachambersignca
-        // DN: CN=Global Chambersign Root - 2008,
-        //     O=AC Camerfirma S.A., SERIALNUMBER=A82743287,
-        //     L=Madrid (see current address at www.camerfirma.com/address),
-        //     C=EU
-        "136335439334A7698016A0D324DE72284E079D7B5220BB8FBD747816EEBEBACA"
-    );
+    // SHA-256 certificate fingerprint of distrusted root for TLS
+    // cacerts alias: camerfirmachambersca
+    // DN: CN=Chambers of Commerce Root - 2008,
+    //     O=AC Camerfirma S.A., SERIALNUMBER=A82743287,
+    //     L=Madrid (see current address at www.camerfirma.com/address),
+    //     C=EU
+    private static final String FINGERPRINT =
+            "063E4AFAC491DFD332F3089B8542E94617D893D7FE944E10A7937EE29D9693C0";
 
     // Any TLS Server certificate that is anchored by one of the Camerfirma
     // roots above and is issued after this date will be distrusted.
@@ -85,7 +73,7 @@ final class CamerfirmaTLSPolicy {
             throw new ValidatorException("Cannot generate fingerprint for "
                 + "trust anchor of TLS server certificate");
         }
-        if (FINGERPRINTS.contains(fp)) {
+        if (FINGERPRINT.equalsIgnoreCase(fp)) {
             Date notBefore = chain[0].getNotBefore();
             LocalDate ldNotBefore = LocalDate.ofInstant(notBefore.toInstant(),
                                                         ZoneOffset.UTC);
diff -pruN 24.0.1+9-1/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties 24.0.2+12-1/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties
--- 24.0.1+9-1/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties	2025-06-27 08:03:14.000000000 +0000
@@ -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 -pruN 24.0.1+9-1/src/java.base/share/data/cacerts/baltimorecybertrustca 24.0.2+12-1/src/java.base/share/data/cacerts/baltimorecybertrustca
--- 24.0.1+9-1/src/java.base/share/data/cacerts/baltimorecybertrustca	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/data/cacerts/baltimorecybertrustca	1970-01-01 00:00:00.000000000 +0000
@@ -1,28 +0,0 @@
-Owner: CN=Baltimore CyberTrust Root, OU=CyberTrust, O=Baltimore, C=IE
-Issuer: CN=Baltimore CyberTrust Root, OU=CyberTrust, O=Baltimore, C=IE
-Serial number: 20000b9
-Valid from: Fri May 12 18:46:00 GMT 2000 until: Mon May 12 23:59:00 GMT 2025
-Signature algorithm name: SHA1withRSA
-Subject Public Key Algorithm: 2048-bit RSA key
-Version: 3
------BEGIN CERTIFICATE-----
-MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
-RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
-VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
-DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
-ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
-VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
-mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
-IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
-mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
-XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
-dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
-jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
-BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
-DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
-9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
-jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
-Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
-ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
-R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
------END CERTIFICATE-----
diff -pruN 24.0.1+9-1/src/java.base/share/data/cacerts/camerfirmachamberscommerceca 24.0.2+12-1/src/java.base/share/data/cacerts/camerfirmachamberscommerceca
--- 24.0.1+9-1/src/java.base/share/data/cacerts/camerfirmachamberscommerceca	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/data/cacerts/camerfirmachamberscommerceca	1970-01-01 00:00:00.000000000 +0000
@@ -1,35 +0,0 @@
-Owner: CN=Chambers of Commerce Root, OU=http://www.chambersign.org, O=AC Camerfirma SA CIF A82743287, C=EU
-Issuer: CN=Chambers of Commerce Root, OU=http://www.chambersign.org, O=AC Camerfirma SA CIF A82743287, C=EU
-Serial number: 0
-Valid from: Tue Sep 30 16:13:43 GMT 2003 until: Wed Sep 30 16:13:44 GMT 2037
-Signature algorithm name: SHA1withRSA
-Subject Public Key Algorithm: 2048-bit RSA key
-Version: 3
------BEGIN CERTIFICATE-----
-MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn
-MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL
-ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg
-b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa
-MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB
-ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw
-IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B
-AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb
-unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d
-BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq
-7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3
-0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX
-roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG
-A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j
-aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p
-26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA
-BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud
-EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN
-BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz
-aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB
-AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd
-p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi
-1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc
-XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0
-eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu
-tGWaIZDgqtCYvDi1czyL+Nw=
------END CERTIFICATE-----
diff -pruN 24.0.1+9-1/src/java.base/share/data/cacerts/camerfirmachambersignca 24.0.2+12-1/src/java.base/share/data/cacerts/camerfirmachambersignca
--- 24.0.1+9-1/src/java.base/share/data/cacerts/camerfirmachambersignca	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/data/cacerts/camerfirmachambersignca	1970-01-01 00:00:00.000000000 +0000
@@ -1,48 +0,0 @@
-Owner: CN=Global Chambersign Root - 2008, O=AC Camerfirma S.A., SERIALNUMBER=A82743287, L=Madrid (see current address at www.camerfirma.com/address), C=EU
-Issuer: CN=Global Chambersign Root - 2008, O=AC Camerfirma S.A., SERIALNUMBER=A82743287, L=Madrid (see current address at www.camerfirma.com/address), C=EU
-Serial number: c9cdd3e9d57d23ce
-Valid from: Fri Aug 01 12:31:40 GMT 2008 until: Sat Jul 31 12:31:40 GMT 2038
-Signature algorithm name: SHA1withRSA
-Subject Public Key Algorithm: 4096-bit RSA key
-Version: 3
------BEGIN CERTIFICATE-----
-MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD
-VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0
-IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3
-MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
-aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx
-MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy
-cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG
-A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl
-BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI
-hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed
-KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7
-G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2
-zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4
-ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG
-HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2
-Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V
-yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e
-beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r
-6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
-wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog
-zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW
-BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr
-ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp
-ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk
-cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt
-YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC
-CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow
-KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI
-hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ
-UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz
-X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x
-fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz
-a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd
-Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd
-SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O
-AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso
-M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge
-v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
-09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
------END CERTIFICATE-----
diff -pruN 24.0.1+9-1/src/java.base/share/data/cacerts/sectigocodesignroote46 24.0.2+12-1/src/java.base/share/data/cacerts/sectigocodesignroote46
--- 24.0.1+9-1/src/java.base/share/data/cacerts/sectigocodesignroote46	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/data/cacerts/sectigocodesignroote46	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,21 @@
+Owner: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB
+Issuer: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB
+Serial number: 50249ba2ef8ea6bf6c2c1f1a6385d4c3
+Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
+Signature algorithm name: SHA384withECDSA
+Subject Public Key Algorithm: 384-bit EC (secp384r1) key
+Version: 3
+-----BEGIN CERTIFICATE-----
+MIICKDCCAa+gAwIBAgIQUCSbou+Opr9sLB8aY4XUwzAKBggqhkjOPQQDAzBWMQsw
+CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRT
+ZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBFNDYwHhcNMjEwMzIyMDAw
+MDAwWhcNNDYwMzIxMjM1OTU5WjBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2Vj
+dGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25p
+bmcgUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQIMoEDH487om+BR4zl
+e7m6wWmyW0nAKLkUWG8kM85Qm3PZO8FoOZx6Yc5c0iJHRKuAhanllayqrmZYhlan
+uIODzLTRDqlR+EtnOX+MubY5aDSPGUq6jiHrQrisVp0J3AejQjBAMB0GA1UdDgQW
+BBTPfSygkHqYHd22XoXC4NoVcdLlXjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/
+BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjACd++zAerlV83j8HflRwwwlLmgchbs
+aGX/4g44dv/oG8KfzCVTRg6sZHMobtK0IqYCMGk5W6+oBFyZMtOebrSwXs8lGjll
+/zHz43Zy8DMXO+iiqzSEwWGneZ6KupkGGqfVKw==
+-----END CERTIFICATE-----
diff -pruN 24.0.1+9-1/src/java.base/share/data/cacerts/sectigocodesignrootr46 24.0.2+12-1/src/java.base/share/data/cacerts/sectigocodesignrootr46
--- 24.0.1+9-1/src/java.base/share/data/cacerts/sectigocodesignrootr46	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/data/cacerts/sectigocodesignrootr46	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,39 @@
+Owner: CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB
+Issuer: CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB
+Serial number: 4b2c3b01018bad2abc8c7b5b3eed9057
+Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
+Signature algorithm name: SHA384withRSA
+Subject Public Key Algorithm: 4096-bit RSA key
+Version: 3
+-----BEGIN CERTIFICATE-----
+MIIFeDCCA2CgAwIBAgIQSyw7AQGLrSq8jHtbPu2QVzANBgkqhkiG9w0BAQwFADBW
+MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQD
+EyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwHhcNMjEwMzIy
+MDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMP
+U2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNp
+Z25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCN
+55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+shJHjUoq14pbe0IdjJImK
+/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCDJ9qaDStQ6Utbs7hkNqR+
+Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7P2bSlDFp+m2zNKzBenjc
+klDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extmeme/G3h+pDHazJyCh1rr9
+gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUzT2MuuC3hv2WnBGsY2HH6
+zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6qRT5uWl+PoVvLnTCGMOgD
+s0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mczmrYI4IAFSEDu9oJkRqj1
+c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEcQNYWFyn8XJwYK+pF9e+9
+1WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2TOglmmVhcKaO5DKYwODzQ
+RjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/AZwQsRb8zG4Y3G9i/qZQ
+p7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QIDAQABo0IwQDAdBgNVHQ4E
+FgQUMuuSmv81lkgvKEBCcCA2kVwXheYwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAHZlwuPXIkrXHYle/2lexhQCTXOm
+zc0oyrA36r+nySGqql/av/aDbNCA0QpcAKTL88w5D55BcYjVPOiKe4wXI/fKNHSR
+bAauUD8AWbImPDwXg1cDPi3RGj3UzwdUskMLUnKoiPXEF/Jv0Vil0WjkPZgIGO42
+9EhImvpUcPCI1HAWMEJJ0Nk/dUtFcdiuorthDoiFUFe5uhErNikfjyBynlyeidGC
+2kWNapnahHFrM6UQu3nwl/Z0gaA/V8eGjDCMDjiVrgHGHqvcqB9vL9f/dh6uF3Nt
+5bl1s2EGqJUzwk5vsjfylb6FVBK5yL1iQnb3Kvz1NzEDJlf+0ebb8BYCcoOMCLOE
+rKnkB/ihiMQTWlBHVEKm7dBBNCyYsT6iNKEMXb2s9395p79tDFYyhRtLl7jhrOSk
+PHHxo+FOY9b0Rrr1CwjhYzztolkvCtQsayOinqFN7tESzRgzUO1Bbst/PUFgC2ML
+ePV170MVtzYLEK/cXBipmNk22R3YhLMGioLjexskp0LO7g8+VlwyfexL3lYrOzu6
++XpY0FG2bNb2WKJSJHpEhqEcYD9J0/z6+YQcBcI0v+Lm8RkqmS9WVzWctfUHw0Yv
+3jg9GQ37o/HfE57nqXJYMa+96trX1m13MzOO9Kz9wb9Jh9JwBWd0Bqb2eEAtFgSR
+Dx/TFsS4ehcNJMmy
+-----END CERTIFICATE-----
diff -pruN 24.0.1+9-1/src/java.base/share/data/cacerts/sectigotlsroote46 24.0.2+12-1/src/java.base/share/data/cacerts/sectigotlsroote46
--- 24.0.1+9-1/src/java.base/share/data/cacerts/sectigotlsroote46	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/data/cacerts/sectigotlsroote46	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,21 @@
+Owner: CN=Sectigo Public Server Authentication Root E46, O=Sectigo Limited, C=GB
+Issuer: CN=Sectigo Public Server Authentication Root E46, O=Sectigo Limited, C=GB
+Serial number: 42f2ccda1b6937445f15fe752810b8f4
+Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
+Signature algorithm name: SHA384withECDSA
+Subject Public Key Algorithm: 384-bit EC (secp384r1) key
+Version: 3
+-----BEGIN CERTIFICATE-----
+MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw
+CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T
+ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN
+MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG
+A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT
+ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC
+WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+
+6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B
+Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa
+qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q
+4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw==
+-----END CERTIFICATE-----
diff -pruN 24.0.1+9-1/src/java.base/share/data/cacerts/sectigotlsrootr46 24.0.2+12-1/src/java.base/share/data/cacerts/sectigotlsrootr46
--- 24.0.1+9-1/src/java.base/share/data/cacerts/sectigotlsrootr46	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/data/cacerts/sectigotlsrootr46	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,39 @@
+Owner: CN=Sectigo Public Server Authentication Root R46, O=Sectigo Limited, C=GB
+Issuer: CN=Sectigo Public Server Authentication Root R46, O=Sectigo Limited, C=GB
+Serial number: 758dfd8bae7c0700faa925a7e1c7ad14
+Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
+Signature algorithm name: SHA384withRSA
+Subject Public Key Algorithm: 4096-bit RSA key
+Version: 3
+-----BEGIN CERTIFICATE-----
+MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf
+MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD
+Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw
+HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY
+MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp
+YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa
+ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz
+SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf
+iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X
+ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3
+IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS
+VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE
+SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu
++Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt
+8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L
+HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt
+zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P
+AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c
+mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ
+YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52
+gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA
+Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB
+JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX
+DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui
+TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5
+dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65
+LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp
+0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY
+QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL
+-----END CERTIFICATE-----
diff -pruN 24.0.1+9-1/src/java.base/share/data/currency/CurrencyData.properties 24.0.2+12-1/src/java.base/share/data/currency/CurrencyData.properties
--- 24.0.1+9-1/src/java.base/share/data/currency/CurrencyData.properties	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/data/currency/CurrencyData.properties	2025-06-27 08:03:14.000000000 +0000
@@ -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-A
     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 -pruN 24.0.1+9-1/src/java.base/share/data/tzdata/VERSION 24.0.2+12-1/src/java.base/share/data/tzdata/VERSION
--- 24.0.1+9-1/src/java.base/share/data/tzdata/VERSION	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/data/tzdata/VERSION	2025-06-27 08:03:14.000000000 +0000
@@ -21,4 +21,4 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-tzdata2025a
+tzdata2025b
diff -pruN 24.0.1+9-1/src/java.base/share/data/tzdata/asia 24.0.2+12-1/src/java.base/share/data/tzdata/asia
--- 24.0.1+9-1/src/java.base/share/data/tzdata/asia	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/data/tzdata/asia	2025-06-27 08:03:14.000000000 +0000
@@ -1523,6 +1523,16 @@ Zone Asia/Jayapura	9:22:48 -	LMT	1932 No
 # (UIT No. 143 17.XI.1977) and not 23 September (UIT No. 141 13.IX.1977).
 # UIT is the Operational Bulletin of International Telecommunication Union.
 
+# From Roozbeh Pournader (2025-03-18):
+# ... the exact time of Iran's transition from +0400 to +0330 ... was Friday
+# 1357/8/19 AP=1978-11-10. Here's a newspaper clip from the Ettela'at
+# newspaper, dated 1357/8/14 AP=1978-11-05, translated from Persian
+# (at https://w.wiki/DUEY):
+#	Following the government's decision about returning the official time
+#	to the previous status, the spokesperson for the Ministry of Energy
+#	announced today: At the hour 24 of Friday 19th of Aban (=1978-11-10),
+#	the country's time will be pulled back half an hour.
+#
 # From Roozbeh Pournader (2003-03-15):
 # This is an English translation of what I just found (originally in Persian).
 # The Gregorian dates in brackets are mine:
@@ -1650,7 +1660,7 @@ Rule	Iran	2021	2022	-	Sep	21	24:00	0	-
 Zone	Asia/Tehran	3:25:44	-	LMT	1916
 			3:25:44	-	TMT	1935 Jun 13 # Tehran Mean Time
 			3:30	Iran	%z	1977 Oct 20 24:00
-			4:00	Iran	%z	1979
+			4:00	Iran	%z	1978 Nov 10 24:00
 			3:30	Iran	%z
 
 
diff -pruN 24.0.1+9-1/src/java.base/share/data/tzdata/northamerica 24.0.2+12-1/src/java.base/share/data/tzdata/northamerica
--- 24.0.1+9-1/src/java.base/share/data/tzdata/northamerica	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/data/tzdata/northamerica	2025-06-27 08:03:14.000000000 +0000
@@ -1634,6 +1634,15 @@ Zone America/Moncton	-4:19:08 -	LMT	1883
 # For more on Orillia, see: Daubs K. Bold attempt at daylight saving
 # time became a comic failure in Orillia. Toronto Star 2017-07-08.
 # https://www.thestar.com/news/insight/2017/07/08/bold-attempt-at-daylight-saving-time-became-a-comic-failure-in-orillia.html
+# From Paul Eggert (2025-03-20):
+# Also see the 1912-06-17 front page of The Evening Sunbeam,
+# reproduced in: Richardson M. "Daylight saving was a confusing
+# time in Orillia" in the 2025-03-15 Orillia Matters. Richardson writes,
+# "The first Sunday after the switch was made, [DST proponent and
+# Orillia mayor William Sword] Frost walked into church an hour late.
+# This became a symbol of the downfall of daylight saving in Orillia."
+# The mayor became known as "Daylight Bill".
+# https://www.orilliamatters.com/local-news/column-daylight-saving-was-a-confusing-time-in-orillia-10377529
 
 # From Mark Brader (2010-03-06):
 #
diff -pruN 24.0.1+9-1/src/java.base/share/data/tzdata/southamerica 24.0.2+12-1/src/java.base/share/data/tzdata/southamerica
--- 24.0.1+9-1/src/java.base/share/data/tzdata/southamerica	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/data/tzdata/southamerica	2025-06-27 08:03:14.000000000 +0000
@@ -1269,35 +1269,45 @@ Zone America/Rio_Branco	-4:31:12 -	LMT	1
 # dates to 2014.
 # DST End: last Saturday of April 2014 (Sun 27 Apr 2014 03:00 UTC)
 # DST Start: first Saturday of September 2014 (Sun 07 Sep 2014 04:00 UTC)
-# http://www.diariooficial.interior.gob.cl//media/2014/02/19/do-20140219.pdf
+# From Tim Parenti (2025-03-22):
+# Decreto 307 of 2014 of the Ministry of the Interior and Public Security,
+# promulgated 2014-01-30 and published 2014-02-19:
+# https://www.diariooficial.interior.gob.cl/media/2014/02/19/do-20140219.pdf#page=1
+# https://www.bcn.cl/leychile/navegar?idNorma=1059557
 
 # From Eduardo Romero Urra (2015-03-03):
 # Today has been published officially that Chile will use the DST time
 # permanently until March 25 of 2017
-# http://www.diariooficial.interior.gob.cl/media/2015/03/03/1-large.jpg
-#
-# From Paul Eggert (2015-03-03):
-# For now, assume that the extension will persist indefinitely.
+# From Tim Parenti (2025-03-22):
+# Decreto 106 of 2015 of the Ministry of the Interior and Public Security,
+# promulgated 2015-01-27 and published 2015-03-03:
+# https://www.diariooficial.interior.gob.cl/media/2015/03/03/do-20150303.pdf#page=1
+# https://www.bcn.cl/leychile/navegar?idNorma=1075157
 
 # From Juan Correa (2016-03-18):
-# The decree regarding DST has been published in today's Official Gazette:
-# http://www.diariooficial.interior.gob.cl/versiones-anteriores/do/20160318/
-# http://www.leychile.cl/Navegar?idNorma=1088502
+# The decree regarding DST has been published in today's Official Gazette...
 # It does consider the second Saturday of May and August as the dates
 # for the transition; and it lists DST dates until 2019, but I think
 # this scheme will stick.
-#
 # From Paul Eggert (2016-03-18):
-# For now, assume the pattern holds for the indefinite future.
 # The decree says transitions occur at 24:00; in practice this appears
 # to mean 24:00 mainland time, not 24:00 local time, so that Easter
 # Island is always two hours behind the mainland.
+# From Tim Parenti (2025-03-22):
+# Decreto 253 of 2016 of the Ministry of the Interior and Public Security,
+# promulgated 2016-03-16 and published 2016-03-18.
+# https://www.diariooficial.interior.gob.cl/media/2016/03/18/do-20160318.pdf#page=1
+# https://www.bcn.cl/leychile/navegar?idNorma=1088502
 
 # From Juan Correa (2016-12-04):
 # Magallanes region ... will keep DST (UTC -3) all year round....
 # http://www.soychile.cl/Santiago/Sociedad/2016/12/04/433428/Bachelet-firmo-el-decreto-para-establecer-un-horario-unico-para-la-Region-de-Magallanes.aspx
-# From Deborah Goldsmith (2017-01-19):
-# http://www.diariooficial.interior.gob.cl/publicaciones/2017/01/17/41660/01/1169626.pdf
+# From Tim Parenti (2025-03-22), via Deborah Goldsmith (2017-01-19):
+# Decreto 1820 of 2016 of the Ministry of the Interior and Public Security,
+# promulgated 2016-12-02 and published 2017-01-17:
+# https://www.diariooficial.interior.gob.cl/publicaciones/2017/01/17/41660/01/1169626.pdf
+# https://www.bcn.cl/leychile/Navegar?idNorma=1099217
+# Model this as a change to standard offset effective 2016-12-04.
 
 # From Juan Correa (2018-08-13):
 # As of moments ago, the Ministry of Energy in Chile has announced the new
@@ -1316,13 +1326,20 @@ Zone America/Rio_Branco	-4:31:12 -	LMT	1
 # https://twitter.com/MinEnergia/status/1029009354001973248
 # "We will keep the new time policy unchanged for at least the next 4 years."
 # So we extend the new rules on Saturdays at 24:00 mainland time indefinitely.
-# From Juan Correa (2019-02-04):
-# http://www.diariooficial.interior.gob.cl/publicaciones/2018/11/23/42212/01/1498738.pdf
+# From Tim Parenti (2025-03-22), via Juan Correa (2019-02-04):
+# Decreto 1286 of 2018 of the Ministry of the Interior and Public Security,
+# promulgated 2018-09-21 and published 2018-11-23:
+# https://www.diariooficial.interior.gob.cl/publicaciones/2018/11/23/42212/01/1498738.pdf
+# https://www.bcn.cl/leychile/Navegar?idNorma=1125760
 
 # From Juan Correa (2022-04-02):
 # I found there was a decree published last Thursday that will keep
-# Magallanes region to UTC -3 "indefinitely". The decree is available at
+# Magallanes region to UTC -3 "indefinitely".
+# From Tim Parenti (2025-03-22):
+# Decreto 143 of 2022 of the Ministry of the Interior and Public Security,
+# promulgated 2022-03-29 and published 2022-03-31:
 # https://www.diariooficial.interior.gob.cl/publicaciones/2022/03/31/43217-B/01/2108910.pdf
+# https://www.bcn.cl/leychile/Navegar?idNorma=1174342
 
 # From Juan Correa (2022-08-09):
 # the Internal Affairs Ministry (Ministerio del Interior) informed DST
@@ -1331,13 +1348,36 @@ Zone America/Rio_Branco	-4:31:12 -	LMT	1
 # will keep UTC -3 "indefinitely"...  This is because on September 4th
 # we will have a voting whether to approve a new Constitution.
 #
-# From Eduardo Romero Urra (2022-08-17):
+# From Tim Parenti (2025-03-22), via Eduardo Romero Urra (2022-08-17):
+# Decreto 224 of 2022 of the Ministry of the Interior and Public Security,
+# promulgated 2022-07-14 and published 2022-08-13:
 # https://www.diariooficial.interior.gob.cl/publicaciones/2022/08/13/43327/01/2172567.pdf
+# https://www.bcn.cl/leychile/navegar?idNorma=1179983
 #
 # From Paul Eggert (2022-08-17):
 # Although the presidential decree stops at fall 2026, assume that
 # similar DST rules will continue thereafter.
 
+# From Paul Eggert (2025-01-15):
+# Diario Regional Aysén's Sebastián Martel reports that 94% of Aysén
+# citizens polled in November favored changing the rules from
+# -04/-03-with-DST to -03 all year...
+# https://www.diarioregionalaysen.cl/noticia/actualidad/2024/12/presentan-decision-que-gano-la-votacion-sobre-el-cambio-del-huso-horario-en-aysen
+#
+# From Yonathan Dossow (2025-03-20):
+# [T]oday we have more confirmation of the change.  [Aysén] region will keep
+# UTC-3 all year...
+# https://www.cnnchile.com/pais/region-de-aysen-mantendra-horario-de-verano-todo-el-ano_20250320/
+# https://www.latercera.com/nacional/noticia/tras-consulta-ciudadana-region-de-aysen-mantendra-el-horario-de-verano-durante-todo-el-ano/
+# https://x.com/min_interior/status/1902692504270672098
+#
+# From Tim Parenti (2025-03-22), via Eduardo Romero Urra (2025-03-20):
+# Decreto 93 of 2025 of the Ministry of the Interior and Public Security,
+# promulgated 2025-03-11 and published 2025-03-20:
+# https://www.diariooficial.interior.gob.cl/publicaciones/2025/03/20/44104/01/2624263.pdf
+# https://www.bcn.cl/leychile/Navegar?idNorma=1211955
+# Model this as a change to standard offset effective 2025-03-20.
+
 # Rule	NAME	FROM	TO	-	IN	ON	AT	SAVE	LETTER/S
 Rule	Chile	1927	1931	-	Sep	 1	0:00	1:00	-
 Rule	Chile	1928	1932	-	Apr	 1	0:00	0	-
@@ -1394,6 +1434,20 @@ Zone America/Santiago	-4:42:45 -	LMT	189
 			-5:00	1:00	%z	1947 Mar 31 24:00
 			-5:00	-	%z	1947 May 21 23:00
 			-4:00	Chile	%z
+Zone America/Coyhaique	-4:48:16 -	LMT	1890
+			-4:42:45 -	SMT	1910 Jan 10
+			-5:00	-	%z	1916 Jul  1
+			-4:42:45 -	SMT	1918 Sep 10
+			-4:00	-	%z	1919 Jul  1
+			-4:42:45 -	SMT	1927 Sep  1
+			-5:00	Chile	%z	1932 Sep  1
+			-4:00	-	%z	1942 Jun  1
+			-5:00	-	%z	1942 Aug  1
+			-4:00	-	%z	1946 Aug 28 24:00
+			-5:00	1:00	%z	1947 Mar 31 24:00
+			-5:00	-	%z	1947 May 21 23:00
+			-4:00	Chile	%z	2025 Mar 20
+			-3:00	-	%z
 Zone America/Punta_Arenas -4:43:40 -	LMT	1890
 			-4:42:45 -	SMT	1910 Jan 10
 			-5:00	-	%z	1916 Jul  1
diff -pruN 24.0.1+9-1/src/java.base/share/data/tzdata/zone.tab 24.0.2+12-1/src/java.base/share/data/tzdata/zone.tab
--- 24.0.1+9-1/src/java.base/share/data/tzdata/zone.tab	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/share/data/tzdata/zone.tab	2025-06-27 08:03:14.000000000 +0000
@@ -162,7 +162,8 @@ CH	+4723+00832	Europe/Zurich
 CI	+0519-00402	Africa/Abidjan
 CK	-2114-15946	Pacific/Rarotonga
 CL	-3327-07040	America/Santiago	most of Chile
-CL	-5309-07055	America/Punta_Arenas	Region of Magallanes
+CL	-4534-07204	America/Coyhaique	Aysen Region
+CL	-5309-07055	America/Punta_Arenas	Magallanes Region
 CL	-2709-10926	Pacific/Easter	Easter Island
 CM	+0403+00942	Africa/Douala
 CN	+3114+12128	Asia/Shanghai	Beijing Time
diff -pruN 24.0.1+9-1/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template 24.0.2+12-1/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template
--- 24.0.1+9-1/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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,6 +124,8 @@ class UnixConstants {
 // fgetxattr error codes for absent attributes depend on the OS:
 #ifdef _ALLBSD_SOURCE
     static final int PREFIX_XATTR_NOT_FOUND = ENOATTR;
+#elif defined(_AIX)
+    static final int PREFIX_XATTR_NOT_FOUND = ENOATTR;
 #elif defined(__linux__)
     static final int PREFIX_XATTR_NOT_FOUND = ENODATA;
 #else
diff -pruN 24.0.1+9-1/src/java.base/unix/native/libjava/ProcessImpl_md.c 24.0.2+12-1/src/java.base/unix/native/libjava/ProcessImpl_md.c
--- 24.0.1+9-1/src/java.base/unix/native/libjava/ProcessImpl_md.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/unix/native/libjava/ProcessImpl_md.c	2025-06-27 08:03:14.000000000 +0000
@@ -558,7 +558,9 @@ spawnChild(JNIEnv *env, jobject process,
         return -1;
     }
     offset = copystrings(buf, 0, &c->argv[0]);
-    offset = copystrings(buf, offset, &c->envv[0]);
+    if (c->envv != NULL) {
+        offset = copystrings(buf, offset, &c->envv[0]);
+    }
     if (c->pdir != NULL) {
         if (sp.dirlen > 0) {
             memcpy(buf+offset, c->pdir, sp.dirlen);
diff -pruN 24.0.1+9-1/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c 24.0.2+12-1/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
--- 24.0.1+9-1/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -46,6 +46,10 @@
 #include <sys/xattr.h>
 #endif
 
+#if defined(_AIX)
+#include <sys/ea.h>
+#endif
+
 /* For POSIX-compliant getpwuid_r */
 #include <pwd.h>
 #include <grp.h>
@@ -387,7 +391,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_ini
 
     /* supports extended attributes */
 
-#if defined(_SYS_XATTR_H) || defined(_SYS_XATTR_H_)
+#if defined(_SYS_XATTR_H) || defined(_SYS_XATTR_H_) || defined(_AIX)
     capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_XATTR;
 #endif
 
@@ -1381,6 +1385,8 @@ Java_sun_nio_fs_UnixNativeDispatcher_fge
     res = fgetxattr(fd, name, value, valueLen);
 #elif defined(_ALLBSD_SOURCE)
     res = fgetxattr(fd, name, value, valueLen, 0, 0);
+#elif defined(_AIX)
+    res = fgetea(fd, name, value, valueLen);
 #else
     throwUnixException(env, ENOTSUP);
 #endif
@@ -1402,6 +1408,8 @@ Java_sun_nio_fs_UnixNativeDispatcher_fse
     res = fsetxattr(fd, name, value, valueLen, 0);
 #elif defined(_ALLBSD_SOURCE)
     res = fsetxattr(fd, name, value, valueLen, 0, 0);
+#elif defined(_AIX)
+    res = fsetea(fd, name, value, valueLen, 0);
 #else
     throwUnixException(env, ENOTSUP);
 #endif
@@ -1421,6 +1429,8 @@ Java_sun_nio_fs_UnixNativeDispatcher_fre
     res = fremovexattr(fd, name);
 #elif defined(_ALLBSD_SOURCE)
     res = fremovexattr(fd, name, 0);
+#elif defined(_AIX)
+    res = fremoveea(fd, name);
 #else
     throwUnixException(env, ENOTSUP);
 #endif
@@ -1440,6 +1450,8 @@ Java_sun_nio_fs_UnixNativeDispatcher_fli
     res = flistxattr(fd, list, (size_t)size);
 #elif defined(_ALLBSD_SOURCE)
     res = flistxattr(fd, list, (size_t)size, 0);
+#elif defined(_AIX)
+    res = flistea(fd, list, (size_t)size);
 #else
     throwUnixException(env, ENOTSUP);
 #endif
diff -pruN 24.0.1+9-1/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java 24.0.2+12-1/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java
--- 24.0.1+9-1/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2022, 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
@@ -404,7 +404,11 @@ public class AquaTabbedPaneCopyFromBasic
         }
         tabPane.addContainerListener(getHandler());
         if (tabPane.getTabCount() > 0) {
-            htmlViews = createHTMLVector();
+            Boolean htmlDisabled = (Boolean)
+                                   tabPane.getClientProperty("html.disable");
+            if (!(Boolean.TRUE.equals(htmlDisabled))) {
+                htmlViews = createHTMLVector();
+            }
         }
     }
 
@@ -3445,8 +3449,10 @@ public class AquaTabbedPaneCopyFromBasic
 
         private void updateHtmlViews(int index, boolean inserted) {
             final String title = tabPane.getTitleAt(index);
+            Boolean htmlDisabled = (Boolean)
+                                   tabPane.getClientProperty("html.disable");
             final boolean isHTML = BasicHTML.isHTMLString(title);
-            if (isHTML) {
+            if (isHTML && !(Boolean.TRUE.equals(htmlDisabled))) {
                 if (htmlViews == null) { // Initialize vector
                     htmlViews = createHTMLVector();
                 } else { // Vector already exists
diff -pruN 24.0.1+9-1/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java 24.0.2+12-1/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java
--- 24.0.1+9-1/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2023, 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
@@ -28,9 +28,11 @@ package sun.lwawt.macosx;
 import java.awt.Component;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
+import java.util.Objects;
 
 import javax.accessibility.Accessible;
 import javax.accessibility.AccessibleContext;
+import javax.swing.JSpinner;
 import javax.swing.JTabbedPane;
 
 import static javax.accessibility.AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY;
@@ -120,7 +122,11 @@ class CAccessible extends CFRetainedReso
                 if (name.equals(ACCESSIBLE_CARET_PROPERTY)) {
                     selectedTextChanged(ptr);
                 } else if (name.equals(ACCESSIBLE_TEXT_PROPERTY)) {
-                    valueChanged(ptr);
+                    AccessibleContext thisAC = accessible.getAccessibleContext();
+                    Accessible parentAccessible = thisAC.getAccessibleParent();
+                    if (!(parentAccessible instanceof JSpinner.NumberEditor)) {
+                        valueChanged(ptr);
+                    }
                 } else if (name.equals(ACCESSIBLE_SELECTION_PROPERTY)) {
                     selectionChanged(ptr);
                 } else if (name.equals(ACCESSIBLE_TABLE_MODEL_CHANGED)) {
@@ -182,7 +188,7 @@ class CAccessible extends CFRetainedReso
 
                     // Do send check box state changes to native side
                     if (thisRole == AccessibleRole.CHECK_BOX) {
-                        if (newValue != null && !newValue.equals(oldValue)) {
+                        if (!Objects.equals(newValue, oldValue)) {
                             valueChanged(ptr);
                         }
 
@@ -208,7 +214,7 @@ class CAccessible extends CFRetainedReso
 
                     // Do send toggle button state changes to native side
                     if (thisRole == AccessibleRole.TOGGLE_BUTTON) {
-                        if (newValue != null && !newValue.equals(oldValue)) {
+                        if (!Objects.equals(newValue, oldValue)) {
                             valueChanged(ptr);
                         }
                     }
diff -pruN 24.0.1+9-1/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m 24.0.2+12-1/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m
--- 24.0.1+9-1/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m	2025-06-27 08:03:14.000000000 +0000
@@ -237,6 +237,7 @@ CGGI_CopyImageFromCanvasToRGBInfo(CGGI_G
 {
     UInt32 *src = (UInt32 *)canvas->image->data;
     size_t srcRowWidth = canvas->image->width;
+    size_t srcHeight = canvas->image->height;
 
     UInt8 *dest = (UInt8 *)info->image;
     size_t destRowWidth = info->width;
@@ -246,12 +247,12 @@ CGGI_CopyImageFromCanvasToRGBInfo(CGGI_G
     size_t y;
 
     // fill empty glyph image with black-on-white glyph
-    for (y = 0; y < height; y++) {
+    for (y = 0; y < height && y < srcHeight; y++) {
         size_t destRow = y * destRowWidth * 3;
         size_t srcRow = y * srcRowWidth;
 
         size_t x;
-        for (x = 0; x < destRowWidth; x++) {
+        for (x = 0; x < destRowWidth && x < srcRowWidth; x++) {
             CGGI_CopyARGBPixelToRGBPixel(src[srcRow + x],
                                          dest + destRow + x * 3);
         }
@@ -289,6 +290,7 @@ CGGI_CopyImageFromCanvasToAlphaInfo(CGGI
 {
     UInt32 *src = (UInt32 *)canvas->image->data;
     size_t srcRowWidth = canvas->image->width;
+    size_t srcHeight = canvas->image->height;
 
     UInt8 *dest = (UInt8 *)info->image;
     size_t destRowWidth = info->width;
@@ -298,11 +300,11 @@ CGGI_CopyImageFromCanvasToAlphaInfo(CGGI
     size_t y;
 
     // fill empty glyph image with black-on-white glyph
-    for (y = 0; y < height; y++) {
+    for (y = 0; y < height && y < srcHeight; y++) {
         size_t destRow = y * destRowWidth;
         size_t srcRow = y * srcRowWidth;
         size_t x;
-        for (x = 0; x < destRowWidth; x++) {
+        for (x = 0; x < destRowWidth && x < srcRowWidth; x++) {
             UInt32 p = src[srcRow + x];
             dest[destRow + x] = CGGI_ConvertBWPixelToByteGray(p);
         }
@@ -317,6 +319,7 @@ CGGI_CopyImageFromCanvasToARGBInfo(CGGI_
 
     UInt32 *src = (UInt32 *)canvas->image->data;
     size_t srcRowWidth = canvas->image->width;
+    size_t srcHeight = canvas->image->height;
 
     UInt8 *dest = (UInt8 *)info->image;
     size_t destRowWidth = info->width;
@@ -325,15 +328,16 @@ CGGI_CopyImageFromCanvasToARGBInfo(CGGI_
 
     size_t y;
 
-    for (y = 0; y < height; y++) {
+    for (y = 0; y < height && y < srcHeight; y++) {
         size_t srcRow = y * srcRowWidth;
         if (littleEndian) {
-            UInt16 destRowBytes = info->rowBytes;
+            size_t srcRowBytes = canvas->image->rowBytes;
+            UInt16 destRowBytes = (info->rowBytes < srcRowBytes) ? info->rowBytes : srcRowBytes;
             memcpy(dest, src + srcRow, destRowBytes);
             dest += destRowBytes;
         } else {
             size_t x;
-            for (x = 0; x < destRowWidth; x++) {
+            for (x = 0; x < destRowWidth && x < srcRowWidth; x++) {
                 UInt32 p = src[srcRow + x];
                 *dest++ = (p >> 24  & 0xFF); // blue  (alpha-premultiplied)
                 *dest++ = (p >> 16 & 0xFF); // green (alpha-premultiplied)
@@ -426,8 +430,10 @@ CGGI_InitCanvas(CGGI_GlyphCanvas *canvas
 
     canvas->image->data = (void *)calloc(byteCount, sizeof(UInt8));
     if (canvas->image->data == NULL) {
-        [[NSException exceptionWithName:NSMallocException
-            reason:@"Failed to allocate memory for the buffer which backs the CGContext for glyph strikes." userInfo:nil] raise];
+        canvas->image->width = 0;
+        canvas->image->height = 0;
+        canvas->image->rowBytes = 0;
+        canvas->image->data = malloc(0);
     }
 
     uint32_t bmpInfo = kCGImageAlphaPremultipliedFirst;
@@ -477,6 +483,10 @@ CGGI_FreeCanvas(CGGI_GlyphCanvas *canvas
 
 /*
  * Quick and easy inline to check if this canvas is big enough.
+ * This function only increases the size. To get a smaller canvas, free it first.
+ * This function adds padding / slack multiplier to the requested size.
+ * So resizes must be based on the size you need, not the size of the canvas.
+ * The function will internally account for the multiplier it uses.
  */
 static inline void
 CGGI_SizeCanvas(CGGI_GlyphCanvas *canvas, const vImagePixelCount width,
@@ -484,18 +494,31 @@ CGGI_SizeCanvas(CGGI_GlyphCanvas *canvas
         const CGGI_RenderingMode* mode)
 {
     if (canvas->image != NULL &&
-        width  < canvas->image->width &&
+        width < canvas->image->width &&
         height < canvas->image->height)
     {
         return;
     }
 
+    vImagePixelCount w = width * CGGI_GLYPH_CANVAS_SLACK;
+    vImagePixelCount h = height * CGGI_GLYPH_CANVAS_SLACK;
+
+    // Do not allow the canvas to be resized smaller.
+    if (canvas->image != NULL) {
+       if (w < canvas->image->width) {
+           w = canvas->image->width;
+       }
+       if (h < canvas->image->height) {
+           h = canvas->image->height;
+       }
+    }
+
     // if we don't have enough space to strike the largest glyph in the
     // run, resize the canvas
     CGGI_FreeCanvas(canvas);
     CGGI_InitCanvas(canvas,
-                    width * CGGI_GLYPH_CANVAS_SLACK,
-                    height * CGGI_GLYPH_CANVAS_SLACK,
+                    w,
+                    h,
                     mode);
     JRSFontSetRenderingStyleOnContext(canvas->context, mode->cgFontMode);
 }
@@ -511,6 +534,12 @@ CGGI_ClearCanvas(CGGI_GlyphCanvas *canva
     canvasRectToClear.data = canvas->image->data;
     canvasRectToClear.height = info->height;
     canvasRectToClear.width = info->width;
+    if (canvas->image->width < canvasRectToClear.width) {
+          canvasRectToClear.width = canvas->image->width;
+    }
+    if (canvas->image->height < canvasRectToClear.height) {
+          canvasRectToClear.height = canvas->image->height;
+    }
     // use the row stride of the canvas, not the info
     canvasRectToClear.rowBytes = canvas->image->rowBytes;
 
@@ -870,7 +899,6 @@ CGGI_CreateGlyphInfos(jlong *glyphInfos,
         CGRect bbox = bboxes[i];
 
         GlyphInfo *glyphInfo = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, mainFontDescriptor);
-
         if (maxWidth < glyphInfo->width)   maxWidth = glyphInfo->width;
         if (maxHeight < glyphInfo->height) maxHeight = glyphInfo->height;
 
@@ -946,26 +974,32 @@ CGGlyphImages_GetGlyphImagePtrs(jlong gl
         return;
     }
 
-    // just do one malloc, and carve it up for all the buffers
-    void *buffer = malloc(sizeof(CGRect) * sizeof(CGSize) *
-                          sizeof(CGGlyph) * sizeof(UnicodeScalarValue) * len);
-    if (buffer == NULL) {
+    CGRect *bboxes   = (CGRect*)calloc(len, sizeof(CGRect));
+    CGSize *advances = (CGSize*)calloc(len, sizeof(CGSize));
+    CGGlyph *glyphs  = (CGGlyph*)calloc(len, sizeof(CGGlyph));
+    UnicodeScalarValue *uniChars = (UnicodeScalarValue*)calloc(len, sizeof(UnicodeScalarValue));
+
+    if (bboxes == NULL || advances == NULL || glyphs == NULL || uniChars == NULL) {
+        free(bboxes);
+        free(advances);
+        free(glyphs);
+        free(uniChars);
         [[NSException exceptionWithName:NSMallocException
             reason:@"Failed to allocate memory for the temporary glyph strike and measurement buffers." userInfo:nil] raise];
     }
 
-    CGRect *bboxes = (CGRect *)(buffer);
-    CGSize *advances = (CGSize *)(bboxes + sizeof(CGRect) * len);
-    CGGlyph *glyphs = (CGGlyph *)(advances + sizeof(CGGlyph) * len);
-    UnicodeScalarValue *uniChars = (UnicodeScalarValue *)(glyphs + sizeof(UnicodeScalarValue) * len);
-
     CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode,
                                             rawGlyphCodes, uniChars, glyphs,
                                             advances, bboxes, len);
 
-    free(buffer);
+    free(bboxes);
+    free(advances);
+    free(glyphs);
+    free(uniChars);
 }
 
+#define TX_FIXED_UNSAFE(v)  (isinf(v) || isnan(v) || fabs(v) >= (1<<30))
+
 /*
  * Calculates bounding boxes (for given transform) and advance (for untransformed 1pt-size font) for specified glyphs.
  */
@@ -977,6 +1011,27 @@ CGGlyphImages_GetGlyphMetrics(const CTFo
                               size_t count,
                               CGRect bboxes[],
                               CGSize advances[]) {
+
+    if (TX_FIXED_UNSAFE(tx->a) || TX_FIXED_UNSAFE(tx->b) || TX_FIXED_UNSAFE(tx->c) ||
+        TX_FIXED_UNSAFE(tx->d) || TX_FIXED_UNSAFE(tx->tx) || TX_FIXED_UNSAFE(tx->tx)) {
+
+        if (bboxes) {
+            for (int i = 0; i < count; i++) {
+                bboxes[i].origin.x = 0;
+                bboxes[i].origin.y = 0;
+                bboxes[i].size.width = 0;
+                bboxes[i].size.height = 0;
+            }
+        }
+        if (advances) {
+            for (int i = 0; i < count; i++) {
+                advances[i].width = 0;
+                advances[i].height = 0;
+            }
+        }
+        return;
+    }
+
     if (IsEmojiFont(font)) {
         // Glyph metrics for emoji font are not strictly proportional to font size,
         // so we need to construct real-sized font object to calculate them.
diff -pruN 24.0.1+9-1/src/java.desktop/share/classes/com/sun/beans/finder/MethodFinder.java 24.0.2+12-1/src/java.desktop/share/classes/com/sun/beans/finder/MethodFinder.java
--- 24.0.1+9-1/src/java.desktop/share/classes/com/sun/beans/finder/MethodFinder.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/classes/com/sun/beans/finder/MethodFinder.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -77,8 +77,7 @@ public final class MethodFinder extends
         Signature signature = new Signature(type, name, args);
 
         try {
-            Method method = CACHE.get(signature);
-            return (method == null) ? method : CACHE.create(signature);
+            return CACHE.get(signature);
         }
         catch (SignatureException exception) {
             throw exception.toNoSuchMethodException("Method '" + name + "' is not found");
diff -pruN 24.0.1+9-1/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java 24.0.2+12-1/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java
--- 24.0.1+9-1/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java	2025-06-27 08:03:14.000000000 +0000
@@ -141,10 +141,11 @@ public class ICC_ColorSpace extends Colo
         if (profileClass != ICC_Profile.CLASS_INPUT
                 && profileClass != ICC_Profile.CLASS_DISPLAY
                 && profileClass != ICC_Profile.CLASS_OUTPUT
+                && profileClass != ICC_Profile.CLASS_DEVICELINK
                 && profileClass != ICC_Profile.CLASS_COLORSPACECONVERSION
                 && profileClass != ICC_Profile.CLASS_NAMEDCOLOR
                 && profileClass != ICC_Profile.CLASS_ABSTRACT) {
-            throw new IllegalArgumentException("Invalid profile type");
+            throw new IllegalArgumentException("Invalid profile class");
         }
 
         thisProfile = profile;
diff -pruN 24.0.1+9-1/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java 24.0.2+12-1/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java
--- 24.0.1+9-1/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -756,6 +756,7 @@ public sealed class ICC_Profile implemen
      */
     public static final int icXYZNumberX = 8;
 
+    private static final int HEADER_SIZE = 128;
 
     /**
      * Constructs an {@code ICC_Profile} object with a given ID.
@@ -786,10 +787,15 @@ public sealed class ICC_Profile implemen
         ProfileDataVerifier.verify(data);
         Profile p;
         try {
+            byte[] theHeader = new byte[HEADER_SIZE];
+            System.arraycopy(data, 0, theHeader, 0, HEADER_SIZE);
+            verifyHeader(theHeader);
+
             p = CMSManager.getModule().loadProfile(data);
         } catch (CMMException c) {
             throw new IllegalArgumentException("Invalid ICC Profile Data");
         }
+
         try {
             if (getColorSpaceType(p) == ColorSpace.TYPE_GRAY
                     && getData(p, icSigMediaWhitePointTag) != null
@@ -972,6 +978,10 @@ public sealed class ICC_Profile implemen
             return info.profileClass;
         }
         byte[] theHeader = getData(icSigHead);
+        return getProfileClass(theHeader);
+    }
+
+    private static int getProfileClass(byte[] theHeader) {
         int theClassSig = intFromBigEndian(theHeader, icHdrDeviceClass);
         return switch (theClassSig) {
             case icSigInputClass -> CLASS_INPUT;
@@ -1013,6 +1023,11 @@ public sealed class ICC_Profile implemen
         return iccCStoJCS(theColorSpaceSig);
     }
 
+    private static int getColorSpaceType(byte[] theHeader) {
+        int theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace);
+        return iccCStoJCS(theColorSpaceSig);
+    }
+
     /**
      * Returns the color space type of the Profile Connection Space (PCS).
      * Returns one of the color space type constants defined by the ColorSpace
@@ -1032,6 +1047,21 @@ public sealed class ICC_Profile implemen
         return iccCStoJCS(thePCSSig);
     }
 
+    private static int getPCSType(byte[] theHeader) {
+        int thePCSSig = intFromBigEndian(theHeader, icHdrPcs);
+        int theDeviceClass = intFromBigEndian(theHeader, icHdrDeviceClass);
+
+        if (theDeviceClass == icSigLinkClass) {
+            return iccCStoJCS(thePCSSig);
+        } else {
+            return switch (thePCSSig) {
+                case icSigXYZData -> ColorSpace.TYPE_XYZ;
+                case icSigLabData -> ColorSpace.TYPE_Lab;
+                default -> throw new IllegalArgumentException("Unexpected PCS type");
+            };
+        }
+    }
+
     /**
      * Write this {@code ICC_Profile} to a file.
      *
@@ -1112,9 +1142,42 @@ public sealed class ICC_Profile implemen
      * @see #getData
      */
     public void setData(int tagSignature, byte[] tagData) {
+        if (tagSignature == ICC_Profile.icSigHead) {
+            verifyHeader(tagData);
+        }
         CMSManager.getModule().setTagData(cmmProfile(), tagSignature, tagData);
     }
 
+    private static void verifyHeader(byte[] data) {
+        if (data == null || data.length < HEADER_SIZE) {
+            throw new IllegalArgumentException("Invalid header data");
+        }
+        getProfileClass(data);
+        getColorSpaceType(data);
+        getPCSType(data);
+        checkRenderingIntent(data);
+    }
+
+    private static boolean checkRenderingIntent(byte[] header) {
+        int index = ICC_Profile.icHdrRenderingIntent;
+
+        /* According to ICC spec, only the least-significant 16 bits shall be
+         * used to encode the rendering intent. The most significant 16 bits
+         * shall be set to zero. Thus, we are ignoring two most significant
+         * bytes here. Please refer ICC Spec Document for more details.
+         */
+        int renderingIntent = ((header[index+2] & 0xff) <<  8) |
+                              (header[index+3] & 0xff);
+
+        switch (renderingIntent) {
+            case icPerceptual, icMediaRelativeColorimetric,
+                    icSaturation, icAbsoluteColorimetric -> {
+                return true;
+            }
+            default -> throw new IllegalArgumentException("Unknown Rendering Intent");
+        }
+    }
+
     /**
      * Returns the number of color components in the "input" color space of this
      * profile. For example if the color space type of this profile is
diff -pruN 24.0.1+9-1/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java 24.0.2+12-1/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java
--- 24.0.1+9-1/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -738,6 +738,10 @@ public class TitledBorder extends Abstra
     }
 
     private JLabel getLabel(Component c) {
+        if (c instanceof JComponent comp) {
+            this.label.putClientProperty("html.disable",
+                                         comp.getClientProperty("html.disable"));
+        }
         this.label.setText(getTitle());
         this.label.setFont(getFont(c));
         this.label.setForeground(getColor(c));
diff -pruN 24.0.1+9-1/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java 24.0.2+12-1/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java
--- 24.0.1+9-1/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -468,6 +468,10 @@ public class BasicOptionPaneUI extends O
                 }
                 JLabel label;
                 label = new JLabel(s, JLabel.LEADING);
+                if (Boolean.TRUE.equals(
+                    this.optionPane.getClientProperty("html.disable"))) {
+                    label.putClientProperty("html.disable", true);
+                }
                 label.setName("OptionPane.label");
                 configureMessageLabel(label);
                 addMessageComponents(container, cons, label, maxll, true);
diff -pruN 24.0.1+9-1/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java 24.0.2+12-1/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java
--- 24.0.1+9-1/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -495,7 +495,11 @@ public class BasicTabbedPaneUI extends T
         }
         tabPane.addContainerListener(getHandler());
         if (tabPane.getTabCount()>0) {
-            htmlViews = createHTMLVector();
+            Boolean htmlDisabled = (Boolean)
+                                    tabPane.getClientProperty("html.disable");
+            if (!(Boolean.TRUE.equals(htmlDisabled))) {
+                htmlViews = createHTMLVector();
+            }
         }
     }
 
@@ -4065,8 +4069,10 @@ public class BasicTabbedPaneUI extends T
 
         private void updateHtmlViews(int index, boolean inserted) {
             String title = tabPane.getTitleAt(index);
+            Boolean htmlDisabled = (Boolean)
+                                    tabPane.getClientProperty("html.disable");
             boolean isHTML = BasicHTML.isHTMLString(title);
-            if (isHTML) {
+            if (isHTML && !(Boolean.TRUE.equals(htmlDisabled))) {
                 if (htmlViews==null) {    // Initialize vector
                     htmlViews = createHTMLVector();
                 } else {                  // Vector already exists
diff -pruN 24.0.1+9-1/src/java.desktop/share/classes/sun/print/CustomMediaSizeName.java 24.0.2+12-1/src/java.desktop/share/classes/sun/print/CustomMediaSizeName.java
--- 24.0.1+9-1/src/java.desktop/share/classes/sun/print/CustomMediaSizeName.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/classes/sun/print/CustomMediaSizeName.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, 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
@@ -203,16 +203,17 @@ class CustomMediaSizeName extends MediaS
         if (value == null) {
             value = new CustomMediaSizeName(name, choice, width, length);
             customMap.put(key, value);
-
-            // add this new custom media size name to MediaSize array
-            if ((width > 0.0) && (length > 0.0)) {
-                try {
-                    new MediaSize(width, length, Size2DSyntax.INCH, value);
-                } catch (IllegalArgumentException e) {
+            if (value.getStandardMedia() == null) {
+                // add this new custom media size name to MediaSize array
+                if ((width > 0.0) && (length > 0.0)) {
+                    try {
+                        new MediaSize(width, length, Size2DSyntax.INCH, value);
+                    } catch (IllegalArgumentException e) {
                         /* PDF printer in Linux for Ledger paper causes
                         "IllegalArgumentException: X dimension > Y dimension".
                         We rotate based on IPP spec. */
-                    new MediaSize(length, width, Size2DSyntax.INCH, value);
+                        new MediaSize(length, width, Size2DSyntax.INCH, value);
+                    }
                 }
             }
         }
diff -pruN 24.0.1+9-1/src/java.desktop/share/legal/freetype.md 24.0.2+12-1/src/java.desktop/share/legal/freetype.md
--- 24.0.1+9-1/src/java.desktop/share/legal/freetype.md	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/legal/freetype.md	2025-06-27 08:03:14.000000000 +0000
@@ -1,4 +1,4 @@
-## The FreeType Project: Freetype v2.13.2
+## The FreeType Project: Freetype v2.13.3
 
 
 ### FreeType Notice
@@ -21,23 +21,23 @@ which fits your needs best.
 ### FreeType License
 ```
 
-Copyright (C) 1996-2023 by David Turner, Robert Wilhelm, and Werner Lemberg.
-Copyright (C) 2007-2023 by Dereg Clegg and Michael Toftdal.
-Copyright (C) 1996-2023 by Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
-Copyright (C) 2022-2023 by David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and
-Copyright (C) 2004-2023 by Masatake YAMATO and Redhat K.K.
-Copyright (C) 2007-2023 by Derek Clegg and Michael Toftdal.
-Copyright (C) 2003-2023 by Masatake YAMATO, Red Hat K.K.,
-Copyright (C) 1996-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches.
-Copyright (C) 2007-2023 by David Turner.
-Copyright (C) 2022-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
-Copyright (C) 2007-2023 by Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
-Copyright (C) 2008-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya.
-Copyright (C) 2013-2023 by Google, Inc.
-Copyright (C) 2019-2023 by Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
-Copyright (C) 2009-2023 by Oran Agra and Mickey Gabel.
-Copyright (C) 2018-2023 by David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg.
-Copyright (C) 2004-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.
+Copyright (C) 1996-2024 by David Turner, Robert Wilhelm, and Werner Lemberg.
+Copyright (C) 2007-2024 by Dereg Clegg and Michael Toftdal.
+Copyright (C) 1996-2024 by Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
+Copyright (C) 2022-2024 by David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and
+Copyright (C) 2004-2024 by Masatake YAMATO and Redhat K.K.
+Copyright (C) 2007-2024 by Derek Clegg and Michael Toftdal.
+Copyright (C) 2003-2024 by Masatake YAMATO, Red Hat K.K.,
+Copyright (C) 1996-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches.
+Copyright (C) 2007-2024 by David Turner.
+Copyright (C) 2022-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
+Copyright (C) 2007-2024 by Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
+Copyright (C) 2008-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya.
+Copyright (C) 2013-2024 by Google, Inc.
+Copyright (C) 2019-2024 by Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
+Copyright (C) 2009-2024 by Oran Agra and Mickey Gabel.
+Copyright (C) 2018-2024 by David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg.
+Copyright (C) 2004-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.
 
 
                     The FreeType Project LICENSE
@@ -559,7 +559,7 @@ Public License instead of this License.
 ```
 
 ---------------------------------
-The below license applies to the following files:
+The below applies to the following file(s):
 libfreetype/src/psaux/psarrst.c
 libfreetype/src/psaux/psarrst.h
 libfreetype/src/psaux/psblues.c
@@ -582,7 +582,7 @@ libfreetype/src/psaux/psstack.c
 libfreetype/src/psaux/psstack.h
 libfreetype/src/psaux/pstypes.h
 
-Copyright 2006-2014 Adobe Systems Incorporated.
+Copyright (C) 2006-2014 Adobe Systems Incorporated.
 
 This software, and all works of authorship, whether in source or
 object code form as indicated by the copyright notice(s) included
@@ -618,12 +618,12 @@ and you accept them fully.
 ```
 
 ---------------------------------
-The below license applies to the following files:
+The below applies to the following file(s):
 libfreetype/include/freetype/internal/fthash.h
 libfreetype/src/base/fthash.c
 
-Copyright 2000 Computing Research Labs, New Mexico State University
-Copyright 2001-2015
+Copyright (C) 2000 Computing Research Labs, New Mexico State University
+Copyright (C) 2001-2015
 
   Francesco Zappa Nardelli
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/legal/harfbuzz.md 24.0.2+12-1/src/java.desktop/share/legal/harfbuzz.md
--- 24.0.1+9-1/src/java.desktop/share/legal/harfbuzz.md	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/legal/harfbuzz.md	2025-06-27 08:03:14.000000000 +0000
@@ -1,4 +1,4 @@
-## Harfbuzz v8.2.2
+## Harfbuzz v10.4.0
 
 ### Harfbuzz License
 
@@ -8,14 +8,14 @@ HarfBuzz is licensed under the so-called
 For parts of HarfBuzz that are licensed under different licenses see individual
 files names COPYING in subdirectories where applicable.
 
-Copyright © 2010-2023  Google, Inc.
+Copyright © 2010-2024  Google, Inc.
 Copyright © 2018-2020  Ebrahim Byagowi
 Copyright © 2004-2013  Red Hat, Inc.
 Copyright © 2019  Facebook, Inc.
 Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com)
 Copyright © 2007  Chris Wilson
 Copyright © 2018-2019 Adobe Inc.
-Copyright © 2006-2023 Behdad Esfahbod
+Copyright © 2006-2025 Behdad Esfahbod
 Copyright © 1998-2004  David Turner and Werner Lemberg
 Copyright © 2009  Keith Stribley
 Copyright © 2018  Khaled Hosny
@@ -54,7 +54,7 @@ exception is licensed with a slightly di
 The contents of this directory are licensed under the following terms:
 
 ---------------------------------
-The below license applies to the following files:
+The below applies to the following file(s):
 libharfbuzz/hb-ucd.cc
 
 Copyright (C) 2012 Grigori Goronzy <greg@kinoho.net>
@@ -72,13 +72,14 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 ---------------------------------
-The below license applies to the following files:
+The below applies to the following file(s):
 libharfbuzz/hb-unicode-emoji-table.hh
 
-© 2023 Unicode®, Inc.
+© 2024 Unicode®, Inc.
+
 Unicode and the Unicode Logo are registered trademarks of Unicode, Inc.
 in the U.S. and other countries.
-For terms of use, see https://www.unicode.org/terms_of_use.html
+For terms of use and license, see https://www.unicode.org/terms_of_use.html
 
 </pre>
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/legal/lcms.md 24.0.2+12-1/src/java.desktop/share/legal/lcms.md
--- 24.0.1+9-1/src/java.desktop/share/legal/lcms.md	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/legal/lcms.md	2025-06-27 08:03:14.000000000 +0000
@@ -1,11 +1,11 @@
-## Little Color Management System (LCMS) v2.16
+## Little Color Management System (LCMS) v2.17
 
 ### LCMS License
 <pre>
 
 MIT License
 
-Copyright (C) 1998-2023 Marti Maria Saguer
+Copyright (C) 1998-2025 Marti Maria Saguer
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the "Software"),
@@ -26,10 +26,10 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING
 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 ---------------------------------
-The below license applies to the following files:
+The below applies to the following file(s):
 liblcms/cmssm.c
 
-Copyright 2001, softSurfer (www.softsurfer.com)
+Copyright (C) 2001, softSurfer (www.softsurfer.com)
 
 This code may be freely used and modified for any purpose
 providing that this copyright notice is included with it.
@@ -99,5 +99,5 @@ Christian Albrecht
 Dimitrios Anastassakis
 Lemke Software
 Tim Zaman
-
-```
+Amir Montazery and Open Source Technology Improvement Fund (ostif.org), Google, for fuzzer fundings.
+```
\ No newline at end of file
diff -pruN 24.0.1+9-1/src/java.desktop/share/legal/libpng.md 24.0.2+12-1/src/java.desktop/share/legal/libpng.md
--- 24.0.1+9-1/src/java.desktop/share/legal/libpng.md	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/legal/libpng.md	2025-06-27 08:03:14.000000000 +0000
@@ -1,4 +1,4 @@
-## libpng v1.6.43
+## libpng v1.6.47
 
 ### libpng License
 <pre>
@@ -9,8 +9,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENS
 PNG Reference Library License version 2
 ---------------------------------------
 
-Copyright (C) 1995-2024 The PNG Reference Library Authors.
-Copyright (C) 2018-2024 Cosmin Truta
+Copyright (c) 1995-2025 The PNG Reference Library Authors.
+Copyright (C) 2018-2025 Cosmin Truta
 Copyright (C) 1998-2018 Glenn Randers-Pehrson
 Copyright (C) 1996-1997 Andreas Dilger
 Copyright (C) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -170,6 +170,7 @@ Authors, for copyright and licensing pur
  * James Yu
  * John Bowler
  * Kevin Bracey
+ * Lucas Chollet
  * Magnus Holmgren
  * Mandar Sahastrabuddhe
  * Mans Rullgard
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libawt/java2d/loops/TransformHelper.c 24.0.2+12-1/src/java.desktop/share/native/libawt/java2d/loops/TransformHelper.c
--- 24.0.1+9-1/src/java.desktop/share/native/libawt/java2d/loops/TransformHelper.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libawt/java2d/loops/TransformHelper.c	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -33,6 +33,8 @@
 #include "sun_java2d_loops_TransformHelper.h"
 #include "java_awt_image_AffineTransformOp.h"
 
+#include "ub.h"
+
 /*
  * The stub functions replace the bilinear and bicubic interpolation
  * functions with NOP versions so that the performance of the helper
@@ -661,6 +663,7 @@ Transform_SafeHelper(JNIEnv *env,
         ((jubyte *)pRes)[comp] = (jubyte) ((cR + (1<<15)) >> 16); \
     } while (0)
 
+ATTRIBUTE_NO_UBSAN
 static void
 BilinearInterp(jint *pRGB, jint numpix,
                jint xfract, jint dxfract,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libawt/java2d/pipe/ShapeSpanIterator.c 24.0.2+12-1/src/java.desktop/share/native/libawt/java2d/pipe/ShapeSpanIterator.c
--- 24.0.1+9-1/src/java.desktop/share/native/libawt/java2d/pipe/ShapeSpanIterator.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libawt/java2d/pipe/ShapeSpanIterator.c	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -39,6 +39,8 @@
 #include "sun_java2d_pipe_ShapeSpanIterator.h"
 #include "java_awt_geom_PathIterator.h"
 
+#include "ub.h"
+
 /*
  * This structure holds all of the information needed to trace and
  * manage a single line segment of the shape's outline.
@@ -1233,6 +1235,7 @@ ShapeSIIntersectClipBox(JNIEnv *env, voi
     }
 }
 
+ATTRIBUTE_NO_UBSAN
 static jboolean
 ShapeSINextSpan(void *state, jint spanbox[])
 {
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   ANSI-specific configuration file (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Build macros of the FreeType 2 library.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   User-selectable configuration macros (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -757,6 +757,22 @@ FT_BEGIN_HEADER
 #endif
 
 
+  /**************************************************************************
+   *
+   * Option `TT_CONFIG_OPTION_GPOS_KERNING` enables a basic GPOS kerning
+   * implementation (for TrueType fonts only).  With this defined, FreeType
+   * is able to get kerning pair data from the GPOS 'kern' feature as well as
+   * legacy 'kern' tables; without this defined, FreeType will only be able
+   * to use legacy 'kern' tables.
+   *
+   * Note that FreeType does not support more advanced GPOS layout features;
+   * even the 'kern' feature implemented here doesn't handle more
+   * sophisticated kerning variants.  Use a higher-level library like
+   * HarfBuzz instead for that.
+   */
+/* #define TT_CONFIG_OPTION_GPOS_KERNING */
+
+
   /*************************************************************************/
   /*************************************************************************/
   /****                                                                 ****/
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   ANSI-specific library and header configuration file (specification
  *   only).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType integer types definitions.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Mac/OS X support configuration header.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Define a set of compiler macros used in public FreeType headers.
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType high-level API and common types (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -1322,9 +1322,13 @@ FT_BEGIN_HEADER
    *   FT_FACE_FLAG_KERNING ::
    *     The face contains kerning information.  If set, the kerning distance
    *     can be retrieved using the function @FT_Get_Kerning.  Otherwise the
-   *     function always returns the vector (0,0).  Note that FreeType
-   *     doesn't handle kerning data from the SFNT 'GPOS' table (as present
-   *     in many OpenType fonts).
+   *     function always returns the vector (0,0).
+   *
+   *     Note that for TrueType fonts only, FreeType supports both the 'kern'
+   *     table and the basic, pair-wise kerning feature from the 'GPOS' table
+   *     (with `TT_CONFIG_OPTION_GPOS_KERNING` enabled), though FreeType does
+   *     not support the more advanced GPOS layout features; use a library
+   *     like HarfBuzz for those instead.
    *
    *   FT_FACE_FLAG_FAST_GLYPHS ::
    *     THIS FLAG IS DEPRECATED.  DO NOT USE OR TEST IT.
@@ -3767,87 +3771,18 @@ FT_BEGIN_HEADER
    *     pixels and use the @FT_PIXEL_MODE_LCD_V mode.
    *
    *   FT_RENDER_MODE_SDF ::
-   *     This mode corresponds to 8-bit, single-channel signed distance field
-   *     (SDF) bitmaps.  Each pixel in the SDF grid is the value from the
-   *     pixel's position to the nearest glyph's outline.  The distances are
-   *     calculated from the center of the pixel and are positive if they are
-   *     filled by the outline (i.e., inside the outline) and negative
-   *     otherwise.  Check the note below on how to convert the output values
-   *     to usable data.
+   *     The positive (unsigned) 8-bit bitmap values can be converted to the
+   *     single-channel signed distance field (SDF) by subtracting 128, with
+   *     the positive and negative results corresponding to the inside and
+   *     the outside of a glyph contour, respectively.  The distance units are
+   *     arbitrarily determined by an adjustable @spread property.
    *
    * @note:
-   *   The selected render mode only affects vector glyphs of a font.
+   *   The selected render mode only affects scalable vector glyphs of a font.
    *   Embedded bitmaps often have a different pixel mode like
    *   @FT_PIXEL_MODE_MONO.  You can use @FT_Bitmap_Convert to transform them
    *   into 8-bit pixmaps.
    *
-   *   For @FT_RENDER_MODE_SDF the output bitmap buffer contains normalized
-   *   distances that are packed into unsigned 8-bit values.  To get pixel
-   *   values in floating point representation use the following pseudo-C
-   *   code for the conversion.
-   *
-   *   ```
-   *   // Load glyph and render using FT_RENDER_MODE_SDF,
-   *   // then use the output buffer as follows.
-   *
-   *   ...
-   *   FT_Byte  buffer = glyph->bitmap->buffer;
-   *
-   *
-   *   for pixel in buffer
-   *   {
-   *     // `sd` is the signed distance and `spread` is the current spread;
-   *     // the default spread is 2 and can be changed.
-   *
-   *     float  sd = (float)pixel - 128.0f;
-   *
-   *
-   *     // Convert to pixel values.
-   *     sd = ( sd / 128.0f ) * spread;
-   *
-   *     // Store `sd` in a buffer or use as required.
-   *   }
-   *
-   *   ```
-   *
-   *   FreeType has two rasterizers for generating SDF, namely:
-   *
-   *   1. `sdf` for generating SDF directly from glyph's outline, and
-   *
-   *   2. `bsdf` for generating SDF from rasterized bitmaps.
-   *
-   *   Depending on the glyph type (i.e., outline or bitmap), one of the two
-   *   rasterizers is chosen at runtime and used for generating SDFs.  To
-   *   force the use of `bsdf` you should render the glyph with any of the
-   *   FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and
-   *   then re-render with `FT_RENDER_MODE_SDF`.
-   *
-   *   There are some issues with stability and possible failures of the SDF
-   *   renderers (specifically `sdf`).
-   *
-   *   1. The `sdf` rasterizer is sensitive to really small features (e.g.,
-   *      sharp turns that are less than 1~pixel) and imperfections in the
-   *      glyph's outline, causing artifacts in the final output.
-   *
-   *   2. The `sdf` rasterizer has limited support for handling intersecting
-   *      contours and *cannot* handle self-intersecting contours whatsoever.
-   *      Self-intersection happens when a single connected contour
-   *      intersects itself at some point; having these in your font
-   *      definitely poses a problem to the rasterizer and cause artifacts,
-   *      too.
-   *
-   *   3. Generating SDF for really small glyphs may result in undesirable
-   *      output; the pixel grid (which stores distance information) becomes
-   *      too coarse.
-   *
-   *   4. Since the output buffer is normalized, precision at smaller spreads
-   *      is greater than precision at larger spread values because the
-   *      output range of [0..255] gets mapped to a smaller SDF range.  A
-   *      spread of~2 should be sufficient in most cases.
-   *
-   *   Points (1) and (2) can be avoided by using the `bsdf` rasterizer,
-   *   which is more stable than the `sdf` rasterizer in general.
-   *
    */
   typedef enum  FT_Render_Mode_
   {
@@ -4058,9 +3993,26 @@ FT_BEGIN_HEADER
    *   out of the scope of this API function -- they can be implemented
    *   through format-specific interfaces.
    *
-   *   Kerning for OpenType fonts implemented in a 'GPOS' table is not
-   *   supported; use @FT_HAS_KERNING to find out whether a font has data
-   *   that can be extracted with `FT_Get_Kerning`.
+   *   Note that, for TrueType fonts only, this can extract data from both
+   *   the 'kern' table and the basic, pair-wise kerning feature from the
+   *   GPOS table (with `TT_CONFIG_OPTION_GPOS_KERNING` enabled), though
+   *   FreeType does not support the more advanced GPOS layout features; use
+   *   a library like HarfBuzz for those instead.  If a font has both a
+   *   'kern' table and kern features of a GPOS table, the 'kern' table will
+   *   be used.
+   *
+   *   Also note for right-to-left scripts, the functionality may differ for
+   *   fonts with GPOS tables vs. 'kern' tables.  For GPOS, right-to-left
+   *   fonts typically use both a placement offset and an advance for pair
+   *   positioning, which this API does not support, so it would output
+   *   kerning values of zero; though if the right-to-left font used only
+   *   advances in GPOS pair positioning, then this API could output kerning
+   *   values for it, but it would use `left_glyph` to mean the first glyph
+   *   for that case.  Whereas 'kern' tables are always advance-only and
+   *   always store the left glyph first.
+   *
+   *   Use @FT_HAS_KERNING to find out whether a font has data that can be
+   *   extracted with `FT_Get_Kerning`.
    */
   FT_EXPORT( FT_Error )
   FT_Get_Kerning( FT_Face     face,
@@ -5222,7 +5174,7 @@ FT_BEGIN_HEADER
    */
 #define FREETYPE_MAJOR  2
 #define FREETYPE_MINOR  13
-#define FREETYPE_PATCH  2
+#define FREETYPE_PATCH  3
 
 
   /**************************************************************************
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Quick computation of advance widths (specification only).
  *
- * Copyright (C) 2008-2023 by
+ * Copyright (C) 2008-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType exact bbox computation (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing BDF-specific strings (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType utility functions for bitmaps (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing CID font information (specification).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * Dereg Clegg and Michael Toftdal.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType's glyph color management (specification).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType API for controlling driver modules (specification only).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -817,6 +817,80 @@ FT_BEGIN_HEADER
    *   2.5
    */
 
+
+  /**************************************************************************
+   *
+   * @property:
+   *   spread
+   *
+   * @description:
+   *   This property of the 'sdf' and 'bsdf' renderers defines how the signed
+   *   distance field (SDF) is represented in the output bitmap.  The output
+   *   values are calculated as follows, '128 * ( SDF / spread + 1 )', with
+   *   the result clamped to the 8-bit range [0..255].  Therefore, 'spread'
+   *   is also the maximum euclidean distance from the edge after which the
+   *   values are clamped.  The spread is specified in pixels with the
+   *   default value of 8.  For accurate SDF texture mapping (interpolation),
+   *   the spread should be large enough to accommodate the target grid unit.
+   *
+   * @example:
+   *   The following example code demonstrates how to set the SDF spread
+   *   (omitting the error handling).
+   *
+   *   ```
+   *     FT_Library  library;
+   *     FT_Int      spread = 2;
+   *
+   *
+   *     FT_Init_FreeType( &library );
+   *
+   *     FT_Property_Set( library, "sdf", "spread", &spread );
+   *   ```
+   *
+   * @note:
+   *   FreeType has two rasterizers for generating SDF, namely:
+   *
+   *   1. `sdf` for generating SDF directly from glyph's outline, and
+   *
+   *   2. `bsdf` for generating SDF from rasterized bitmaps.
+   *
+   *   Depending on the glyph type (i.e., outline or bitmap), one of the two
+   *   rasterizers is chosen at runtime and used for generating SDFs.  To
+   *   force the use of `bsdf` you should render the glyph with any of the
+   *   FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and
+   *   then re-render with `FT_RENDER_MODE_SDF`.
+   *
+   *   There are some issues with stability and possible failures of the SDF
+   *   renderers (specifically `sdf`).
+   *
+   *   1. The `sdf` rasterizer is sensitive to really small features (e.g.,
+   *      sharp turns that are less than 1~pixel) and imperfections in the
+   *      glyph's outline, causing artifacts in the final output.
+   *
+   *   2. The `sdf` rasterizer has limited support for handling intersecting
+   *      contours and *cannot* handle self-intersecting contours whatsoever.
+   *      Self-intersection happens when a single connected contour
+   *      intersects itself at some point; having these in your font
+   *      definitely poses a problem to the rasterizer and cause artifacts,
+   *      too.
+   *
+   *   3. Generating SDF for really small glyphs may result in undesirable
+   *      output; the pixel grid (which stores distance information) becomes
+   *      too coarse.
+   *
+   *   4. Since the output buffer is normalized, precision at smaller spreads
+   *      is greater than precision at larger spread values because the
+   *      output range of [0..255] gets mapped to a smaller SDF range.  A
+   *      spread of~2 should be sufficient in most cases.
+   *
+   *   Points (1) and (2) can be avoided by using the `bsdf` rasterizer,
+   *   which is more stable than the `sdf` rasterizer in general.
+   *
+   * @since:
+   *   2.11
+   */
+
+
   /**************************************************************************
    *
    * @property:
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType error codes (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType error code handling (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Support functions for font formats.
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Access of TrueType's 'gasp' table (specification).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType convenience functions to handle glyphs (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Gzip-compressed stream support.
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   FreeType glyph image formats and default raster interface
  *   (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -21,6 +21,11 @@
    * Note: A 'raster' is simply a scan-line converter, used to render
    *       `FT_Outline`s into `FT_Bitmap`s.
    *
+   * Note: This file can be used for `STANDALONE_` compilation of raster
+   *       (B/W) and smooth (anti-aliased) renderers.  Therefore, it must
+   *       rely on standard variable types only instead of aliases in
+   *       `fttypes.h`.
+   *
    */
 
 
@@ -318,7 +323,7 @@ FT_BEGIN_HEADER
    *
    *     If bit~2 is set, bits 5-7 contain the drop-out mode (as defined in
    *     the OpenType specification; the value is the same as the argument to
-   *     the 'SCANMODE' instruction).
+   *     the 'SCANTYPE' instruction).
    *
    *     Bits 3 and~4 are reserved for internal purposes.
    *
@@ -341,14 +346,14 @@ FT_BEGIN_HEADER
    */
   typedef struct  FT_Outline_
   {
-    short       n_contours;      /* number of contours in glyph        */
-    short       n_points;        /* number of points in the glyph      */
+    unsigned short   n_contours;  /* number of contours in glyph        */
+    unsigned short   n_points;    /* number of points in the glyph      */
 
-    FT_Vector*  points;          /* the outline's points               */
-    char*       tags;            /* the points flags                   */
-    short*      contours;        /* the contour end points             */
+    FT_Vector*       points;      /* the outline's points               */
+    unsigned char*   tags;        /* the points flags                   */
+    unsigned short*  contours;    /* the contour end points             */
 
-    int         flags;           /* outline masks                      */
+    int              flags;       /* outline masks                      */
 
   } FT_Outline;
 
@@ -356,8 +361,8 @@ FT_BEGIN_HEADER
 
   /* Following limits must be consistent with */
   /* FT_Outline.{n_contours,n_points}         */
-#define FT_OUTLINE_CONTOURS_MAX  SHRT_MAX
-#define FT_OUTLINE_POINTS_MAX    SHRT_MAX
+#define FT_OUTLINE_CONTOURS_MAX  USHRT_MAX
+#define FT_OUTLINE_POINTS_MAX    USHRT_MAX
 
 
   /**************************************************************************
@@ -434,8 +439,8 @@ FT_BEGIN_HEADER
    *   rasterizer; see the `tags` field in @FT_Outline.
    *
    *   Please refer to the description of the 'SCANTYPE' instruction in the
-   *   OpenType specification (in file `ttinst1.doc`) how simple drop-outs,
-   *   smart drop-outs, and stubs are defined.
+   *   [OpenType specification](https://learn.microsoft.com/en-us/typography/opentype/spec/tt_instructions#scantype)
+   *   how simple drop-outs, smart drop-outs, and stubs are defined.
    */
 #define FT_OUTLINE_NONE             0x0
 #define FT_OUTLINE_OWNER            0x1
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType incremental loading (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   FreeType API for color filtering of subpixel bitmap glyphs
  *   (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Generic list support for FreeType (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Additional debugging APIs.
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Additional Mac-specific API.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType Multiple Master font interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -19,8 +19,13 @@
 #ifndef FTMM_H_
 #define FTMM_H_
 
+#include <freetype/freetype.h>
 
-#include <freetype/t1tables.h>
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
 
 
 FT_BEGIN_HEADER
@@ -54,6 +59,30 @@ FT_BEGIN_HEADER
 
 
   /**************************************************************************
+   *
+   * @enum:
+   *   T1_MAX_MM_XXX
+   *
+   * @description:
+   *   Multiple Masters limits as defined in their specifications.
+   *
+   * @values:
+   *   T1_MAX_MM_AXIS ::
+   *     The maximum number of Multiple Masters axes.
+   *
+   *   T1_MAX_MM_DESIGNS ::
+   *     The maximum number of Multiple Masters designs.
+   *
+   *   T1_MAX_MM_MAP_POINTS ::
+   *     The maximum number of elements in a design map.
+   *
+   */
+#define T1_MAX_MM_AXIS         4
+#define T1_MAX_MM_DESIGNS     16
+#define T1_MAX_MM_MAP_POINTS  20
+
+
+  /**************************************************************************
    *
    * @struct:
    *   FT_MM_Axis
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType modules public interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType module error offsets (specification).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Support for the FT_Outline type used to store glyph shapes of
  *   most scalable font formats (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -112,7 +112,7 @@ FT_BEGIN_HEADER
    *   Degenerate contours, segments, and Bezier arcs may be reported.  In
    *   most cases, it is best to filter these out before using the outline
    *   for stroking or other path modification purposes (which may cause
-   *   degenerate segments to become non-degenrate and visible, like when
+   *   degenerate segments to become non-degenerate and visible, like when
    *   stroke caps are used or the path is otherwise outset).  Some glyph
    *   outlines may contain deliberate degenerate single points for mark
    *   attachement.
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType API for possible FT_Parameter tags (specification only).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType renderer modules public interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType size objects management (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h	2025-06-27 08:03:14.000000000 +0000
@@ -7,7 +7,7 @@
  *
  *   This is _not_ used to retrieve glyph names!
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType path stroker (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   FreeType synthesizing code for emboldening and slanting
  *   (specification).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType low-level system interface definition (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType trigonometric functions (specification).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType simple types definitions (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   High-level 'autohint' module-specific interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Basic OpenType/CFF object type definitions (specification).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Basic OpenType/CFF type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -248,10 +248,10 @@ FT_BEGIN_HEADER
     FT_Byte   num_family_blues;
     FT_Byte   num_family_other_blues;
 
-    FT_Pos    blue_values[14];
-    FT_Pos    other_blues[10];
-    FT_Pos    family_blues[14];
-    FT_Pos    family_other_blues[10];
+    FT_Fixed  blue_values[14];
+    FT_Fixed  other_blues[10];
+    FT_Fixed  family_blues[14];
+    FT_Fixed  family_other_blues[10];
 
     FT_Fixed  blue_scale;
     FT_Pos    blue_shift;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Compiler-specific macro definitions used internally by FreeType.
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Arithmetic computations (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -415,7 +415,7 @@ FT_BEGIN_HEADER
 
 #define FT_MSB( x )  ( 31 - _CountLeadingZeros( x ) )
 
-#elif defined( _M_ARM64 ) || defined( _M_ARM )
+#elif defined( _M_ARM64 ) || defined( _M_ARM ) || defined( _M_ARM64EC )
 
 #include <intrin.h>
 #pragma intrinsic( _CountLeadingZeros )
@@ -455,6 +455,12 @@ FT_BEGIN_HEADER
 
 #define FT_MSB( x )  FT_MSB_i386( x )
 
+#elif defined( __SunOS_5_11 )
+
+#include <string.h>
+
+#define FT_MSB( x )  ( fls( x ) - 1 )
+
 #elif defined( __DECC ) || defined( __DECCXX )
 
 #include <builtins.h>
@@ -489,8 +495,6 @@ FT_BEGIN_HEADER
             FT_Fixed  y );
 
 
-#if 0
-
   /**************************************************************************
    *
    * @function:
@@ -507,12 +511,11 @@ FT_BEGIN_HEADER
    *   The result of 'sqrt(x)'.
    *
    * @note:
-   *   This function is not very fast.
+   *   This function is slow and should be avoided.  Consider @FT_Hypot or
+   *   @FT_Vector_NormLen instead.
    */
-  FT_BASE( FT_Int32 )
-  FT_SqrtFixed( FT_Int32  x );
-
-#endif /* 0 */
+  FT_BASE( FT_UInt32 )
+  FT_SqrtFixed( FT_UInt32  x );
 
 
 #define INT_TO_F26DOT6( x )    ( (FT_Long)(x) * 64  )    /* << 6  */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Debugging and logging component (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType internal font driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph loader (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType memory management macros (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg
  *
  * This file is part of the FreeType project, and may only be used,
@@ -371,8 +371,11 @@ extern "C++"
 #define FT_STRDUP( dst, str )                           \
           FT_MEM_SET_ERROR( FT_MEM_STRDUP( dst, str ) )
 
-#define FT_MEM_DUP( dst, address, size )                                    \
-          (dst) = ft_mem_dup( memory, (address), (FT_ULong)(size), &error )
+#define FT_MEM_DUP( dst, address, size )                       \
+          FT_ASSIGNP_INNER( dst, ft_mem_dup( memory,           \
+                                             (address),        \
+                                             (FT_ULong)(size), \
+                                             &error ) )
 
 #define FT_DUP( dst, address, size )                           \
           FT_MEM_SET_ERROR( FT_MEM_DUP( dst, address, size ) )
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   OpenType Variations type definitions for internal use
  *   with the multi-masters service (specification).
  *
- * Copyright (C) 2022-2023 by
+ * Copyright (C) 2022-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and
  * Dominik Röttsches.
  *
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType private base classes (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -604,12 +604,6 @@ FT_BEGIN_HEADER
 #define FT_FACE_MEMORY( x )   FT_FACE( x )->memory
 #define FT_FACE_STREAM( x )   FT_FACE( x )->stream
 
-#define FT_SIZE_FACE( x )     FT_SIZE( x )->face
-#define FT_SLOT_FACE( x )     FT_SLOT( x )->face
-
-#define FT_FACE_SLOT( x )     FT_FACE( x )->glyph
-#define FT_FACE_SIZE( x )     FT_FACE( x )->size
-
 
   /**************************************************************************
    *
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Get and set properties of PostScript drivers (specification).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Embedded resource forks accessor (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * Masatake YAMATO and Redhat K.K.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType services (specification only).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Stream handling (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Tracing handling (specification only).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -64,6 +64,7 @@ FT_TRACE_DEF( ttbdf )     /* TrueType em
 FT_TRACE_DEF( ttcmap )    /* charmap handler         (ttcmap.c)   */
 FT_TRACE_DEF( ttcolr )    /* glyph layer table       (ttcolr.c)   */
 FT_TRACE_DEF( ttcpal )    /* color palette table     (ttcpal.c)   */
+FT_TRACE_DEF( ttgpos )    /* GPOS handler            (ttgpos.c)   */
 FT_TRACE_DEF( ttsvg )     /* OpenType SVG table      (ttsvg.c)    */
 FT_TRACE_DEF( ttkern )    /* kerning handler         (ttkern.c)   */
 FT_TRACE_DEF( ttload )    /* basic TrueType tables   (ttload.c)   */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType validation support (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Auxiliary functions and data structures related to PostScript fonts
  *   (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -225,6 +225,7 @@ FT_BEGIN_HEADER
 
   typedef enum  T1_FieldLocation_
   {
+    T1_FIELD_LOCATION_NONE = 0,
     T1_FIELD_LOCATION_CID_INFO,
     T1_FIELD_LOCATION_FONT_DICT,
     T1_FIELD_LOCATION_FONT_EXTRA,
@@ -249,6 +250,7 @@ FT_BEGIN_HEADER
   /* structure type used to model object fields */
   typedef struct  T1_FieldRec_
   {
+    FT_UInt             len;          /* field identifier length        */
     const char*         ident;        /* field identifier               */
     T1_FieldLocation    location;
     T1_FieldType        type;         /* type of field                  */
@@ -273,8 +275,9 @@ FT_BEGIN_HEADER
 
 #define T1_NEW_SIMPLE_FIELD( _ident, _type, _fname, _dict ) \
           {                                                 \
+            sizeof ( _ident ) - 1,                          \
             _ident, T1CODE, _type,                          \
-            0,                                              \
+            NULL,                                           \
             FT_FIELD_OFFSET( _fname ),                      \
             FT_FIELD_SIZE( _fname ),                        \
             0, 0,                                           \
@@ -283,6 +286,7 @@ FT_BEGIN_HEADER
 
 #define T1_NEW_CALLBACK_FIELD( _ident, _reader, _dict ) \
           {                                             \
+            sizeof ( _ident ) - 1,                      \
             _ident, T1CODE, T1_FIELD_TYPE_CALLBACK,     \
             (T1_Field_ParseFunc)_reader,                \
             0, 0,                                       \
@@ -292,8 +296,9 @@ FT_BEGIN_HEADER
 
 #define T1_NEW_TABLE_FIELD( _ident, _type, _fname, _max, _dict ) \
           {                                                      \
+            sizeof ( _ident ) - 1,                               \
             _ident, T1CODE, _type,                               \
-            0,                                                   \
+            NULL,                                                \
             FT_FIELD_OFFSET( _fname ),                           \
             FT_FIELD_SIZE_DELTA( _fname ),                       \
             _max,                                                \
@@ -303,8 +308,9 @@ FT_BEGIN_HEADER
 
 #define T1_NEW_TABLE_FIELD2( _ident, _type, _fname, _max, _dict ) \
           {                                                       \
+            sizeof ( _ident ) - 1,                                \
             _ident, T1CODE, _type,                                \
-            0,                                                    \
+            NULL,                                                 \
             FT_FIELD_OFFSET( _fname ),                            \
             FT_FIELD_SIZE_DELTA( _fname ),                        \
             _max, 0,                                              \
@@ -354,6 +360,13 @@ FT_BEGIN_HEADER
 #define T1_FIELD_CALLBACK( _ident, _name, _dict )       \
           T1_NEW_CALLBACK_FIELD( _ident, _name, _dict )
 
+#define T1_FIELD_ZERO                                         \
+          {                                                   \
+            0,                                                \
+            NULL, T1_FIELD_LOCATION_NONE, T1_FIELD_TYPE_NONE, \
+            NULL, 0, 0, 0, 0, 0                               \
+          }
+
 
   /*************************************************************************/
   /*************************************************************************/
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h	2025-06-27 08:03:14.000000000 +0000
@@ -6,7 +6,7 @@
  *   recorders (specification only).  These are used to support native
  *   T1/T2 hints in the 'type1', 'cid', and 'cff' font drivers.
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType BDF services (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType CFF tables loader service (specification).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType CID font services (specification).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * Derek Clegg and Michael Toftdal.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType font format service (specification only).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph dictionary services (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType API for validating TrueTypeGX/AAT tables (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType Kerning service (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType services for metrics variations (specification).
  *
- * Copyright (C) 2016-2023 by
+ * Copyright (C) 2016-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType Multiple Masters and GX var services (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType OpenType validation service (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Internal PFR service functions (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType PostScript name services (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType property service (specification).
  *
- * Copyright (C) 2012-2023 by
+ * Copyright (C) 2012-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType PostScript charmap service (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType PostScript info service (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType SFNT table loading service (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType TrueType/sfnt cmap extra information service.
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * Masatake YAMATO, Redhat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType TrueType engine query service (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType TrueType glyph service.
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * David Turner.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType Windows FNT/FONT service (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   High-level 'sfnt' driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -924,6 +924,7 @@ FT_BEGIN_HEADER
     /* this field was called `load_kerning' up to version 2.1.10 */
     TT_Load_Table_Func  load_kern;
 
+    TT_Load_Table_Func  load_gpos;
     TT_Load_Table_Func  load_gasp;
     TT_Load_Table_Func  load_pclt;
 
@@ -944,6 +945,8 @@ FT_BEGIN_HEADER
 
     /* new elements introduced after version 2.1.10 */
 
+    TT_Face_GetKerningFunc  get_gpos_kerning;
+
     /* load the font directory, i.e., the offset table and */
     /* the table directory                                 */
     TT_Load_Table_Func    load_font_dir;
@@ -1002,6 +1005,7 @@ FT_BEGIN_HEADER
           load_name_,                    \
           free_name_,                    \
           load_kern_,                    \
+          load_gpos_,                    \
           load_gasp_,                    \
           load_pclt_,                    \
           load_bhed_,                    \
@@ -1009,6 +1013,7 @@ FT_BEGIN_HEADER
           get_psname_,                   \
           free_psnames_,                 \
           get_kerning_,                  \
+          get_gpos_kerning_,             \
           load_font_dir_,                \
           load_hmtx_,                    \
           load_eblc_,                    \
@@ -1050,6 +1055,7 @@ FT_BEGIN_HEADER
     load_name_,                          \
     free_name_,                          \
     load_kern_,                          \
+    load_gpos_,                          \
     load_gasp_,                          \
     load_pclt_,                          \
     load_bhed_,                          \
@@ -1057,6 +1063,7 @@ FT_BEGIN_HEADER
     get_psname_,                         \
     free_psnames_,                       \
     get_kerning_,                        \
+    get_gpos_kerning_,                   \
     load_font_dir_,                      \
     load_hmtx_,                          \
     load_eblc_,                          \
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Interface of ot-svg module (specification only).
  *
- * Copyright (C) 2022-2023 by
+ * Copyright (C) 2022-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Basic Type1/Type2 type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -21,7 +21,7 @@
 #define T1TYPES_H_
 
 
-#include <freetype/t1tables.h>
+#include <freetype/ftmm.h>
 #include <freetype/internal/pshints.h>
 #include <freetype/internal/ftserv.h>
 #include <freetype/internal/fthash.h>
@@ -137,6 +137,54 @@ FT_BEGIN_HEADER
   } CID_SubrsRec, *CID_Subrs;
 
 
+  /* this structure is used to store the BlendDesignMap entry for an axis */
+  typedef struct  PS_DesignMap_
+  {
+    FT_Byte    num_points;
+    FT_Long*   design_points;
+    FT_Fixed*  blend_points;
+
+  } PS_DesignMapRec, *PS_DesignMap;
+
+  /* backward compatible definition */
+  typedef PS_DesignMapRec  T1_DesignMap;
+
+
+  typedef struct  PS_BlendRec_
+  {
+    FT_UInt          num_designs;
+    FT_UInt          num_axis;
+
+    FT_String*       axis_names[T1_MAX_MM_AXIS];
+    FT_Fixed*        design_pos[T1_MAX_MM_DESIGNS];
+    PS_DesignMapRec  design_map[T1_MAX_MM_AXIS];
+
+    FT_Fixed*        weight_vector;
+    FT_Fixed*        default_weight_vector;
+
+    PS_FontInfo      font_infos[T1_MAX_MM_DESIGNS + 1];
+    PS_Private       privates  [T1_MAX_MM_DESIGNS + 1];
+
+    FT_ULong         blend_bitflags;
+
+    FT_BBox*         bboxes    [T1_MAX_MM_DESIGNS + 1];
+
+    /* since 2.3.0 */
+
+    /* undocumented, optional: the default design instance;   */
+    /* corresponds to default_weight_vector --                */
+    /* num_default_design_vector == 0 means it is not present */
+    /* in the font and associated metrics files               */
+    FT_UInt          default_design_vector[T1_MAX_MM_DESIGNS];
+    FT_UInt          num_default_design_vector;
+
+  } PS_BlendRec, *PS_Blend;
+
+
+  /* backward compatible definition */
+  typedef PS_BlendRec  T1_Blend;
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Basic SFNT/TrueType type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -24,6 +24,7 @@
 #include <freetype/tttables.h>
 #include <freetype/internal/ftobjs.h>
 #include <freetype/ftcolor.h>
+#include "freetype/fttypes.h"
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 #include <freetype/ftmm.h>
@@ -1581,6 +1582,11 @@ FT_BEGIN_HEADER
     FT_UInt32             kern_avail_bits;
     FT_UInt32             kern_order_bits;
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+    FT_Byte*              gpos_table;
+    FT_Bool               gpos_kerning_available;
+#endif
+
 #ifdef TT_CONFIG_OPTION_BDF
     TT_BDFRec             bdf;
 #endif /* TT_CONFIG_OPTION_BDF */
@@ -1649,9 +1655,9 @@ FT_BEGIN_HEADER
   {
     FT_Memory   memory;
     FT_UShort   max_points;
-    FT_Short    max_contours;
+    FT_UShort   max_contours;
     FT_UShort   n_points;    /* number of points in zone    */
-    FT_Short    n_contours;  /* number of contours          */
+    FT_UShort   n_contours;  /* number of contours          */
 
     FT_Vector*  org;         /* original point coordinates  */
     FT_Vector*  cur;         /* current point coordinates   */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Basic WOFF/WOFF2 type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Interface for OT-SVG support related things (specification).
  *
- * Copyright (C) 2022-2023 by
+ * Copyright (C) 2022-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Basic Type 1/Type 2 tables definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -269,64 +269,6 @@ FT_BEGIN_HEADER
   /* */
 
 
-  /* maximum number of Multiple Masters designs, as defined in the spec */
-#define T1_MAX_MM_DESIGNS     16
-
-  /* maximum number of Multiple Masters axes, as defined in the spec */
-#define T1_MAX_MM_AXIS        4
-
-  /* maximum number of elements in a design map */
-#define T1_MAX_MM_MAP_POINTS  20
-
-
-  /* this structure is used to store the BlendDesignMap entry for an axis */
-  typedef struct  PS_DesignMap_
-  {
-    FT_Byte    num_points;
-    FT_Long*   design_points;
-    FT_Fixed*  blend_points;
-
-  } PS_DesignMapRec, *PS_DesignMap;
-
-  /* backward compatible definition */
-  typedef PS_DesignMapRec  T1_DesignMap;
-
-
-  typedef struct  PS_BlendRec_
-  {
-    FT_UInt          num_designs;
-    FT_UInt          num_axis;
-
-    FT_String*       axis_names[T1_MAX_MM_AXIS];
-    FT_Fixed*        design_pos[T1_MAX_MM_DESIGNS];
-    PS_DesignMapRec  design_map[T1_MAX_MM_AXIS];
-
-    FT_Fixed*        weight_vector;
-    FT_Fixed*        default_weight_vector;
-
-    PS_FontInfo      font_infos[T1_MAX_MM_DESIGNS + 1];
-    PS_Private       privates  [T1_MAX_MM_DESIGNS + 1];
-
-    FT_ULong         blend_bitflags;
-
-    FT_BBox*         bboxes    [T1_MAX_MM_DESIGNS + 1];
-
-    /* since 2.3.0 */
-
-    /* undocumented, optional: the default design instance;   */
-    /* corresponds to default_weight_vector --                */
-    /* num_default_design_vector == 0 means it is not present */
-    /* in the font and associated metrics files               */
-    FT_UInt          default_design_vector[T1_MAX_MM_DESIGNS];
-    FT_UInt          num_default_design_vector;
-
-  } PS_BlendRec, *PS_Blend;
-
-
-  /* backward compatible definition */
-  typedef PS_BlendRec  T1_Blend;
-
-
   /**************************************************************************
    *
    * @struct:
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType name ID definitions (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Basic SFNT/TrueType tables definitions and interface
  *   (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -838,8 +838,9 @@ FT_BEGIN_HEADER
    *     The target charmap.
    *
    * @return:
-   *   The format of `charmap`.  If `charmap` doesn't belong to an SFNT face,
-   *   return -1.
+   *   The format of `charmap`.  If `charmap` doesn't belong to an SFNT face
+   *   (including the synthetic Unicode charmap sometimes created by
+   *   FreeType), return -1.
    */
   FT_EXPORT( FT_Long )
   FT_Get_CMap_Format( FT_CharMap  charmap );
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Tags for TrueType and OpenType tables (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/ft2build.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/ft2build.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/include/ft2build.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/include/ft2build.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType 2 build and setup macros.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c	2025-06-27 08:03:14.000000000 +0000
@@ -7,7 +7,7 @@
  *
  *   Auto-fitter data for blue strings (body).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter data for blue strings (body).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat	2025-06-27 08:03:14.000000000 +0000
@@ -2,7 +2,7 @@
 //
 //   Auto-fitter data for blue strings.
 //
-// Copyright (C) 2013-2023 by
+// Copyright (C) 2013-2024 by
 // David Turner, Robert Wilhelm, and Werner Lemberg.
 //
 // This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h	2025-06-27 08:03:14.000000000 +0000
@@ -7,7 +7,7 @@
  *
  *   Auto-fitter data for blue strings (specification).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter data for blue strings (specification).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for CJK writing system (body).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for CJK writing system (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -84,7 +84,7 @@ FT_BEGIN_HEADER
     /* used for horizontal metrics too for CJK */
     FT_Bool        control_overshoot;
     FT_UInt        blue_count;
-    AF_CJKBlueRec  blues[AF_BLUE_STRINGSET_MAX];
+    AF_CJKBlueRec  blues[AF_BLUE_STRINGSET_MAX_LEN];
 
     FT_Fixed       org_scale;
     FT_Pos         org_delta;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter coverages (specification only).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Auto-fitter dummy routines to be used if no hinting should be
  *   performed (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Auto-fitter dummy routines to be used if no hinting should be
  *   performed (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Autofitter error codes (specification only).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter routines to compute global hinting values (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Auto-fitter routines to compute global hinting values
  *   (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -979,8 +979,8 @@
       /* compute coordinates & Bezier flags, next and prev */
       {
         FT_Vector*  vec           = outline->points;
-        char*       tag           = outline->tags;
-        FT_Short    endpoint      = outline->contours[0];
+        FT_Byte*    tag           = outline->tags;
+        FT_UShort   endpoint      = outline->contours[0];
         AF_Point    end           = points + endpoint;
         AF_Point    prev          = end;
         FT_Int      contour_index = 0;
@@ -1046,16 +1046,16 @@
 
       /* set up the contours array */
       {
-        AF_Point*  contour       = hints->contours;
-        AF_Point*  contour_limit = contour + hints->num_contours;
-        short*     end           = outline->contours;
-        short      idx           = 0;
+        AF_Point*   contour       = hints->contours;
+        AF_Point*   contour_limit = contour + hints->num_contours;
+        FT_UShort*  end           = outline->contours;
+        FT_Int      idx           = 0;
 
 
         for ( ; contour < contour_limit; contour++, end++ )
         {
           contour[0] = points + idx;
-          idx        = (short)( end[0] + 1 );
+          idx        = *end + 1;
         }
       }
 
@@ -1292,7 +1292,7 @@
     AF_Point    point = hints->points;
     AF_Point    limit = point + hints->num_points;
     FT_Vector*  vec   = outline->points;
-    char*       tag   = outline->tags;
+    FT_Byte*    tag   = outline->tags;
 
 
     for ( ; point < limit; point++, vec++, tag++ )
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for Indic writing system (body).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Auto-fitter hinting routines for Indic writing system
  *   (specification).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for latin writing system (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -981,7 +981,7 @@
       /* `ref' and `shoot' values of two blue zones must not overlap */
 
       FT_UInt       i;
-      AF_LatinBlue  blue_sorted[AF_BLUE_STRINGSET_MAX_LEN + 2];
+      AF_LatinBlue  blue_sorted[AF_BLUE_STRINGSET_MAX_LEN];
 
 
       for ( i = 0; i < axis->blue_count; i++ )
@@ -1263,10 +1263,9 @@
               max_height = FT_MAX( max_height, -Axis->blues[nn].descender );
             }
 
-            dist  = FT_ABS( FT_MulFix( max_height, new_scale - scale ) );
-            dist &= ~127;
+            dist  = FT_MulFix( max_height, new_scale - scale );
 
-            if ( dist == 0 )
+            if ( -128 < dist && dist < 128 )
             {
               FT_TRACE5(( "af_latin_metrics_scale_dim:"
                           " x height alignment (style `%s'):\n",
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Auto-fitter hinting routines for latin writing system
  *   (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -98,7 +98,7 @@ FT_BEGIN_HEADER
 
     /* ignored for horizontal metrics */
     FT_UInt          blue_count;
-    AF_LatinBlueRec  blues[AF_BLUE_STRINGSET_MAX];
+    AF_LatinBlueRec  blues[AF_BLUE_STRINGSET_MAX_LEN];
 
     FT_Fixed         org_scale;
     FT_Pos           org_delta;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter glyph loading routines (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter glyph loading routines (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter module implementation (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -438,7 +438,7 @@
     AF_Module  module = (AF_Module)module_;
 
     FT_Error   error  = FT_Err_Ok;
-    FT_Memory  memory = module->root.library->memory;
+    FT_Memory  memory = module->root.memory;
 
 #ifdef FT_DEBUG_AUTOFIT
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter module implementation (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter Unicode script ranges (body).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter Unicode script ranges (specification).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter scripts (specification only).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   HarfBuzz interface for accessing OpenType features (body).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   HarfBuzz interface for accessing OpenType features (specification).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter styles (specification only).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter types (specification only).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter writing system declarations (specification only).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter writing systems iterator (specification only).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Quick computation of advance widths (body).
  *
- * Copyright (C) 2008-2023 by
+ * Copyright (C) 2008-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftbase.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftbase.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftbase.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftbase.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Private functions used in the `base' module (specification).
  *
- * Copyright (C) 2008-2023 by
+ * Copyright (C) 2008-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType bbox computation (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
@@ -489,7 +489,7 @@
       return FT_THROW( Invalid_Outline );
 
     /* if outline is empty, return (0,0,0,0) */
-    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+    if ( outline->n_points == 0 || outline->n_contours == 0 )
     {
       abbox->xMin = abbox->xMax = 0;
       abbox->yMin = abbox->yMax = 0;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType utility functions for bitmaps (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Arithmetic computations (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -69,13 +69,15 @@
 
   /* transfer sign, leaving a positive number;                        */
   /* we need an unsigned value to safely negate INT_MIN (or LONG_MIN) */
-#define FT_MOVE_SIGN( x, x_unsigned, s ) \
-  FT_BEGIN_STMNT                         \
-    if ( x < 0 )                         \
-    {                                    \
-      x_unsigned = 0U - (x_unsigned);    \
-      s          = -s;                   \
-    }                                    \
+#define FT_MOVE_SIGN( utype, x, x_unsigned, s ) \
+  FT_BEGIN_STMNT                                \
+    if ( x < 0 )                                \
+    {                                           \
+      x_unsigned = 0U - (utype)x;               \
+      s          = -s;                          \
+    }                                           \
+    else                                        \
+      x_unsigned = (utype)x;                    \
   FT_END_STMNT
 
   /* The following three functions are available regardless of whether */
@@ -179,13 +181,9 @@
     FT_Long    d_;
 
 
-    a = (FT_UInt64)a_;
-    b = (FT_UInt64)b_;
-    c = (FT_UInt64)c_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
-    FT_MOVE_SIGN( c_, c, s );
+    FT_MOVE_SIGN( FT_UInt64, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt64, b_, b, s );
+    FT_MOVE_SIGN( FT_UInt64, c_, c, s );
 
     d = c > 0 ? ( a * b + ( c >> 1 ) ) / c
               : 0x7FFFFFFFUL;
@@ -208,13 +206,9 @@
     FT_Long    d_;
 
 
-    a = (FT_UInt64)a_;
-    b = (FT_UInt64)b_;
-    c = (FT_UInt64)c_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
-    FT_MOVE_SIGN( c_, c, s );
+    FT_MOVE_SIGN( FT_UInt64, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt64, b_, b, s );
+    FT_MOVE_SIGN( FT_UInt64, c_, c, s );
 
     d = c > 0 ? a * b / c
               : 0x7FFFFFFFUL;
@@ -257,11 +251,8 @@
     FT_Long    q_;
 
 
-    a = (FT_UInt64)a_;
-    b = (FT_UInt64)b_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
+    FT_MOVE_SIGN( FT_UInt64, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt64, b_, b, s );
 
     q = b > 0 ? ( ( a << 16 ) + ( b >> 1 ) ) / b
               : 0x7FFFFFFFUL;
@@ -422,13 +413,9 @@
 
     /* XXX: this function does not allow 64-bit arguments */
 
-    a = (FT_UInt32)a_;
-    b = (FT_UInt32)b_;
-    c = (FT_UInt32)c_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
-    FT_MOVE_SIGN( c_, c, s );
+    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
+    FT_MOVE_SIGN( FT_UInt32, c_, c, s );
 
     if ( c == 0 )
       a = 0x7FFFFFFFUL;
@@ -470,13 +457,9 @@
 
     /* XXX: this function does not allow 64-bit arguments */
 
-    a = (FT_UInt32)a_;
-    b = (FT_UInt32)b_;
-    c = (FT_UInt32)c_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
-    FT_MOVE_SIGN( c_, c, s );
+    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
+    FT_MOVE_SIGN( FT_UInt32, c_, c, s );
 
     if ( c == 0 )
       a = 0x7FFFFFFFUL;
@@ -575,11 +558,8 @@
 
     /* XXX: this function does not allow 64-bit arguments */
 
-    a = (FT_UInt32)a_;
-    b = (FT_UInt32)b_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
+    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
 
     if ( a + ( b >> 8 ) <= 8190UL )
       a = ( a * b + 0x8000UL ) >> 16;
@@ -614,11 +594,8 @@
 
     /* XXX: this function does not allow 64-bit arguments */
 
-    a = (FT_UInt32)a_;
-    b = (FT_UInt32)b_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
+    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
 
     if ( b == 0 )
     {
@@ -829,11 +806,8 @@
     FT_Int     sx = 1, sy = 1, shift;
 
 
-    x = (FT_UInt32)x_;
-    y = (FT_UInt32)y_;
-
-    FT_MOVE_SIGN( x_, x, sx );
-    FT_MOVE_SIGN( y_, y, sy );
+    FT_MOVE_SIGN( FT_UInt32, x_, x, sx );
+    FT_MOVE_SIGN( FT_UInt32, y_, y, sy );
 
     /* trivial cases */
     if ( x == 0 )
@@ -913,43 +887,71 @@
   }
 
 
-#if 0
-
   /* documentation is in ftcalc.h */
 
-  FT_BASE_DEF( FT_Int32 )
-  FT_SqrtFixed( FT_Int32  x )
+  FT_BASE_DEF( FT_UInt32 )
+  FT_SqrtFixed( FT_UInt32  v )
   {
-    FT_UInt32  root, rem_hi, rem_lo, test_div;
-    FT_Int     count;
+    if ( v == 0 )
+      return 0;
 
+#ifndef FT_INT64
+
+    /* Algorithm by Christophe Meessen (1993) with overflow fixed and     */
+    /* rounding added.  Any unsigned fixed 16.16 argument is acceptable.  */
+    /* However, this algorithm is slower than the Babylonian method with  */
+    /* a good initial guess.  We only use it for large 32-bit values when */
+    /* 64-bit computations are not desirable.                             */
+    else if ( v > 0x10000U )
+    {
+      FT_UInt32  r = v >> 1;
+      FT_UInt32  q = ( v & 1 ) << 15;
+      FT_UInt32  b = 0x20000000;
+      FT_UInt32  t;
 
-    root = 0;
 
-    if ( x > 0 )
-    {
-      rem_hi = 0;
-      rem_lo = (FT_UInt32)x;
-      count  = 24;
       do
       {
-        rem_hi   = ( rem_hi << 2 ) | ( rem_lo >> 30 );
-        rem_lo <<= 2;
-        root   <<= 1;
-        test_div = ( root << 1 ) + 1;
-
-        if ( rem_hi >= test_div )
+        t = q + b;
+        if ( r >= t )
         {
-          rem_hi -= test_div;
-          root   += 1;
+          r -= t;
+          q  = t + b;  /* equivalent to q += 2*b */
         }
-      } while ( --count );
+        r <<= 1;
+        b >>= 1;
+
+      } while ( b > 0x10 );  /* exactly 25 cycles */
+
+      return ( q + 0x40 ) >> 7;
     }
+    else
+    {
+      FT_UInt32  r = ( v << 16 ) - 1;
 
-    return (FT_Int32)root;
-  }
+#else /* FT_INT64 */
 
-#endif /* 0 */
+    else
+    {
+      FT_UInt64  r = ( (FT_UInt64)v << 16 ) - 1;
+
+#endif /* FT_INT64 */
+
+      FT_UInt32  q = 1 << ( ( 17 + FT_MSB( v ) ) >> 1 );
+      FT_UInt32  t;
+
+
+      /* Babylonian method with rounded-up division */
+      do
+      {
+        t = q;
+        q = ( t + (FT_UInt32)( r / t ) + 1 ) >> 1;
+
+      } while ( q != t );  /* less than 6 cycles */
+
+      return q;
+    }
+  }
 
 
   /* documentation is in ftcalc.h */
@@ -1094,11 +1096,8 @@
       FT_UInt32  factor;
 
 
-      scalar = (FT_UInt32)s[i];
-      factor = (FT_UInt32)f[i];
-
-      FT_MOVE_SIGN( s[i], scalar, sign );
-      FT_MOVE_SIGN( f[i], factor, sign );
+      FT_MOVE_SIGN( FT_UInt32, s[i], scalar, sign );
+      FT_MOVE_SIGN( FT_UInt32, f[i], factor, sign );
 
       ft_multo64( scalar, factor, &multResult );
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftcid.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftcid.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftcid.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftcid.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing CID font information.
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * Derek Clegg and Michael Toftdal.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType's glyph color management (body).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Memory debugger (body).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Debugging and logging component (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file for font formats (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file to access FSType data (body).
  *
- * Copyright (C) 2008-2023 by
+ * Copyright (C) 2008-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Access of TrueType's `gasp' table (body).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph loader (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg
  *
  * This file is part of the FreeType project, and may only be used,
@@ -355,34 +355,25 @@
   FT_BASE_DEF( void )
   FT_GlyphLoader_Add( FT_GlyphLoader  loader )
   {
-    FT_GlyphLoad  base;
-    FT_GlyphLoad  current;
-
-    FT_Int        n_curr_contours;
-    FT_Int        n_base_points;
-    FT_Int        n;
+    FT_Outline*  base;
+    FT_Outline*  current;
+    FT_Int       n;
 
 
     if ( !loader )
       return;
 
-    base    = &loader->base;
-    current = &loader->current;
-
-    n_curr_contours = current->outline.n_contours;
-    n_base_points   = base->outline.n_points;
+    base    = &loader->base.outline;
+    current = &loader->current.outline;
 
-    base->outline.n_points =
-      (short)( base->outline.n_points + current->outline.n_points );
-    base->outline.n_contours =
-      (short)( base->outline.n_contours + current->outline.n_contours );
+    /* adjust contours count in newest outline */
+    for ( n = 0; n < current->n_contours; n++ )
+      current->contours[n] += base->n_points;
 
-    base->num_subglyphs += current->num_subglyphs;
+    base->n_points   += current->n_points;
+    base->n_contours += current->n_contours;
 
-    /* adjust contours count in newest outline */
-    for ( n = 0; n < n_curr_contours; n++ )
-      current->outline.contours[n] =
-        (short)( current->outline.contours[n] + n_base_points );
+    loader->base.num_subglyphs += loader->current.num_subglyphs;
 
     /* prepare for another new glyph image */
     FT_GlyphLoader_Prepare( loader );
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType convenience functions to handle glyphs (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftinit.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftinit.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftinit.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftinit.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType initialization layer (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType API for color filtering of subpixel bitmap glyphs (body).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftmac.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftmac.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftmac.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftmac.c	2025-06-27 08:03:14.000000000 +0000
@@ -8,7 +8,7 @@
  * This file is for Mac OS X only; see builds/mac/ftoldmac.c for
  * classic platforms built by MPW.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -812,6 +812,7 @@
     ResourceIndex  res_index;
     Handle         fond;
     short          num_faces_in_res;
+    FT_Long        count;
 
 
     if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
@@ -821,8 +822,10 @@
     if ( ResError() )
       return FT_THROW( Cannot_Open_Resource );
 
+    res_index        = 1;
     num_faces_in_res = 0;
-    for ( res_index = 1; ; res_index++ )
+    count            = face_index;
+    while ( count >= 0 )
     {
       short  num_faces_in_fond;
 
@@ -834,15 +837,21 @@
       num_faces_in_fond  = count_faces( fond, pathname );
       num_faces_in_res  += num_faces_in_fond;
 
-      if ( 0 <= face_index && face_index < num_faces_in_fond && error )
-        error = FT_New_Face_From_FOND( library, fond, face_index, aface );
+      if ( count < num_faces_in_fond )
+        error = FT_New_Face_From_FOND( library, fond, count, aface );
 
-      face_index -= num_faces_in_fond;
+      res_index++;
+      count -= num_faces_in_fond;
     }
 
     CloseResFile( res_ref );
+
     if ( !error && aface && *aface )
-      (*aface)->num_faces = num_faces_in_res;
+    {
+      (*aface)->num_faces  = num_faces_in_res;
+      (*aface)->face_index = face_index;
+    }
+
     return error;
   }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftmm.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftmm.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftmm.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftmm.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Multiple Master font support (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType private base classes (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -2302,7 +2302,10 @@
                                       face_index_internal, aface );
       FT_FREE( data_offsets );
       if ( !error )
-        (*aface)->num_faces = count;
+      {
+        (*aface)->num_faces  = count;
+        (*aface)->face_index = face_index_internal;
+      }
     }
 
     return error;
@@ -5791,7 +5794,7 @@
     ttface = (TT_Face)face;
     sfnt   = (SFNT_Service)ttface->sfnt;
 
-    if ( sfnt->get_colr_layer )
+    if ( sfnt->get_colr_glyph_paint )
       return sfnt->get_colr_glyph_paint( ttface,
                                          base_glyph,
                                          root_transform,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType outline management (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -53,7 +53,7 @@
 
     FT_Vector*  point;
     FT_Vector*  limit;
-    char*       tags;
+    FT_Byte*    tags;
 
     FT_Error    error;
 
@@ -332,8 +332,8 @@
          FT_NEW_ARRAY( anoutline->contours, numContours ) )
       goto Fail;
 
-    anoutline->n_points    = (FT_Short)numPoints;
-    anoutline->n_contours  = (FT_Short)numContours;
+    anoutline->n_points    = (FT_UShort)numPoints;
+    anoutline->n_contours  = (FT_UShort)numContours;
     anoutline->flags      |= FT_OUTLINE_OWNER;
 
     return FT_Err_Ok;
@@ -359,12 +359,14 @@
       FT_Int  n;
 
 
+      FT_TRACE5(( "FT_Outline_Check: contours = %d, points = %d\n",
+                  n_contours, n_points ));
       /* empty glyph? */
       if ( n_points == 0 && n_contours == 0 )
         return FT_Err_Ok;
 
       /* check point and contour counts */
-      if ( n_points <= 0 || n_contours <= 0 )
+      if ( n_points == 0 || n_contours == 0 )
         goto Bad;
 
       end0 = -1;
@@ -576,13 +578,13 @@
 
       /* reverse tags table */
       {
-        char*  p = outline->tags + first;
-        char*  q = outline->tags + last;
+        FT_Byte*  p = outline->tags + first;
+        FT_Byte*  q = outline->tags + last;
 
 
         while ( p < q )
         {
-          char  swap;
+          FT_Byte  swap;
 
 
           swap = *p;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   FreeType API for checking patented TrueType bytecode instructions
  *   (body).  Obsolete, retained for backward compatibility.
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * David Turner.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Get and set properties of PostScript drivers (body).
  *   See `ftdriver.h' for available properties.
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Embedded resource forks accessor (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * Masatake YAMATO and Redhat K.K.
  *
  * FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c	2025-06-27 08:03:14.000000000 +0000
@@ -7,7 +7,7 @@
  *
  *   This is _not_ used to retrieve glyph names!
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftstream.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftstream.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftstream.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftstream.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   I/O stream support (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -763,10 +763,10 @@
       case ft_frame_bytes:  /* read a byte sequence */
       case ft_frame_skip:   /* skip some bytes      */
         {
-          FT_UInt  len = fields->size;
+          FT_Offset  len = fields->size;
 
 
-          if ( cursor + len > stream->limit )
+          if ( len > (FT_Offset)( stream->limit - cursor ) )
           {
             error = FT_THROW( Invalid_Stream_Operation );
             goto Exit;
@@ -830,7 +830,7 @@
         goto Exit;
       }
 
-      /* now, compute the signed value is necessary */
+      /* now, compute the signed value if necessary */
       if ( fields->value & FT_FRAME_OP_SIGNED )
         value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType path stroker (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -711,7 +711,7 @@
     {
       FT_UInt   count = border->num_points;
       FT_Byte*  read  = border->tags;
-      FT_Byte*  write = (FT_Byte*)outline->tags + outline->n_points;
+      FT_Byte*  write = outline->tags + outline->n_points;
 
 
       for ( ; count > 0; count--, read++, write++ )
@@ -727,10 +727,10 @@
 
     /* copy contours */
     {
-      FT_UInt    count = border->num_points;
-      FT_Byte*   tags  = border->tags;
-      FT_Short*  write = outline->contours + outline->n_contours;
-      FT_Short   idx   = (FT_Short)outline->n_points;
+      FT_UInt     count = border->num_points;
+      FT_Byte*    tags  = border->tags;
+      FT_UShort*  write = outline->contours + outline->n_contours;
+      FT_UShort   idx   = outline->n_points;
 
 
       for ( ; count > 0; count--, tags++, idx++ )
@@ -743,7 +743,7 @@
       }
     }
 
-    outline->n_points += (short)border->num_points;
+    outline->n_points += (FT_UShort)border->num_points;
 
     FT_ASSERT( FT_Outline_Check( outline ) == 0 );
   }
@@ -2050,7 +2050,7 @@
 
     FT_Vector*  point;
     FT_Vector*  limit;
-    char*       tags;
+    FT_Byte*    tags;
 
     FT_Error    error;
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType synthesizing code for emboldening and slanting (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   ANSI-specific FreeType low-level system interface (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType trigonometric functions (body).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/fttype1.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/fttype1.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/fttype1.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/fttype1.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file for PS names support (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftutil.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftutil.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/base/ftutil.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/base/ftutil.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file for memory and list management (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CFF character mapping table (cmap) support (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CFF character mapping table (cmap) support (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   OpenType font driver implementation (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   High-level OpenType driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CFF error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   OpenType Glyph Loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   OpenType Glyph Loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffload.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffload.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffload.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffload.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   OpenType and CFF data/program tables loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -1202,17 +1202,21 @@
         {
           CFF_AxisCoords*  axis = &region->axisList[j];
 
-          FT_Int16  start14, peak14, end14;
+          FT_Int  start, peak, end;
 
 
-          if ( FT_READ_SHORT( start14 ) ||
-               FT_READ_SHORT( peak14 )  ||
-               FT_READ_SHORT( end14 )   )
+          if ( FT_READ_SHORT( start ) ||
+               FT_READ_SHORT( peak )  ||
+               FT_READ_SHORT( end )   )
             goto Exit;
 
-          axis->startCoord = FT_fdot14ToFixed( start14 );
-          axis->peakCoord  = FT_fdot14ToFixed( peak14 );
-          axis->endCoord   = FT_fdot14ToFixed( end14 );
+          /* immediately tag invalid ranges with special peak = 0 */
+          if ( ( start < 0 && end > 0 ) || start > peak || peak > end )
+            peak = 0;
+
+          axis->startCoord = FT_fdot14ToFixed( start );
+          axis->peakCoord  = FT_fdot14ToFixed( peak );
+          axis->endCoord   = FT_fdot14ToFixed( end );
         }
       }
 
@@ -1379,10 +1383,10 @@
       /* opcode in both CFF and CFF2 DICTs.  See `cff_parse_num' for    */
       /* decode of this, which rounds to an integer.                    */
       *subFont->blend_top++ = 255;
-      *subFont->blend_top++ = (FT_Byte)( sum >> 24 );
-      *subFont->blend_top++ = (FT_Byte)( sum >> 16 );
-      *subFont->blend_top++ = (FT_Byte)( sum >>  8 );
-      *subFont->blend_top++ = (FT_Byte)sum;
+      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum >> 24 );
+      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum >> 16 );
+      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum >>  8 );
+      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum );
     }
 
     /* leave only numBlends results on parser stack */
@@ -1495,44 +1499,31 @@
       for ( j = 0; j < lenNDV; j++ )
       {
         CFF_AxisCoords*  axis = &varRegion->axisList[j];
-        FT_Fixed         axisScalar;
 
 
-        /* compute the scalar contribution of this axis; */
-        /* ignore invalid ranges                         */
-        if ( axis->startCoord > axis->peakCoord ||
-             axis->peakCoord > axis->endCoord   )
-          axisScalar = FT_FIXED_ONE;
-
-        else if ( axis->startCoord < 0 &&
-                  axis->endCoord > 0   &&
-                  axis->peakCoord != 0 )
-          axisScalar = FT_FIXED_ONE;
-
-        /* peak of 0 means ignore this axis */
-        else if ( axis->peakCoord == 0 )
-          axisScalar = FT_FIXED_ONE;
+        /* compute the scalar contribution of this axis */
+        /* with peak of 0 used for invalid axes         */
+        if ( axis->peakCoord == NDV[j] ||
+             axis->peakCoord == 0      )
+          continue;
 
         /* ignore this region if coords are out of range */
-        else if ( NDV[j] < axis->startCoord ||
-                  NDV[j] > axis->endCoord   )
-          axisScalar = 0;
-
-        /* calculate a proportional factor */
-        else
+        else if ( NDV[j] <= axis->startCoord ||
+                  NDV[j] >= axis->endCoord   )
         {
-          if ( NDV[j] == axis->peakCoord )
-            axisScalar = FT_FIXED_ONE;
-          else if ( NDV[j] < axis->peakCoord )
-            axisScalar = FT_DivFix( NDV[j] - axis->startCoord,
-                                    axis->peakCoord - axis->startCoord );
-          else
-            axisScalar = FT_DivFix( axis->endCoord - NDV[j],
-                                    axis->endCoord - axis->peakCoord );
+          blend->BV[master] = 0;
+          break;
         }
 
-        /* take product of all the axis scalars */
-        blend->BV[master] = FT_MulFix( blend->BV[master], axisScalar );
+        /* adjust proportionally */
+        else if ( NDV[j] < axis->peakCoord )
+          blend->BV[master] = FT_MulDiv( blend->BV[master],
+                                         NDV[j] - axis->startCoord,
+                                         axis->peakCoord - axis->startCoord );
+        else   /* NDV[j] > axis->peakCoord ) */
+          blend->BV[master] = FT_MulDiv( blend->BV[master],
+                                         axis->endCoord - NDV[j],
+                                         axis->endCoord - axis->peakCoord );
       }
 
       FT_TRACE4(( ", %f ",
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffload.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffload.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffload.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffload.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   OpenType & CFF data/program tables loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   OpenType objects manager (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -42,6 +42,8 @@
 #include <freetype/internal/psaux.h>
 #include <freetype/internal/services/svcfftl.h>
 
+#define CFF_fixedToInt( x )                          \
+          ( (FT_Short)( ( (x) + 0x8000U ) >> 16 ) )
 
   /**************************************************************************
    *
@@ -124,19 +126,20 @@
 
     count = priv->num_blue_values = cpriv->num_blue_values;
     for ( n = 0; n < count; n++ )
-      priv->blue_values[n] = (FT_Short)cpriv->blue_values[n];
+      priv->blue_values[n] = CFF_fixedToInt( cpriv->blue_values[n] );
 
     count = priv->num_other_blues = cpriv->num_other_blues;
     for ( n = 0; n < count; n++ )
-      priv->other_blues[n] = (FT_Short)cpriv->other_blues[n];
+      priv->other_blues[n] = CFF_fixedToInt( cpriv->other_blues[n] );
 
     count = priv->num_family_blues = cpriv->num_family_blues;
     for ( n = 0; n < count; n++ )
-      priv->family_blues[n] = (FT_Short)cpriv->family_blues[n];
+      priv->family_blues[n] = CFF_fixedToInt( cpriv->family_blues[n] );
 
     count = priv->num_family_other_blues = cpriv->num_family_other_blues;
     for ( n = 0; n < count; n++ )
-      priv->family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n];
+      priv->family_other_blues[n] =
+        CFF_fixedToInt( cpriv->family_other_blues[n] );
 
     priv->blue_scale = cpriv->blue_scale;
     priv->blue_shift = (FT_Int)cpriv->blue_shift;
@@ -421,32 +424,23 @@
   static void
   remove_subset_prefix( FT_String*  name )
   {
-    FT_Int32  idx             = 0;
-    FT_Int32  length          = (FT_Int32)ft_strlen( name ) + 1;
-    FT_Bool   continue_search = 1;
+    FT_UInt32  i = 0, idx = 0;
 
 
-    while ( continue_search )
+    /* six ASCII uppercase letters followed by a plus sign */
+    while ( 'A' <= name[i] && name[i++] <= 'Z' &&
+            'A' <= name[i] && name[i++] <= 'Z' &&
+            'A' <= name[i] && name[i++] <= 'Z' &&
+            'A' <= name[i] && name[i++] <= 'Z' &&
+            'A' <= name[i] && name[i++] <= 'Z' &&
+            'A' <= name[i] && name[i++] <= 'Z' &&
+                              name[i++] == '+' )
     {
-      if ( length >= 7 && name[6] == '+' )
-      {
-        for ( idx = 0; idx < 6; idx++ )
-        {
-          /* ASCII uppercase letters */
-          if ( !( 'A' <= name[idx] && name[idx] <= 'Z' ) )
-            continue_search = 0;
-        }
-
-        if ( continue_search )
-        {
-          for ( idx = 7; idx < length; idx++ )
-            name[idx - 7] = name[idx];
-          length -= 7;
-        }
-      }
-      else
-        continue_search = 0;
+      idx = i;
     }
+
+    if ( idx )
+      FT_MEM_MOVE( name, name + idx, ft_strlen( name + idx ) + 1 );
   }
 
 
@@ -456,42 +450,20 @@
   remove_style( FT_String*        family_name,
                 const FT_String*  style_name )
   {
-    FT_Int32  family_name_length, style_name_length;
+    FT_String*        f = family_name + ft_strlen( family_name );
+    const FT_String*  s =  style_name + ft_strlen(  style_name );
 
 
-    family_name_length = (FT_Int32)ft_strlen( family_name );
-    style_name_length  = (FT_Int32)ft_strlen( style_name );
-
-    if ( family_name_length > style_name_length )
-    {
-      FT_Int  idx;
-
-
-      for ( idx = 1; idx <= style_name_length; idx++ )
-      {
-        if ( family_name[family_name_length - idx] !=
-             style_name[style_name_length - idx] )
-          break;
-      }
-
-      if ( idx > style_name_length )
-      {
-        /* family_name ends with style_name; remove it */
-        idx = family_name_length - style_name_length - 1;
-
-        /* also remove special characters     */
-        /* between real family name and style */
-        while ( idx > 0                     &&
-                ( family_name[idx] == '-' ||
-                  family_name[idx] == ' ' ||
-                  family_name[idx] == '_' ||
-                  family_name[idx] == '+' ) )
-          idx--;
-
-        if ( idx > 0 )
-          family_name[idx + 1] = '\0';
-      }
-    }
+    /* compare strings moving backwards */
+    while ( s > style_name )
+      if ( f == family_name || *--s != *--f )
+        return;
+
+    /* terminate and remove special characters */
+    do
+      *f = '\0';
+    while ( f-- > family_name                                    &&
+            ( *f == '-' || *f == ' ' || *f == '_' || *f == '+' ) );
   }
 
 
@@ -722,8 +694,7 @@
         FT_UInt  instance_index = (FT_UInt)face_index >> 16;
 
 
-        if ( FT_HAS_MULTIPLE_MASTERS( cffface ) &&
-             instance_index > 0                 )
+        if ( FT_HAS_MULTIPLE_MASTERS( cffface ) )
         {
           error = FT_Set_Named_Instance( cffface, instance_index );
           if ( error )
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   OpenType objects manager (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CFF token stream parser (body)
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -501,10 +501,10 @@
       return cff_parse_real( *d, parser->limit, scaling, NULL );
     else if ( **d == 255 )
     {
-      FT_Fixed val = ( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) |
-                         ( (FT_UInt32)*( d[0] + 2 ) << 16 ) |
-                         ( (FT_UInt32)*( d[0] + 3 ) <<  8 ) |
-                           (FT_UInt32)*( d[0] + 4 )         ) );
+      FT_Fixed val = (FT_Int32)( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) |
+                                   ( (FT_UInt32)*( d[0] + 2 ) << 16 ) |
+                                   ( (FT_UInt32)*( d[0] + 3 ) <<  8 ) |
+                                     (FT_UInt32)*( d[0] + 4 )         ) );
 
       if ( scaling )
       {
@@ -1031,10 +1031,14 @@
           CFF_FIELD( code, name, id, cff_kind_string )
 #define CFF_FIELD_BOOL( code, name, id )             \
           CFF_FIELD( code, name, id, cff_kind_bool )
+#define CFF_FIELD_DELTA( code, name, max, id )                        \
+          CFF_FIELD_DELTA_KIND( code, name, max, id, cff_kind_delta )
+#define CFF_FIELD_DELTA_FIXED( code, name, max, id )                        \
+          CFF_FIELD_DELTA_KIND( code, name, max, id, cff_kind_delta_fixed )
 
 
 #undef  CFF_FIELD
-#undef  CFF_FIELD_DELTA
+#undef  CFF_FIELD_DELTA_KIND
 
 
 #ifndef FT_DEBUG_LEVEL_TRACE
@@ -1064,18 +1068,18 @@
             code | CFFCODE,               \
             FT_FIELD_OFFSET( name ),      \
             FT_FIELD_SIZE( name ),        \
-            0, 0, 0                       \
+            NULL, 0, 0                    \
           },
 
-#define CFF_FIELD_DELTA( code, name, max, id ) \
-          {                                    \
-            cff_kind_delta,                    \
-            code | CFFCODE,                    \
-            FT_FIELD_OFFSET( name ),           \
-            FT_FIELD_SIZE_DELTA( name ),       \
-            0,                                 \
-            max,                               \
-            FT_FIELD_OFFSET( num_ ## name )    \
+#define CFF_FIELD_DELTA_KIND( code, name, max, id, kind ) \
+          {                                               \
+            kind,                                         \
+            code | CFFCODE,                               \
+            FT_FIELD_OFFSET( name ),                      \
+            FT_FIELD_SIZE_DELTA( name ),                  \
+            NULL,                                         \
+            max,                                          \
+            FT_FIELD_OFFSET( num_ ## name )               \
           },
 
   static const CFF_Field_Handler  cff_field_handlers[] =
@@ -1083,7 +1087,7 @@
 
 #include "cfftoken.h"
 
-    { 0, 0, 0, 0, 0, 0, 0 }
+    { 0, 0, 0, 0, NULL, 0, 0 }
   };
 
 
@@ -1117,20 +1121,20 @@
             code | CFFCODE,               \
             FT_FIELD_OFFSET( name ),      \
             FT_FIELD_SIZE( name ),        \
-            0, 0, 0,                      \
+            NULL, 0, 0,                   \
             id                            \
           },
 
-#define CFF_FIELD_DELTA( code, name, max, id ) \
-          {                                    \
-            cff_kind_delta,                    \
-            code | CFFCODE,                    \
-            FT_FIELD_OFFSET( name ),           \
-            FT_FIELD_SIZE_DELTA( name ),       \
-            0,                                 \
-            max,                               \
-            FT_FIELD_OFFSET( num_ ## name ),   \
-            id                                 \
+#define CFF_FIELD_DELTA_KIND( code, name, max, id, kind ) \
+          {                                               \
+            kind,                                         \
+            code | CFFCODE,                               \
+            FT_FIELD_OFFSET( name ),                      \
+            FT_FIELD_SIZE_DELTA( name ),                  \
+            NULL,                                         \
+            max,                                          \
+            FT_FIELD_OFFSET( num_ ## name ),              \
+            id                                            \
           },
 
   static const CFF_Field_Handler  cff_field_handlers[] =
@@ -1138,7 +1142,7 @@
 
 #include "cfftoken.h"
 
-    { 0, 0, 0, 0, 0, 0, 0, 0 }
+    { 0, 0, 0, 0, NULL, 0, 0, NULL }
   };
 
 
@@ -1356,7 +1360,8 @@
 
             /* check that we have enough arguments -- except for */
             /* delta encoded arrays, which can be empty          */
-            if ( field->kind != cff_kind_delta && num_args < 1 )
+            if ( field->kind != cff_kind_delta                       &&
+                 field->kind != cff_kind_delta_fixed && num_args < 1 )
               goto Stack_Underflow;
 
             switch ( field->kind )
@@ -1465,6 +1470,38 @@
 
                   q += field->size;
                   num_args--;
+                }
+
+                FT_TRACE4(( "]\n" ));
+              }
+              break;
+
+            case cff_kind_delta_fixed:
+              {
+                FT_Byte*   qcount = (FT_Byte*)parser->object +
+                                      field->count_offset;
+
+                FT_Byte**  data = parser->stack;
+
+
+                if ( num_args > field->array_max )
+                  num_args = field->array_max;
+
+                FT_TRACE4(( " [" ));
+
+                /* store count */
+                *qcount = (FT_Byte)num_args;
+
+                val = 0;
+                while ( num_args > 0 )
+                {
+                  val = ADD_LONG( val, cff_parse_fixed( parser, data++ ) );
+                  *(FT_Long*)q = val;
+
+                  FT_TRACE4(( " %f\n", (double)val / 65536 ));
+
+                  q += field->size;
+                  num_args--;
                 }
 
                 FT_TRACE4(( "]\n" ));
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CFF token stream parser (specification)
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -107,6 +107,7 @@ FT_BEGIN_HEADER
     cff_kind_string,
     cff_kind_bool,
     cff_kind_delta,
+    cff_kind_delta_fixed,
     cff_kind_callback,
     cff_kind_blend,
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CFF token definitions (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -80,26 +80,26 @@
 #undef  CFFCODE
 #define CFFCODE       CFF_CODE_PRIVATE
 
-  CFF_FIELD_DELTA     ( 6,     blue_values, 14,        "BlueValues" )
-  CFF_FIELD_DELTA     ( 7,     other_blues, 10,        "OtherBlues" )
-  CFF_FIELD_DELTA     ( 8,     family_blues, 14,       "FamilyBlues" )
-  CFF_FIELD_DELTA     ( 9,     family_other_blues, 10, "FamilyOtherBlues" )
-  CFF_FIELD_FIXED_1000( 0x109, blue_scale,             "BlueScale" )
-  CFF_FIELD_NUM       ( 0x10A, blue_shift,             "BlueShift" )
-  CFF_FIELD_NUM       ( 0x10B, blue_fuzz,              "BlueFuzz" )
-  CFF_FIELD_NUM       ( 10,    standard_width,         "StdHW" )
-  CFF_FIELD_NUM       ( 11,    standard_height,        "StdVW" )
-  CFF_FIELD_DELTA     ( 0x10C, snap_widths, 13,        "StemSnapH" )
-  CFF_FIELD_DELTA     ( 0x10D, snap_heights, 13,       "StemSnapV" )
-  CFF_FIELD_BOOL      ( 0x10E, force_bold,             "ForceBold" )
-  CFF_FIELD_FIXED     ( 0x10F, force_bold_threshold,   "ForceBoldThreshold" )
-  CFF_FIELD_NUM       ( 0x110, lenIV,                  "lenIV" )
-  CFF_FIELD_NUM       ( 0x111, language_group,         "LanguageGroup" )
-  CFF_FIELD_FIXED     ( 0x112, expansion_factor,       "ExpansionFactor" )
-  CFF_FIELD_NUM       ( 0x113, initial_random_seed,    "initialRandomSeed" )
-  CFF_FIELD_NUM       ( 19,    local_subrs_offset,     "Subrs" )
-  CFF_FIELD_NUM       ( 20,    default_width,          "defaultWidthX" )
-  CFF_FIELD_NUM       ( 21,    nominal_width,          "nominalWidthX" )
+  CFF_FIELD_DELTA_FIXED( 6,     blue_values, 14,        "BlueValues" )
+  CFF_FIELD_DELTA_FIXED( 7,     other_blues, 10,        "OtherBlues" )
+  CFF_FIELD_DELTA_FIXED( 8,     family_blues, 14,       "FamilyBlues" )
+  CFF_FIELD_DELTA_FIXED( 9,     family_other_blues, 10, "FamilyOtherBlues" )
+  CFF_FIELD_FIXED_1000 ( 0x109, blue_scale,             "BlueScale" )
+  CFF_FIELD_NUM        ( 0x10A, blue_shift,             "BlueShift" )
+  CFF_FIELD_NUM        ( 0x10B, blue_fuzz,              "BlueFuzz" )
+  CFF_FIELD_NUM        ( 10,    standard_width,         "StdHW" )
+  CFF_FIELD_NUM        ( 11,    standard_height,        "StdVW" )
+  CFF_FIELD_DELTA      ( 0x10C, snap_widths, 13,        "StemSnapH" )
+  CFF_FIELD_DELTA      ( 0x10D, snap_heights, 13,       "StemSnapV" )
+  CFF_FIELD_BOOL       ( 0x10E, force_bold,             "ForceBold" )
+  CFF_FIELD_FIXED      ( 0x10F, force_bold_threshold,   "ForceBoldThreshold" )
+  CFF_FIELD_NUM        ( 0x110, lenIV,                  "lenIV" )
+  CFF_FIELD_NUM        ( 0x111, language_group,         "LanguageGroup" )
+  CFF_FIELD_FIXED      ( 0x112, expansion_factor,       "ExpansionFactor" )
+  CFF_FIELD_NUM        ( 0x113, initial_random_seed,    "initialRandomSeed" )
+  CFF_FIELD_NUM        ( 19,    local_subrs_offset,     "Subrs" )
+  CFF_FIELD_NUM        ( 20,    default_width,          "defaultWidthX" )
+  CFF_FIELD_NUM        ( 21,    nominal_width,          "nominalWidthX" )
 
 
 #undef  FT_STRUCTURE
@@ -129,22 +129,22 @@
 #undef  CFFCODE
 #define CFFCODE       CFF2_CODE_PRIVATE
 
-  CFF_FIELD_DELTA     ( 6,     blue_values, 14,        "BlueValues" )
-  CFF_FIELD_DELTA     ( 7,     other_blues, 10,        "OtherBlues" )
-  CFF_FIELD_DELTA     ( 8,     family_blues, 14,       "FamilyBlues" )
-  CFF_FIELD_DELTA     ( 9,     family_other_blues, 10, "FamilyOtherBlues" )
-  CFF_FIELD_FIXED_1000( 0x109, blue_scale,             "BlueScale" )
-  CFF_FIELD_NUM       ( 0x10A, blue_shift,             "BlueShift" )
-  CFF_FIELD_NUM       ( 0x10B, blue_fuzz,              "BlueFuzz" )
-  CFF_FIELD_NUM       ( 10,    standard_width,         "StdHW" )
-  CFF_FIELD_NUM       ( 11,    standard_height,        "StdVW" )
-  CFF_FIELD_DELTA     ( 0x10C, snap_widths, 13,        "StemSnapH" )
-  CFF_FIELD_DELTA     ( 0x10D, snap_heights, 13,       "StemSnapV" )
-  CFF_FIELD_NUM       ( 0x111, language_group,         "LanguageGroup" )
-  CFF_FIELD_FIXED     ( 0x112, expansion_factor,       "ExpansionFactor" )
-  CFF_FIELD_CALLBACK  ( 22,    vsindex,                "vsindex" )
-  CFF_FIELD_BLEND     ( 23,                            "blend" )
-  CFF_FIELD_NUM       ( 19,    local_subrs_offset,     "Subrs" )
+  CFF_FIELD_DELTA_FIXED( 6,     blue_values, 14,        "BlueValues" )
+  CFF_FIELD_DELTA_FIXED( 7,     other_blues, 10,        "OtherBlues" )
+  CFF_FIELD_DELTA_FIXED( 8,     family_blues, 14,       "FamilyBlues" )
+  CFF_FIELD_DELTA_FIXED( 9,     family_other_blues, 10, "FamilyOtherBlues" )
+  CFF_FIELD_FIXED_1000 ( 0x109, blue_scale,             "BlueScale" )
+  CFF_FIELD_NUM        ( 0x10A, blue_shift,             "BlueShift" )
+  CFF_FIELD_NUM        ( 0x10B, blue_fuzz,              "BlueFuzz" )
+  CFF_FIELD_NUM        ( 10,    standard_width,         "StdHW" )
+  CFF_FIELD_NUM        ( 11,    standard_height,        "StdVW" )
+  CFF_FIELD_DELTA      ( 0x10C, snap_widths, 13,        "StemSnapH" )
+  CFF_FIELD_DELTA      ( 0x10D, snap_heights, 13,       "StemSnapV" )
+  CFF_FIELD_NUM        ( 0x111, language_group,         "LanguageGroup" )
+  CFF_FIELD_FIXED      ( 0x112, expansion_factor,       "ExpansionFactor" )
+  CFF_FIELD_CALLBACK   ( 22,    vsindex,                "vsindex" )
+  CFF_FIELD_BLEND      ( 23,                            "blend" )
+  CFF_FIELD_NUM        ( 19,    local_subrs_offset,     "Subrs" )
 
 
 /* END */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CID error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 Glyph Loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   OpenType Glyph Loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidload.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidload.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidload.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidload.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 font loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -388,7 +388,7 @@
     T1_FIELD_CALLBACK( "ExpansionFactor", parse_expansion_factor, 0 )
     T1_FIELD_CALLBACK( "FontName",        parse_font_name, 0 )
 
-    { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
+    T1_FIELD_ZERO
   };
 
 
@@ -469,36 +469,23 @@
             T1_Field  keyword = (T1_Field)cid_field_records;
 
 
-            for (;;)
+            while ( keyword->len )
             {
-              FT_Byte*  name;
+              FT_Byte*  name = (FT_Byte*)keyword->ident;
 
 
-              name = (FT_Byte*)keyword->ident;
-              if ( !name )
-                break;
-
-              if ( cur[0] == name[0]                     &&
-                   len == ft_strlen( (const char*)name ) )
+              if ( keyword->len == len              &&
+                   ft_memcmp( cur, name, len ) == 0 )
               {
-                FT_UInt  n;
-
-
-                for ( n = 1; n < len; n++ )
-                  if ( cur[n] != name[n] )
-                    break;
-
-                if ( n >= len )
-                {
-                  /* we found it - run the parsing callback */
-                  parser->root.error = cid_load_keyword( face,
-                                                         loader,
-                                                         keyword );
-                  if ( parser->root.error )
-                    return parser->root.error;
-                  break;
-                }
+                /* we found it - run the parsing callback */
+                parser->root.error = cid_load_keyword( face,
+                                                       loader,
+                                                       keyword );
+                if ( parser->root.error )
+                  return parser->root.error;
+                break;
               }
+
               keyword++;
             }
           }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidload.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidload.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidload.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidload.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 font loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CID objects manager (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CID objects manager (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 parser (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -90,10 +90,15 @@
     if ( error )
       goto Exit;
 
-  Again:
-    /* now, read the rest of the file until we find */
-    /* `StartData' or `/sfnts'                      */
+    if ( !stream->read ) {
+      /* just parse memory-based streams */
+      offset = stream->size;
+    }
+    else
     {
+      /* Find the last `StartData` or `/sfnts`.  The parser requires */
+      /* contiguous memory; attempt to pin as little as necessary.   */
+
       /*
        * The algorithm is as follows (omitting the case with less than 256
        * bytes to fill for simplicity).
@@ -119,7 +124,8 @@
       FT_Byte*  p           = buffer;
 
 
-      for ( offset = FT_STREAM_POS(); ; offset += 256 )
+      offset = 0;
+      while ( 1 )
       {
         FT_ULong  stream_len;
 
@@ -127,7 +133,7 @@
         stream_len = stream->size - FT_STREAM_POS();
 
         read_len = FT_MIN( read_len, stream_len );
-        if ( FT_STREAM_READ( p, read_len ) )
+        if ( read_len && FT_STREAM_READ( p, read_len ) )
           goto Exit;
 
         /* ensure that we do not compare with data beyond the buffer */
@@ -141,20 +147,23 @@
                ft_strncmp( (char*)p, STARTDATA, STARTDATA_LEN ) == 0 )
           {
             /* save offset of binary data after `StartData' */
-            offset += (FT_ULong)( p - buffer ) + STARTDATA_LEN + 1;
-            goto Found;
+            offset = FT_STREAM_POS() - read_len - read_offset
+                     + (FT_ULong)( p - buffer ) + STARTDATA_LEN + 1;
           }
           else if ( p[1] == 's'                                   &&
                     ft_strncmp( (char*)p, SFNTS, SFNTS_LEN ) == 0 )
           {
-            offset += (FT_ULong)( p - buffer ) + SFNTS_LEN + 1;
-            goto Found;
+            offset = FT_STREAM_POS() - read_len - read_offset
+                     + (FT_ULong)( p - buffer ) + SFNTS_LEN + 1;
           }
         }
 
-        if ( read_offset + read_len < STARTDATA_LEN )
+        if ( read_offset + read_len <= STARTDATA_LEN )
         {
-          FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" ));
+          if ( offset )
+            goto Found;
+
+          FT_TRACE2(( "cid_parser_new: no `StartData` keyword found\n" ));
           error = FT_THROW( Invalid_File_Format );
           goto Exit;
         }
@@ -171,9 +180,9 @@
     }
 
   Found:
-    /* We have found the start of the binary data or the `/sfnts' token. */
-    /* Now rewind and extract the frame corresponding to this PostScript */
-    /* section.                                                          */
+    /* We have found an efficient range to look for the binary data or    */
+    /* `/sfnts' token.  Now rewind and extract the frame corresponding to */
+    /* this PostScript section.                                           */
 
     ps_len = offset - base_offset;
     if ( FT_STREAM_SEEK( base_offset )                  ||
@@ -187,8 +196,8 @@
     parser->root.limit     = parser->root.cursor + ps_len;
     parser->num_dict       = FT_UINT_MAX;
 
-    /* Finally, we check whether `StartData' or `/sfnts' was real --  */
-    /* it could be in a comment or string.  We also get the arguments */
+    /* Find the first real `StartData' or `/sfnts' -- the last one    */
+    /* could be in a comment or string.  We also get the arguments    */
     /* of `StartData' to find out whether the data is represented in  */
     /* binary or hex format.                                          */
 
@@ -216,6 +225,7 @@
       {
         T1_TokenRec  type_token;
         FT_Long      binary_length;
+        FT_ULong     found_offset;
 
 
         parser->root.cursor = arg1;
@@ -234,6 +244,24 @@
             parser->binary_length = (FT_ULong)binary_length;
         }
 
+        /* set the real values for the parser, if different */
+        found_offset = (FT_ULong)( cur - parser->postscript )
+                       + STARTDATA_LEN + 1;
+        if ( found_offset != offset )
+        {
+          FT_FRAME_RELEASE( parser->postscript );
+
+          ps_len = found_offset - base_offset;
+          if ( FT_STREAM_SEEK( base_offset )                  ||
+               FT_FRAME_EXTRACT( ps_len, parser->postscript ) )
+            goto Exit;
+
+          parser->data_offset    = found_offset;
+          parser->postscript_len = ps_len;
+          parser->root.base      = parser->postscript;
+          parser->root.cursor    = parser->postscript;
+          parser->root.limit     = parser->root.cursor + ps_len;
+        }
         goto Exit;
       }
       else if ( cur[1] == 's'                                   &&
@@ -251,11 +279,8 @@
       cur  = parser->root.cursor;
     }
 
-    /* we haven't found the correct `StartData'; go back and continue */
-    /* searching                                                      */
-    FT_FRAME_RELEASE( parser->postscript );
-    if ( !FT_STREAM_SEEK( offset ) )
-      goto Again;
+    FT_TRACE2(( "cid_parser_new: no `StartData` token found\n" ));
+    error = FT_THROW( Invalid_File_Format );
 
   Exit:
     return error;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 parser (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CID driver interface (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   High-level CID driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   CID token definitions (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   AFM parser (body).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   AFM parser (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   PostScript CFF (Type 2) decoding routines (body).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -17,6 +17,7 @@
 
 
 #include <freetype/freetype.h>
+#include <freetype/internal/ftcalc.h>
 #include <freetype/internal/ftdebug.h>
 #include <freetype/internal/ftserv.h>
 #include <freetype/internal/services/svcfftl.h>
@@ -1752,22 +1753,9 @@
 
           /* without upper limit the loop below might not finish */
           if ( args[0] > 0x7FFFFFFFL )
-            args[0] = 46341;
+            args[0] = 0xB504F4L;    /* sqrt( 32768.0044 ) */
           else if ( args[0] > 0 )
-          {
-            FT_Fixed  root = args[0];
-            FT_Fixed  new_root;
-
-
-            for (;;)
-            {
-              new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
-              if ( new_root == root )
-                break;
-              root = new_root;
-            }
-            args[0] = new_root;
-          }
+            args[0] = (FT_Fixed)FT_SqrtFixed( args[0] );
           else
             args[0] = 0;
           args++;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   PostScript CFF (Type 2) decoding routines (specification).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   PS auxiliary module error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType auxiliary PostScript module implementation (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType auxiliary PostScript module implementation (specification).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c	2025-06-27 08:03:14.000000000 +0000
@@ -54,14 +54,6 @@
 #define FT_COMPONENT  cf2blues
 
 
-  /*
-   * For blue values, the FreeType parser produces an array of integers,
-   * while the Adobe CFF engine produces an array of fixed.
-   * Define a macro to convert FreeType to fixed.
-   */
-#define cf2_blueToFixed( x )  cf2_intToFixed( x )
-
-
   FT_LOCAL_DEF( void )
   cf2_blues_init( CF2_Blues  blues,
                   CF2_Font   font )
@@ -78,10 +70,10 @@
     size_t  numFamilyBlues;
     size_t  numFamilyOtherBlues;
 
-    FT_Pos*  blueValues;
-    FT_Pos*  otherBlues;
-    FT_Pos*  familyBlues;
-    FT_Pos*  familyOtherBlues;
+    FT_Fixed*  blueValues;
+    FT_Fixed*  otherBlues;
+    FT_Fixed*  familyBlues;
+    FT_Fixed*  familyOtherBlues;
 
     size_t     i;
     CF2_Fixed  emBoxBottom, emBoxTop;
@@ -138,13 +130,13 @@
       emBoxTop    = CF2_ICF_Top;
     }
 
-    if ( cf2_getLanguageGroup( decoder ) == 1                   &&
-         ( numBlueValues == 0                                 ||
-           ( numBlueValues == 4                             &&
-             cf2_blueToFixed( blueValues[0] ) < emBoxBottom &&
-             cf2_blueToFixed( blueValues[1] ) < emBoxBottom &&
-             cf2_blueToFixed( blueValues[2] ) > emBoxTop    &&
-             cf2_blueToFixed( blueValues[3] ) > emBoxTop    ) ) )
+    if ( cf2_getLanguageGroup( decoder ) == 1     &&
+         ( numBlueValues == 0                   ||
+           ( numBlueValues == 4               &&
+             blueValues[0] < emBoxBottom      &&
+             blueValues[1] < emBoxBottom      &&
+             blueValues[2] > emBoxTop         &&
+             blueValues[3] > emBoxTop         ) ) )
     {
       /*
        * Construct hint edges suitable for synthetic ghost hints at top
@@ -189,10 +181,8 @@
     /* bottom zones                                                      */
     for ( i = 0; i < numBlueValues; i += 2 )
     {
-      blues->zone[blues->count].csBottomEdge =
-        cf2_blueToFixed( blueValues[i] );
-      blues->zone[blues->count].csTopEdge =
-        cf2_blueToFixed( blueValues[i + 1] );
+      blues->zone[blues->count].csBottomEdge = blueValues[i];
+      blues->zone[blues->count].csTopEdge    = blueValues[i + 1];
 
       zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
                               blues->zone[blues->count].csBottomEdge );
@@ -238,10 +228,8 @@
 
     for ( i = 0; i < numOtherBlues; i += 2 )
     {
-      blues->zone[blues->count].csBottomEdge =
-        cf2_blueToFixed( otherBlues[i] );
-      blues->zone[blues->count].csTopEdge =
-        cf2_blueToFixed( otherBlues[i + 1] );
+      blues->zone[blues->count].csBottomEdge = otherBlues[i];
+      blues->zone[blues->count].csTopEdge    = otherBlues[i + 1];
 
       zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
                               blues->zone[blues->count].csBottomEdge );
@@ -299,7 +287,7 @@
         for ( j = 0; j < numFamilyOtherBlues; j += 2 )
         {
           /* top edge */
-          flatFamilyEdge = cf2_blueToFixed( familyOtherBlues[j + 1] );
+          flatFamilyEdge = familyOtherBlues[j + 1];
 
           diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
 
@@ -317,7 +305,7 @@
         if ( numFamilyBlues >= 2 )
         {
           /* top edge */
-          flatFamilyEdge = cf2_blueToFixed( familyBlues[1] );
+          flatFamilyEdge = familyBlues[1];
 
           diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
 
@@ -337,7 +325,7 @@
         for ( j = 2; j < numFamilyBlues; j += 2 )
         {
           /* bottom edge */
-          flatFamilyEdge = cf2_blueToFixed( familyBlues[j] );
+          flatFamilyEdge = familyBlues[j];
 
           /* adjust edges of top zone upward by twice darkening amount */
           flatFamilyEdge += 2 * font->darkenY;      /* bottom edge */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Some convenience conversions (body).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Some convenience conversions (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psft.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psft.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psft.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psft.c	2025-06-27 08:03:14.000000000 +0000
@@ -566,12 +566,12 @@
   FT_LOCAL_DEF( void )
   cf2_getBlueValues( PS_Decoder*  decoder,
                      size_t*      count,
-                     FT_Pos*     *data )
+                     FT_Fixed*   *data )
   {
     FT_ASSERT( decoder && decoder->current_subfont );
 
     *count = decoder->current_subfont->private_dict.num_blue_values;
-    *data  = (FT_Pos*)
+    *data  = (FT_Fixed*)
                &decoder->current_subfont->private_dict.blue_values;
   }
 
@@ -579,12 +579,12 @@
   FT_LOCAL_DEF( void )
   cf2_getOtherBlues( PS_Decoder*  decoder,
                      size_t*      count,
-                     FT_Pos*     *data )
+                     FT_Fixed*   *data )
   {
     FT_ASSERT( decoder && decoder->current_subfont );
 
     *count = decoder->current_subfont->private_dict.num_other_blues;
-    *data  = (FT_Pos*)
+    *data  = (FT_Fixed*)
                &decoder->current_subfont->private_dict.other_blues;
   }
 
@@ -592,12 +592,12 @@
   FT_LOCAL_DEF( void )
   cf2_getFamilyBlues( PS_Decoder*  decoder,
                       size_t*      count,
-                      FT_Pos*     *data )
+                      FT_Fixed*   *data )
   {
     FT_ASSERT( decoder && decoder->current_subfont );
 
     *count = decoder->current_subfont->private_dict.num_family_blues;
-    *data  = (FT_Pos*)
+    *data  = (FT_Fixed*)
                &decoder->current_subfont->private_dict.family_blues;
   }
 
@@ -605,12 +605,12 @@
   FT_LOCAL_DEF( void )
   cf2_getFamilyOtherBlues( PS_Decoder*  decoder,
                            size_t*      count,
-                           FT_Pos*     *data )
+                           FT_Fixed*   *data )
   {
     FT_ASSERT( decoder && decoder->current_subfont );
 
     *count = decoder->current_subfont->private_dict.num_family_other_blues;
-    *data  = (FT_Pos*)
+    *data  = (FT_Fixed*)
                &decoder->current_subfont->private_dict.family_other_blues;
   }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psft.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psft.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psft.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psft.h	2025-06-27 08:03:14.000000000 +0000
@@ -92,19 +92,19 @@ FT_BEGIN_HEADER
   FT_LOCAL( void )
   cf2_getBlueValues( PS_Decoder*  decoder,
                      size_t*      count,
-                     FT_Pos*     *data );
+                     FT_Fixed*   *data );
   FT_LOCAL( void )
   cf2_getOtherBlues( PS_Decoder*  decoder,
                      size_t*      count,
-                     FT_Pos*     *data );
+                     FT_Fixed*   *data );
   FT_LOCAL( void )
   cf2_getFamilyBlues( PS_Decoder*  decoder,
                       size_t*      count,
-                      FT_Pos*     *data );
+                      FT_Fixed*   *data );
   FT_LOCAL( void )
   cf2_getFamilyOtherBlues( PS_Decoder*  decoder,
                            size_t*      count,
-                           FT_Pos*     *data );
+                           FT_Fixed*   *data );
 
   FT_LOCAL( CF2_Int )
   cf2_getLanguageGroup( PS_Decoder*  decoder );
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c	2025-06-27 08:03:14.000000000 +0000
@@ -37,6 +37,7 @@
 
 
 #include "psft.h"
+#include <freetype/internal/ftcalc.h>
 #include <freetype/internal/ftdebug.h>
 #include <freetype/internal/services/svcfftl.h>
 
@@ -428,6 +429,8 @@
     base  = cf2_stack_count( opStack ) - numOperands;
     delta = base + numBlends;
 
+    FT_TRACE6(( " (" ));
+
     for ( i = 0; i < numBlends; i++ )
     {
       const CF2_Fixed*  weight = &blend->BV[1];
@@ -442,10 +445,14 @@
                                     cf2_stack_getReal( opStack,
                                                        delta++ ) ) );
 
+      FT_TRACE6(( "%f ", (double)sum / 65536 ));
+
       /* store blended result  */
       cf2_stack_setReal( opStack, i + base, sum );
     }
 
+    FT_TRACE6(( "blended)\n" ));
+
     /* leave only `numBlends' results on stack */
     cf2_stack_pop( opStack, numOperands - numBlends );
   }
@@ -734,7 +741,7 @@
           FT_UInt  numBlends;
 
 
-          FT_TRACE4(( " blend\n" ));
+          FT_TRACE4(( " blend" ));
 
           if ( !font->isCFF2 )
             break;    /* clear stack & ignore */
@@ -2275,23 +2282,7 @@
 
                     arg = cf2_stack_popFixed( opStack );
                     if ( arg > 0 )
-                    {
-                      /* use a start value that doesn't make */
-                      /* the algorithm's addition overflow   */
-                      FT_Fixed  root = arg < 10 ? arg : arg >> 1;
-                      FT_Fixed  new_root;
-
-
-                      /* Babylonian method */
-                      for (;;)
-                      {
-                        new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
-                        if ( new_root == root )
-                          break;
-                        root = new_root;
-                      }
-                      arg = new_root;
-                    }
+                      arg = (CF2_F16Dot16)FT_SqrtFixed( (FT_UInt32)arg );
                     else
                       arg = 0;
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auxiliary functions for PostScript fonts (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -23,6 +23,7 @@
 
 #include "psobjs.h"
 #include "psconv.h"
+#include "psft.h"
 
 #include "psauxerr.h"
 #include "psauxmod.h"
@@ -200,7 +201,9 @@
     /* add the object to the base block and adjust offset */
     table->elements[idx] = FT_OFFSET( table->block, table->cursor );
     table->lengths [idx] = length;
-    FT_MEM_COPY( table->block + table->cursor, object, length );
+    /* length == 0 also implies a NULL destination, so skip the copy call */
+    if ( length > 0 )
+      FT_MEM_COPY( table->block + table->cursor, object, length );
 
     table->cursor += length;
     return FT_Err_Ok;
@@ -1624,7 +1627,7 @@
     if ( builder->load_points )
     {
       FT_Vector*  point   = outline->points + outline->n_points;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
+      FT_Byte*    control = outline->tags   + outline->n_points;
 
 
       point->x = FIXED_TO_INT( x );
@@ -1677,8 +1680,7 @@
     if ( !error )
     {
       if ( outline->n_contours > 0 )
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
 
       outline->n_contours++;
     }
@@ -1740,7 +1742,7 @@
     {
       FT_Vector*  p1      = outline->points + first;
       FT_Vector*  p2      = outline->points + outline->n_points - 1;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
+      FT_Byte*    control = outline->tags   + outline->n_points - 1;
 
 
       /* `delete' last point only if it coincides with the first */
@@ -1760,8 +1762,7 @@
         outline->n_points--;
       }
       else
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
     }
   }
 
@@ -1899,7 +1900,7 @@
     if ( builder->load_points )
     {
       FT_Vector*  point   = outline->points + outline->n_points;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
+      FT_Byte*    control = outline->tags   + outline->n_points;
 
 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
       PS_Driver  driver   = (PS_Driver)FT_FACE_DRIVER( builder->face );
@@ -1959,8 +1960,7 @@
     if ( !error )
     {
       if ( outline->n_contours > 0 )
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
 
       outline->n_contours++;
     }
@@ -2019,7 +2019,7 @@
     {
       FT_Vector*  p1      = outline->points + first;
       FT_Vector*  p2      = outline->points + outline->n_points - 1;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
+      FT_Byte*    control = outline->tags   + outline->n_points - 1;
 
 
       /* `delete' last point only if it coincides with the first    */
@@ -2039,8 +2039,7 @@
         outline->n_points--;
       }
       else
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
     }
   }
 
@@ -2188,7 +2187,7 @@
     if ( builder->load_points )
     {
       FT_Vector*  point   = outline->points + outline->n_points;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
+      FT_Byte*    control = outline->tags   + outline->n_points;
 
 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
       PS_Driver  driver   = (PS_Driver)FT_FACE_DRIVER( builder->face );
@@ -2267,8 +2266,7 @@
     if ( !error )
     {
       if ( outline->n_contours > 0 )
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
 
       outline->n_contours++;
     }
@@ -2327,7 +2325,7 @@
     {
       FT_Vector*  p1      = outline->points + first;
       FT_Vector*  p2      = outline->points + outline->n_points - 1;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
+      FT_Byte*    control = outline->tags   + outline->n_points - 1;
 
 
       /* `delete' last point only if it coincides with the first */
@@ -2347,8 +2345,7 @@
         outline->n_points--;
       }
       else
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
     }
   }
 
@@ -2463,19 +2460,20 @@
 
     count = cpriv->num_blue_values = priv->num_blue_values;
     for ( n = 0; n < count; n++ )
-      cpriv->blue_values[n] = (FT_Pos)priv->blue_values[n];
+      cpriv->blue_values[n] = cf2_intToFixed( priv->blue_values[n] );
 
     count = cpriv->num_other_blues = priv->num_other_blues;
     for ( n = 0; n < count; n++ )
-      cpriv->other_blues[n] = (FT_Pos)priv->other_blues[n];
+      cpriv->other_blues[n] = cf2_intToFixed( priv->other_blues[n] );
 
     count = cpriv->num_family_blues = priv->num_family_blues;
     for ( n = 0; n < count; n++ )
-      cpriv->family_blues[n] = (FT_Pos)priv->family_blues[n];
+      cpriv->family_blues[n] = cf2_intToFixed( priv->family_blues[n] );
 
     count = cpriv->num_family_other_blues = priv->num_family_other_blues;
     for ( n = 0; n < count; n++ )
-      cpriv->family_other_blues[n] = (FT_Pos)priv->family_other_blues[n];
+      cpriv->family_other_blues[n] =
+        cf2_intToFixed( priv->family_other_blues[n] );
 
     cpriv->blue_scale = priv->blue_scale;
     cpriv->blue_shift = (FT_Pos)priv->blue_shift;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Auxiliary functions for PostScript fonts (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Type 1 character map support (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Type 1 character map support (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   PostScript Type 1 decoding routines (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   PostScript Type 1 decoding routines (specification).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   PostScript hinting algorithm (body).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
@@ -1118,7 +1118,7 @@
     FT_UInt     n;
     PSH_Point   point = glyph->points;
     FT_Vector*  vec   = glyph->outline->points;
-    char*       tags  = glyph->outline->tags;
+    FT_Byte*    tags  = glyph->outline->tags;
 
 
     for ( n = 0; n < glyph->num_points; n++ )
@@ -1171,8 +1171,8 @@
          FT_QNEW_ARRAY( glyph->contours, outline->n_contours ) )
       goto Exit;
 
-    glyph->num_points   = (FT_UInt)outline->n_points;
-    glyph->num_contours = (FT_UInt)outline->n_contours;
+    glyph->num_points   = outline->n_points;
+    glyph->num_contours = outline->n_contours;
 
     {
       FT_UInt      first = 0, next, n;
@@ -1186,7 +1186,7 @@
         PSH_Point  point;
 
 
-        next  = (FT_UInt)outline->contours[n] + 1;
+        next  = outline->contours[n] + 1;
         count = next - first;
 
         contour->start = points + first;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   PostScript hinting algorithm (specification).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   PostScript hinter global hinting management (body).
  *   Inspired by the new auto-hinter module.
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   PostScript hinter global hinting management.
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType PostScript hinter module implementation (body).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   PostScript hinter module interface (specification).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   PS Hinter error codes (specification only).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType PostScript hints recorder (body).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -806,7 +806,7 @@
   ps_hints_stem( PS_Hints  hints,
                  FT_UInt   dimension,
                  FT_Int    count,
-                 FT_Long*  stems )
+                 FT_Pos*   stems )
   {
     PS_Dimension  dim;
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Postscript (Type1/Type2) hints recorder (specification).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   psnames module implementation (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   High-level psnames module interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   PS names module error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   PostScript glyph names.
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Miscellaneous macros for stand-alone rasterizer (specification
  *   only).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
@@ -93,27 +93,6 @@
 
 
   static FT_Long
-  FT_MulDiv( FT_Long  a,
-             FT_Long  b,
-             FT_Long  c )
-  {
-    FT_Int   s;
-    FT_Long  d;
-
-
-    s = 1;
-    if ( a < 0 ) { a = -a; s = -1; }
-    if ( b < 0 ) { b = -b; s = -s; }
-    if ( c < 0 ) { c = -c; s = -s; }
-
-    d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
-                         : 0x7FFFFFFFL );
-
-    return ( s > 0 ) ? d : -d;
-  }
-
-
-  static FT_Long
   FT_MulDiv_No_Round( FT_Long  a,
                       FT_Long  b,
                       FT_Long  c )
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -63,8 +63,7 @@
 #else /* !STANDALONE_ */
 
 #include "ftraster.h"
-#include <freetype/internal/ftcalc.h> /* for FT_MulDiv and FT_MulDiv_No_Round */
-#include <freetype/ftoutln.h>         /* for FT_Outline_Get_CBox              */
+#include <freetype/internal/ftcalc.h> /* for FT_MulDiv_No_Round */
 
 #endif /* !STANDALONE_ */
 
@@ -115,12 +114,12 @@
    *   a change of direction is detected in the outline, a new profile is
    *   generated until the end of the outline.
    *
-   *   Note that when all profiles have been generated, the function
-   *   Finalize_Profile_Table() is used to record, for each profile, its
-   *   bottom-most scanline as well as the scanline above its upmost
-   *   boundary.  These positions are called `y-turns' because they (sort
-   *   of) correspond to local extrema.  They are stored in a sorted list
-   *   built from the top of the render pool as a downwards stack:
+   *   Note that, for all generated profiles, the function End_Profile()
+   *   is used to record all their bottom-most scanlines as well as the
+   *   scanline above their upmost boundary.  These positions are called
+   *   `y-turns' because they (sort of) correspond to local extrema.
+   *   They are stored in a sorted list built from the top of the render
+   *   pool as a downwards stack:
    *
    *     _ _ _______________________________________
    *                           |                    |
@@ -136,7 +135,7 @@
    *   optimize performance (see technical note on the sweep below).
    *
    *   Of course, the raster detects whether the two stacks collide and
-   *   handles the situation properly.
+   *   handles the situation by bisecting the job and restarting.
    *
    */
 
@@ -252,7 +251,6 @@
   /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
   /* for clipping computations.  It simply uses the FT_MulDiv() function   */
   /* defined in `ftcalc.h'.                                                */
-#define SMulDiv           FT_MulDiv
 #define SMulDiv_No_Round  FT_MulDiv_No_Round
 
   /* The rasterizer is a very general purpose component; please leave */
@@ -305,16 +303,6 @@
   typedef unsigned char   Byte, *PByte;
   typedef char            Bool;
 
-
-  typedef union  Alignment_
-  {
-    Long    l;
-    void*   p;
-    void  (*f)(void);
-
-  } Alignment, *PAlignment;
-
-
   typedef struct  TPoint_
   {
     Long  x;
@@ -327,6 +315,7 @@
 #define Flow_Up           0x08U
 #define Overshoot_Top     0x10U
 #define Overshoot_Bottom  0x20U
+#define Dropout           0x40U
 
 
   /* States of each line, arc, and profile */
@@ -345,31 +334,28 @@
 
   struct  TProfile_
   {
-    FT_F26Dot6  X;           /* current coordinate during sweep          */
     PProfile    link;        /* link to next profile (various purposes)  */
-    PLong       offset;      /* start of profile's data in render pool   */
+    PProfile    next;        /* next profile in same contour, used       */
+                             /* during drop-out control                  */
+    Int         offset;      /* bottom or currently scanned array index  */
+    Int         height;      /* profile's height in scanlines            */
+    Int         start;       /* profile's starting scanline, also use    */
+                             /* as activation counter                    */
     UShort      flags;       /* Bit 0-2: drop-out mode                   */
                              /* Bit 3: profile orientation (up/down)     */
                              /* Bit 4: is top profile?                   */
                              /* Bit 5: is bottom profile?                */
-    Long        height;      /* profile's height in scanlines            */
-    Long        start;       /* profile's starting scanline              */
-
-    Int         countL;      /* number of lines to step before this      */
-                             /* profile becomes drawable                 */
+                             /* Bit 6: dropout detected                  */
 
-    PProfile    next;        /* next profile in same contour, used       */
-                             /* during drop-out control                  */
+    FT_F26Dot6  X;           /* current coordinate during sweep          */
+    Long        x[1];        /* actually variable array of scanline      */
+                             /* intersections with `height` elements     */
   };
 
   typedef PProfile   TProfileList;
   typedef PProfile*  PProfileList;
 
 
-#define AlignProfileSize \
-  ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( Long ) )
-
-
 #undef RAS_ARG
 #undef RAS_ARGS
 #undef RAS_VAR
@@ -407,15 +393,13 @@
 
   /* prototypes used for sweep function dispatch */
   typedef void
-  Function_Sweep_Init( RAS_ARGS Short  min,
-                                Short  max );
+  Function_Sweep_Init( RAS_ARGS Int  min,
+                                Int  max );
 
   typedef void
-  Function_Sweep_Span( RAS_ARGS Short       y,
+  Function_Sweep_Span( RAS_ARGS Int         y,
                                 FT_F26Dot6  x1,
-                                FT_F26Dot6  x2,
-                                PProfile    left,
-                                PProfile    right );
+                                FT_F26Dot6  x2 );
 
   typedef void
   Function_Sweep_Step( RAS_ARG );
@@ -441,8 +425,7 @@
           (Bool)( x - FLOOR( x ) >= ras.precision_half )
 
   /* Smart dropout rounding to find which pixel is closer to span ends. */
-  /* To mimick Windows, symmetric cases break down indepenently of the  */
-  /* precision.                                                         */
+  /* To mimic Windows, symmetric cases do not depend on the precision.  */
 #define SMART( p, q )  FLOOR( ( (p) + (q) + ras.precision * 63 / 64 ) >> 1 )
 
 #if FT_RENDER_POOL_SIZE > 2048
@@ -462,7 +445,6 @@
     Int         precision_half;
     Int         precision_scale;
     Int         precision_step;
-    Int         precision_jitter;
 
     PLong       buff;               /* The profiles buffer                 */
     PLong       sizeBuff;           /* Render pool size                    */
@@ -471,24 +453,14 @@
 
     FT_Error    error;
 
-    Int         numTurns;           /* number of Y-turns in outline        */
-
     Byte        dropOutControl;     /* current drop_out control method     */
 
-    UShort      bWidth;             /* target bitmap width                 */
-    PByte       bOrigin;            /* target bitmap bottom-left origin    */
-    PByte       bLine;              /* target bitmap current line          */
-
     Long        lastX, lastY;
     Long        minY, maxY;
 
     UShort      num_Profs;          /* current number of profiles          */
+    Int         numTurns;           /* number of Y-turns in outline        */
 
-    Bool        fresh;              /* signals a fresh new profile which   */
-                                    /* `start' field must be completed     */
-    Bool        joint;              /* signals that the last arc ended     */
-                                    /* exactly on a scanline.  Allows      */
-                                    /* removal of doublets                 */
     PProfile    cProfile;           /* current profile                     */
     PProfile    fProfile;           /* head of linked list of profiles     */
     PProfile    gProfile;           /* contour's first profile in case     */
@@ -496,9 +468,14 @@
 
     TStates     state;              /* rendering state                     */
 
-    FT_Bitmap   target;             /* description of target bit/pixmap    */
     FT_Outline  outline;
 
+    Int         bTop;               /* target bitmap max line  index       */
+    Int         bRight;             /* target bitmap rightmost index       */
+    Int         bPitch;             /* target bitmap pitch                 */
+    PByte       bOrigin;            /* target bitmap bottom-left origin    */
+    PByte       bLine;              /* target bitmap current line          */
+
     /* dispatch variables */
 
     Function_Sweep_Init*  Proc_Sweep_Init;
@@ -563,31 +540,19 @@
      *
      *   256 / (1 << 12) = 0.0625 pixels.
      *
-     * `precision_jitter' is an epsilon threshold used in
-     * `Vertical_Sweep_Span' to deal with small imperfections in the Bezier
-     * decomposition (after all, we are working with approximations only);
-     * it avoids switching on additional pixels which would cause artifacts
-     * otherwise.
-     *
-     * The value of `precision_jitter' has been determined heuristically.
-     *
      */
 
     if ( High )
     {
       ras.precision_bits   = 12;
       ras.precision_step   = 256;
-      ras.precision_jitter = 30;
     }
     else
     {
       ras.precision_bits   = 6;
       ras.precision_step   = 32;
-      ras.precision_jitter = 2;
     }
 
-    FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
-
     ras.precision       = 1 << ras.precision_bits;
     ras.precision_half  = ras.precision >> 1;
     ras.precision_scale = ras.precision >> Pixel_Bits;
@@ -597,6 +562,63 @@
   /**************************************************************************
    *
    * @Function:
+   *   Insert_Y_Turn
+   *
+   * @Description:
+   *   Insert a salient into the sorted list placed on top of the render
+   *   pool.
+   *
+   * @Input:
+   *   New y scanline position.
+   *
+   * @Return:
+   *   SUCCESS on success.  FAILURE in case of overflow.
+   */
+  static Bool
+  Insert_Y_Turns( RAS_ARGS Int  y,
+                           Int  top )
+  {
+    Int    n       = ras.numTurns;
+    PLong  y_turns = ras.maxBuff;
+
+
+    /* update top value */
+    if ( n == 0 || top > y_turns[n] )
+      y_turns[n] = top;
+
+    /* look for first y value that is <= */
+    while ( n-- && y < y_turns[n] )
+      ;
+
+    /* if it is <, simply insert it, ignore if == */
+    if ( n < 0 || y > y_turns[n] )
+    {
+      ras.maxBuff--;
+      if ( ras.maxBuff <= ras.top )
+      {
+        ras.error = FT_THROW( Raster_Overflow );
+        return FAILURE;
+      }
+
+      do
+      {
+        Int  y2 = (Int)y_turns[n];
+
+
+        y_turns[n] = y;
+        y = y2;
+      } while ( n-- >= 0 );
+
+      ras.numTurns++;
+    }
+
+    return SUCCESS;
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
    *   New_Profile
    *
    * @Description:
@@ -606,52 +628,48 @@
    *   aState ::
    *     The state/orientation of the new profile.
    *
-   *   overshoot ::
-   *     Whether the profile's unrounded start position
-   *     differs by at least a half pixel.
-   *
    * @Return:
    *  SUCCESS on success.  FAILURE in case of overflow or of incoherent
    *  profile.
    */
   static Bool
-  New_Profile( RAS_ARGS TStates  aState,
-                        Bool     overshoot )
+  New_Profile( RAS_ARGS TStates  aState )
   {
-    if ( !ras.fProfile )
+    Long  e;
+
+
+    if ( !ras.cProfile || ras.cProfile->height )
     {
       ras.cProfile  = (PProfile)ras.top;
-      ras.fProfile  = ras.cProfile;
-      ras.top      += AlignProfileSize;
-    }
+      ras.top       = ras.cProfile->x;
 
-    if ( ras.top >= ras.maxBuff )
-    {
-      ras.error = FT_THROW( Raster_Overflow );
-      return FAILURE;
+      if ( ras.top >= ras.maxBuff )
+      {
+        FT_TRACE1(( "overflow in New_Profile\n" ));
+        ras.error = FT_THROW( Raster_Overflow );
+        return FAILURE;
+      }
+
+      ras.cProfile->height = 0;
     }
 
-    ras.cProfile->start  = 0;
-    ras.cProfile->height = 0;
-    ras.cProfile->offset = ras.top;
-    ras.cProfile->link   = (PProfile)0;
-    ras.cProfile->next   = (PProfile)0;
     ras.cProfile->flags  = ras.dropOutControl;
 
     switch ( aState )
     {
     case Ascending_State:
       ras.cProfile->flags |= Flow_Up;
-      if ( overshoot )
+      if ( IS_BOTTOM_OVERSHOOT( ras.lastY ) )
         ras.cProfile->flags |= Overshoot_Bottom;
 
-      FT_TRACE6(( "  new ascending profile = %p\n", (void *)ras.cProfile ));
+      e = CEILING( ras.lastY );
       break;
 
     case Descending_State:
-      if ( overshoot )
+      if ( IS_TOP_OVERSHOOT( ras.lastY ) )
         ras.cProfile->flags |= Overshoot_Top;
-      FT_TRACE6(( "  new descending profile = %p\n", (void *)ras.cProfile ));
+
+      e = FLOOR( ras.lastY );
       break;
 
     default:
@@ -660,12 +678,20 @@
       return FAILURE;
     }
 
-    if ( !ras.gProfile )
-      ras.gProfile = ras.cProfile;
+    if ( e > ras.maxY )
+      e = ras.maxY;
+    if ( e < ras.minY )
+      e = ras.minY;
+    ras.cProfile->start = (Int)TRUNC( e );
+
+    FT_TRACE7(( "  new %s profile = %p, start = %d\n",
+                aState == Ascending_State ? "ascending" : "descending",
+                (void *)ras.cProfile, ras.cProfile->start ));
+
+    if ( ras.lastY == e )
+      *ras.top++ = ras.lastX;
 
     ras.state = aState;
-    ras.fresh = TRUE;
-    ras.joint = FALSE;
 
     return SUCCESS;
   }
@@ -677,24 +703,19 @@
    *   End_Profile
    *
    * @Description:
-   *   Finalize the current profile.
-   *
-   * @Input:
-   *   overshoot ::
-   *     Whether the profile's unrounded end position differs
-   *     by at least a half pixel.
+   *   Finalize the current profile and record y-turns.
    *
    * @Return:
    *   SUCCESS on success.  FAILURE in case of overflow or incoherency.
    */
   static Bool
-  End_Profile( RAS_ARGS Bool  overshoot )
+  End_Profile( RAS_ARG )
   {
-    Long  h;
+    PProfile  p = ras.cProfile;
+    Int       h = (Int)( ras.top - p->x );
+    Int       bottom, top;
 
 
-    h = (Long)( ras.top - ras.cProfile->offset );
-
     if ( h < 0 )
     {
       FT_ERROR(( "End_Profile: negative height encountered\n" ));
@@ -704,98 +725,46 @@
 
     if ( h > 0 )
     {
-      PProfile  oldProfile;
+      FT_TRACE7(( "  ending profile %p, start = %2d, height = %+3d\n",
+                  (void *)p, p->start, p->flags & Flow_Up ? h : -h ));
 
+      p->height = h;
 
-      FT_TRACE6(( "  ending profile %p, start = %ld, height = %ld\n",
-                  (void *)ras.cProfile, ras.cProfile->start, h ));
+      if ( p->flags & Flow_Up )
+      {
+        if ( IS_TOP_OVERSHOOT( ras.lastY ) )
+          p->flags |= Overshoot_Top;
 
-      ras.cProfile->height = h;
-      if ( overshoot )
+        bottom    = p->start;
+        top       = bottom + h;
+        p->offset = 0;
+        p->X      = p->x[0];
+      }
+      else
       {
-        if ( ras.cProfile->flags & Flow_Up )
-          ras.cProfile->flags |= Overshoot_Top;
-        else
-          ras.cProfile->flags |= Overshoot_Bottom;
+        if ( IS_BOTTOM_OVERSHOOT( ras.lastY ) )
+          p->flags |= Overshoot_Bottom;
+
+        top       = p->start + 1;
+        bottom    = top - h;
+        p->start  = bottom;
+        p->offset = h - 1;
+        p->X      = p->x[h - 1];
       }
 
-      oldProfile   = ras.cProfile;
-      ras.cProfile = (PProfile)ras.top;
+      if ( Insert_Y_Turns( RAS_VARS bottom, top ) )
+        return FAILURE;
 
-      ras.top += AlignProfileSize;
+      if ( !ras.gProfile )
+        ras.gProfile = p;
 
-      ras.cProfile->height = 0;
-      ras.cProfile->offset = ras.top;
+      /* preliminary values to be finalized */
+      p->next = ras.gProfile;
+      p->link = (PProfile)ras.top;
 
-      oldProfile->next = ras.cProfile;
       ras.num_Profs++;
     }
 
-    if ( ras.top >= ras.maxBuff )
-    {
-      FT_TRACE1(( "overflow in End_Profile\n" ));
-      ras.error = FT_THROW( Raster_Overflow );
-      return FAILURE;
-    }
-
-    ras.joint = FALSE;
-
-    return SUCCESS;
-  }
-
-
-  /**************************************************************************
-   *
-   * @Function:
-   *   Insert_Y_Turn
-   *
-   * @Description:
-   *   Insert a salient into the sorted list placed on top of the render
-   *   pool.
-   *
-   * @Input:
-   *   New y scanline position.
-   *
-   * @Return:
-   *   SUCCESS on success.  FAILURE in case of overflow.
-   */
-  static Bool
-  Insert_Y_Turn( RAS_ARGS Int  y )
-  {
-    PLong  y_turns;
-    Int    n;
-
-
-    n       = ras.numTurns - 1;
-    y_turns = ras.sizeBuff - ras.numTurns;
-
-    /* look for first y value that is <= */
-    while ( n >= 0 && y < y_turns[n] )
-      n--;
-
-    /* if it is <, simply insert it, ignore if == */
-    if ( n >= 0 && y > y_turns[n] )
-      do
-      {
-        Int  y2 = (Int)y_turns[n];
-
-
-        y_turns[n] = y;
-        y = y2;
-      } while ( --n >= 0 );
-
-    if ( n < 0 )
-    {
-      ras.maxBuff--;
-      if ( ras.maxBuff <= ras.top )
-      {
-        ras.error = FT_THROW( Raster_Overflow );
-        return FAILURE;
-      }
-      ras.numTurns++;
-      ras.sizeBuff[-ras.numTurns] = y;
-    }
-
     return SUCCESS;
   }
 
@@ -807,56 +776,29 @@
    *
    * @Description:
    *   Adjust all links in the profiles list.
-   *
-   * @Return:
-   *   SUCCESS on success.  FAILURE in case of overflow.
    */
-  static Bool
+  static void
   Finalize_Profile_Table( RAS_ARG )
   {
-    UShort    n;
-    PProfile  p;
-
+    UShort    n = ras.num_Profs;
+    PProfile  p = ras.fProfile;
+    PProfile  q;
 
-    n = ras.num_Profs;
-    p = ras.fProfile;
 
-    if ( n > 1 && p )
+    /* there should be at least two profiles, up and down */
+    while ( --n )
     {
-      do
-      {
-        Int  bottom, top;
+      q = p->link;
 
+      /* fix the contour loop */
+      if ( q->next == p->next )
+        p->next = q;
 
-        if ( n > 1 )
-          p->link = (PProfile)( p->offset + p->height );
-        else
-          p->link = NULL;
-
-        if ( p->flags & Flow_Up )
-        {
-          bottom = (Int)p->start;
-          top    = (Int)( p->start + p->height - 1 );
-        }
-        else
-        {
-          bottom     = (Int)( p->start - p->height + 1 );
-          top        = (Int)p->start;
-          p->start   = bottom;
-          p->offset += p->height - 1;
-        }
-
-        if ( Insert_Y_Turn( RAS_VARS bottom )  ||
-             Insert_Y_Turn( RAS_VARS top + 1 ) )
-          return FAILURE;
-
-        p = p->link;
-      } while ( --n );
+      p = q;
     }
-    else
-      ras.fProfile = NULL;
 
-    return SUCCESS;
+    /* null-terminate */
+    p->link = NULL;
   }
 
 
@@ -986,107 +928,78 @@
                     Long  miny,
                     Long  maxy )
   {
-    Long   Dx, Dy;
-    Int    e1, e2, f1, f2, size;     /* XXX: is `Short' sufficient? */
-    Long   Ix, Rx, Ax;
+    Long  e, e2, Dx, Dy;
+    Long  Ix, Rx, Ax;
+    Int   size;
 
     PLong  top;
 
 
-    Dx = x2 - x1;
-    Dy = y2 - y1;
-
-    if ( Dy <= 0 || y2 < miny || y1 > maxy )
+    if ( y2 < miny || y1 > maxy )
       return SUCCESS;
 
-    if ( y1 < miny )
-    {
-      /* Take care: miny-y1 can be a very large value; we use     */
-      /*            a slow MulDiv function to avoid clipping bugs */
-      x1 += SMulDiv( Dx, miny - y1, Dy );
-      e1  = (Int)TRUNC( miny );
-      f1  = 0;
-    }
-    else
-    {
-      e1 = (Int)TRUNC( y1 );
-      f1 = (Int)FRAC( y1 );
-    }
+    e2 = y2 > maxy ? maxy : FLOOR( y2 );
+    e  = y1 < miny ? miny : CEILING( y1 );
 
-    if ( y2 > maxy )
-    {
-      /* x2 += FMulDiv( Dx, maxy - y2, Dy );  UNNECESSARY */
-      e2  = (Int)TRUNC( maxy );
-      f2  = 0;
-    }
-    else
-    {
-      e2 = (Int)TRUNC( y2 );
-      f2 = (Int)FRAC( y2 );
-    }
-
-    if ( f1 > 0 )
-    {
-      if ( e1 == e2 )
-        return SUCCESS;
-      else
-      {
-        x1 += SMulDiv( Dx, ras.precision - f1, Dy );
-        e1 += 1;
-      }
-    }
-    else
-      if ( ras.joint )
-      {
-        ras.top--;
-        ras.joint = FALSE;
-      }
+    if ( y1 == e )
+      e += ras.precision;
 
-    ras.joint = (char)( f2 == 0 );
+    if ( e2 < e )  /* nothing to do */
+      return SUCCESS;
 
-    if ( ras.fresh )
-    {
-      ras.cProfile->start = e1;
-      ras.fresh           = FALSE;
-    }
+    size = (Int)TRUNC( e2 - e ) + 1;
+    top  = ras.top;
 
-    size = e2 - e1 + 1;
-    if ( ras.top + size >= ras.maxBuff )
+    if ( top + size >= ras.maxBuff )
     {
       ras.error = FT_THROW( Raster_Overflow );
       return FAILURE;
     }
 
-    if ( Dx > 0 )
-    {
-      Ix = SMulDiv_No_Round( ras.precision, Dx, Dy );
-      Rx = ( ras.precision * Dx ) % Dy;
-      Dx = 1;
-    }
-    else
+    Dx = x2 - x1;
+    Dy = y2 - y1;
+
+    if ( Dx == 0 )  /* very easy */
     {
-      Ix = -SMulDiv_No_Round( ras.precision, -Dx, Dy );
-      Rx = ( ras.precision * -Dx ) % Dy;
-      Dx = -1;
+      do
+        *top++ = x1;
+      while ( --size );
+      goto Fin;
     }
 
-    Ax  = -Dy;
-    top = ras.top;
+    Ix     = SMulDiv_No_Round( e - y1, Dx, Dy );
+    x1    += Ix;
+    *top++ = x1;
+
+    if ( --size )
+    {
+      Ax = Dx * ( e - y1 )    - Dy * Ix;  /* remainder */
+      Ix = FMulDiv( ras.precision, Dx, Dy );
+      Rx = Dx * ras.precision - Dy * Ix;  /* remainder */
+      Dx = 1;
 
-    while ( size > 0 )
-    {
-      *top++ = x1;
+      if ( x2 < x1 )
+      {
+        Ax = -Ax;
+        Rx = -Rx;
+        Dx = -Dx;
+      }
 
-      x1 += Ix;
-      Ax += Rx;
-      if ( Ax >= 0 )
+      do
       {
-        Ax -= Dy;
-        x1 += Dx;
+        x1 += Ix;
+        Ax += Rx;
+        if ( Ax >= Dy )
+        {
+          Ax -= Dy;
+          x1 += Dx;
+        }
+        *top++ = x1;
       }
-      size--;
+      while ( --size );
     }
 
+  Fin:
     ras.top = top;
     return SUCCESS;
   }
@@ -1131,17 +1044,7 @@
                       Long  miny,
                       Long  maxy )
   {
-    Bool  result, fresh;
-
-
-    fresh  = ras.fresh;
-
-    result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
-
-    if ( fresh && !ras.fresh )
-      ras.cProfile->start = -ras.cProfile->start;
-
-    return result;
+    return Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
   }
 
 
@@ -1181,105 +1084,73 @@
                       Long       miny,
                       Long       maxy )
   {
-    Long   y1, y2, e, e2, e0;
-    Short  f1;
-
-    TPoint*  start_arc;
+    Long  y1, y2, e, e2, dy;
+    Long  dx, x2;
 
-    PLong top;
+    PLong  top;
 
 
     y1  = arc[degree].y;
     y2  = arc[0].y;
-    top = ras.top;
 
     if ( y2 < miny || y1 > maxy )
-      goto Fin;
-
-    e2 = FLOOR( y2 );
-
-    if ( e2 > maxy )
-      e2 = maxy;
-
-    e0 = miny;
-
-    if ( y1 < miny )
-      e = miny;
-    else
-    {
-      e  = CEILING( y1 );
-      f1 = (Short)( FRAC( y1 ) );
-      e0 = e;
-
-      if ( f1 == 0 )
-      {
-        if ( ras.joint )
-        {
-          top--;
-          ras.joint = FALSE;
-        }
+      return SUCCESS;
 
-        *top++ = arc[degree].x;
+    e2 = y2 > maxy ? maxy : FLOOR( y2 );
+    e  = y1 < miny ? miny : CEILING( y1 );
 
-        e += ras.precision;
-      }
-    }
+    if ( y1 == e )
+      e += ras.precision;
 
-    if ( ras.fresh )
-    {
-      ras.cProfile->start = TRUNC( e0 );
-      ras.fresh = FALSE;
-    }
+    if ( e2 < e )  /* nothing to do */
+      return SUCCESS;
 
-    if ( e2 < e )
-      goto Fin;
+    top = ras.top;
 
     if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
     {
-      ras.top   = top;
       ras.error = FT_THROW( Raster_Overflow );
       return FAILURE;
     }
 
-    start_arc = arc;
-
     do
     {
-      ras.joint = FALSE;
-
       y2 = arc[0].y;
+      x2 = arc[0].x;
 
       if ( y2 > e )
       {
-        y1 = arc[degree].y;
-        if ( y2 - y1 >= ras.precision_step )
+        dy = y2 - arc[degree].y;
+        dx = x2 - arc[degree].x;
+
+        /* split condition should be invariant of direction */
+        if (  dy > ras.precision_step ||
+              dx > ras.precision_step ||
+             -dx > ras.precision_step )
         {
           splitter( arc );
           arc += degree;
         }
         else
         {
-          *top++ = arc[degree].x + FMulDiv( arc[0].x - arc[degree].x,
-                                            e - y1, y2 - y1 );
+          *top++ = x2 - FMulDiv( y2 - e, dx, dy );
+          e     += ras.precision;
           arc -= degree;
-          e   += ras.precision;
         }
       }
       else
       {
         if ( y2 == e )
         {
-          ras.joint  = TRUE;
-          *top++     = arc[0].x;
-
-          e += ras.precision;
+          *top++ = x2;
+          e     += ras.precision;
         }
-        arc -= degree;
+        arc   -= degree;
       }
-    } while ( arc >= start_arc && e <= e2 );
+    }
+    while ( e <= e2 );
 
-  Fin:
-    ras.top  = top;
+    ras.top = top;
     return SUCCESS;
   }
 
@@ -1316,7 +1187,7 @@
                         Long       miny,
                         Long       maxy )
   {
-    Bool     result, fresh;
+    Bool  result;
 
 
     arc[0].y = -arc[0].y;
@@ -1325,13 +1196,8 @@
     if ( degree > 2 )
       arc[3].y = -arc[3].y;
 
-    fresh = ras.fresh;
-
     result = Bezier_Up( RAS_VARS degree, arc, splitter, -maxy, -miny );
 
-    if ( fresh && !ras.fresh )
-      ras.cProfile->start = -ras.cProfile->start;
-
     arc[0].y = -arc[0].y;
     return result;
   }
@@ -1362,74 +1228,50 @@
   Line_To( RAS_ARGS Long  x,
                     Long  y )
   {
-    /* First, detect a change of direction */
+    TStates  state;
 
-    switch ( ras.state )
-    {
-    case Unknown_State:
-      if ( y > ras.lastY )
-      {
-        if ( New_Profile( RAS_VARS Ascending_State,
-                                   IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
-          return FAILURE;
-      }
-      else
-      {
-        if ( y < ras.lastY )
-          if ( New_Profile( RAS_VARS Descending_State,
-                                     IS_TOP_OVERSHOOT( ras.lastY ) ) )
-            return FAILURE;
-      }
-      break;
 
-    case Ascending_State:
-      if ( y < ras.lastY )
-      {
-        if ( End_Profile( RAS_VARS IS_TOP_OVERSHOOT( ras.lastY ) ) ||
-             New_Profile( RAS_VARS Descending_State,
-                                   IS_TOP_OVERSHOOT( ras.lastY ) ) )
-          return FAILURE;
-      }
-      break;
+    if ( y == ras.lastY )
+      goto Fin;
 
-    case Descending_State:
-      if ( y > ras.lastY )
-      {
-        if ( End_Profile( RAS_VARS IS_BOTTOM_OVERSHOOT( ras.lastY ) ) ||
-             New_Profile( RAS_VARS Ascending_State,
-                                   IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
-          return FAILURE;
-      }
-      break;
+    /* First, detect a change of direction */
 
-    default:
-      ;
+    state = ras.lastY < y ? Ascending_State : Descending_State;
+
+    if ( ras.state != state )
+    {
+      /* finalize current profile if any */
+      if ( ras.state != Unknown_State &&
+           End_Profile( RAS_VAR )     )
+        goto Fail;
+
+      /* create a new profile */
+      if ( New_Profile( RAS_VARS state ) )
+        goto Fail;
     }
 
     /* Then compute the lines */
 
-    switch ( ras.state )
+    if ( state == Ascending_State )
     {
-    case Ascending_State:
       if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
                              x, y, ras.minY, ras.maxY ) )
-        return FAILURE;
-      break;
-
-    case Descending_State:
+        goto Fail;
+    }
+    else
+    {
       if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
                                x, y, ras.minY, ras.maxY ) )
-        return FAILURE;
-      break;
-
-    default:
-      ;
+        goto Fail;
     }
 
+  Fin:
     ras.lastX = x;
     ras.lastY = y;
-
     return SUCCESS;
+
+  Fail:
+    return FAILURE;
   }
 
 
@@ -1500,7 +1342,7 @@
         ymax = y1;
       }
 
-      if ( y2 < ymin || y2 > ymax )
+      if ( y2 < FLOOR( ymin ) || y2 > CEILING( ymax ) )
       {
         /* this arc has no given direction, split it! */
         Split_Conic( arc );
@@ -1508,8 +1350,12 @@
       }
       else if ( y1 == y3 )
       {
-        /* this arc is flat, ignore it and pop it from the Bezier stack */
+        /* this arc is flat, advance position */
+        /* and pop it from the Bezier stack   */
         arc -= 2;
+
+        ras.lastX = x3;
+        ras.lastY = y3;
       }
       else
       {
@@ -1518,18 +1364,13 @@
         state_bez = y1 < y3 ? Ascending_State : Descending_State;
         if ( ras.state != state_bez )
         {
-          Bool  o = ( state_bez == Ascending_State )
-                      ? IS_BOTTOM_OVERSHOOT( y1 )
-                      : IS_TOP_OVERSHOOT( y1 );
-
-
           /* finalize current profile if any */
           if ( ras.state != Unknown_State &&
-               End_Profile( RAS_VARS o )  )
+               End_Profile( RAS_VAR )     )
             goto Fail;
 
           /* create a new profile */
-          if ( New_Profile( RAS_VARS state_bez, o ) )
+          if ( New_Profile( RAS_VARS state_bez ) )
             goto Fail;
         }
 
@@ -1545,13 +1386,13 @@
                                      ras.minY, ras.maxY ) )
             goto Fail;
         arc -= 2;
+
+        ras.lastX = x3;
+        ras.lastY = y3;
       }
 
     } while ( arc >= arcs );
 
-    ras.lastX = x3;
-    ras.lastY = y3;
-
     return SUCCESS;
 
   Fail:
@@ -1648,7 +1489,7 @@
         ymax2 = y2;
       }
 
-      if ( ymin2 < ymin1 || ymax2 > ymax1 )
+      if ( ymin2 < FLOOR( ymin1 ) || ymax2 > CEILING( ymax1 ) )
       {
         /* this arc has no given direction, split it! */
         Split_Cubic( arc );
@@ -1656,27 +1497,26 @@
       }
       else if ( y1 == y4 )
       {
-        /* this arc is flat, ignore it and pop it from the Bezier stack */
+        /* this arc is flat, advance position */
+        /* and pop it from the Bezier stack   */
         arc -= 3;
+
+        ras.lastX = x4;
+        ras.lastY = y4;
       }
       else
       {
-        state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;
+        state_bez = y1 < y4 ? Ascending_State : Descending_State;
 
         /* detect a change of direction */
         if ( ras.state != state_bez )
         {
-          Bool  o = ( state_bez == Ascending_State )
-                      ? IS_BOTTOM_OVERSHOOT( y1 )
-                      : IS_TOP_OVERSHOOT( y1 );
-
-
           /* finalize current profile if any */
           if ( ras.state != Unknown_State &&
-               End_Profile( RAS_VARS o )  )
+               End_Profile( RAS_VAR )     )
             goto Fail;
 
-          if ( New_Profile( RAS_VARS state_bez, o ) )
+          if ( New_Profile( RAS_VARS state_bez ) )
             goto Fail;
         }
 
@@ -1692,13 +1532,13 @@
                                      ras.minY, ras.maxY ) )
             goto Fail;
         arc -= 3;
+
+        ras.lastX = x4;
+        ras.lastY = y4;
       }
 
     } while ( arc >= arcs );
 
-    ras.lastX = x4;
-    ras.lastY = y4;
-
     return SUCCESS;
 
   Fail:
@@ -1740,6 +1580,11 @@
    *
    * @Return:
    *   SUCCESS on success, FAILURE on error.
+   *
+   * @Note:
+   *   Unlike FT_Outline_Decompose(), this function handles the scanmode
+   *   dropout tags in the individual contours.  Therefore, it cannot be
+   *   replaced.
    */
   static Bool
   Decompose_Curve( RAS_ARGS Int  first,
@@ -1753,7 +1598,7 @@
     FT_Vector*  points;
     FT_Vector*  point;
     FT_Vector*  limit;
-    char*       tags;
+    FT_Byte*    tags;
 
     UInt        tag;       /* current point's state           */
 
@@ -1974,24 +1819,17 @@
 
 
     ras.fProfile = NULL;
-    ras.joint    = FALSE;
-    ras.fresh    = FALSE;
+    ras.cProfile = NULL;
 
-    ras.maxBuff  = ras.sizeBuff - AlignProfileSize;
+    ras.top      = ras.buff;
+    ras.maxBuff  = ras.sizeBuff - 1;  /* top reserve */
 
-    ras.numTurns = 0;
-
-    ras.cProfile         = (PProfile)ras.top;
-    ras.cProfile->offset = ras.top;
-    ras.num_Profs        = 0;
+    ras.numTurns  = 0;
+    ras.num_Profs = 0;
 
     last = -1;
     for ( i = 0; i < ras.outline.n_contours; i++ )
     {
-      PProfile  lastProfile;
-      Bool      o;
-
-
       ras.state    = Unknown_State;
       ras.gProfile = NULL;
 
@@ -2001,35 +1839,30 @@
       if ( Decompose_Curve( RAS_VARS first, last, flipped ) )
         return FAILURE;
 
+      /* Note that ras.gProfile can stay nil if the contour was */
+      /* too small to be drawn or degenerate.                   */
+      if ( !ras.gProfile )
+        continue;
+
       /* we must now check whether the extreme arcs join or not */
       if ( FRAC( ras.lastY ) == 0 &&
            ras.lastY >= ras.minY  &&
            ras.lastY <= ras.maxY  )
-        if ( ras.gProfile                        &&
-             ( ras.gProfile->flags & Flow_Up ) ==
+        if ( ( ras.gProfile->flags & Flow_Up ) ==
                ( ras.cProfile->flags & Flow_Up ) )
           ras.top--;
-        /* Note that ras.gProfile can be nil if the contour was too small */
-        /* to be drawn.                                                   */
 
-      lastProfile = ras.cProfile;
-      if ( ras.top != ras.cProfile->offset &&
-           ( ras.cProfile->flags & Flow_Up ) )
-        o = IS_TOP_OVERSHOOT( ras.lastY );
-      else
-        o = IS_BOTTOM_OVERSHOOT( ras.lastY );
-      if ( End_Profile( RAS_VARS o ) )
+      if ( End_Profile( RAS_VAR ) )
         return FAILURE;
 
-      /* close the `next profile in contour' linked list */
-      if ( ras.gProfile )
-        lastProfile->next = ras.gProfile;
+      if ( !ras.fProfile )
+        ras.fProfile = ras.gProfile;
     }
 
-    if ( Finalize_Profile_Table( RAS_VAR ) )
-      return FAILURE;
+    if ( ras.fProfile )
+      Finalize_Profile_Table( RAS_VAR );
 
-    return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
+    return SUCCESS;
   }
 
 
@@ -2044,22 +1877,9 @@
 
   /**************************************************************************
    *
-   * Init_Linked
-   *
-   *   Initializes an empty linked list.
-   */
-  static void
-  Init_Linked( TProfileList*  l )
-  {
-    *l = NULL;
-  }
-
-
-  /**************************************************************************
-   *
    * InsNew
    *
-   *   Inserts a new profile in a linked list.
+   *   Inserts a new profile in a linked list, sorted by coordinate.
    */
   static void
   InsNew( PProfileList  list,
@@ -2073,10 +1893,8 @@
     current = *old;
     x       = profile->X;
 
-    while ( current )
+    while ( current && current->X < x )
     {
-      if ( x < current->X )
-        break;
       old     = &current->link;
       current = *old;
     }
@@ -2088,79 +1906,51 @@
 
   /**************************************************************************
    *
-   * DelOld
+   * Increment
    *
-   *   Removes an old profile from a linked list.
+   *   Advances all profile in the list to the next scanline.  It also
+   *   sorts the trace list in the unlikely case of profile crossing.
+   *   The profiles are inserted in sorted order.  We might need a single
+   *   swap to fix it when profiles (contours) cross.
+   *   Bubble sort with immediate restart is good enough and simple.
    */
   static void
-  DelOld( PProfileList    list,
-          const PProfile  profile )
+  Increment( PProfileList  list,
+             Int           flow )
   {
-    PProfile  *old, current;
-
+    PProfile  *old, current, next;
 
-    old     = list;
-    current = *old;
 
-    while ( current )
+    /* First, set the new X coordinates and remove exhausted profiles */
+    old = list;
+    while ( *old )
     {
-      if ( current == profile )
+      current = *old;
+      if ( --current->height )
       {
-        *old = current->link;
-        return;
+        current->offset += flow;
+        current->X       = current->x[current->offset];
+        old = &current->link;
       }
-
-      old     = &current->link;
-      current = *old;
-    }
-
-    /* we should never get there, unless the profile was not part of */
-    /* the list.                                                     */
-  }
-
-
-  /**************************************************************************
-   *
-   * Sort
-   *
-   *   Sorts a trace list.  In 95%, the list is already sorted.  We need
-   *   an algorithm which is fast in this case.  Bubble sort is enough
-   *   and simple.
-   */
-  static void
-  Sort( PProfileList  list )
-  {
-    PProfile  *old, current, next;
-
-
-    /* First, set the new X coordinate of each profile */
-    current = *list;
-    while ( current )
-    {
-      current->X       = *current->offset;
-      current->offset += ( current->flags & Flow_Up ) ? 1 : -1;
-      current->height--;
-      current = current->link;
+      else
+        *old = current->link;  /* remove */
     }
 
-    /* Then sort them */
+    /* Then make sure the list remains sorted */
     old     = list;
     current = *old;
 
     if ( !current )
       return;
 
-    next = current->link;
-
-    while ( next )
+    while ( current->link )
     {
+      next = current->link;
+
       if ( current->X <= next->X )
       {
         old     = &current->link;
-        current = *old;
-
-        if ( !current )
-          return;
+        current = next;
       }
       else
       {
@@ -2168,11 +1958,10 @@
         current->link = next->link;
         next->link    = current;
 
+        /* this is likely the only necessary swap -- restart */
         old     = list;
         current = *old;
       }
-
-      next = current->link;
     }
   }
 
@@ -2187,74 +1976,51 @@
    */
 
   static void
-  Vertical_Sweep_Init( RAS_ARGS Short  min,
-                                Short  max )
+  Vertical_Sweep_Init( RAS_ARGS Int  min,
+                                Int  max )
   {
     FT_UNUSED( max );
 
 
-    ras.bLine = ras.bOrigin - min * ras.target.pitch;
+    ras.bLine = ras.bOrigin - min * ras.bPitch;
   }
 
 
   static void
-  Vertical_Sweep_Span( RAS_ARGS Short       y,
+  Vertical_Sweep_Span( RAS_ARGS Int         y,
                                 FT_F26Dot6  x1,
-                                FT_F26Dot6  x2,
-                                PProfile    left,
-                                PProfile    right )
+                                FT_F26Dot6  x2 )
   {
-    Long  e1, e2;
-
-    Int  dropOutControl = left->flags & 7;
+    Int  e1 = (Int)TRUNC( CEILING( x1 ) );
+    Int  e2 = (Int)TRUNC(   FLOOR( x2 ) );
 
     FT_UNUSED( y );
-    FT_UNUSED( left );
-    FT_UNUSED( right );
 
 
-    /* in high-precision mode, we need 12 digits after the comma to */
-    /* represent multiples of 1/(1<<12) = 1/4096                    */
-    FT_TRACE7(( "  y=%d x=[% .12f;% .12f]",
+    FT_TRACE7(( "  y=%d x=[% .*f;% .*f]",
                 y,
-                (double)x1 / (double)ras.precision,
-                (double)x2 / (double)ras.precision ));
-
-    /* Drop-out control */
+                ras.precision_bits, (double)x1 / (double)ras.precision,
+                ras.precision_bits, (double)x2 / (double)ras.precision ));
 
-    e1 = CEILING( x1 );
-    e2 = FLOOR( x2 );
-
-    /* take care of the special case where both the left */
-    /* and right contour lie exactly on pixel centers    */
-    if ( dropOutControl != 2                             &&
-         x2 - x1 - ras.precision <= ras.precision_jitter &&
-         e1 != x1 && e2 != x2                            )
-      e2 = e1;
-
-    e1 = TRUNC( e1 );
-    e2 = TRUNC( e2 );
-
-    if ( e2 >= 0 && e1 < ras.bWidth )
+    if ( e2 >= 0 && e1 <= ras.bRight )
     {
-      Byte*  target;
+      PByte  target;
 
-      Int   c1, c2;
-      Byte  f1, f2;
+      Int   c1, f1, c2, f2;
 
 
       if ( e1 < 0 )
         e1 = 0;
-      if ( e2 >= ras.bWidth )
-        e2 = ras.bWidth - 1;
+      if ( e2 > ras.bRight )
+        e2 = ras.bRight;
 
-      FT_TRACE7(( " -> x=[%ld;%ld]", e1, e2 ));
+      FT_TRACE7(( " -> x=[%d;%d]", e1, e2 ));
 
-      c1 = (Short)( e1 >> 3 );
-      c2 = (Short)( e2 >> 3 );
+      c1 = e1 >> 3;
+      c2 = e2 >> 3;
 
-      f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
-      f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
+      f1 =  0xFF >> ( e1 & 7 );
+      f2 = ~0x7F >> ( e2 & 7 );
 
       target = ras.bLine + c1;
       c2 -= c1;
@@ -2280,163 +2046,50 @@
 
 
   static void
-  Vertical_Sweep_Drop( RAS_ARGS Short       y,
+  Vertical_Sweep_Drop( RAS_ARGS Int         y,
                                 FT_F26Dot6  x1,
-                                FT_F26Dot6  x2,
-                                PProfile    left,
-                                PProfile    right )
+                                FT_F26Dot6  x2 )
   {
-    Long   e1, e2, pxl;
-    Short  c1, f1;
-
+    Int  e1 = (Int)TRUNC( x1 );
+    Int  e2 = (Int)TRUNC( x2 );
+    Int  c1, f1;
 
-    FT_TRACE7(( "  y=%d x=[% .12f;% .12f]",
-                y,
-                (double)x1 / (double)ras.precision,
-                (double)x2 / (double)ras.precision ));
+    FT_UNUSED( y );
 
-    /* Drop-out control */
 
-    /*   e2            x2                    x1           e1   */
-    /*                                                         */
-    /*                 ^                     |                 */
-    /*                 |                     |                 */
-    /*   +-------------+---------------------+------------+    */
-    /*                 |                     |                 */
-    /*                 |                     v                 */
-    /*                                                         */
-    /* pixel         contour              contour       pixel  */
-    /* center                                           center */
-
-    /* drop-out mode    scan conversion rules (as defined in OpenType) */
-    /* --------------------------------------------------------------- */
-    /*  0                1, 2, 3                                       */
-    /*  1                1, 2, 4                                       */
-    /*  2                1, 2                                          */
-    /*  3                same as mode 2                                */
-    /*  4                1, 2, 5                                       */
-    /*  5                1, 2, 6                                       */
-    /*  6, 7             same as mode 2                                */
-
-    e1  = CEILING( x1 );
-    e2  = FLOOR  ( x2 );
-    pxl = e1;
+    /* undocumented but confirmed: If the drop-out would result in a  */
+    /* pixel outside of the bounding box, use the pixel inside of the */
+    /* bounding box instead                                           */
+    if ( e1 < 0 || e1 > ras.bRight )
+      e1 = e2;
 
-    if ( e1 > e2 )
+    /* otherwise check that the other pixel isn't set */
+    else if ( e2 >=0 && e2 <= ras.bRight )
     {
-      Int  dropOutControl = left->flags & 7;
-
-
-      if ( e1 == e2 + ras.precision )
-      {
-        switch ( dropOutControl )
-        {
-        case 0: /* simple drop-outs including stubs */
-          pxl = e2;
-          break;
-
-        case 4: /* smart drop-outs including stubs */
-          pxl = SMART( x1, x2 );
-          break;
-
-        case 1: /* simple drop-outs excluding stubs */
-        case 5: /* smart drop-outs excluding stubs  */
-
-          /* Drop-out Control Rules #4 and #6 */
-
-          /* The specification neither provides an exact definition */
-          /* of a `stub' nor gives exact rules to exclude them.     */
-          /*                                                        */
-          /* Here the constraints we use to recognize a stub.       */
-          /*                                                        */
-          /*  upper stub:                                           */
-          /*                                                        */
-          /*   - P_Left and P_Right are in the same contour         */
-          /*   - P_Right is the successor of P_Left in that contour */
-          /*   - y is the top of P_Left and P_Right                 */
-          /*                                                        */
-          /*  lower stub:                                           */
-          /*                                                        */
-          /*   - P_Left and P_Right are in the same contour         */
-          /*   - P_Left is the successor of P_Right in that contour */
-          /*   - y is the bottom of P_Left                          */
-          /*                                                        */
-          /* We draw a stub if the following constraints are met.   */
-          /*                                                        */
-          /*   - for an upper or lower stub, there is top or bottom */
-          /*     overshoot, respectively                            */
-          /*   - the covered interval is greater or equal to a half */
-          /*     pixel                                              */
-
-          /* upper stub test */
-          if ( left->next == right                &&
-               left->height <= 0                  &&
-               !( left->flags & Overshoot_Top   &&
-                  x2 - x1 >= ras.precision_half ) )
-            goto Exit;
-
-          /* lower stub test */
-          if ( right->next == left                 &&
-               left->start == y                    &&
-               !( left->flags & Overshoot_Bottom &&
-                  x2 - x1 >= ras.precision_half  ) )
-            goto Exit;
-
-          if ( dropOutControl == 1 )
-            pxl = e2;
-          else
-            pxl = SMART( x1, x2 );
-          break;
-
-        default: /* modes 2, 3, 6, 7 */
-          goto Exit;  /* no drop-out control */
-        }
+      c1 = e2 >> 3;
+      f1 = 0x80 >> ( e2 & 7 );
 
-        /* undocumented but confirmed: If the drop-out would result in a  */
-        /* pixel outside of the bounding box, use the pixel inside of the */
-        /* bounding box instead                                           */
-        if ( pxl < 0 )
-          pxl = e1;
-        else if ( TRUNC( pxl ) >= ras.bWidth )
-          pxl = e2;
-
-        /* check that the other pixel isn't set */
-        e1 = ( pxl == e1 ) ? e2 : e1;
-
-        e1 = TRUNC( e1 );
-
-        c1 = (Short)( e1 >> 3 );
-        f1 = (Short)( e1 &  7 );
-
-        if ( e1 >= 0 && e1 < ras.bWidth     &&
-             ras.bLine[c1] & ( 0x80 >> f1 ) )
-          goto Exit;
-      }
-      else
-        goto Exit;
+      if ( ras.bLine[c1] & f1 )
+        return;
     }
 
-    e1 = TRUNC( pxl );
-
-    if ( e1 >= 0 && e1 < ras.bWidth )
+    if ( e1 >= 0 && e1 <= ras.bRight )
     {
-      FT_TRACE7(( " -> x=%ld", e1 ));
+      c1 = e1 >> 3;
+      f1 = 0x80 >> ( e1 & 7 );
 
-      c1 = (Short)( e1 >> 3 );
-      f1 = (Short)( e1 & 7 );
+      FT_TRACE7(( "  y=%d x=%d%s\n", y, e1,
+                  ras.bLine[c1] & f1 ? " redundant" : "" ));
 
-      ras.bLine[c1] |= (char)( 0x80 >> f1 );
+      ras.bLine[c1] |= f1;
     }
-
-  Exit:
-    FT_TRACE7(( " dropout=%d\n", left->flags & 7 ));
   }
 
 
   static void
   Vertical_Sweep_Step( RAS_ARG )
   {
-    ras.bLine -= ras.target.pitch;
+    ras.bLine -= ras.bPitch;
   }
 
 
@@ -2450,8 +2103,8 @@
    */
 
   static void
-  Horizontal_Sweep_Init( RAS_ARGS Short  min,
-                                  Short  max )
+  Horizontal_Sweep_Init( RAS_ARGS Int  min,
+                                  Int  max )
   {
     /* nothing, really */
     FT_UNUSED_RASTER;
@@ -2461,22 +2114,18 @@
 
 
   static void
-  Horizontal_Sweep_Span( RAS_ARGS Short       y,
+  Horizontal_Sweep_Span( RAS_ARGS Int         y,
                                   FT_F26Dot6  x1,
-                                  FT_F26Dot6  x2,
-                                  PProfile    left,
-                                  PProfile    right )
+                                  FT_F26Dot6  x2 )
   {
-    Long  e1, e2;
+    Long  e1 = CEILING( x1 );
+    Long  e2 =   FLOOR( x2 );
 
-    FT_UNUSED( left );
-    FT_UNUSED( right );
 
-
-    FT_TRACE7(( "  x=%d y=[% .12f;% .12f]",
+    FT_TRACE7(( "  x=%d y=[% .*f;% .*f]",
                 y,
-                (double)x1 / (double)ras.precision,
-                (double)x2 / (double)ras.precision ));
+                ras.precision_bits, (double)x1 / (double)ras.precision,
+                ras.precision_bits, (double)x2 / (double)ras.precision ));
 
     /* We should not need this procedure but the vertical sweep   */
     /* mishandles horizontal lines through pixel centers.  So we  */
@@ -2484,20 +2133,18 @@
     /*                                                            */
     /* XXX: Can we handle horizontal lines better and drop this?  */
 
-    e1 = CEILING( x1 );
-
     if ( x1 == e1 )
     {
       e1 = TRUNC( e1 );
 
-      if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
+      if ( e1 >= 0 && e1 <= ras.bTop )
       {
-        Byte   f1;
+        Int    f1;
         PByte  bits;
 
 
-        bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
-        f1   = (Byte)( 0x80 >> ( y & 7 ) );
+        bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.bPitch;
+        f1   = 0x80 >> ( y & 7 );
 
         FT_TRACE7(( bits[0] & f1 ? " redundant"
                                  : " -> y=%ld edge", e1 ));
@@ -2506,20 +2153,18 @@
       }
     }
 
-    e2 = FLOOR  ( x2 );
-
     if ( x2 == e2 )
     {
       e2 = TRUNC( e2 );
 
-      if ( e2 >= 0 && (ULong)e2 < ras.target.rows )
+      if ( e2 >= 0 && e2 <= ras.bTop )
       {
-        Byte   f1;
+        Int    f1;
         PByte  bits;
 
 
-        bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.target.pitch;
-        f1   = (Byte)( 0x80 >> ( y & 7 ) );
+        bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.bPitch;
+        f1   = 0x80 >> ( y & 7 );
 
         FT_TRACE7(( bits[0] & f1 ? " redundant"
                                  : " -> y=%ld edge", e2 ));
@@ -2533,122 +2178,42 @@
 
 
   static void
-  Horizontal_Sweep_Drop( RAS_ARGS Short       y,
+  Horizontal_Sweep_Drop( RAS_ARGS Int         y,
                                   FT_F26Dot6  x1,
-                                  FT_F26Dot6  x2,
-                                  PProfile    left,
-                                  PProfile    right )
+                                  FT_F26Dot6  x2 )
   {
-    Long   e1, e2, pxl;
+    Int    e1 = (Int)TRUNC( x1 );
+    Int    e2 = (Int)TRUNC( x2 );
     PByte  bits;
-    Byte   f1;
+    Int    f1;
 
 
-    FT_TRACE7(( "  x=%d y=[% .12f;% .12f]",
-                y,
-                (double)x1 / (double)ras.precision,
-                (double)x2 / (double)ras.precision ));
+    /* undocumented but confirmed: If the drop-out would result in a  */
+    /* pixel outside of the bounding box, use the pixel inside of the */
+    /* bounding box instead                                           */
+    if ( e1 < 0 || e1 > ras.bTop )
+      e1 = e2;
 
-    /* During the horizontal sweep, we only take care of drop-outs */
-
-    /* e1     +       <-- pixel center */
-    /*        |                        */
-    /* x1  ---+-->    <-- contour      */
-    /*        |                        */
-    /*        |                        */
-    /* x2  <--+---    <-- contour      */
-    /*        |                        */
-    /*        |                        */
-    /* e2     +       <-- pixel center */
-
-    e1  = CEILING( x1 );
-    e2  = FLOOR  ( x2 );
-    pxl = e1;
-
-    if ( e1 > e2 )
+    /* otherwise check that the other pixel isn't set */
+    else if ( e2 >=0 && e2 <= ras.bTop )
     {
-      Int  dropOutControl = left->flags & 7;
-
-
-      if ( e1 == e2 + ras.precision )
-      {
-        switch ( dropOutControl )
-        {
-        case 0: /* simple drop-outs including stubs */
-          pxl = e2;
-          break;
+      bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.bPitch;
+      f1   = 0x80 >> ( y & 7 );
 
-        case 4: /* smart drop-outs including stubs */
-          pxl = SMART( x1, x2 );
-          break;
-
-        case 1: /* simple drop-outs excluding stubs */
-        case 5: /* smart drop-outs excluding stubs  */
-          /* see Vertical_Sweep_Drop for details */
-
-          /* rightmost stub test */
-          if ( left->next == right                &&
-               left->height <= 0                  &&
-               !( left->flags & Overshoot_Top   &&
-                  x2 - x1 >= ras.precision_half ) )
-            goto Exit;
-
-          /* leftmost stub test */
-          if ( right->next == left                 &&
-               left->start == y                    &&
-               !( left->flags & Overshoot_Bottom &&
-                  x2 - x1 >= ras.precision_half  ) )
-            goto Exit;
-
-          if ( dropOutControl == 1 )
-            pxl = e2;
-          else
-            pxl = SMART( x1, x2 );
-          break;
-
-        default: /* modes 2, 3, 6, 7 */
-          goto Exit;  /* no drop-out control */
-        }
-
-        /* undocumented but confirmed: If the drop-out would result in a  */
-        /* pixel outside of the bounding box, use the pixel inside of the */
-        /* bounding box instead                                           */
-        if ( pxl < 0 )
-          pxl = e1;
-        else if ( (ULong)( TRUNC( pxl ) ) >= ras.target.rows )
-          pxl = e2;
-
-        /* check that the other pixel isn't set */
-        e1 = ( pxl == e1 ) ? e2 : e1;
-
-        e1 = TRUNC( e1 );
-
-        bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
-        f1   = (Byte)( 0x80 >> ( y & 7 ) );
-
-        if ( e1 >= 0                     &&
-             (ULong)e1 < ras.target.rows &&
-             *bits & f1                  )
-          goto Exit;
-      }
-      else
-        goto Exit;
+      if ( *bits & f1 )
+        return;
     }
 
-    e1 = TRUNC( pxl );
-
-    if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
+    if ( e1 >= 0 && e1 <= ras.bTop )
     {
-      FT_TRACE7(( " -> y=%ld", e1 ));
+      bits  = ras.bOrigin + ( y >> 3 ) - e1 * ras.bPitch;
+      f1    = 0x80 >> ( y & 7 );
 
-      bits  = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
-      f1    = (Byte)( 0x80 >> ( y & 7 ) );
+      FT_TRACE7(( "  x=%d y=%d%s\n", y, e1,
+                  *bits & f1 ? " redundant" : "" ));
 
-      bits[0] |= f1;
+      *bits |= f1;
     }
-
-  Exit:
-    FT_TRACE7(( " dropout=%d\n", left->flags & 7 ));
   }
 
 
@@ -2664,116 +2229,61 @@
    *
    * Generic Sweep Drawing routine
    *
+   * Note that this routine is executed with the pool containing at least
+   * two valid profiles (up and down) and two y-turns (top and bottom).
+   *
    */
 
-  static Bool
+  static void
   Draw_Sweep( RAS_ARG )
   {
-    Short         y, y_change, y_height;
+    Int           min_Y, max_Y, dropouts;
+    Int           y, y_turn;
 
-    PProfile      P, Q, P_Left, P_Right;
+    PProfile      *Q, P, P_Left, P_Right;
 
-    Short         min_Y, max_Y, top, bottom, dropouts;
+    TProfileList  waiting    = ras.fProfile;
+    TProfileList  draw_left  = NULL;
+    TProfileList  draw_right = NULL;
 
-    Long          x1, x2, xs, e1, e2;
 
-    TProfileList  waiting;
-    TProfileList  draw_left, draw_right;
+    /* use y_turns to set the drawing range */
 
-
-    /* initialize empty linked lists */
-
-    Init_Linked( &waiting );
-
-    Init_Linked( &draw_left  );
-    Init_Linked( &draw_right );
-
-    /* first, compute min and max Y */
-
-    P     = ras.fProfile;
-    max_Y = (Short)TRUNC( ras.minY );
-    min_Y = (Short)TRUNC( ras.maxY );
-
-    while ( P )
-    {
-      Q = P->link;
-
-      bottom = (Short)P->start;
-      top    = (Short)( P->start + P->height - 1 );
-
-      if ( min_Y > bottom )
-        min_Y = bottom;
-      if ( max_Y < top )
-        max_Y = top;
-
-      P->X = 0;
-      InsNew( &waiting, P );
-
-      P = Q;
-    }
-
-    /* check the Y-turns */
-    if ( ras.numTurns == 0 )
-    {
-      ras.error = FT_THROW( Invalid_Outline );
-      return FAILURE;
-    }
+    min_Y = (Int)ras.maxBuff[0];
+    max_Y = (Int)ras.maxBuff[ras.numTurns] - 1;
 
     /* now initialize the sweep */
 
     ras.Proc_Sweep_Init( RAS_VARS min_Y, max_Y );
 
-    /* then compute the distance of each profile from min_Y */
-
-    P = waiting;
-
-    while ( P )
-    {
-      P->countL = P->start - min_Y;
-      P = P->link;
-    }
-
     /* let's go */
 
-    y        = min_Y;
-    y_height = 0;
-
-    if ( ras.numTurns > 0                     &&
-         ras.sizeBuff[-ras.numTurns] == min_Y )
-      ras.numTurns--;
-
-    while ( ras.numTurns > 0 )
+    for ( y = min_Y; y <= max_Y; )
     {
-      /* check waiting list for new activations */
+      /* check waiting list for new profile activations */
 
-      P = waiting;
-
-      while ( P )
+      Q = &waiting;
+      while ( *Q )
       {
-        Q = P->link;
-        P->countL -= y_height;
-        if ( P->countL == 0 )
+        P = *Q;
+        if ( P->start == y )
         {
-          DelOld( &waiting, P );
+          *Q = P->link;  /* remove */
 
+          /* each active list contains profiles with the same flow */
+          /* left and right are arbitrary, correspond to TrueType  */
           if ( P->flags & Flow_Up )
             InsNew( &draw_left,  P );
           else
             InsNew( &draw_right, P );
         }
-
-        P = Q;
+        else
+          Q = &P->link;
       }
 
-      /* sort the drawing lists */
-
-      Sort( &draw_left );
-      Sort( &draw_right );
+      y_turn = (Int)*++ras.maxBuff;
 
-      y_change = (Short)ras.sizeBuff[-ras.numTurns--];
-      y_height = (Short)( y_change - y );
-
-      while ( y < y_change )
+      do
       {
         /* let's trace */
 
@@ -2784,9 +2294,13 @@
 
         while ( P_Left && P_Right )
         {
-          x1 = P_Left ->X;
-          x2 = P_Right->X;
+          Long  x1 = P_Left ->X;
+          Long  x2 = P_Right->X;
+          Long  xs;
 
+
+          /* TrueType should have x2 > x1, but can be opposite */
+          /* by mistake or in CFF/Type1, fix it then           */
           if ( x1 > x2 )
           {
             xs = x1;
@@ -2794,205 +2308,130 @@
             x2 = xs;
           }
 
-          e1 = FLOOR( x1 );
-          e2 = CEILING( x2 );
+          if ( CEILING( x1 ) <= FLOOR( x2 ) )
+            ras.Proc_Sweep_Span( RAS_VARS y, x1, x2 );
 
-          if ( x2 - x1 <= ras.precision &&
-               e1 != x1 && e2 != x2     )
+          /* otherwise, bottom ceiling > top floor, it is a drop-out */
+          else
           {
-            if ( e1 > e2 || e2 == e1 + ras.precision )
-            {
-              Int  dropOutControl = P_Left->flags & 7;
+            Int  dropOutControl = P_Left->flags & 7;
 
 
-              if ( dropOutControl != 2 )
-              {
-                /* a drop-out was detected */
+            /* Drop-out control */
 
-                P_Left ->X = x1;
-                P_Right->X = x2;
+            /*   e2            x2                    x1           e1   */
+            /*                                                         */
+            /*                 ^                     |                 */
+            /*                 |                     |                 */
+            /*   +-------------+---------------------+------------+    */
+            /*                 |                     |                 */
+            /*                 |                     v                 */
+            /*                                                         */
+            /* pixel         contour              contour       pixel  */
+            /* center                                           center */
+
+            /* drop-out mode   scan conversion rules (OpenType specs)  */
+            /* ------------------------------------------------------- */
+            /*  bit 0          exclude stubs if set                    */
+            /*  bit 1          ignore drop-outs if set                 */
+            /*  bit 2          smart rounding if set                   */
+
+            if ( dropOutControl & 2 )
+              goto Next_Pair;
+
+            /* The specification neither provides an exact definition */
+            /* of a `stub' nor gives exact rules to exclude them.     */
+            /*                                                        */
+            /* Here the constraints we use to recognize a stub.       */
+            /*                                                        */
+            /*  upper stub:                                           */
+            /*                                                        */
+            /*   - P_Left and P_Right are in the same contour         */
+            /*   - P_Right is the successor of P_Left in that contour */
+            /*   - y is the top of P_Left and P_Right                 */
+            /*                                                        */
+            /*  lower stub:                                           */
+            /*                                                        */
+            /*   - P_Left and P_Right are in the same contour         */
+            /*   - P_Left is the successor of P_Right in that contour */
+            /*   - y is the bottom of P_Left                          */
+            /*                                                        */
+            /* We draw a stub if the following constraints are met.   */
+            /*                                                        */
+            /*   - for an upper or lower stub, there is top or bottom */
+            /*     overshoot, respectively                            */
+            /*   - the covered interval is greater or equal to a half */
+            /*     pixel                                              */
 
-                /* mark profile for drop-out processing */
-                P_Left->countL = 1;
-                dropouts++;
-              }
+            if ( dropOutControl & 1 )
+            {
+              /* upper stub test */
+              if ( P_Left->height == 1                &&
+                   P_Left->next == P_Right            &&
+                   !( P_Left->flags & Overshoot_Top   &&
+                      x2 - x1 >= ras.precision_half   ) )
+                goto Next_Pair;
+
+              /* lower stub test */
+              if ( P_Left->offset == 0                 &&
+                   P_Right->next == P_Left             &&
+                   !( P_Left->flags & Overshoot_Bottom &&
+                      x2 - x1 >= ras.precision_half    ) )
+                goto Next_Pair;
+            }
 
-              goto Skip_To_Next;
+            /* select the pixel to set and the other pixel */
+            if ( dropOutControl & 4 )
+            {
+              x2 = SMART( x1, x2 );
+              x1 = x1 > x2 ? x2 + ras.precision : x2 - ras.precision;
+            }
+            else
+            {
+              x2 = FLOOR  ( x2 );
+              x1 = CEILING( x1 );
             }
-          }
 
-          ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
+            P_Left ->X = x2;
+            P_Right->X = x1;
 
-        Skip_To_Next:
+            /* mark profile for drop-out processing */
+            P_Left->flags |= Dropout;
+            dropouts++;
+          }
 
+        Next_Pair:
           P_Left  = P_Left->link;
           P_Right = P_Right->link;
         }
 
-        /* handle drop-outs _after_ the span drawing --       */
-        /* drop-out processing has been moved out of the loop */
-        /* for performance tuning                             */
-        if ( dropouts > 0 )
-          goto Scan_DropOuts;
-
-      Next_Line:
-
-        ras.Proc_Sweep_Step( RAS_VAR );
-
-        y++;
+        /* handle drop-outs _after_ the span drawing */
+        P_Left  = draw_left;
+        P_Right = draw_right;
 
-        if ( y < y_change )
+        while ( dropouts )
         {
-          Sort( &draw_left  );
-          Sort( &draw_right );
-        }
-      }
-
-      /* now finalize the profiles that need it */
-
-      P = draw_left;
-      while ( P )
-      {
-        Q = P->link;
-        if ( P->height == 0 )
-          DelOld( &draw_left, P );
-        P = Q;
-      }
-
-      P = draw_right;
-      while ( P )
-      {
-        Q = P->link;
-        if ( P->height == 0 )
-          DelOld( &draw_right, P );
-        P = Q;
-      }
-    }
-
-    /* for gray-scaling, flush the bitmap scanline cache */
-    while ( y <= max_Y )
-    {
-      ras.Proc_Sweep_Step( RAS_VAR );
-      y++;
-    }
-
-    return SUCCESS;
-
-  Scan_DropOuts:
-
-    P_Left  = draw_left;
-    P_Right = draw_right;
-
-    while ( P_Left && P_Right )
-    {
-      if ( P_Left->countL )
-      {
-        P_Left->countL = 0;
-#if 0
-        dropouts--;  /* -- this is useful when debugging only */
-#endif
-        ras.Proc_Sweep_Drop( RAS_VARS y,
-                                      P_Left->X,
-                                      P_Right->X,
-                                      P_Left,
-                                      P_Right );
-      }
-
-      P_Left  = P_Left->link;
-      P_Right = P_Right->link;
-    }
-
-    goto Next_Line;
-  }
-
-
-#ifdef STANDALONE_
-
-  /**************************************************************************
-   *
-   * The following functions should only compile in stand-alone mode,
-   * i.e., when building this component without the rest of FreeType.
-   *
-   */
-
-  /**************************************************************************
-   *
-   * @Function:
-   *   FT_Outline_Get_CBox
-   *
-   * @Description:
-   *   Return an outline's `control box'.  The control box encloses all
-   *   the outline's points, including Bézier control points.  Though it
-   *   coincides with the exact bounding box for most glyphs, it can be
-   *   slightly larger in some situations (like when rotating an outline
-   *   that contains Bézier outside arcs).
-   *
-   *   Computing the control box is very fast, while getting the bounding
-   *   box can take much more time as it needs to walk over all segments
-   *   and arcs in the outline.  To get the latter, you can use the
-   *   `ftbbox' component, which is dedicated to this single task.
-   *
-   * @Input:
-   *   outline ::
-   *     A pointer to the source outline descriptor.
-   *
-   * @Output:
-   *   acbox ::
-   *     The outline's control box.
-   *
-   * @Note:
-   *   See @FT_Glyph_Get_CBox for a discussion of tricky fonts.
-   */
-
-  static void
-  FT_Outline_Get_CBox( const FT_Outline*  outline,
-                       FT_BBox           *acbox )
-  {
-    if ( outline && acbox )
-    {
-      Long  xMin, yMin, xMax, yMax;
-
-
-      if ( outline->n_points == 0 )
-      {
-        xMin = 0;
-        yMin = 0;
-        xMax = 0;
-        yMax = 0;
-      }
-      else
-      {
-        FT_Vector*  vec   = outline->points;
-        FT_Vector*  limit = vec + outline->n_points;
-
+          if ( P_Left->flags & Dropout )
+          {
+            ras.Proc_Sweep_Drop( RAS_VARS y, P_Left->X, P_Right->X );
 
-        xMin = xMax = vec->x;
-        yMin = yMax = vec->y;
-        vec++;
+            P_Left->flags &= ~Dropout;
+            dropouts--;
+          }
 
-        for ( ; vec < limit; vec++ )
-        {
-          Long  x, y;
+          P_Left  = P_Left->link;
+          P_Right = P_Right->link;
+        }
 
+        ras.Proc_Sweep_Step( RAS_VAR );
 
-          x = vec->x;
-          if ( x < xMin ) xMin = x;
-          if ( x > xMax ) xMax = x;
-
-          y = vec->y;
-          if ( y < yMin ) yMin = y;
-          if ( y > yMax ) yMax = y;
-        }
+        Increment( &draw_left,   1 );
+        Increment( &draw_right, -1 );
       }
-      acbox->xMin = xMin;
-      acbox->xMax = xMax;
-      acbox->yMin = yMin;
-      acbox->yMax = yMax;
+      while ( ++y < y_turn );
     }
   }
 
-#endif /* STANDALONE_ */
-
 
   /**************************************************************************
    *
@@ -3019,13 +2458,15 @@
     Int  band_stack[32];  /* enough to bisect 32-bit int bands */
 
 
+    FT_TRACE6(( "%s pass [%d..%d]\n",
+                flipped ? "Horizontal" : "Vertical",
+                y_min, y_max ));
+
     while ( 1 )
     {
       ras.minY = (Long)y_min * ras.precision;
       ras.maxY = (Long)y_max * ras.precision;
 
-      ras.top = ras.buff;
-
       ras.error = Raster_Err_Ok;
 
       if ( Convert_Glyph( RAS_VARS flipped ) )
@@ -3038,6 +2479,9 @@
         if ( y_min == y_max )
           return ras.error;  /* still Raster_Overflow */
 
+        FT_TRACE6(( "band [%d..%d]: to be bisected\n",
+                    y_min, y_max ));
+
         y_mid = ( y_min + y_max ) >> 1;
 
         band_stack[band_top++] = y_min;
@@ -3045,9 +2489,12 @@
       }
       else
       {
+        FT_TRACE6(( "band [%d..%d]: %hd profiles; %td bytes remaining\n",
+                    y_min, y_max, ras.num_Profs,
+                    (char*)ras.maxBuff - (char*)ras.top ));
+
         if ( ras.fProfile )
-          if ( Draw_Sweep( RAS_VAR ) )
-             return ras.error;
+          Draw_Sweep( RAS_VAR );
 
         if ( --band_top < 0 )
           break;
@@ -3076,53 +2523,48 @@
   Render_Glyph( RAS_ARG )
   {
     FT_Error  error;
+    Long      buffer[FT_MAX_BLACK_POOL];
 
 
+    ras.buff     = buffer;
+    ras.sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
+
     Set_High_Precision( RAS_VARS ras.outline.flags &
                                  FT_OUTLINE_HIGH_PRECISION );
 
+    ras.dropOutControl = 0;
+
     if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
-      ras.dropOutControl = 2;
-    else
-    {
-      if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
-        ras.dropOutControl = 4;
-      else
-        ras.dropOutControl = 0;
+      ras.dropOutControl |= 2;
 
-      if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
-        ras.dropOutControl += 1;
-    }
+    if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
+      ras.dropOutControl |= 4;
 
-    /* Vertical Sweep */
-    FT_TRACE7(( "Vertical pass (ftraster)\n" ));
+    if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
+      ras.dropOutControl |= 1;
+
+    FT_TRACE6(( "BW Raster: precision 1/%d, dropout mode %d\n",
+                ras.precision, ras.dropOutControl ));
 
+    /* Vertical Sweep */
     ras.Proc_Sweep_Init = Vertical_Sweep_Init;
     ras.Proc_Sweep_Span = Vertical_Sweep_Span;
     ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
     ras.Proc_Sweep_Step = Vertical_Sweep_Step;
 
-    ras.bWidth  = (UShort)ras.target.width;
-    ras.bOrigin = (Byte*)ras.target.buffer;
-
-    if ( ras.target.pitch > 0 )
-      ras.bOrigin += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
-
-    error = Render_Single_Pass( RAS_VARS 0, 0, (Int)ras.target.rows - 1 );
+    error = Render_Single_Pass( RAS_VARS 0, 0, ras.bTop );
     if ( error )
       return error;
 
     /* Horizontal Sweep */
     if ( !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS ) )
     {
-      FT_TRACE7(( "Horizontal pass (ftraster)\n" ));
-
       ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
       ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
       ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
       ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
 
-      error = Render_Single_Pass( RAS_VARS 1, 0, (Int)ras.target.width - 1 );
+      error = Render_Single_Pass( RAS_VARS 1, 0, ras.bRight );
       if ( error )
         return error;
     }
@@ -3233,8 +2675,6 @@
     black_TWorker  worker[1];
 #endif
 
-    Long  buffer[FT_MAX_BLACK_POOL];
-
 
     if ( !raster )
       return FT_THROW( Raster_Uninitialized );
@@ -3243,7 +2683,7 @@
       return FT_THROW( Invalid_Outline );
 
     /* return immediately if the outline is empty */
-    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+    if ( outline->n_points == 0 || outline->n_contours == 0 )
       return Raster_Err_Ok;
 
     if ( !outline->contours || !outline->points )
@@ -3269,10 +2709,14 @@
       return FT_THROW( Invalid_Argument );
 
     ras.outline = *outline;
-    ras.target  = *target_map;
 
-    ras.buff     = buffer;
-    ras.sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
+    ras.bTop    =   (Int)target_map->rows - 1;
+    ras.bRight  =   (Int)target_map->width - 1;
+    ras.bPitch  =   (Int)target_map->pitch;
+    ras.bOrigin = (PByte)target_map->buffer;
+
+    if ( ras.bPitch > 0 )
+      ras.bOrigin += ras.bTop * ras.bPitch;
 
     return Render_Glyph( RAS_VAR );
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer interface (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   monochrome renderer error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   PNG Bitmap glyph support.
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * Google, Inc.
  * Written by Stuart Gill and Behdad Esfahbod.
  *
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   PNG Bitmap glyph support.
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * Google, Inc.
  * Written by Stuart Gill and Behdad Esfahbod.
  *
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   High-level SFNT driver interface (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -49,6 +49,10 @@
 #include <freetype/internal/services/svbdf.h>
 #endif
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+#include "ttgpos.h"
+#endif
+
 #include "ttcmap.h"
 #include "ttkern.h"
 #include "ttmtx.h"
@@ -1251,6 +1255,12 @@
 #define PUT_PS_NAMES( a )  NULL
 #endif
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+#define PUT_GPOS_KERNING( a )  a
+#else
+#define PUT_GPOS_KERNING( a )  NULL
+#endif
+
   FT_DEFINE_SFNT_INTERFACE(
     sfnt_interface,
 
@@ -1274,6 +1284,8 @@
     tt_face_free_name,      /* TT_Free_Table_Func      free_name       */
 
     tt_face_load_kern,      /* TT_Load_Table_Func      load_kern       */
+    PUT_GPOS_KERNING( tt_face_load_gpos ),
+                            /* TT_Load_Table_Func      load_gpos       */
     tt_face_load_gasp,      /* TT_Load_Table_Func      load_gasp       */
     tt_face_load_pclt,      /* TT_Load_Table_Func      load_init       */
 
@@ -1292,6 +1304,9 @@
     /* since version 2.1.8 */
     tt_face_get_kerning,    /* TT_Face_GetKerningFunc  get_kerning     */
 
+    PUT_GPOS_KERNING( tt_face_get_gpos_kerning ),
+                           /* TT_Face_GetKerningFunc  get_gpos_kerning */
+
     /* since version 2.2 */
     tt_face_load_font_dir,  /* TT_Load_Table_Func      load_font_dir   */
     tt_face_load_hmtx,      /* TT_Load_Metrics_Func    load_hmtx       */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   High-level SFNT driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   SFNT error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   SFNT object management (base).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -40,6 +40,10 @@
 #include "ttbdf.h"
 #endif
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+#include "ttgpos.h"
+#endif
+
 
   /**************************************************************************
    *
@@ -1026,6 +1030,10 @@
     LOAD_( gasp );
     LOAD_( kern );
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+    LOAD_( gpos );
+#endif
+
     face->root.num_glyphs = face->max_profile.numGlyphs;
 
     /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes  */
@@ -1119,7 +1127,11 @@
         flags |= FT_FACE_FLAG_VERTICAL;
 
       /* kerning available ? */
-      if ( TT_FACE_HAS_KERNING( face ) )
+      if ( TT_FACE_HAS_KERNING( face )
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+           || face->gpos_kerning_available
+#endif
+         )
         flags |= FT_FACE_FLAG_KERNING;
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
@@ -1470,6 +1482,11 @@
     /* freeing the kerning table */
     tt_face_done_kern( face );
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+    /* freeing the GPOS table */
+    tt_face_done_gpos( face );
+#endif
+
     /* freeing the collection table */
     FT_FREE( face->ttc_header.offsets );
     face->ttc_header.count = 0;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   SFNT object management (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   WOFF format management (base).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -18,6 +18,7 @@
 
 #include "sfwoff.h"
 #include <freetype/tttags.h>
+#include <freetype/internal/ftcalc.h>
 #include <freetype/internal/ftdebug.h>
 #include <freetype/internal/ftstream.h>
 #include <freetype/ftgzip.h>
@@ -149,6 +150,7 @@
     /* Miscellaneous checks. */
     if ( woff.length != stream->size                              ||
          woff.num_tables == 0                                     ||
+         woff.num_tables >  0xFFFU                                ||
          44 + woff.num_tables * 20UL >= woff.length               ||
          12 + woff.num_tables * 16UL >= woff.totalSfntSize        ||
          ( woff.totalSfntSize & 3 ) != 0                          ||
@@ -169,21 +171,11 @@
 
     /* Write sfnt header. */
     {
-      FT_UInt  searchRange, entrySelector, rangeShift, x;
+      FT_Int  entrySelector = FT_MSB( woff.num_tables );
+      FT_Int  searchRange   = ( 1 << entrySelector ) * 16;
+      FT_Int  rangeShift    = woff.num_tables * 16 - searchRange;
 
 
-      x             = woff.num_tables;
-      entrySelector = 0;
-      while ( x )
-      {
-        x            >>= 1;
-        entrySelector += 1;
-      }
-      entrySelector--;
-
-      searchRange = ( 1 << entrySelector ) * 16;
-      rangeShift  = woff.num_tables * 16 - searchRange;
-
       WRITE_ULONG ( sfnt_header, woff.flavor );
       WRITE_USHORT( sfnt_header, woff.num_tables );
       WRITE_USHORT( sfnt_header, searchRange );
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   WOFFF format management (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   WOFF2 format management (base).
  *
- * Copyright (C) 2019-2023 by
+ * Copyright (C) 2019-2024 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -18,6 +18,7 @@
 #include "sfwoff2.h"
 #include "woff2tags.h"
 #include <freetype/tttags.h>
+#include <freetype/internal/ftcalc.h>
 #include <freetype/internal/ftdebug.h>
 #include <freetype/internal/ftstream.h>
 
@@ -289,23 +290,15 @@
     FT_ULong  checksum     = 0;
     FT_ULong  aligned_size = size & ~3UL;
     FT_ULong  i;
-    FT_ULong  v;
+    FT_Int    shift;
 
 
     for ( i = 0; i < aligned_size; i += 4 )
-      checksum += ( (FT_ULong)buf[i    ] << 24 ) |
-                  ( (FT_ULong)buf[i + 1] << 16 ) |
-                  ( (FT_ULong)buf[i + 2] <<  8 ) |
-                  ( (FT_ULong)buf[i + 3] <<  0 );
-
-    /* If size is not aligned to 4, treat as if it is padded with 0s. */
-    if ( size != aligned_size )
-    {
-      v = 0;
-      for ( i = aligned_size ; i < size; ++i )
-        v |= (FT_ULong)buf[i] << ( 24 - 8 * ( i & 3 ) );
-      checksum += v;
-    }
+      checksum += FT_NEXT_ULONG( buf );
+
+    /* remaining bytes can be shifted and added one at a time */
+    for ( shift = 24; i < size; i++, shift -= 8 )
+      checksum += (FT_UInt32)FT_NEXT_BYTE( buf ) << shift;
 
     return checksum;
   }
@@ -1799,7 +1792,6 @@
 
     FT_Byte*   sfnt        = NULL;
     FT_Stream  sfnt_stream = NULL;
-    FT_Byte*   sfnt_header;
     FT_ULong   sfnt_size;
 
     FT_Byte*  uncompressed_buf = NULL;
@@ -1853,6 +1845,7 @@
     /* Miscellaneous checks. */
     if ( woff2.length != stream->size                               ||
          woff2.num_tables == 0                                      ||
+         woff2.num_tables >  0xFFFU                                 ||
          48 + woff2.num_tables * 20UL >= woff2.length               ||
          ( woff2.metaOffset == 0 && ( woff2.metaLength != 0     ||
                                       woff2.metaOrigLength != 0 ) ) ||
@@ -2143,6 +2136,13 @@
       WOFF2_TtcFont  ttc_font = woff2.ttc_fonts + face_index;
 
 
+      if ( ttc_font->num_tables == 0 || ttc_font->num_tables > 0xFFFU )
+      {
+        FT_ERROR(( "woff2_open_font: invalid WOFF2 CollectionFontEntry\n" ));
+        error = FT_THROW( Invalid_Table );
+        goto Exit;
+      }
+
       /* Create a temporary array. */
       if ( FT_QNEW_ARRAY( temp_indices,
                           ttc_font->num_tables ) )
@@ -2198,27 +2198,15 @@
          FT_NEW( sfnt_stream )        )
       goto Exit;
 
-    sfnt_header = sfnt;
-
-    WRITE_ULONG( sfnt_header, woff2.flavor );
-
-    if ( woff2.num_tables )
     {
-      FT_UInt  searchRange, entrySelector, rangeShift, x;
+      FT_Byte*  sfnt_header = sfnt;
 
+      FT_Int  entrySelector = FT_MSB( woff2.num_tables );
+      FT_Int  searchRange   = ( 1 << entrySelector ) * 16;
+      FT_Int  rangeShift    = woff2.num_tables * 16 - searchRange;
 
-      x             = woff2.num_tables;
-      entrySelector = 0;
-      while ( x )
-      {
-        x            >>= 1;
-        entrySelector += 1;
-      }
-      entrySelector--;
-
-      searchRange = ( 1 << entrySelector ) * 16;
-      rangeShift  = ( woff2.num_tables * 16 ) - searchRange;
 
+      WRITE_ULONG ( sfnt_header, woff2.flavor );
       WRITE_USHORT( sfnt_header, woff2.num_tables );
       WRITE_USHORT( sfnt_header, searchRange );
       WRITE_USHORT( sfnt_header, entrySelector );
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   WOFFF2 format management (specification).
  *
- * Copyright (C) 2019-2023 by
+ * Copyright (C) 2019-2024 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType character mapping table (cmap) support (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType character mapping table (cmap) support (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TT CMAP classes definitions (specification only).
  *
- * Copyright (C) 2009-2023 by
+ * Copyright (C) 2009-2024 by
  * Oran Agra and Mickey Gabel.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType colored glyph layer support (body).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang <shaozhang@fb.com>.
@@ -208,18 +208,19 @@
     colr->num_base_glyphs = FT_NEXT_USHORT( p );
     base_glyph_offset     = FT_NEXT_ULONG( p );
 
-    if ( base_glyph_offset >= table_size )
+    if ( table_size <= base_glyph_offset )
       goto InvalidTable;
-    if ( colr->num_base_glyphs * BASE_GLYPH_SIZE >
-           table_size - base_glyph_offset )
+    if ( ( table_size - base_glyph_offset ) / BASE_GLYPH_SIZE
+             < colr->num_base_glyphs )
       goto InvalidTable;
 
     layer_offset     = FT_NEXT_ULONG( p );
     colr->num_layers = FT_NEXT_USHORT( p );
 
-    if ( layer_offset >= table_size )
+    if ( table_size <= layer_offset )
       goto InvalidTable;
-    if ( colr->num_layers * LAYER_SIZE > table_size - layer_offset )
+    if ( ( table_size - layer_offset ) / LAYER_SIZE
+             < colr->num_layers )
       goto InvalidTable;
 
     if ( colr->version == 1 )
@@ -229,14 +230,14 @@
 
       base_glyphs_offset_v1 = FT_NEXT_ULONG( p );
 
-      if ( base_glyphs_offset_v1 >= table_size - 4 )
+      if ( table_size - 4 <= base_glyphs_offset_v1 )
         goto InvalidTable;
 
       p1                 = (FT_Byte*)( table + base_glyphs_offset_v1 );
       num_base_glyphs_v1 = FT_PEEK_ULONG( p1 );
 
-      if ( num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE >
-             table_size - base_glyphs_offset_v1 )
+      if ( ( table_size - base_glyphs_offset_v1 ) / BASE_GLYPH_PAINT_RECORD_SIZE
+               < num_base_glyphs_v1 )
         goto InvalidTable;
 
       colr->num_base_glyphs_v1 = num_base_glyphs_v1;
@@ -244,19 +245,19 @@
 
       layer_offset_v1 = FT_NEXT_ULONG( p );
 
-      if ( layer_offset_v1 >= table_size )
+      if ( table_size <= layer_offset_v1 )
         goto InvalidTable;
 
       if ( layer_offset_v1 )
       {
-        if ( layer_offset_v1 >= table_size - 4 )
+        if ( table_size - 4 <= layer_offset_v1 )
           goto InvalidTable;
 
         p1            = (FT_Byte*)( table + layer_offset_v1 );
         num_layers_v1 = FT_PEEK_ULONG( p1 );
 
-        if ( num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE >
-               table_size - layer_offset_v1 )
+        if ( ( table_size - layer_offset_v1 ) / LAYER_V1_LIST_PAINT_OFFSET_SIZE
+                < num_layers_v1 )
           goto InvalidTable;
 
         colr->num_layers_v1 = num_layers_v1;
@@ -279,7 +280,7 @@
 
       clip_list_offset = FT_NEXT_ULONG( p );
 
-      if ( clip_list_offset >= table_size )
+      if ( table_size <= clip_list_offset )
         goto InvalidTable;
 
       if ( clip_list_offset )
@@ -311,7 +312,7 @@
           goto InvalidTable;
 
         var_store_offset = FT_NEXT_ULONG( p );
-        if ( var_store_offset >= table_size )
+        if ( table_size <= var_store_offset )
           goto InvalidTable;
 
         if ( var_store_offset )
@@ -661,6 +662,7 @@
       FT_UInt32  first_layer_index;
 
 
+      ENSURE_READ_BYTES( 5 );
       num_layers = FT_NEXT_BYTE( p );
       if ( num_layers > colr->num_layers_v1 )
         return 0;
@@ -1278,7 +1280,8 @@
 
     while ( min < max )
     {
-      FT_UInt  mid = min + ( max - min ) / 2;
+      FT_UInt    mid = min + ( max - min ) / 2;
+      FT_UShort  gid;
 
       /*
        * `base_glyph_begin` is the beginning of `BaseGlyphV1List`;
@@ -1287,8 +1290,7 @@
        */
       FT_Byte  *p = base_glyph_begin + 4 + mid * BASE_GLYPH_PAINT_RECORD_SIZE;
 
-      FT_UShort  gid = FT_NEXT_USHORT( p );
-
+      gid = FT_NEXT_USHORT( p );
 
       if ( gid < glyph_id )
         min = mid + 1;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType colored glyph layer support (specification).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang <shaozhang@fb.com>.
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType color palette support (body).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang <shaozhang@fb.com>.
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType color palette support (specification).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang <shaozhang@fb.com>.
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Load the basic TrueType kerning table.  This doesn't handle
  *   kerning data within the GPOS table at the moment.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Load the basic TrueType kerning table.  This doesn't handle
  *   kerning data within the GPOS table at the moment.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Load the basic TrueType tables, i.e., tables that can be either in
  *   TTF or OTF fonts (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -1046,7 +1046,7 @@
   FT_LOCAL_DEF( void )
   tt_face_free_name( TT_Face  face )
   {
-    FT_Memory     memory = face->root.driver->root.memory;
+    FT_Memory     memory = face->root.memory;
     TT_NameTable  table  = &face->name_table;
 
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   Load the basic TrueType tables, i.e., tables that can be either in
  *   TTF or OTF fonts (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Load the metrics tables common to TTF and OTF fonts (body).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Load the metrics tables common to TTF and OTF fonts (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   PostScript name table processing for TrueType and OpenType fonts
  *   (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -204,8 +204,8 @@
     /* now load the name strings */
     if ( num_names )
     {
-      FT_ULong   p;
-      FT_Byte*   strings;
+      FT_Byte*   p;
+      FT_Byte*   p_end;
 
 
       post_len -= (FT_ULong)num_glyphs * 2;
@@ -214,36 +214,36 @@
                                     post_len + 1 ) )
         goto Fail;
 
-      strings = (FT_Byte*)( name_strings + num_names );
-      if ( FT_STREAM_READ( strings, post_len ) )
+      p = (FT_Byte*)( name_strings + num_names );
+      if ( FT_STREAM_READ( p, post_len ) )
         goto Fail;
 
+      p_end = p + post_len;
+
       /* convert from Pascal- to C-strings and set pointers */
-      for ( p = 0, n = 0; p < post_len && n < num_names; n++ )
+      for ( n = 0; p < p_end && n < num_names; n++ )
       {
-        FT_UInt  len = strings[p];
+        FT_UInt  len = *p;
+
 
+        /* names in the Adobe Glyph List are shorter than 40 characters */
+        if ( len >= 40U )
+          FT_TRACE4(( "load_format_20: unusual %u-char name found\n", len ));
 
-        if ( len > 63U )
-        {
-          error = FT_THROW( Invalid_File_Format );
-          goto Fail;
-        }
-
-        strings[p]      = 0;
-        name_strings[n] = strings + p + 1;
-        p              += len + 1;
+        *p++            = 0;
+        name_strings[n] = p;
+        p              += len;
       }
-      strings[post_len] = 0;
+      *p_end = 0;
 
       /* deal with missing or insufficient string data */
       if ( n < num_names )
       {
         FT_TRACE4(( "load_format_20: %hu PostScript names are truncated\n",
-                    num_names - n ));
+                    (FT_UShort)( num_names - n ) ));
 
         for ( ; n < num_names; n++ )
-          name_strings[n] = strings + post_len;
+          name_strings[n] = p_end;
       }
     }
 
@@ -436,13 +436,8 @@
 
     format = face->postscript.FormatType;
 
-    if ( format == 0x00010000L )
-    {
-      if ( idx < 258 )                    /* paranoid checking */
-        *PSname = MAC_NAME( idx );
-    }
-    else if ( format == 0x00020000L ||
-              format == 0x00025000L )
+    if ( format == 0x00020000L ||
+         format == 0x00025000L )
     {
       TT_Post_Names  names = &face->postscript_names;
 
@@ -466,6 +461,11 @@
       }
     }
 
+    /* version 1.0 is only valid with 258 glyphs */
+    else if ( format == 0x00010000L              &&
+              face->max_profile.numGlyphs == 258 )
+      *PSname = MAC_NAME( idx );
+
     /* nothing to do for format == 0x00030000L */
 
   End:
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h	2025-06-27 08:03:14.000000000 +0000
@@ -5,7 +5,7 @@
  *   PostScript name table processing for TrueType and OpenType fonts
  *   (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType embedded bitmap support (body).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Copyright 2013 by Google, Inc.
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType embedded bitmap support (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   WOFF2 Font table tags (base).
  *
- * Copyright (C) 2019-2023 by
+ * Copyright (C) 2019-2024 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   WOFF2 Font table tags (specification).
  *
- * Copyright (C) 2019-2023 by
+ * Copyright (C) 2019-2024 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   A new `perfect' anti-aliasing renderer (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -489,7 +489,7 @@ typedef ptrdiff_t  FT_PtrDist;
 
   typedef struct  gray_TWorker_
   {
-    ft_jmp_buf  jump_buffer;
+    FT_BBox     cbox;
 
     TCoord  min_ex, max_ex;  /* min and max integer pixel coordinates */
     TCoord  min_ey, max_ey;
@@ -510,6 +510,8 @@ typedef ptrdiff_t  FT_PtrDist;
     FT_Raster_Span_Func  render_span;
     void*                render_span_data;
 
+    ft_jmp_buf  jump_buffer;
+
   } gray_TWorker, *gray_PWorker;
 
 #if defined( _MSC_VER )
@@ -997,49 +999,12 @@ typedef ptrdiff_t  FT_PtrDist;
 #endif
 
   /*
-   * Benchmarking shows that using DDA to flatten the quadratic Bézier arcs
-   * is slightly faster in the following cases:
-   *
-   *   - When the host CPU is 64-bit.
-   *   - When SSE2 SIMD registers and instructions are available (even on
-   *     x86).
-   *
-   * For other cases, using binary splits is actually slightly faster.
-   */
-#if ( defined( __SSE2__ )                          ||   \
-      defined( __x86_64__ )                        ||   \
-      defined( _M_AMD64 )                          ||   \
-      ( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 ) ) && \
-    !defined( __VMS )
-#  define FT_SSE2 1
-#else
-#  define FT_SSE2 0
-#endif
-
-#if FT_SSE2                || \
-    defined( __aarch64__ ) || \
-    defined( _M_ARM64 )
-#  define BEZIER_USE_DDA  1
-#else
-#  define BEZIER_USE_DDA  0
-#endif
-
-  /*
-   * For now, the code that depends on `BEZIER_USE_DDA` requires `FT_Int64`
-   * to be defined.  If `FT_INT64` is not defined, meaning there is no
-   * 64-bit type available, disable it to avoid compilation errors.  See for
-   * example https://gitlab.freedesktop.org/freetype/freetype/-/issues/1071.
+   * For now, the code that uses DDA to render conic curves requires
+   * `FT_Int64` to be defined.  See for example
+   *    https://gitlab.freedesktop.org/freetype/freetype/-/issues/1071.
    */
-#if !defined( FT_INT64 )
-#  undef BEZIER_USE_DDA
-#  define BEZIER_USE_DDA  0
-#endif
-
-#if BEZIER_USE_DDA
 
-#if FT_SSE2
-#  include <emmintrin.h>
-#endif
+#ifdef FT_INT64
 
 #define LEFT_SHIFT( a, b )  (FT_Int64)( (FT_UInt64)(a) << (b) )
 
@@ -1095,16 +1060,17 @@ typedef ptrdiff_t  FT_PtrDist;
       return;
     }
 
-    /* We can calculate the number of necessary bisections because  */
+    /* We can calculate the number of necessary segments because    */
     /* each bisection predictably reduces deviation exactly 4-fold. */
     /* Even 32-bit deviation would vanish after 16 bisections.      */
-    shift = 0;
+    shift = 16;
     do
     {
-      dx   >>= 2;
-      shift += 1;
+      dx >>= 2;
+      shift--;
 
     } while ( dx > ONE_PIXEL / 4 );
+    count = 0x10000U >> shift;
 
     /*
      * The (P0,P1,P2) arc equation, for t in [0,1] range:
@@ -1150,75 +1116,19 @@ typedef ptrdiff_t  FT_PtrDist;
      *             = (B << (33 - N)) + (A << (32 - 2*N))
      */
 
-#if FT_SSE2
-    /* Experience shows that for small shift values, */
-    /* SSE2 is actually slower.                      */
-    if ( shift > 2 )
-    {
-      union
-      {
-        struct { FT_Int64  ax, ay, bx, by; }  i;
-        struct { __m128i  a, b; }  vec;
-
-      } u;
-
-      union
-      {
-        struct { FT_Int32  px_lo, px_hi, py_lo, py_hi; }  i;
-        __m128i  vec;
-
-      } v;
-
-      __m128i  a, b;
-      __m128i  r, q, q2;
-      __m128i  p;
-
-
-      u.i.ax = ax;
-      u.i.ay = ay;
-      u.i.bx = bx;
-      u.i.by = by;
-
-      a = _mm_load_si128( &u.vec.a );
-      b = _mm_load_si128( &u.vec.b );
-
-      r  = _mm_slli_epi64( a, 33 - 2 * shift );
-      q  = _mm_slli_epi64( b, 33 - shift );
-      q2 = _mm_slli_epi64( a, 32 - 2 * shift );
-
-      q = _mm_add_epi64( q2, q );
-
-      v.i.px_lo = 0;
-      v.i.px_hi = p0.x;
-      v.i.py_lo = 0;
-      v.i.py_hi = p0.y;
-
-      p = _mm_load_si128( &v.vec );
-
-      for ( count = 1U << shift; count > 0; count-- )
-      {
-        p = _mm_add_epi64( p, q );
-        q = _mm_add_epi64( q, r );
-
-        _mm_store_si128( &v.vec, p );
-
-        gray_render_line( RAS_VAR_ v.i.px_hi, v.i.py_hi );
-      }
-
-      return;
-    }
-#endif  /* FT_SSE2 */
+    rx = LEFT_SHIFT( ax, shift + shift );
+    ry = LEFT_SHIFT( ay, shift + shift );
 
-    rx = LEFT_SHIFT( ax, 33 - 2 * shift );
-    ry = LEFT_SHIFT( ay, 33 - 2 * shift );
+    qx = LEFT_SHIFT( bx, shift + 17 ) + rx;
+    qy = LEFT_SHIFT( by, shift + 17 ) + ry;
 
-    qx = LEFT_SHIFT( bx, 33 - shift ) + LEFT_SHIFT( ax, 32 - 2 * shift );
-    qy = LEFT_SHIFT( by, 33 - shift ) + LEFT_SHIFT( ay, 32 - 2 * shift );
+    rx *= 2;
+    ry *= 2;
 
     px = LEFT_SHIFT( p0.x, 32 );
     py = LEFT_SHIFT( p0.y, 32 );
 
-    for ( count = 1U << shift; count > 0; count-- )
+    do
     {
       px += qx;
       py += qy;
@@ -1227,10 +1137,10 @@ typedef ptrdiff_t  FT_PtrDist;
 
       gray_render_line( RAS_VAR_ (FT_Pos)( px >> 32 ),
                                  (FT_Pos)( py >> 32 ) );
-    }
+    } while ( --count );
   }
 
-#else  /* !BEZIER_USE_DDA */
+#else  /* !FT_INT64 */
 
   /*
    * Note that multiple attempts to speed up the function below
@@ -1324,7 +1234,7 @@ typedef ptrdiff_t  FT_PtrDist;
     } while ( --draw );
   }
 
-#endif  /* !BEZIER_USE_DDA */
+#endif  /* !FT_INT64 */
 
 
   /*
@@ -1486,139 +1396,6 @@ typedef ptrdiff_t  FT_PtrDist;
   }
 
 
-  static void
-  gray_sweep( RAS_ARG )
-  {
-    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
-                                                                 : INT_MIN;
-    int  coverage;
-    int  y;
-
-
-    for ( y = ras.min_ey; y < ras.max_ey; y++ )
-    {
-      PCell   cell  = ras.ycells[y - ras.min_ey];
-      TCoord  x     = ras.min_ex;
-      TArea   cover = 0;
-
-      unsigned char*  line = ras.target.origin - ras.target.pitch * y;
-
-
-      for ( ; cell != ras.cell_null; cell = cell->next )
-      {
-        TArea  area;
-
-
-        if ( cover != 0 && cell->x > x )
-        {
-          FT_FILL_RULE( coverage, cover, fill );
-          FT_GRAY_SET( line + x, coverage, cell->x - x );
-        }
-
-        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
-        area   = cover - cell->area;
-
-        if ( area != 0 && cell->x >= ras.min_ex )
-        {
-          FT_FILL_RULE( coverage, area, fill );
-          line[cell->x] = (unsigned char)coverage;
-        }
-
-        x = cell->x + 1;
-      }
-
-      if ( cover != 0 )  /* only if cropped */
-      {
-        FT_FILL_RULE( coverage, cover, fill );
-        FT_GRAY_SET( line + x, coverage, ras.max_ex - x );
-      }
-    }
-  }
-
-
-  static void
-  gray_sweep_direct( RAS_ARG )
-  {
-    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
-                                                                 : INT_MIN;
-    int  coverage;
-    int  y;
-
-    FT_Span  span[FT_MAX_GRAY_SPANS];
-    int      n = 0;
-
-
-    for ( y = ras.min_ey; y < ras.max_ey; y++ )
-    {
-      PCell   cell  = ras.ycells[y - ras.min_ey];
-      TCoord  x     = ras.min_ex;
-      TArea   cover = 0;
-
-
-      for ( ; cell != ras.cell_null; cell = cell->next )
-      {
-        TArea  area;
-
-
-        if ( cover != 0 && cell->x > x )
-        {
-          FT_FILL_RULE( coverage, cover, fill );
-
-          span[n].coverage = (unsigned char)coverage;
-          span[n].x        = (short)x;
-          span[n].len      = (unsigned short)( cell->x - x );
-
-          if ( ++n == FT_MAX_GRAY_SPANS )
-          {
-            /* flush the span buffer and reset the count */
-            ras.render_span( y, n, span, ras.render_span_data );
-            n = 0;
-          }
-        }
-
-        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
-        area   = cover - cell->area;
-
-        if ( area != 0 && cell->x >= ras.min_ex )
-        {
-          FT_FILL_RULE( coverage, area, fill );
-
-          span[n].coverage = (unsigned char)coverage;
-          span[n].x        = (short)cell->x;
-          span[n].len      = 1;
-
-          if ( ++n == FT_MAX_GRAY_SPANS )
-          {
-            /* flush the span buffer and reset the count */
-            ras.render_span( y, n, span, ras.render_span_data );
-            n = 0;
-          }
-        }
-
-        x = cell->x + 1;
-      }
-
-      if ( cover != 0 )  /* only if cropped */
-      {
-        FT_FILL_RULE( coverage, cover, fill );
-
-        span[n].coverage = (unsigned char)coverage;
-        span[n].x        = (short)x;
-        span[n].len      = (unsigned short)( ras.max_ex - x );
-
-        ++n;
-      }
-
-      if ( n )
-      {
-        /* flush the span buffer and reset the count */
-        ras.render_span( y, n, span, ras.render_span_data );
-        n = 0;
-      }
-    }
-  }
-
-
 #ifdef STANDALONE_
 
   /**************************************************************************
@@ -1934,7 +1711,7 @@ typedef ptrdiff_t  FT_PtrDist;
       if ( continued )
         FT_Trace_Enable();
 
-      FT_TRACE7(( "band [%d..%d]: %td cell%s remaining/\n",
+      FT_TRACE7(( "band [%d..%d]: %td cell%s remaining\n",
                   ras.min_ey,
                   ras.max_ey,
                   ras.cell_null - ras.cell_free,
@@ -1952,14 +1729,144 @@ typedef ptrdiff_t  FT_PtrDist;
   }
 
 
+  static void
+  gray_sweep( RAS_ARG )
+  {
+    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
+                                                                 : INT_MIN;
+    int  coverage;
+    int  y;
+
+
+    for ( y = ras.min_ey; y < ras.max_ey; y++ )
+    {
+      PCell   cell  = ras.ycells[y - ras.min_ey];
+      TCoord  x     = ras.min_ex;
+      TArea   cover = 0;
+
+      unsigned char*  line = ras.target.origin - ras.target.pitch * y;
+
+
+      for ( ; cell != ras.cell_null; cell = cell->next )
+      {
+        TArea  area;
+
+
+        if ( cover != 0 && cell->x > x )
+        {
+          FT_FILL_RULE( coverage, cover, fill );
+          FT_GRAY_SET( line + x, coverage, cell->x - x );
+        }
+
+        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
+        area   = cover - cell->area;
+
+        if ( area != 0 && cell->x >= ras.min_ex )
+        {
+          FT_FILL_RULE( coverage, area, fill );
+          line[cell->x] = (unsigned char)coverage;
+        }
+
+        x = cell->x + 1;
+      }
+
+      if ( cover != 0 )  /* only if cropped */
+      {
+        FT_FILL_RULE( coverage, cover, fill );
+        FT_GRAY_SET( line + x, coverage, ras.max_ex - x );
+      }
+    }
+  }
+
+
+  static void
+  gray_sweep_direct( RAS_ARG )
+  {
+    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
+                                                                 : INT_MIN;
+    int  coverage;
+    int  y;
+
+    FT_Span  span[FT_MAX_GRAY_SPANS];
+    int      n = 0;
+
+
+    for ( y = ras.min_ey; y < ras.max_ey; y++ )
+    {
+      PCell   cell  = ras.ycells[y - ras.min_ey];
+      TCoord  x     = ras.min_ex;
+      TArea   cover = 0;
+
+
+      for ( ; cell != ras.cell_null; cell = cell->next )
+      {
+        TArea  area;
+
+
+        if ( cover != 0 && cell->x > x )
+        {
+          FT_FILL_RULE( coverage, cover, fill );
+
+          span[n].coverage = (unsigned char)coverage;
+          span[n].x        = (short)x;
+          span[n].len      = (unsigned short)( cell->x - x );
+
+          if ( ++n == FT_MAX_GRAY_SPANS )
+          {
+            /* flush the span buffer and reset the count */
+            ras.render_span( y, n, span, ras.render_span_data );
+            n = 0;
+          }
+        }
+
+        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
+        area   = cover - cell->area;
+
+        if ( area != 0 && cell->x >= ras.min_ex )
+        {
+          FT_FILL_RULE( coverage, area, fill );
+
+          span[n].coverage = (unsigned char)coverage;
+          span[n].x        = (short)cell->x;
+          span[n].len      = 1;
+
+          if ( ++n == FT_MAX_GRAY_SPANS )
+          {
+            /* flush the span buffer and reset the count */
+            ras.render_span( y, n, span, ras.render_span_data );
+            n = 0;
+          }
+        }
+
+        x = cell->x + 1;
+      }
+
+      if ( cover != 0 )  /* only if cropped */
+      {
+        FT_FILL_RULE( coverage, cover, fill );
+
+        span[n].coverage = (unsigned char)coverage;
+        span[n].x        = (short)x;
+        span[n].len      = (unsigned short)( ras.max_ex - x );
+
+        ++n;
+      }
+
+      if ( n )
+      {
+        /* flush the span buffer and reset the count */
+        ras.render_span( y, n, span, ras.render_span_data );
+        n = 0;
+      }
+    }
+  }
+
+
   static int
   gray_convert_glyph( RAS_ARG )
   {
-    const TCoord  yMin = ras.min_ey;
-    const TCoord  yMax = ras.max_ey;
-
     TCell    buffer[FT_MAX_GRAY_POOL];
-    size_t   height = (size_t)( yMax - yMin );
+    size_t   height = (size_t)( ras.cbox.yMax - ras.cbox.yMin );
     size_t   n = FT_MAX_GRAY_POOL / 8;
     TCoord   y;
     TCoord   bands[32];  /* enough to accommodate bisections */
@@ -1985,35 +1892,36 @@ typedef ptrdiff_t  FT_PtrDist;
       height  = ( height + n - 1 ) / n;
     }
 
-    for ( y = yMin; y < yMax; )
+    for ( y = ras.cbox.yMin; y < ras.cbox.yMax; )
     {
       ras.min_ey = y;
       y         += height;
-      ras.max_ey = FT_MIN( y, yMax );
+      ras.max_ey = FT_MIN( y, ras.cbox.yMax );
+
+      ras.count_ey = ras.max_ey - ras.min_ey;
 
       band    = bands;
-      band[1] = ras.min_ey;
-      band[0] = ras.max_ey;
+      band[1] = ras.cbox.xMin;
+      band[0] = ras.cbox.xMax;
 
       do
       {
-        TCoord  width = band[0] - band[1];
-        TCoord  w;
+        TCoord  i;
         int     error;
 
 
-        for ( w = 0; w < width; ++w )
-          ras.ycells[w] = ras.cell_null;
+        ras.min_ex = band[1];
+        ras.max_ex = band[0];
+
+        /* memory management: zero out and skip ycells */
+        for ( i = 0; i < ras.count_ey; ++i )
+          ras.ycells[i] = ras.cell_null;
 
-        /* memory management: skip ycells */
-        n = ( (size_t)width * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) /
-              sizeof ( TCell );
+        n = ( (size_t)ras.count_ey * sizeof ( PCell ) + sizeof ( TCell ) - 1 )
+              / sizeof ( TCell );
 
         ras.cell_free = buffer + n;
         ras.cell      = ras.cell_null;
-        ras.min_ey    = band[1];
-        ras.max_ey    = band[0];
-        ras.count_ey  = width;
 
         error     = gray_convert_glyph_inner( RAS_VAR_ continued );
         continued = 1;
@@ -2031,10 +1939,10 @@ typedef ptrdiff_t  FT_PtrDist;
           return error;
 
         /* render pool overflow; we will reduce the render band by half */
-        width >>= 1;
+        i = ( band[0] - band[1] ) >> 1;
 
         /* this should never happen even with tiny rendering pool */
-        if ( width == 0 )
+        if ( i == 0 )
         {
           FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
           return FT_THROW( Raster_Overflow );
@@ -2042,7 +1950,7 @@ typedef ptrdiff_t  FT_PtrDist;
 
         band++;
         band[1]  = band[0];
-        band[0] += width;
+        band[0] += i;
       } while ( band >= bands );
     }
 
@@ -2073,7 +1981,7 @@ typedef ptrdiff_t  FT_PtrDist;
       return FT_THROW( Invalid_Outline );
 
     /* return immediately if the outline is empty */
-    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+    if ( outline->n_points == 0 || outline->n_contours == 0 )
       return Smooth_Err_Ok;
 
     if ( !outline->contours || !outline->points )
@@ -2093,10 +2001,7 @@ typedef ptrdiff_t  FT_PtrDist;
       ras.render_span      = (FT_Raster_Span_Func)params->gray_spans;
       ras.render_span_data = params->user;
 
-      ras.min_ex = params->clip_box.xMin;
-      ras.min_ey = params->clip_box.yMin;
-      ras.max_ex = params->clip_box.xMax;
-      ras.max_ey = params->clip_box.yMax;
+      ras.cbox = params->clip_box;
     }
     else
     {
@@ -2122,14 +2027,14 @@ typedef ptrdiff_t  FT_PtrDist;
       ras.render_span      = (FT_Raster_Span_Func)NULL;
       ras.render_span_data = NULL;
 
-      ras.min_ex = 0;
-      ras.min_ey = 0;
-      ras.max_ex = (FT_Pos)target_map->width;
-      ras.max_ey = (FT_Pos)target_map->rows;
+      ras.cbox.xMin = 0;
+      ras.cbox.yMin = 0;
+      ras.cbox.xMax = (FT_Pos)target_map->width;
+      ras.cbox.yMax = (FT_Pos)target_map->rows;
     }
 
     /* exit if nothing to do */
-    if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey )
+    if ( ras.cbox.xMin >= ras.cbox.xMax || ras.cbox.yMin >= ras.cbox.yMax )
       return Smooth_Err_Ok;
 
     return gray_convert_glyph( RAS_VAR );
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   FreeType smooth renderer declaration
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   smooth renderer error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Anti-aliasing renderer interface (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Anti-aliasing renderer interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType font driver implementation (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -217,7 +217,20 @@
     kerning->y = 0;
 
     if ( sfnt )
-      kerning->x = sfnt->get_kerning( ttface, left_glyph, right_glyph );
+    {
+      /* Use 'kern' table if available since that can be faster; otherwise */
+      /* use GPOS kerning pairs if available.                              */
+      if ( ttface->kern_avail_bits != 0 )
+        kerning->x = sfnt->get_kerning( ttface,
+                                        left_glyph,
+                                        right_glyph );
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+      else if ( ttface->gpos_kerning_available )
+        kerning->x = sfnt->get_gpos_kerning( ttface,
+                                             left_glyph,
+                                             right_glyph );
+#endif
+    }
 
     return 0;
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   High-level TrueType driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType Glyph Loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -353,7 +353,8 @@
     FT_Byte         c, count;
     FT_Vector       *vec, *vec_limit;
     FT_Pos          x, y;
-    FT_Short        *cont, *cont_limit, last;
+    FT_UShort       *cont, *cont_limit;
+    FT_Int          last;
 
 
     /* check that we can add the contours to the glyph */
@@ -372,7 +373,7 @@
     last = -1;
     for ( ; cont < cont_limit; cont++ )
     {
-      *cont = FT_NEXT_SHORT( p );
+      *cont = FT_NEXT_USHORT( p );
 
       if ( *cont <= last )
         goto Invalid_Outline;
@@ -418,11 +419,9 @@
       /* and thus allocate the bytecode array size by ourselves     */
       if ( n_ins )
       {
-        if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) )
+        if ( FT_DUP( exec->glyphIns, p, n_ins ) )
           return error;
 
-        FT_MEM_COPY( exec->glyphIns, p, (FT_Long)n_ins );
-
         exec->glyphSize  = n_ins;
       }
     }
@@ -432,7 +431,7 @@
     p += n_ins;
 
     /* reading the point tags */
-    flag       = (FT_Byte*)outline->tags;
+    flag       = outline->tags;
     flag_limit = flag + n_points;
 
     FT_ASSERT( flag );
@@ -465,7 +464,7 @@
 
     vec       = outline->points;
     vec_limit = vec + n_points;
-    flag      = (FT_Byte*)outline->tags;
+    flag      = outline->tags;
     x         = 0;
 
     for ( ; vec < vec_limit; vec++, flag++ )
@@ -499,7 +498,7 @@
 
     vec       = outline->points;
     vec_limit = vec + n_points;
-    flag      = (FT_Byte*)outline->tags;
+    flag      = outline->tags;
     y         = 0;
 
     for ( ; vec < vec_limit; vec++, flag++ )
@@ -532,8 +531,8 @@
       *flag  = (FT_Byte)( f & ON_CURVE_POINT );
     }
 
-    outline->n_points   = (FT_Short)n_points;
-    outline->n_contours = (FT_Short)n_contours;
+    outline->n_points   = (FT_UShort)n_points;
+    outline->n_contours = (FT_UShort)n_contours;
 
     load->cursor = p;
 
@@ -754,15 +753,13 @@
                    FT_UInt       start_point,
                    FT_UInt       start_contour )
   {
-    zone->n_points    = (FT_UShort)load->outline.n_points + 4 -
-                          (FT_UShort)start_point;
-    zone->n_contours  = load->outline.n_contours -
-                          (FT_Short)start_contour;
+    zone->n_points    = load->outline.n_points + 4 - (FT_UShort)start_point;
+    zone->n_contours  = load->outline.n_contours - (FT_UShort)start_contour;
     zone->org         = load->extra_points + start_point;
     zone->cur         = load->outline.points + start_point;
     zone->orus        = load->extra_points2 + start_point;
-    zone->tags        = (FT_Byte*)load->outline.tags + start_point;
-    zone->contours    = (FT_UShort*)load->outline.contours + start_contour;
+    zone->tags        = load->outline.tags + start_point;
+    zone->contours    = load->outline.contours + start_contour;
     zone->first_point = (FT_UShort)start_point;
   }
 
@@ -1046,7 +1043,7 @@
     current.points   = gloader->base.outline.points +
                          num_base_points;
     current.n_points = gloader->base.outline.n_points -
-                         (short)num_base_points;
+                         (FT_UShort)num_base_points;
 
     have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE     |
                                               WE_HAVE_AN_XY_SCALE |
@@ -1059,7 +1056,7 @@
     /* get offset */
     if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
     {
-      FT_UInt     num_points = (FT_UInt)gloader->base.outline.n_points;
+      FT_UInt     num_points = gloader->base.outline.n_points;
       FT_UInt     k = (FT_UInt)subglyph->arg1;
       FT_UInt     l = (FT_UInt)subglyph->arg2;
       FT_Vector*  p1;
@@ -1721,8 +1718,8 @@
         FT_List_Add( &loader->composites, node );
       }
 
-      start_point   = (FT_UInt)gloader->base.outline.n_points;
-      start_contour = (FT_UInt)gloader->base.outline.n_contours;
+      start_point   = gloader->base.outline.n_points;
+      start_contour = gloader->base.outline.n_contours;
 
       /* for each subglyph, read composite header */
       error = face->read_composite_glyph( loader );
@@ -1741,14 +1738,14 @@
       if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
            FT_IS_VARIATION( FT_FACE( face ) )      )
       {
-        short        i, limit;
+        FT_UShort    i, limit;
         FT_SubGlyph  subglyph;
 
         FT_Outline  outline = { 0, 0, NULL, NULL, NULL, 0 };
         FT_Vector*  unrounded = NULL;
 
 
-        limit = (short)gloader->current.num_subglyphs;
+        limit = (FT_UShort)gloader->current.num_subglyphs;
 
         /* construct an outline structure for              */
         /* communication with `TT_Vary_Apply_Glyph_Deltas' */
@@ -1874,7 +1871,7 @@
           linear_hadvance = loader->linear;
           linear_vadvance = loader->vadvance;
 
-          num_base_points = (FT_UInt)gloader->base.outline.n_points;
+          num_base_points = gloader->base.outline.n_points;
 
           error = load_truetype_glyph( loader,
                                        (FT_UInt)subglyph->index,
@@ -1898,7 +1895,7 @@
             loader->vadvance = linear_vadvance;
           }
 
-          num_points = (FT_UInt)gloader->base.outline.n_points;
+          num_points = gloader->base.outline.n_points;
 
           if ( num_points == num_base_points )
             continue;
@@ -2313,7 +2310,7 @@
        *
        * 1) we have a `tricky' font that heavily relies on the interpreter to
        *    render glyphs correctly, for example DFKai-SB, or
-       * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
+       * 2) FT_RENDER_MODE_MONO (i.e, monochrome rendering) is requested.
        *
        * In those cases, backward compatibility needs to be turned off to get
        * correct rendering.  The rendering is then completely up to the
@@ -2719,7 +2716,7 @@
          size->metrics->y_ppem < 24         )
       glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
 
-    FT_TRACE1(( "  subglyphs = %u, contours = %hd, points = %hd,"
+    FT_TRACE1(( "  subglyphs = %u, contours = %hu, points = %hu,"
                 " flags = 0x%.3x\n",
                 loader.gloader->base.num_subglyphs,
                 glyph->outline.n_contours,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType Glyph Loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType GX Font Variation loader
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -129,9 +129,6 @@
    *   stream ::
    *     The data stream.
    *
-   *   size ::
-   *     The size of the table holding the data.
-   *
    * @Output:
    *   point_cnt ::
    *     The number of points read.  A zero value means that
@@ -144,14 +141,14 @@
    */
   static FT_UShort*
   ft_var_readpackedpoints( FT_Stream  stream,
-                           FT_ULong   size,
                            FT_UInt   *point_cnt )
   {
     FT_UShort *points = NULL;
     FT_UInt    n;
-    FT_UInt    runcnt;
+    FT_UInt    runcnt, cnt;
     FT_UInt    i, j;
     FT_UShort  first;
+    FT_Byte*   p;
     FT_Memory  memory = stream->memory;
     FT_Error   error;
 
@@ -169,56 +166,60 @@
       n  |= FT_GET_BYTE();
     }
 
-    if ( n > size )
-    {
-      FT_TRACE1(( "ft_var_readpackedpoints: number of points too large\n" ));
+    if ( FT_QNEW_ARRAY( points, n ) )
       return NULL;
-    }
-
-    /* in the nested loops below we increase `i' twice; */
-    /* it is faster to simply allocate one more slot    */
-    /* than to add another test within the loop         */
-    if ( FT_QNEW_ARRAY( points, n + 1 ) )
-      return NULL;
-
-    *point_cnt = n;
 
+    p     = stream->cursor;
     first = 0;
     i     = 0;
     while ( i < n )
     {
-      runcnt = FT_GET_BYTE();
+      if ( p >= stream->limit )
+        goto Fail;
+
+      runcnt = FT_NEXT_BYTE( p );
+      cnt    = runcnt & GX_PT_POINT_RUN_COUNT_MASK;
+
+      /* first point not included in run count */
+      cnt++;
+      if ( cnt > n - i )
+        cnt = n - i;
+
       if ( runcnt & GX_PT_POINTS_ARE_WORDS )
       {
-        runcnt     &= GX_PT_POINT_RUN_COUNT_MASK;
-        first      += FT_GET_USHORT();
-        points[i++] = first;
+        if ( 2 * cnt > (FT_UInt)( stream->limit - p ) )
+          goto Fail;
 
-        /* first point not included in run count */
-        for ( j = 0; j < runcnt; j++ )
+        for ( j = 0; j < cnt; j++ )
         {
-          first      += FT_GET_USHORT();
+          first      += FT_NEXT_USHORT( p );
           points[i++] = first;
-          if ( i >= n )
-            break;
         }
       }
       else
       {
-        first      += FT_GET_BYTE();
-        points[i++] = first;
+        if ( cnt > (FT_UInt)( stream->limit - p ) )
+          goto Fail;
 
-        for ( j = 0; j < runcnt; j++ )
+        for ( j = 0; j < cnt; j++ )
         {
-          first      += FT_GET_BYTE();
+          first      += FT_NEXT_BYTE( p );
           points[i++] = first;
-          if ( i >= n )
-            break;
         }
       }
     }
 
+    stream->cursor = p;
+
+    *point_cnt = n;
+
     return points;
+
+  Fail:
+    FT_TRACE1(( "ft_var_readpackedpoints: invalid table\n" ));
+
+    FT_FREE( points );
+    return NULL;
   }
 
 
@@ -240,9 +241,6 @@
    *   stream ::
    *     The data stream.
    *
-   *   size ::
-   *     The size of the table holding the data.
-   *
    *   delta_cnt ::
    *     The number of deltas to be read.
    *
@@ -258,13 +256,12 @@
    */
   static FT_Fixed*
   ft_var_readpackeddeltas( FT_Stream  stream,
-                           FT_ULong   size,
                            FT_UInt    delta_cnt )
   {
     FT_Fixed  *deltas = NULL;
     FT_UInt    runcnt, cnt;
     FT_UInt    i, j;
-    FT_UInt    bytes_used;
+    FT_Byte*   p;
     FT_Memory  memory = stream->memory;
     FT_Error   error;
 
@@ -272,68 +269,51 @@
     if ( FT_QNEW_ARRAY( deltas, delta_cnt ) )
       return NULL;
 
-    i          = 0;
-    bytes_used = 0;
-
-    while ( i < delta_cnt && bytes_used < size )
+    p = stream->cursor;
+    i = 0;
+    while ( i < delta_cnt )
     {
-      runcnt = FT_GET_BYTE();
+      if ( p >= stream->limit )
+        goto Fail;
+
+      runcnt = FT_NEXT_BYTE( p );
       cnt    = runcnt & GX_DT_DELTA_RUN_COUNT_MASK;
 
-      bytes_used++;
+      /* first point not included in run count */
+      cnt++;
+      if ( cnt > delta_cnt - i )
+        cnt = delta_cnt - i;
 
       if ( runcnt & GX_DT_DELTAS_ARE_ZERO )
       {
-        /* `cnt` + 1 zeroes get added */
-        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
+        for ( j = 0; j < cnt; j++ )
           deltas[i++] = 0;
       }
       else if ( runcnt & GX_DT_DELTAS_ARE_WORDS )
       {
-        /* `cnt` + 1 shorts from the stack */
-        bytes_used += 2 * ( cnt + 1 );
-        if ( bytes_used > size )
-        {
-          FT_TRACE1(( "ft_var_readpackeddeltas:"
-                      " number of short deltas too large\n" ));
+        if ( 2 * cnt > (FT_UInt)( stream->limit - p ) )
           goto Fail;
-        }
 
-        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
-          deltas[i++] = FT_intToFixed( FT_GET_SHORT() );
+        for ( j = 0; j < cnt; j++ )
+          deltas[i++] = FT_intToFixed( FT_NEXT_SHORT( p ) );
       }
       else
       {
-        /* `cnt` + 1 signed bytes from the stack */
-        bytes_used += cnt + 1;
-        if ( bytes_used > size )
-        {
-          FT_TRACE1(( "ft_var_readpackeddeltas:"
-                      " number of byte deltas too large\n" ));
+        if ( cnt > (FT_UInt)( stream->limit - p ) )
           goto Fail;
-        }
 
-        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
-          deltas[i++] = FT_intToFixed( FT_GET_CHAR() );
-      }
-
-      if ( j <= cnt )
-      {
-        FT_TRACE1(( "ft_var_readpackeddeltas:"
-                    " number of deltas too large\n" ));
-        goto Fail;
+        for ( j = 0; j < cnt; j++ )
+          deltas[i++] = FT_intToFixed( FT_NEXT_CHAR( p ) );
       }
     }
 
-    if ( i < delta_cnt )
-    {
-      FT_TRACE1(( "ft_var_readpackeddeltas: not enough deltas\n" ));
-      goto Fail;
-    }
+    stream->cursor = p;
 
     return deltas;
 
   Fail:
+    FT_TRACE1(( "ft_var_readpackeddeltas: invalid table\n" ));
+
     FT_FREE( deltas );
     return NULL;
   }
@@ -596,7 +576,7 @@
 
       for ( j = 0; j < itemStore->axisCount; j++ )
       {
-        FT_Short  start, peak, end;
+        FT_Int  start, peak, end;
 
 
         if ( FT_READ_SHORT( start ) ||
@@ -604,6 +584,10 @@
              FT_READ_SHORT( end )   )
           goto Exit;
 
+        /* immediately tag invalid ranges with special peak = 0 */
+        if ( ( start < 0 && end > 0 ) || start > peak || peak > end )
+          peak = 0;
+
         axisCoords[j].startCoord = FT_fdot14ToFixed( start );
         axisCoords[j].peakCoord  = FT_fdot14ToFixed( peak );
         axisCoords[j].endCoord   = FT_fdot14ToFixed( end );
@@ -1024,6 +1008,9 @@
     if ( innerIndex >= varData->itemCount )
       return 0; /* Out of range. */
 
+    if ( varData->regionIdxCount == 0 )
+      return 0; /* Avoid "applying zero offset to null pointer". */
+
     if ( varData->regionIdxCount < 16 )
     {
       deltaSet = deltaSetStack;
@@ -1074,43 +1061,32 @@
       /* inner loop steps through axes in this region */
       for ( j = 0; j < itemStore->axisCount; j++, axis++ )
       {
-        /* compute the scalar contribution of this axis; */
-        /* ignore invalid ranges                         */
-        if ( axis->startCoord > axis->peakCoord ||
-             axis->peakCoord > axis->endCoord   )
-          continue;
+        FT_Fixed  ncv = ttface->blend->normalizedcoords[j];
 
-        else if ( axis->startCoord < 0 &&
-                  axis->endCoord > 0   &&
-                  axis->peakCoord != 0 )
-          continue;
 
-        /* peak of 0 means ignore this axis */
-        else if ( axis->peakCoord == 0 )
-          continue;
-
-        else if ( ttface->blend->normalizedcoords[j] == axis->peakCoord )
+        /* compute the scalar contribution of this axis */
+        /* with peak of 0 used for invalid axes         */
+        if ( axis->peakCoord == ncv ||
+             axis->peakCoord == 0   )
           continue;
 
         /* ignore this region if coords are out of range */
-        else if ( ttface->blend->normalizedcoords[j] <= axis->startCoord ||
-                  ttface->blend->normalizedcoords[j] >= axis->endCoord   )
+        else if ( ncv <= axis->startCoord ||
+                  ncv >= axis->endCoord   )
         {
           scalar = 0;
           break;
         }
 
         /* cumulative product of all the axis scalars */
-        else if ( ttface->blend->normalizedcoords[j] < axis->peakCoord )
-          scalar =
-            FT_MulDiv( scalar,
-                       ttface->blend->normalizedcoords[j] - axis->startCoord,
-                       axis->peakCoord - axis->startCoord );
-        else
-          scalar =
-            FT_MulDiv( scalar,
-                       axis->endCoord - ttface->blend->normalizedcoords[j],
-                       axis->endCoord - axis->peakCoord );
+        else if ( ncv < axis->peakCoord )
+          scalar = FT_MulDiv( scalar,
+                              ncv - axis->startCoord,
+                              axis->peakCoord - axis->startCoord );
+        else   /* ncv > axis->peakCoord */
+          scalar = FT_MulDiv( scalar,
+                              axis->endCoord - ncv,
+                              axis->endCoord - axis->peakCoord );
 
       } /* per-axis loop */
 
@@ -1920,32 +1896,27 @@
 
     for ( i = 0; i < blend->num_axis; i++ )
     {
-      FT_TRACE6(( "    axis %d coordinate %.5f:\n",
-                  i, (double)blend->normalizedcoords[i] / 65536 ));
+      FT_Fixed  ncv = blend->normalizedcoords[i];
+
+
+      FT_TRACE6(( "    axis %d coordinate %.5f:\n", i, (double)ncv / 65536 ));
 
       /* It's not clear why (for intermediate tuples) we don't need     */
       /* to check against start/end -- the documentation says we don't. */
       /* Similarly, it's unclear why we don't need to scale along the   */
       /* axis.                                                          */
 
-      if ( tuple_coords[i] == 0 )
+      if ( tuple_coords[i] == ncv )
       {
-        FT_TRACE6(( "      tuple coordinate is zero, ignore\n" ));
+        FT_TRACE6(( "      tuple coordinate %.5f fits perfectly\n",
+                    (double)tuple_coords[i] / 65536 ));
+        /* `apply' does not change */
         continue;
       }
 
-      if ( blend->normalizedcoords[i] == 0 )
-      {
-        FT_TRACE6(( "      axis coordinate is zero, stop\n" ));
-        apply = 0;
-        break;
-      }
-
-      if ( blend->normalizedcoords[i] == tuple_coords[i] )
+      if ( tuple_coords[i] == 0 )
       {
-        FT_TRACE6(( "      tuple coordinate %.5f fits perfectly\n",
-                    (double)tuple_coords[i] / 65536 ));
-        /* `apply' does not change */
+        FT_TRACE6(( "      tuple coordinate is zero, ignore\n" ));
         continue;
       }
 
@@ -1953,27 +1924,27 @@
       {
         /* not an intermediate tuple */
 
-        if ( blend->normalizedcoords[i] < FT_MIN( 0, tuple_coords[i] ) ||
-             blend->normalizedcoords[i] > FT_MAX( 0, tuple_coords[i] ) )
+        if ( ( tuple_coords[i] > ncv && ncv > 0 ) ||
+             ( tuple_coords[i] < ncv && ncv < 0 ) )
+        {
+          FT_TRACE6(( "      tuple coordinate %.5f fits\n",
+                      (double)tuple_coords[i] / 65536 ));
+          apply = FT_MulDiv( apply, ncv, tuple_coords[i] );
+        }
+        else
         {
           FT_TRACE6(( "      tuple coordinate %.5f is exceeded, stop\n",
                       (double)tuple_coords[i] / 65536 ));
           apply = 0;
           break;
         }
-
-        FT_TRACE6(( "      tuple coordinate %.5f fits\n",
-                    (double)tuple_coords[i] / 65536 ));
-        apply = FT_MulDiv( apply,
-                           blend->normalizedcoords[i],
-                           tuple_coords[i] );
       }
       else
       {
         /* intermediate tuple */
 
-        if ( blend->normalizedcoords[i] <= im_start_coords[i] ||
-             blend->normalizedcoords[i] >= im_end_coords[i]   )
+        if ( ncv <= im_start_coords[i] ||
+             ncv >= im_end_coords[i]   )
         {
           FT_TRACE6(( "      intermediate tuple range ]%.5f;%.5f[ is exceeded,"
                       " stop\n",
@@ -1986,13 +1957,13 @@
         FT_TRACE6(( "      intermediate tuple range ]%.5f;%.5f[ fits\n",
                     (double)im_start_coords[i] / 65536,
                     (double)im_end_coords[i] / 65536 ));
-        if ( blend->normalizedcoords[i] < tuple_coords[i] )
+        if ( ncv < tuple_coords[i] )
           apply = FT_MulDiv( apply,
-                             blend->normalizedcoords[i] - im_start_coords[i],
+                             ncv - im_start_coords[i],
                              tuple_coords[i] - im_start_coords[i] );
-        else
+        else /* ncv > tuple_coords[i] */
           apply = FT_MulDiv( apply,
-                             im_end_coords[i] - blend->normalizedcoords[i],
+                             im_end_coords[i] - ncv,
                              im_end_coords[i] - tuple_coords[i] );
       }
     }
@@ -2141,11 +2112,12 @@
                                          outerIndex,
                                          innerIndex );
 
-      v += delta << 2;
+          /* Convert delta in F2DOT14 to 16.16 before adding. */
+          v += MUL_INT( delta, 4 );
 
-      /* Clamp value range. */
-      v = v >=  0x10000L ?  0x10000 : v;
-      v = v <= -0x10000L ? -0x10000 : v;
+          /* Clamp value to range [-1, 1]. */
+          v = v >=  0x10000L ?  0x10000 : v;
+          v = v <= -0x10000L ? -0x10000 : v;
 
           new_normalized[i] = v;
         }
@@ -2721,9 +2693,8 @@
       FT_UInt  n;
 
 
-      if ( FT_ALLOC( mmvar, ttface->blend->mmvar_len ) )
+      if ( FT_DUP( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len ) )
         goto Exit;
-      FT_MEM_COPY( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len );
 
       axis_flags =
         (FT_UShort*)( (char*)mmvar + mmvar_size );
@@ -3533,9 +3504,10 @@
     FT_ULong  here;
     FT_UInt   i, j;
 
-    FT_Fixed*  tuple_coords    = NULL;
-    FT_Fixed*  im_start_coords = NULL;
-    FT_Fixed*  im_end_coords   = NULL;
+    FT_Fixed*  peak_coords = NULL;
+    FT_Fixed*  tuple_coords;
+    FT_Fixed*  im_start_coords;
+    FT_Fixed*  im_end_coords;
 
     GX_Blend  blend = face->blend;
 
@@ -3556,16 +3528,16 @@
     {
       FT_TRACE2(( "\n" ));
       FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" ));
-      error = FT_Err_Ok;
-      goto Exit;
+
+      return FT_Err_Ok;
     }
 
     if ( !face->cvt )
     {
       FT_TRACE2(( "\n" ));
       FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" ));
-      error = FT_Err_Ok;
-      goto Exit;
+
+      return FT_Err_Ok;
     }
 
     error = face->goto_table( face, TTAG_cvar, stream, &table_len );
@@ -3573,15 +3545,11 @@
     {
       FT_TRACE2(( "is missing\n" ));
 
-      error = FT_Err_Ok;
-      goto Exit;
+      return FT_Err_Ok;
     }
 
     if ( FT_FRAME_ENTER( table_len ) )
-    {
-      error = FT_Err_Ok;
-      goto Exit;
-    }
+      return FT_Err_Ok;
 
     table_start = FT_Stream_FTell( stream );
     if ( FT_GET_LONG() != 0x00010000L )
@@ -3594,11 +3562,6 @@
 
     FT_TRACE2(( "loaded\n" ));
 
-    if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis )    ||
-         FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
-         FT_NEW_ARRAY( im_end_coords, blend->num_axis )   )
-      goto FExit;
-
     tupleCount   = FT_GET_USHORT();
     offsetToData = FT_GET_USHORT();
 
@@ -3621,9 +3584,8 @@
 
       FT_Stream_SeekSet( stream, offsetToData );
 
-      sharedpoints = ft_var_readpackedpoints( stream,
-                                              table_len,
-                                              &spoint_count );
+      sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
+
       offsetToData = FT_Stream_FTell( stream );
 
       FT_Stream_SeekSet( stream, here );
@@ -3634,8 +3596,12 @@
                 tupleCount & GX_TC_TUPLE_COUNT_MASK,
                 ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" ));
 
-    if ( FT_NEW_ARRAY( cvt_deltas, face->cvt_size ) )
-      goto FExit;
+    if ( FT_QNEW_ARRAY( peak_coords, 3 * blend->num_axis ) ||
+         FT_NEW_ARRAY( cvt_deltas, face->cvt_size )        )
+      goto Exit;
+
+    im_start_coords = peak_coords + blend->num_axis;
+    im_end_coords = im_start_coords + blend->num_axis;
 
     for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ )
     {
@@ -3652,32 +3618,19 @@
       if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
       {
         for ( j = 0; j < blend->num_axis; j++ )
-          tuple_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
+          peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
+        tuple_coords = peak_coords;
       }
-      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
+      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount )
+        tuple_coords = blend->tuplecoords +
+            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis;
+      else
       {
         FT_TRACE2(( "tt_face_vary_cvt:"
                     " invalid tuple index\n" ));
 
         error = FT_THROW( Invalid_Table );
-        goto FExit;
-      }
-      else
-      {
-        if ( !blend->tuplecoords )
-        {
-          FT_TRACE2(( "tt_face_vary_cvt:"
-                      " no valid tuple coordinates available\n" ));
-
-          error = FT_THROW( Invalid_Table );
-          goto FExit;
-        }
-
-        FT_MEM_COPY(
-          tuple_coords,
-          blend->tuplecoords +
-            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis,
-          blend->num_axis * sizeof ( FT_Fixed ) );
+        goto Exit;
       }
 
       if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
@@ -3706,9 +3659,7 @@
 
       if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )
       {
-        localpoints = ft_var_readpackedpoints( stream,
-                                               table_len,
-                                               &point_count );
+        localpoints = ft_var_readpackedpoints( stream, &point_count );
         points      = localpoints;
       }
       else
@@ -3719,7 +3670,6 @@
       }
 
       deltas = ft_var_readpackeddeltas( stream,
-                                        table_len,
                                         point_count == 0 ? face->cvt_size
                                                          : point_count );
 
@@ -3820,22 +3770,20 @@
     for ( i = 0; i < face->cvt_size; i++ )
       face->cvt[i] += FT_fixedToFdot6( cvt_deltas[i] );
 
-  FExit:
-    FT_FRAME_EXIT();
+    /* Iterate over all `FT_Size` objects and set `cvt_ready` to -1 */
+    /* to trigger rescaling of all CVT values.                      */
+    FT_List_Iterate( &root->sizes_list,
+                     tt_cvt_ready_iterator,
+                     NULL );
 
   Exit:
     if ( sharedpoints != ALL_POINTS )
       FT_FREE( sharedpoints );
-    FT_FREE( tuple_coords );
-    FT_FREE( im_start_coords );
-    FT_FREE( im_end_coords );
     FT_FREE( cvt_deltas );
+    FT_FREE( peak_coords );
 
-    /* iterate over all FT_Size objects and set `cvt_ready' to -1 */
-    /* to trigger rescaling of all CVT values                     */
-    FT_List_Iterate( &root->sizes_list,
-                     tt_cvt_ready_iterator,
-                     NULL );
+  FExit:
+    FT_FRAME_EXIT();
 
     return error;
 
@@ -4099,9 +4047,10 @@
     FT_ULong  here;
     FT_UInt   i, j;
 
-    FT_Fixed*  tuple_coords    = NULL;
-    FT_Fixed*  im_start_coords = NULL;
-    FT_Fixed*  im_end_coords   = NULL;
+    FT_Fixed*  peak_coords = NULL;
+    FT_Fixed*  tuple_coords;
+    FT_Fixed*  im_start_coords;
+    FT_Fixed*  im_end_coords;
 
     GX_Blend  blend = face->blend;
 
@@ -4136,27 +4085,17 @@
       return FT_Err_Ok;
     }
 
-    if ( FT_NEW_ARRAY( points_org, n_points ) ||
-         FT_NEW_ARRAY( points_out, n_points ) ||
-         FT_NEW_ARRAY( has_delta, n_points )  )
-      goto Fail1;
-
     dataSize = blend->glyphoffsets[glyph_index + 1] -
                  blend->glyphoffsets[glyph_index];
 
     if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) ||
          FT_FRAME_ENTER( dataSize )                         )
-      goto Fail1;
+      return error;
 
     glyph_start = FT_Stream_FTell( stream );
 
     /* each set of glyph variation data is formatted similarly to `cvar' */
 
-    if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis )    ||
-         FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
-         FT_NEW_ARRAY( im_end_coords, blend->num_axis )   )
-      goto Fail2;
-
     tupleCount   = FT_GET_USHORT();
     offsetToData = FT_GET_USHORT();
 
@@ -4168,7 +4107,7 @@
                   " invalid glyph variation array header\n" ));
 
       error = FT_THROW( Invalid_Table );
-      goto Fail2;
+      goto FExit;
     }
 
     offsetToData += glyph_start;
@@ -4179,9 +4118,8 @@
 
       FT_Stream_SeekSet( stream, offsetToData );
 
-      sharedpoints = ft_var_readpackedpoints( stream,
-                                              blend->gvar_size,
-                                              &spoint_count );
+      sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
+
       offsetToData = FT_Stream_FTell( stream );
 
       FT_Stream_SeekSet( stream, here );
@@ -4192,9 +4130,16 @@
                 tupleCount & GX_TC_TUPLE_COUNT_MASK,
                 ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" ));
 
-    if ( FT_NEW_ARRAY( point_deltas_x, n_points ) ||
-         FT_NEW_ARRAY( point_deltas_y, n_points ) )
-      goto Fail3;
+    if ( FT_QNEW_ARRAY( peak_coords, 3 * blend->num_axis ) ||
+         FT_NEW_ARRAY( point_deltas_x, 2 * n_points )      ||
+         FT_QNEW_ARRAY( points_org, n_points )             ||
+         FT_QNEW_ARRAY( points_out, n_points )             ||
+         FT_QNEW_ARRAY( has_delta, n_points )              )
+      goto Exit;
+
+    im_start_coords = peak_coords + blend->num_axis;
+    im_end_coords   = im_start_coords + blend->num_axis;
+    point_deltas_y  = point_deltas_x + n_points;
 
     for ( j = 0; j < n_points; j++ )
     {
@@ -4217,22 +4162,20 @@
       if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
       {
         for ( j = 0; j < blend->num_axis; j++ )
-          tuple_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
+          peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
+        tuple_coords = peak_coords;
       }
-      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
+      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount )
+        tuple_coords = blend->tuplecoords +
+            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis;
+      else
       {
         FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
                     " invalid tuple index\n" ));
 
         error = FT_THROW( Invalid_Table );
-        goto Fail3;
+        goto Exit;
       }
-      else
-        FT_MEM_COPY(
-          tuple_coords,
-          blend->tuplecoords +
-            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis,
-          blend->num_axis * sizeof ( FT_Fixed ) );
 
       if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
       {
@@ -4260,9 +4203,7 @@
 
       if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )
       {
-        localpoints = ft_var_readpackedpoints( stream,
-                                               blend->gvar_size,
-                                               &point_count );
+        localpoints = ft_var_readpackedpoints( stream, &point_count );
         points      = localpoints;
       }
       else
@@ -4272,11 +4213,9 @@
       }
 
       deltas_x = ft_var_readpackeddeltas( stream,
-                                          blend->gvar_size,
                                           point_count == 0 ? n_points
                                                            : point_count );
       deltas_y = ft_var_readpackeddeltas( stream,
-                                          blend->gvar_size,
                                           point_count == 0 ? n_points
                                                            : point_count );
 
@@ -4460,23 +4399,17 @@
                                        unrounded[n_points - 2].y ) / 64;
     }
 
-  Fail3:
-    FT_FREE( point_deltas_x );
-    FT_FREE( point_deltas_y );
-
-  Fail2:
+  Exit:
     if ( sharedpoints != ALL_POINTS )
       FT_FREE( sharedpoints );
-    FT_FREE( tuple_coords );
-    FT_FREE( im_start_coords );
-    FT_FREE( im_end_coords );
-
-    FT_FRAME_EXIT();
-
-  Fail1:
     FT_FREE( points_org );
     FT_FREE( points_out );
     FT_FREE( has_delta );
+    FT_FREE( peak_coords );
+    FT_FREE( point_deltas_x );
+
+  FExit:
+    FT_FRAME_EXIT();
 
     return error;
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType GX Font Variation loader (specification)
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg and George Williams.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType bytecode interpreter (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -5270,11 +5270,11 @@
     FT_UShort        refp;
     FT_F26Dot6       dx, dy;
 
-    FT_Short         contour, bounds;
+    FT_UShort        contour, bounds;
     FT_UShort        start, limit, i;
 
 
-    contour = (FT_Short)args[0];
+    contour = (FT_UShort)args[0];
     bounds  = ( exc->GS.gep2 == 0 ) ? 1 : exc->zp2.n_contours;
 
     if ( BOUNDS( contour, bounds ) )
@@ -5290,15 +5290,13 @@
     if ( contour == 0 )
       start = 0;
     else
-      start = (FT_UShort)( exc->zp2.contours[contour - 1] + 1 -
-                           exc->zp2.first_point );
+      start = exc->zp2.contours[contour - 1] + 1 - exc->zp2.first_point;
 
     /* we use the number of points if in the twilight zone */
     if ( exc->GS.gep2 == 0 )
       limit = exc->zp2.n_points;
     else
-      limit = (FT_UShort)( exc->zp2.contours[contour] -
-                           exc->zp2.first_point + 1 );
+      limit = exc->zp2.contours[contour] + 1 - exc->zp2.first_point;
 
     for ( i = start; i < limit; i++ )
     {
@@ -5341,9 +5339,9 @@
     /*      Normal zone's `n_points' includes phantoms, so must    */
     /*      use end of last contour.                               */
     if ( exc->GS.gep2 == 0 )
-      limit = (FT_UShort)exc->zp2.n_points;
+      limit = exc->zp2.n_points;
     else if ( exc->GS.gep2 == 1 && exc->zp2.n_contours > 0 )
-      limit = (FT_UShort)( exc->zp2.contours[exc->zp2.n_contours - 1] + 1 );
+      limit = exc->zp2.contours[exc->zp2.n_contours - 1] + 1;
     else
       limit = 0;
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType bytecode interpreter (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Objects manager (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -115,7 +115,7 @@
   FT_LOCAL_DEF( FT_Error )
   tt_glyphzone_new( FT_Memory     memory,
                     FT_UShort     maxPoints,
-                    FT_Short      maxContours,
+                    FT_UShort     maxContours,
                     TT_GlyphZone  zone )
   {
     FT_Error  error;
@@ -152,18 +152,20 @@
   static const FT_String*
   tt_skip_pdffont_random_tag( const FT_String*  name )
   {
-    unsigned int  i;
-
-
-    if ( ft_strlen( name ) < 8 || name[6] != '+' )
-      return name;
-
-    for ( i = 0; i < 6; i++ )
-      if ( !ft_isupper( name[i] ) )
-        return name;
+    if ( ft_isupper( name[0] ) &&
+         ft_isupper( name[1] ) &&
+         ft_isupper( name[2] ) &&
+         ft_isupper( name[3] ) &&
+         ft_isupper( name[4] ) &&
+         ft_isupper( name[5] ) &&
+              '+' == name[6]   &&
+                     name[7]   )
+    {
+      FT_TRACE7(( "name without randomization tag: %s\n", name + 7 ));
+      return name + 7;
+    }
 
-    FT_TRACE7(( "name without randomization tag: %s\n", name + 7 ));
-    return name + 7;
+    return name;
   }
 
 
@@ -254,17 +256,20 @@
   {
     FT_Error   error;
     FT_UInt32  checksum = 0;
-    FT_UInt    i;
+    FT_Byte*   p;
+    FT_Int     shift;
 
 
     if ( FT_FRAME_ENTER( length ) )
       return 0;
 
+    p = (FT_Byte*)stream->cursor;
+
     for ( ; length > 3; length -= 4 )
-      checksum += (FT_UInt32)FT_GET_ULONG();
+      checksum += FT_NEXT_ULONG( p );
 
-    for ( i = 3; length > 0; length--, i-- )
-      checksum += (FT_UInt32)FT_GET_BYTE() << ( i * 8 );
+    for ( shift = 24; length > 0; length--, shift -=8 )
+      checksum += (FT_UInt32)FT_NEXT_BYTE( p ) << shift;
 
     FT_FRAME_EXIT();
 
@@ -782,8 +787,7 @@
       FT_UInt  instance_index = (FT_UInt)face_index >> 16;
 
 
-      if ( FT_HAS_MULTIPLE_MASTERS( ttface ) &&
-           instance_index > 0                )
+      if ( FT_HAS_MULTIPLE_MASTERS( ttface ) )
       {
         error = FT_Set_Named_Instance( ttface, instance_index );
         if ( error )
@@ -990,16 +994,16 @@
     FT_Error        error;
     FT_UInt         i;
 
-    /* unscaled CVT values are already stored in 26.6 format */
-    FT_Fixed  scale = size->ttmetrics.scale >> 6;
-
 
     /* Scale the cvt values to the new ppem.            */
     /* By default, we use the y ppem value for scaling. */
     FT_TRACE6(( "CVT values:\n" ));
     for ( i = 0; i < size->cvt_size; i++ )
     {
-      size->cvt[i] = FT_MulFix( face->cvt[i], scale );
+      /* Unscaled CVT values are already stored in 26.6 format.            */
+      /* Note that this scaling operation is very sensitive to rounding;   */
+      /* the integer division by 64 must be applied to the first argument. */
+      size->cvt[i] = FT_MulFix( face->cvt[i] / 64, size->ttmetrics.scale );
       FT_TRACE6(( "  %3d: %f (%f)\n",
                   i, (double)face->cvt[i] / 64, (double)size->cvt[i] / 64 ));
     }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Objects manager (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -105,7 +105,7 @@ FT_BEGIN_HEADER
   FT_LOCAL( FT_Error )
   tt_glyphzone_new( FT_Memory     memory,
                     FT_UShort     maxPoints,
-                    FT_Short      maxContours,
+                    FT_UShort     maxContours,
                     TT_GlyphZone  zone );
 
 #endif /* TT_USE_BYTECODE_INTERPRETER */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType-specific tables loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   TrueType-specific tables loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   AFM support for Type 1 fonts (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   AFM support for Type 1 fonts (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Type 1 driver interface (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -312,10 +312,7 @@
       {
         retval = ft_strlen( type1->glyph_names[idx] ) + 1;
         if ( value && value_len >= retval )
-        {
           ft_memcpy( value, (void *)( type1->glyph_names[idx] ), retval );
-          ((FT_Char *)value)[retval - 1] = (FT_Char)'\0';
-        }
       }
       break;
 
@@ -344,11 +341,8 @@
       {
         retval = ft_strlen( type1->encoding.char_name[idx] ) + 1;
         if ( value && value_len >= retval )
-        {
           ft_memcpy( value, (void *)( type1->encoding.char_name[idx] ),
-                     retval - 1 );
-          ((FT_Char *)value)[retval - 1] = (FT_Char)'\0';
-        }
+                     retval );
       }
       break;
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   High-level Type 1 driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Type 1 error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Type 1 Glyph Loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Type 1 Glyph Loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1load.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1load.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1load.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1load.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Type 1 font loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -751,6 +751,7 @@
         PS_DesignMap  dmap = blend->design_map + n;
 
 
+        FT_FREE( dmap->blend_points );
         FT_FREE( dmap->design_points );
         dmap->num_points = 0;
       }
@@ -1043,9 +1044,9 @@
       }
 
       /* allocate design map data */
-      if ( FT_QNEW_ARRAY( map->design_points, num_points * 2 ) )
+      if ( FT_QNEW_ARRAY( map->design_points, num_points ) ||
+           FT_QNEW_ARRAY( map->blend_points,  num_points ) )
         goto Exit;
-      map->blend_points = map->design_points + num_points;
       map->num_points   = (FT_Byte)num_points;
 
       for ( p = 0; p < num_points; p++ )
@@ -1876,9 +1877,8 @@
         }
 
         /* t1_decrypt() shouldn't write to base -- make temporary copy */
-        if ( FT_QALLOC( temp, size ) )
+        if ( FT_DUP( temp, base, size ) )
           goto Fail;
-        FT_MEM_COPY( temp, base, size );
         psaux->t1_decrypt( temp, size, 4330 );
         size -= (FT_ULong)t1face->type1.private_dict.lenIV;
         error = T1_Add_Table( table,
@@ -2090,9 +2090,8 @@
           }
 
           /* t1_decrypt() shouldn't write to base -- make temporary copy */
-          if ( FT_QALLOC( temp, size ) )
+          if ( FT_DUP( temp, base, size ) )
             goto Fail;
-          FT_MEM_COPY( temp, base, size );
           psaux->t1_decrypt( temp, size, 4330 );
           size -= (FT_ULong)t1face->type1.private_dict.lenIV;
           error = T1_Add_Table( code_table,
@@ -2284,7 +2283,7 @@
                        T1_FIELD_DICT_PRIVATE )
 #endif
 
-    { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
+    T1_FIELD_ZERO
   };
 
 
@@ -2392,18 +2391,13 @@
           T1_Field  keyword = (T1_Field)t1_keywords;
 
 
-          for (;;)
+          while ( keyword->len )
           {
-            FT_Byte*  name;
+            FT_Byte*  name = (FT_Byte*)keyword->ident;
 
 
-            name = (FT_Byte*)keyword->ident;
-            if ( !name )
-              break;
-
-            if ( cur[0] == name[0]                      &&
-                 len == ft_strlen( (const char *)name ) &&
-                 ft_memcmp( cur, name, len ) == 0       )
+            if ( keyword->len == len              &&
+                 ft_memcmp( cur, name, len ) == 0 )
             {
               /* We found it -- run the parsing callback!     */
               /* We record every instance of every field      */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1load.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1load.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1load.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1load.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Type 1 font loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Type 1 objects manager (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Type 1 objects manager (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Type 1 parser (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Type 1 parser (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h
--- 24.0.1+9-1/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   Type 1 tokenizer (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh	2025-06-27 08:03:14.000000000 +0000
@@ -204,6 +204,7 @@ struct IndexSubtable
   {
     TRACE_SANITIZE (this);
     if (!u.header.sanitize (c)) return_trace (false);
+    hb_barrier ();
     switch (u.header.indexFormat)
     {
     case 1: return_trace (u.format1.sanitize (c, glyph_count));
@@ -378,6 +379,7 @@ struct IndexSubtableRecord
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   firstGlyphIndex <= lastGlyphIndex &&
                   offsetToSubtable.sanitize (c, base, lastGlyphIndex - firstGlyphIndex + 1));
   }
@@ -635,6 +637,7 @@ struct BitmapSizeTable
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   indexSubtableArrayOffset.sanitize (c, base, numberOfIndexSubtables) &&
                   horizontal.sanitize (c) &&
                   vertical.sanitize (c));
@@ -738,7 +741,9 @@ struct CBLC
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   likely (version.major == 2 || version.major == 3) &&
+                  hb_barrier () &&
                   sizeTables.sanitize (c, this));
   }
 
@@ -936,10 +941,12 @@ struct CBDT
       }
     }
 
-    bool has_data () const { return cbdt.get_length (); }
+    bool has_data () const { return cbdt->version.major; }
 
     bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data) const
     {
+      if (!has_data ()) return false;
+
       hb_glyph_extents_t extents;
       hb_glyph_extents_t pixel_extents;
       hb_blob_t *blob = reference_png (font, glyph);
@@ -975,6 +982,7 @@ struct CBDT
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   likely (version.major == 2 || version.major == 3));
   }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh	2025-06-27 08:03:14.000000000 +0000
@@ -29,11 +29,14 @@
 #define OT_COLOR_COLR_COLR_HH
 
 #include "../../../hb.hh"
+#include "../../../hb-decycler.hh"
 #include "../../../hb-open-type.hh"
 #include "../../../hb-ot-var-common.hh"
 #include "../../../hb-paint.hh"
 #include "../../../hb-paint-extents.hh"
 
+#include "../CPAL/CPAL.hh"
+
 /*
  * COLR -- Color
  * https://docs.microsoft.com/en-us/typography/opentype/spec/colr
@@ -66,13 +69,13 @@ public:
   hb_paint_funcs_t *funcs;
   void *data;
   hb_font_t *font;
-  unsigned int palette_index;
+  hb_array_t<const BGRAColor> palette;
   hb_color_t foreground;
-  VarStoreInstancer &instancer;
-  hb_map_t current_glyphs;
-  hb_map_t current_layers;
+  ItemVarStoreInstancer &instancer;
+  hb_decycler_t glyphs_decycler;
+  hb_decycler_t layers_decycler;
   int depth_left = HB_MAX_NESTING_LEVEL;
-  int edge_count = HB_COLRV1_MAX_EDGE_COUNT;
+  int edge_count = HB_MAX_GRAPH_EDGE_COUNT;
 
   hb_paint_context_t (const void *base_,
                       hb_paint_funcs_t *funcs_,
@@ -80,12 +83,16 @@ public:
                       hb_font_t *font_,
                       unsigned int palette_,
                       hb_color_t foreground_,
-                      VarStoreInstancer &instancer_) :
+                      ItemVarStoreInstancer &instancer_) :
     base (base_),
     funcs (funcs_),
     data (data_),
     font (font_),
-    palette_index (palette_),
+    palette (
+#ifndef HB_NO_COLOR
+             font->face->table.CPAL->get_palette_colors (palette_)
+#endif
+    ),
     foreground (foreground_),
     instancer (instancer_)
   { }
@@ -99,12 +106,7 @@ public:
     if (color_index != 0xffff)
     {
       if (!funcs->custom_palette_color (data, color_index, &color))
-      {
-        unsigned int clen = 1;
-        hb_face_t *face = hb_font_get_face (font);
-
-        hb_ot_color_palette_get_colors (face, palette_index, color_index, &clen, &color);
-      }
+        color = palette[color_index];
 
       *is_foreground = false;
     }
@@ -159,23 +161,35 @@ struct hb_colrv1_closure_context_t :
   void add_palette_index (unsigned palette_index)
   { palette_indices->add (palette_index); }
 
+  void add_var_idxes (unsigned first_var_idx, unsigned num_idxes)
+  {
+    if (!num_idxes || first_var_idx == VarIdx::NO_VARIATION) return;
+    variation_indices->add_range (first_var_idx, first_var_idx + num_idxes - 1);
+  }
+
   public:
   const void *base;
   hb_set_t visited_paint;
   hb_set_t *glyphs;
   hb_set_t *layer_indices;
   hb_set_t *palette_indices;
+  hb_set_t *variation_indices;
+  unsigned num_var_idxes;
   unsigned nesting_level_left;
 
   hb_colrv1_closure_context_t (const void *base_,
                                hb_set_t *glyphs_,
                                hb_set_t *layer_indices_,
                                hb_set_t *palette_indices_,
+                               hb_set_t *variation_indices_,
+                               unsigned num_var_idxes_ = 1,
                                unsigned nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
                           base (base_),
                           glyphs (glyphs_),
                           layer_indices (layer_indices_),
                           palette_indices (palette_indices_),
+                          variation_indices (variation_indices_),
+                          num_var_idxes (num_var_idxes_),
                           nesting_level_left (nesting_level_left_)
   {}
 };
@@ -242,18 +256,33 @@ struct Variable
   }
 
   void closurev1 (hb_colrv1_closure_context_t* c) const
-  { value.closurev1 (c); }
+  {
+    c->num_var_idxes = 0;
+    // update c->num_var_idxes during value closure
+    value.closurev1 (c);
+    c->add_var_idxes (varIdxBase, c->num_var_idxes);
+  }
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer) const
+               const ItemVarStoreInstancer &instancer) const
   {
     TRACE_SUBSET (this);
     if (!value.subset (c, instancer, varIdxBase)) return_trace (false);
     if (c->plan->all_axes_pinned)
       return_trace (true);
 
-    //TODO: update varIdxBase for partial-instancing
-    return_trace (c->serializer->embed (varIdxBase));
+    VarIdx new_varidx;
+    new_varidx = varIdxBase;
+    if (varIdxBase != VarIdx::NO_VARIATION)
+    {
+      hb_pair_t<unsigned, int> *new_varidx_delta;
+      if (!c->plan->colrv1_variation_idx_delta_map.has (varIdxBase, &new_varidx_delta))
+        return_trace (false);
+
+      new_varidx = hb_first (*new_varidx_delta);
+    }
+
+    return_trace (c->serializer->embed (new_varidx));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -270,7 +299,7 @@ struct Variable
 
   void get_color_stop (hb_paint_context_t *c,
                        hb_color_stop_t *stop,
-                       const VarStoreInstancer &instancer) const
+                       const ItemVarStoreInstancer &instancer) const
   {
     value.get_color_stop (c, stop, varIdxBase, instancer);
   }
@@ -305,7 +334,7 @@ struct NoVariable
   { value.closurev1 (c); }
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer) const
+               const ItemVarStoreInstancer &instancer) const
   {
     TRACE_SUBSET (this);
     return_trace (value.subset (c, instancer, varIdxBase));
@@ -325,7 +354,7 @@ struct NoVariable
 
   void get_color_stop (hb_paint_context_t *c,
                        hb_color_stop_t *stop,
-                       const VarStoreInstancer &instancer) const
+                       const ItemVarStoreInstancer &instancer) const
   {
     value.get_color_stop (c, stop, VarIdx::NO_VARIATION, instancer);
   }
@@ -345,10 +374,13 @@ struct NoVariable
 struct ColorStop
 {
   void closurev1 (hb_colrv1_closure_context_t* c) const
-  { c->add_palette_index (paletteIndex); }
+  {
+    c->add_palette_index (paletteIndex);
+    c->num_var_idxes = 2;
+  }
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -374,7 +406,7 @@ struct ColorStop
   void get_color_stop (hb_paint_context_t *c,
                        hb_color_stop_t *out,
                        uint32_t varIdx,
-                       const VarStoreInstancer &instancer) const
+                       const ItemVarStoreInstancer &instancer) const
   {
     out->offset = stopOffset.to_float(instancer (varIdx, 0));
     out->color = c->get_color (paletteIndex,
@@ -410,7 +442,7 @@ struct ColorLine
   }
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer) const
+               const ItemVarStoreInstancer &instancer) const
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (this);
@@ -439,7 +471,7 @@ struct ColorLine
                    unsigned int start,
                    unsigned int *count,
                    hb_color_stop_t *color_stops,
-                   const VarStoreInstancer &instancer) const
+                   const ItemVarStoreInstancer &instancer) const
   {
     unsigned int len = stops.len;
 
@@ -542,8 +574,11 @@ struct Affine2x3
     return_trace (c->check_struct (this));
   }
 
+  void closurev1 (hb_colrv1_closure_context_t* c) const
+  { c->num_var_idxes = 6; }
+
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -588,7 +623,7 @@ struct PaintColrLayers
   void closurev1 (hb_colrv1_closure_context_t* c) const;
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer HB_UNUSED) const
+               const ItemVarStoreInstancer &instancer HB_UNUSED) const
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->embed (this);
@@ -617,10 +652,13 @@ struct PaintColrLayers
 struct PaintSolid
 {
   void closurev1 (hb_colrv1_closure_context_t* c) const
-  { c->add_palette_index (paletteIndex); }
+  {
+    c->add_palette_index (paletteIndex);
+    c->num_var_idxes = 1;
+  }
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -666,10 +704,13 @@ template <template<typename> class Var>
 struct PaintLinearGradient
 {
   void closurev1 (hb_colrv1_closure_context_t* c) const
-  { (this+colorLine).closurev1 (c); }
+  {
+    (this+colorLine).closurev1 (c);
+    c->num_var_idxes = 6;
+  }
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -733,10 +774,13 @@ template <template<typename> class Var>
 struct PaintRadialGradient
 {
   void closurev1 (hb_colrv1_closure_context_t* c) const
-  { (this+colorLine).closurev1 (c); }
+  {
+    (this+colorLine).closurev1 (c);
+    c->num_var_idxes = 6;
+  }
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -800,10 +844,13 @@ template <template<typename> class Var>
 struct PaintSweepGradient
 {
   void closurev1 (hb_colrv1_closure_context_t* c) const
-  { (this+colorLine).closurev1 (c); }
+  {
+    (this+colorLine).closurev1 (c);
+    c->num_var_idxes = 4;
+  }
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -863,7 +910,7 @@ struct PaintGlyph
   void closurev1 (hb_colrv1_closure_context_t* c) const;
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer) const
+               const ItemVarStoreInstancer &instancer) const
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->embed (this);
@@ -906,7 +953,7 @@ struct PaintColrGlyph
   void closurev1 (hb_colrv1_closure_context_t* c) const;
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer HB_UNUSED) const
+               const ItemVarStoreInstancer &instancer HB_UNUSED) const
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->embed (this);
@@ -936,7 +983,7 @@ struct PaintTransform
   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer) const
+               const ItemVarStoreInstancer &instancer) const
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->embed (this);
@@ -958,7 +1005,7 @@ struct PaintTransform
   void paint_glyph (hb_paint_context_t *c) const
   {
     TRACE_PAINT (this);
-    (this+transform).paint_glyph (c);
+    (this+transform).paint_glyph (c); // This does a push_transform()
     c->recurse (this+src);
     c->funcs->pop_transform (c->data);
   }
@@ -975,7 +1022,7 @@ struct PaintTranslate
   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -1024,7 +1071,7 @@ struct PaintScale
   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -1073,7 +1120,7 @@ struct PaintScaleAroundCenter
   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -1132,7 +1179,7 @@ struct PaintScaleUniform
   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -1176,7 +1223,7 @@ struct PaintScaleUniformAroundCenter
   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -1232,7 +1279,7 @@ struct PaintRotate
   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -1276,7 +1323,7 @@ struct PaintRotateAroundCenter
   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -1332,7 +1379,7 @@ struct PaintSkew
   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -1381,7 +1428,7 @@ struct PaintSkewAroundCenter
   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -1440,7 +1487,7 @@ struct PaintComposite
   void closurev1 (hb_colrv1_closure_context_t* c) const;
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer) const
+               const ItemVarStoreInstancer &instancer) const
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->embed (this);
@@ -1491,7 +1538,7 @@ struct ClipBoxFormat1
     return_trace (c->check_struct (this));
   }
 
-  void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer HB_UNUSED) const
+  void get_clip_box (ClipBoxData &clip_box, const ItemVarStoreInstancer &instancer HB_UNUSED) const
   {
     clip_box.xMin = xMin;
     clip_box.yMin = yMin;
@@ -1500,7 +1547,7 @@ struct ClipBoxFormat1
   }
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer,
+               const ItemVarStoreInstancer &instancer,
                uint32_t varIdxBase) const
   {
     TRACE_SUBSET (this);
@@ -1533,7 +1580,7 @@ struct ClipBoxFormat1
 
 struct ClipBoxFormat2 : Variable<ClipBoxFormat1>
 {
-  void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer) const
+  void get_clip_box (ClipBoxData &clip_box, const ItemVarStoreInstancer &instancer) const
   {
     value.get_clip_box(clip_box, instancer);
     if (instancer)
@@ -1544,12 +1591,15 @@ struct ClipBoxFormat2 : Variable<ClipBox
       clip_box.yMax += roundf (instancer (varIdxBase, 3));
     }
   }
+
+  void closurev1 (hb_colrv1_closure_context_t* c) const
+  { c->variation_indices->add_range (varIdxBase, varIdxBase + 3); }
 };
 
 struct ClipBox
 {
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer) const
+               const ItemVarStoreInstancer &instancer) const
   {
     TRACE_SUBSET (this);
     switch (u.format) {
@@ -1559,6 +1609,14 @@ struct ClipBox
     }
   }
 
+  void closurev1 (hb_colrv1_closure_context_t* c) const
+  {
+    switch (u.format) {
+    case 2: u.format2.closurev1 (c);
+    default:return;
+    }
+  }
+
   template <typename context_t, typename ...Ts>
   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
   {
@@ -1572,7 +1630,7 @@ struct ClipBox
   }
 
   bool get_extents (hb_glyph_extents_t *extents,
-                    const VarStoreInstancer &instancer) const
+                    const ItemVarStoreInstancer &instancer) const
   {
     ClipBoxData clip_box;
     switch (u.format) {
@@ -1606,9 +1664,15 @@ struct ClipRecord
   int cmp (hb_codepoint_t g) const
   { return g < startGlyphID ? -1 : g <= endGlyphID ? 0 : +1; }
 
+  void closurev1 (hb_colrv1_closure_context_t* c, const void *base) const
+  {
+    if (!c->glyphs->intersects (startGlyphID, endGlyphID)) return;
+    (base+clipBox).closurev1 (c);
+  }
+
   bool subset (hb_subset_context_t *c,
                const void *base,
-               const VarStoreInstancer &instancer) const
+               const ItemVarStoreInstancer &instancer) const
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->embed (*this);
@@ -1625,7 +1689,7 @@ struct ClipRecord
 
   bool get_extents (hb_glyph_extents_t *extents,
                     const void *base,
-                    const VarStoreInstancer &instancer) const
+                    const ItemVarStoreInstancer &instancer) const
   {
     return (base+clipBox).get_extents (extents, instancer);
   }
@@ -1642,7 +1706,7 @@ DECLARE_NULL_NAMESPACE_BYTES (OT, ClipRe
 struct ClipList
 {
   unsigned serialize_clip_records (hb_subset_context_t *c,
-                                   const VarStoreInstancer &instancer,
+                                   const ItemVarStoreInstancer &instancer,
                                    const hb_set_t& gids,
                                    const hb_map_t& gid_offset_map) const
   {
@@ -1695,7 +1759,7 @@ struct ClipList
   }
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer) const
+               const ItemVarStoreInstancer &instancer) const
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (*this);
@@ -1735,7 +1799,7 @@ struct ClipList
   bool
   get_extents (hb_codepoint_t gid,
                hb_glyph_extents_t *extents,
-               const VarStoreInstancer &instancer) const
+               const ItemVarStoreInstancer &instancer) const
   {
     auto *rec = clips.as_array ().bsearch (gid);
     if (rec)
@@ -1855,7 +1919,7 @@ struct BaseGlyphPaintRecord
 
   bool serialize (hb_serialize_context_t *s, const hb_map_t* glyph_map,
                   const void* src_base, hb_subset_context_t *c,
-                  const VarStoreInstancer &instancer) const
+                  const ItemVarStoreInstancer &instancer) const
   {
     TRACE_SERIALIZE (this);
     auto *out = s->embed (this);
@@ -1884,7 +1948,7 @@ struct BaseGlyphPaintRecord
 struct BaseGlyphList : SortedArray32Of<BaseGlyphPaintRecord>
 {
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer) const
+               const ItemVarStoreInstancer &instancer) const
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (this);
@@ -1916,7 +1980,7 @@ struct LayerList : Array32OfOffset32To<P
   { return this+(*this)[i]; }
 
   bool subset (hb_subset_context_t *c,
-               const VarStoreInstancer &instancer) const
+               const ItemVarStoreInstancer &instancer) const
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (this);
@@ -1941,6 +2005,76 @@ struct LayerList : Array32OfOffset32To<P
   }
 };
 
+struct delta_set_index_map_subset_plan_t
+{
+  unsigned get_inner_bit_count () const { return inner_bit_count; }
+  unsigned get_width ()           const { return ((outer_bit_count + inner_bit_count + 7) / 8); }
+  hb_array_t<const uint32_t> get_output_map () const { return output_map.as_array (); }
+
+  delta_set_index_map_subset_plan_t (const hb_map_t &new_deltaset_idx_varidx_map)
+  {
+    map_count = 0;
+    outer_bit_count = 0;
+    inner_bit_count = 1;
+    output_map.init ();
+
+    /* search backwards */
+    unsigned count = new_deltaset_idx_varidx_map.get_population ();
+    if (!count) return;
+
+    unsigned last_idx = (unsigned)-1;
+    unsigned last_varidx = (unsigned)-1;
+
+    for (unsigned i = count; i; i--)
+    {
+      unsigned delta_set_idx = i - 1;
+      unsigned var_idx = new_deltaset_idx_varidx_map.get (delta_set_idx);
+      if (i == count)
+      {
+        last_idx = delta_set_idx;
+        last_varidx = var_idx;
+        continue;
+      }
+      if (var_idx != last_varidx)
+        break;
+      last_idx = delta_set_idx;
+    }
+
+    map_count = last_idx + 1;
+  }
+
+  bool remap (const hb_map_t &new_deltaset_idx_varidx_map)
+  {
+    /* recalculate bit_count */
+    outer_bit_count = 1;
+    inner_bit_count = 1;
+
+    if (unlikely (!output_map.resize (map_count, false))) return false;
+
+    for (unsigned idx = 0; idx < map_count; idx++)
+    {
+      uint32_t *var_idx;
+      if (!new_deltaset_idx_varidx_map.has (idx, &var_idx)) return false;
+      output_map.arrayZ[idx] = *var_idx;
+
+      unsigned outer = (*var_idx) >> 16;
+      unsigned bit_count = (outer == 0) ? 1 : hb_bit_storage (outer);
+      outer_bit_count = hb_max (bit_count, outer_bit_count);
+
+      unsigned inner = (*var_idx) & 0xFFFF;
+      bit_count = (inner == 0) ? 1 : hb_bit_storage (inner);
+      inner_bit_count = hb_max (bit_count, inner_bit_count);
+    }
+    return true;
+  }
+
+  private:
+  unsigned map_count;
+  unsigned outer_bit_count;
+  unsigned inner_bit_count;
+  hb_vector_t<uint32_t> output_map;
+};
+
 struct COLR
 {
   static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
@@ -1948,10 +2082,11 @@ struct COLR
   bool has_v0_data () const { return numBaseGlyphs; }
   bool has_v1_data () const
   {
-    if (version == 1)
-      return (this+baseGlyphList).len > 0;
+    if (version < 1)
+      return false;
+    hb_barrier ();
 
-    return false;
+    return (this+baseGlyphList).len > 0;
   }
 
   unsigned int get_glyph_layers (hb_codepoint_t       glyph,
@@ -1991,8 +2126,26 @@ struct COLR
 
     void closure_forV1 (hb_set_t *glyphset,
                         hb_set_t *layer_indices,
-                        hb_set_t *palette_indices) const
-    { colr->closure_forV1 (glyphset, layer_indices, palette_indices); }
+                        hb_set_t *palette_indices,
+                        hb_set_t *variation_indices,
+                        hb_set_t *delta_set_indices) const
+    { colr->closure_forV1 (glyphset, layer_indices, palette_indices, variation_indices, delta_set_indices); }
+
+    bool has_var_store () const
+    { return colr->has_var_store (); }
+
+    const ItemVariationStore &get_var_store () const
+    { return colr->get_var_store (); }
+    const ItemVariationStore *get_var_store_ptr () const
+    { return colr->get_var_store_ptr (); }
+
+    bool has_delta_set_index_map () const
+    { return colr->has_delta_set_index_map (); }
+
+    const DeltaSetIndexMap &get_delta_set_index_map () const
+    { return colr->get_delta_set_index_map (); }
+    const DeltaSetIndexMap *get_delta_set_index_map_ptr () const
+    { return colr->get_delta_set_index_map_ptr (); }
 
     private:
     hb_blob_ptr_t<COLR> colr;
@@ -2029,12 +2182,16 @@ struct COLR
 
   void closure_forV1 (hb_set_t *glyphset,
                       hb_set_t *layer_indices,
-                      hb_set_t *palette_indices) const
+                      hb_set_t *palette_indices,
+                      hb_set_t *variation_indices,
+                      hb_set_t *delta_set_indices) const
   {
-    if (version != 1) return;
+    if (version < 1) return;
+    hb_barrier ();
+
     hb_set_t visited_glyphs;
 
-    hb_colrv1_closure_context_t c (this, &visited_glyphs, layer_indices, palette_indices);
+    hb_colrv1_closure_context_t c (this, &visited_glyphs, layer_indices, palette_indices, variation_indices);
     const BaseGlyphList &baseglyph_paintrecords = this+baseGlyphList;
 
     for (const BaseGlyphPaintRecord &baseglyph_paintrecord: baseglyph_paintrecords.iter ())
@@ -2046,6 +2203,22 @@ struct COLR
       paint.dispatch (&c);
     }
     hb_set_union (glyphset, &visited_glyphs);
+
+    const ClipList &cliplist = this+clipList;
+    c.glyphs = glyphset;
+    for (const ClipRecord &clip_record : cliplist.clips.iter())
+      clip_record.closurev1 (&c, &cliplist);
+
+    // if a DeltaSetIndexMap is included, collected variation indices are
+    // actually delta set indices, we need to map them into variation indices
+    if (has_delta_set_index_map ())
+    {
+      const DeltaSetIndexMap &var_idx_map = this+varIdxMap;
+      delta_set_indices->set (*variation_indices);
+      variation_indices->clear ();
+      for (unsigned delta_set_idx : *delta_set_indices)
+        variation_indices->add (var_idx_map.map (delta_set_idx));
+    }
   }
 
   const LayerList& get_layerList () const
@@ -2054,14 +2227,37 @@ struct COLR
   const BaseGlyphList& get_baseglyphList () const
   { return (this+baseGlyphList); }
 
+  bool has_var_store () const
+  { return version >= 1 && hb_barrier () && varStore != 0; }
+
+  bool has_delta_set_index_map () const
+  { return version >= 1 && hb_barrier () && varIdxMap != 0; }
+
+  bool has_clip_list () const
+  { return version >= 1 && hb_barrier () && clipList != 0; }
+
+  const DeltaSetIndexMap &get_delta_set_index_map () const
+  { return has_delta_set_index_map () && hb_barrier () ? this+varIdxMap : Null (DeltaSetIndexMap); }
+  const DeltaSetIndexMap *get_delta_set_index_map_ptr () const
+  { return has_delta_set_index_map () && hb_barrier () ? &(this+varIdxMap) : nullptr; }
+
+  const ItemVariationStore &get_var_store () const
+  { return has_var_store () && hb_barrier () ? this+varStore : Null (ItemVariationStore); }
+  const ItemVariationStore *get_var_store_ptr () const
+  { return has_var_store () && hb_barrier () ? &(this+varStore) : nullptr; }
+
+  const ClipList &get_clip_list () const
+  { return has_clip_list () && hb_barrier () ? this+clipList : Null (ClipList); }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
                   (this+layersZ).sanitize (c, numLayers) &&
                   (version == 0 ||
-                   (version == 1 &&
+                   (hb_barrier () &&
                     baseGlyphList.sanitize (c, this) &&
                     layerList.sanitize (c, this) &&
                     clipList.sanitize (c, this) &&
@@ -2127,6 +2323,94 @@ struct COLR
     return record;
   }
 
+  bool downgrade_to_V0 (const hb_set_t &glyphset) const
+  {
+    //no more COLRv1 glyphs, downgrade to version 0
+    for (const BaseGlyphPaintRecord& _ : get_baseglyphList ())
+      if (glyphset.has (_.glyphId))
+        return false;
+
+    return true;
+  }
+
+  bool subset_varstore (hb_subset_context_t *c,
+                        COLR* out /* OUT */) const
+  {
+    TRACE_SUBSET (this);
+    if (!varStore || c->plan->all_axes_pinned ||
+        !c->plan->colrv1_variation_idx_delta_map)
+      return_trace (true);
+
+    const ItemVariationStore& var_store = this+varStore;
+    if (c->plan->normalized_coords)
+    {
+      item_variations_t item_vars;
+      /* turn off varstore optimization when varIdxMap is null, so we maintain
+       * original var_idx sequence */
+      bool optimize = (varIdxMap != 0) ? true : false;
+      if (!item_vars.instantiate (var_store, c->plan,
+                                  optimize, /* optimization */
+                                  optimize, /* use_no_variation_idx = false */
+                                  c->plan->colrv1_varstore_inner_maps.as_array ()))
+        return_trace (false);
+
+      /* do not serialize varStore if there's no variation data after
+       * instancing: region_list or var_data is empty */
+      if (item_vars.get_region_list () &&
+          item_vars.get_vardata_encodings () &&
+          !out->varStore.serialize_serialize (c->serializer,
+                                              item_vars.has_long_word (),
+                                              c->plan->axis_tags,
+                                              item_vars.get_region_list (),
+                                              item_vars.get_vardata_encodings ()))
+        return_trace (false);
+
+      /* if varstore is optimized, update colrv1_new_deltaset_idx_varidx_map in
+       * subset plan.
+       * If varstore is empty after instancing, varidx_map would be empty and
+       * all var_idxes will be updated to VarIdx::NO_VARIATION */
+      if (optimize)
+      {
+        const hb_map_t &varidx_map = item_vars.get_varidx_map ();
+        for (auto _ : c->plan->colrv1_new_deltaset_idx_varidx_map.iter_ref ())
+        {
+          uint32_t varidx = _.second;
+          uint32_t *new_varidx;
+          if (varidx_map.has (varidx, &new_varidx))
+            _.second = *new_varidx;
+          else
+            _.second = VarIdx::NO_VARIATION;
+        }
+      }
+    }
+    else
+    {
+      if (unlikely (!out->varStore.serialize_serialize (c->serializer,
+                                                        &var_store,
+                                                        c->plan->colrv1_varstore_inner_maps.as_array ())))
+        return_trace (false);
+    }
+
+    return_trace (true);
+  }
+
+  bool subset_delta_set_index_map (hb_subset_context_t *c,
+                                   COLR* out /* OUT */) const
+  {
+    TRACE_SUBSET (this);
+    if (!varIdxMap || c->plan->all_axes_pinned ||
+        !c->plan->colrv1_new_deltaset_idx_varidx_map)
+      return_trace (true);
+
+    const hb_map_t &deltaset_idx_varidx_map = c->plan->colrv1_new_deltaset_idx_varidx_map;
+    delta_set_index_map_subset_plan_t index_map_plan (deltaset_idx_varidx_map);
+
+    if (unlikely (!index_map_plan.remap (deltaset_idx_varidx_map)))
+      return_trace (false);
+
+    return_trace (out->varIdxMap.serialize_serialize (c->serializer, index_map_plan));
+  }
+
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
@@ -2195,34 +2479,30 @@ struct COLR
     auto *colr_prime = c->serializer->start_embed<COLR> ();
     if (unlikely (!c->serializer->extend_min (colr_prime)))  return_trace (false);
 
-    if (version == 0)
-    return_trace (colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it));
+    if (version == 0 || downgrade_to_V0 (glyphset))
+      return_trace (colr_prime->serialize_V0 (c->serializer, 0, base_it, layer_it));
+
+    hb_barrier ();
 
-    auto snap = c->serializer->snapshot ();
+    //start version 1
     if (!c->serializer->allocate_size<void> (5 * HBUINT32::static_size)) return_trace (false);
+    if (!colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)) return_trace (false);
 
-    VarStoreInstancer instancer (varStore ? &(this+varStore) : nullptr,
-                                 varIdxMap ? &(this+varIdxMap) : nullptr,
-                                 c->plan->normalized_coords.as_array ());
+    /* subset ItemVariationStore first, cause varidx_map needs to be updated
+     * after instancing */
+    if (!subset_varstore (c, colr_prime)) return_trace (false);
+
+    ItemVarStoreInstancer instancer (get_var_store_ptr (),
+                                     get_delta_set_index_map_ptr (),
+                                     c->plan->normalized_coords.as_array ());
 
     if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this, instancer))
-    {
-      if (c->serializer->in_error ()) return_trace (false);
-      //no more COLRv1 glyphs: downgrade to version 0
-      c->serializer->revert (snap);
-      return_trace (colr_prime->serialize_V0 (c->serializer, 0, base_it, layer_it));
-    }
-
-    if (!colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)) return_trace (false);
+      return_trace (false);
 
     colr_prime->layerList.serialize_subset (c, layerList, this, instancer);
     colr_prime->clipList.serialize_subset (c, clipList, this, instancer);
-    if (!varStore || c->plan->all_axes_pinned)
-      return_trace (true);
 
-    colr_prime->varIdxMap.serialize_copy (c->serializer, varIdxMap, this);
-    colr_prime->varStore.serialize_copy (c->serializer, varStore, this);
-    return_trace (true);
+    return_trace (subset_delta_set_index_map (c, colr_prime));
   }
 
   const Paint *get_base_glyph_paint (hb_codepoint_t glyph) const
@@ -2242,12 +2522,10 @@ struct COLR
   bool
   get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
   {
-    if (version != 1)
-      return false;
 
-    VarStoreInstancer instancer (&(this+varStore),
-                                 &(this+varIdxMap),
-                                 hb_array (font->coords, font->num_coords));
+    ItemVarStoreInstancer instancer (get_var_store_ptr (),
+                                     get_delta_set_index_map_ptr (),
+                                     hb_array (font->coords, font->num_coords));
 
     if (get_clip (glyph, extents, instancer))
     {
@@ -2282,8 +2560,10 @@ struct COLR
   bool
   has_paint_for_glyph (hb_codepoint_t glyph) const
   {
-    if (version == 1)
+    if (version >= 1)
     {
+      hb_barrier ();
+
       const Paint *paint = get_base_glyph_paint (glyph);
 
       return paint != nullptr;
@@ -2294,9 +2574,9 @@ struct COLR
 
   bool get_clip (hb_codepoint_t glyph,
                  hb_glyph_extents_t *extents,
-                 const VarStoreInstancer instancer) const
+                 const ItemVarStoreInstancer instancer) const
   {
-    return (this+clipList).get_extents (glyph,
+    return get_clip_list ().get_extents (glyph,
                                         extents,
                                         instancer);
   }
@@ -2305,23 +2585,23 @@ struct COLR
   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
   {
-    VarStoreInstancer instancer (&(this+varStore),
-                                 &(this+varIdxMap),
-                                 hb_array (font->coords, font->num_coords));
+    ItemVarStoreInstancer instancer (get_var_store_ptr (),
+                                     get_delta_set_index_map_ptr (),
+                                     hb_array (font->coords, font->num_coords));
     hb_paint_context_t c (this, funcs, data, font, palette_index, foreground, instancer);
-    c.current_glyphs.add (glyph);
 
-    if (version == 1)
+    hb_decycler_node_t node (c.glyphs_decycler);
+    node.visit (glyph);
+
+    if (version >= 1)
     {
+      hb_barrier ();
+
       const Paint *paint = get_base_glyph_paint (glyph);
       if (paint)
       {
         // COLRv1 glyph
 
-        VarStoreInstancer instancer (&(this+varStore),
-                                     &(this+varIdxMap),
-                                     hb_array (font->coords, font->num_coords));
-
         bool is_bounded = true;
         if (clip)
         {
@@ -2404,7 +2684,7 @@ struct COLR
   Offset32To<LayerList>                 layerList;
   Offset32To<ClipList>                  clipList;   // Offset to ClipList table (may be NULL)
   Offset32To<DeltaSetIndexMap>          varIdxMap;  // Offset to DeltaSetIndexMap table (may be NULL)
-  Offset32To<VariationStore>            varStore;
+  Offset32To<ItemVariationStore>        varStore;
   public:
   DEFINE_SIZE_MIN (14);
 };
@@ -2427,19 +2707,16 @@ void PaintColrLayers::paint_glyph (hb_pa
 {
   TRACE_PAINT (this);
   const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList ();
+  hb_decycler_node_t node (c->layers_decycler);
   for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++)
   {
-    if (unlikely (c->current_layers.has (i)))
-      continue;
-
-    c->current_layers.add (i);
+    if (unlikely (!node.visit (i)))
+      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);
-
-    c->current_layers.del (i);
   }
 }
 
@@ -2447,16 +2724,14 @@ void PaintColrGlyph::paint_glyph (hb_pai
 {
   TRACE_PAINT (this);
 
-  if (unlikely (c->current_glyphs.has (gid)))
+  hb_decycler_node_t node (c->glyphs_decycler);
+  if (unlikely (!node.visit (gid)))
     return;
 
-  c->current_glyphs.add (gid);
-
   c->funcs->push_inverse_root_transform (c->data, c->font);
   if (c->funcs->color_glyph (c->data, gid, c->font))
   {
     c->funcs->pop_transform (c->data);
-    c->current_glyphs.del (gid);
     return;
   }
   c->funcs->pop_transform (c->data);
@@ -2479,8 +2754,6 @@ void PaintColrGlyph::paint_glyph (hb_pai
 
   if (has_clip_box)
     c->funcs->pop_clip (c->data);
-
-  c->current_glyphs.del (gid);
 }
 
 } /* namespace OT */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/colrv1-closure.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/colrv1-closure.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/colrv1-closure.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/colrv1-closure.hh	2025-06-27 08:03:14.000000000 +0000
@@ -66,34 +66,64 @@ HB_INTERNAL void PaintColrGlyph::closure
 
 template <template<typename> class Var>
 HB_INTERNAL void PaintTransform<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+  (this+src).dispatch (c);
+  (this+transform).closurev1 (c);
+}
 
 HB_INTERNAL void PaintTranslate::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+  (this+src).dispatch (c);
+  c->num_var_idxes = 2;
+}
 
 HB_INTERNAL void PaintScale::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+  (this+src).dispatch (c);
+  c->num_var_idxes = 2;
+}
 
 HB_INTERNAL void PaintScaleAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+  (this+src).dispatch (c);
+  c->num_var_idxes = 4;
+}
 
 HB_INTERNAL void PaintScaleUniform::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+  (this+src).dispatch (c);
+  c->num_var_idxes = 1;
+}
 
 HB_INTERNAL void PaintScaleUniformAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+  (this+src).dispatch (c);
+  c->num_var_idxes = 3;
+}
 
 HB_INTERNAL void PaintRotate::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+  (this+src).dispatch (c);
+  c->num_var_idxes = 1;
+}
 
 HB_INTERNAL void PaintRotateAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+  (this+src).dispatch (c);
+  c->num_var_idxes = 3;
+}
 
 HB_INTERNAL void PaintSkew::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+  (this+src).dispatch (c);
+  c->num_var_idxes = 2;
+}
 
 HB_INTERNAL void PaintSkewAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+  (this+src).dispatch (c);
+  c->num_var_idxes = 4;
+}
 
 HB_INTERNAL void PaintComposite::closurev1 (hb_colrv1_closure_context_t* c) const
 {
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh	2025-06-27 08:03:14.000000000 +0000
@@ -187,6 +187,14 @@ struct CPAL
   hb_ot_name_id_t get_color_name_id (unsigned int color_index) const
   { return v1 ().get_color_name_id (this, color_index, numColors); }
 
+  hb_array_t<const BGRAColor> get_palette_colors (unsigned int palette_index) const
+  {
+    if (unlikely (palette_index >= numPalettes))
+      return hb_array_t<const BGRAColor> ();
+    unsigned int start_index = colorRecordIndicesZ[palette_index];
+    hb_array_t<const BGRAColor> all_colors ((this+colorRecordsZ).arrayZ, numColorRecords);
+    return all_colors.sub_array (start_index, numColors);
+  }
   unsigned int get_palette_colors (unsigned int  palette_index,
                                    unsigned int  start_offset,
                                    unsigned int *color_count, /* IN/OUT.  May be NULL. */
@@ -214,13 +222,17 @@ struct CPAL
                          hb_set_t *nameids_to_retain /* OUT */) const
   {
     if (version == 1)
+    {
+      hb_barrier ();
       v1 ().collect_name_ids (this, numPalettes, numColors, color_index_map, nameids_to_retain);
+    }
   }
 
   private:
   const CPALV1Tail& v1 () const
   {
     if (version == 0) return Null (CPALV1Tail);
+    hb_barrier ();
     return StructAfter<CPALV1Tail> (*this);
   }
 
@@ -312,7 +324,10 @@ struct CPAL
       return_trace (false);
 
     if (version == 1)
+    {
+      hb_barrier ();
       return_trace (v1 ().serialize (c->serializer, numPalettes, numColors, this, color_index_map));
+    }
 
     return_trace (true);
   }
@@ -321,6 +336,7 @@ struct CPAL
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   (this+colorRecordsZ).sanitize (c, numColorRecords) &&
                   colorRecordIndicesZ.sanitize (c, numPalettes) &&
                   (version == 0 || v1 ().sanitize (c, this, numPalettes, numColors)));
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh	2025-06-27 08:03:14.000000000 +0000
@@ -368,6 +368,7 @@ struct sbix
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
                           version >= 1 &&
                           strikes.sanitize (c, this)));
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh	2025-06-27 08:03:14.000000000 +0000
@@ -56,6 +56,7 @@ struct SVGDocumentIndexEntry
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   svgDoc.sanitize (c, base, svgDocLength));
   }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/Coverage.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/Coverage.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/Coverage.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/Coverage.hh	2025-06-27 08:03:14.000000000 +0000
@@ -64,6 +64,7 @@ struct Coverage
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
+    hb_barrier ();
     switch (u.format)
     {
     case 1: return_trace (u.format1.sanitize (c));
@@ -95,6 +96,15 @@ struct Coverage
     default:return NOT_COVERED;
     }
   }
+  unsigned int get_coverage (hb_codepoint_t glyph_id,
+                             hb_ot_lookup_cache_t *cache) const
+  {
+    unsigned coverage;
+    if (cache && cache->get (glyph_id, &coverage)) return coverage;
+    coverage = get_coverage (glyph_id);
+    if (cache) cache->set (glyph_id, coverage);
+    return coverage;
+  }
 
   unsigned get_population () const
   {
@@ -200,6 +210,19 @@ struct Coverage
     }
   }
 
+  unsigned cost () const
+  {
+    switch (u.format) {
+    case 1: hb_barrier (); return u.format1.cost ();
+    case 2: hb_barrier (); return u.format2.cost ();
+#ifndef HB_NO_BEYOND_64K
+    case 3: hb_barrier (); return u.format3.cost ();
+    case 4: hb_barrier (); return u.format4.cost ();
+#endif
+    default:return 0u;
+    }
+  }
+
   /* Might return false if array looks unsorted.
    * Used for faster rejection of corrupt data. */
   template <typename set_t>
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh	2025-06-27 08:03:14.000000000 +0000
@@ -103,6 +103,8 @@ struct CoverageFormat1_3
         intersect_glyphs << glyphArray[i];
   }
 
+  unsigned cost () const { return hb_bit_storage ((unsigned) glyphArray.len); /* bsearch cost */ }
+
   template <typename set_t>
   bool collect_coverage (set_t *glyphs) const
   { return glyphs->add_sorted_array (glyphArray.as_array ()); }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh	2025-06-27 08:03:14.000000000 +0000
@@ -157,6 +157,8 @@ struct CoverageFormat2_4
     }
   }
 
+  unsigned cost () const { return hb_bit_storage ((unsigned) rangeRecord.len); /* bsearch cost */ }
+
   template <typename set_t>
   bool collect_coverage (set_t *glyphs) const
   {
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh	2025-06-27 08:03:14.000000000 +0000
@@ -189,7 +189,7 @@ struct CaretValueFormat3
   friend struct CaretValue;
 
   hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction,
-                                 const VariationStore &var_store) const
+                                 const ItemVariationStore &var_store) const
   {
     return HB_DIRECTION_IS_HORIZONTAL (direction) ?
            font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) :
@@ -251,7 +251,7 @@ struct CaretValue
   hb_position_t get_caret_value (hb_font_t *font,
                                  hb_direction_t direction,
                                  hb_codepoint_t glyph_id,
-                                 const VariationStore &var_store) const
+                                 const ItemVariationStore &var_store) const
   {
     switch (u.format) {
     case 1: return u.format1.get_caret_value (font, direction);
@@ -291,6 +291,7 @@ struct CaretValue
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
+    hb_barrier ();
     switch (u.format) {
     case 1: return_trace (u.format1.sanitize (c));
     case 2: return_trace (u.format2.sanitize (c));
@@ -315,7 +316,7 @@ struct LigGlyph
   unsigned get_lig_carets (hb_font_t            *font,
                            hb_direction_t        direction,
                            hb_codepoint_t        glyph_id,
-                           const VariationStore &var_store,
+                           const ItemVariationStore &var_store,
                            unsigned              start_offset,
                            unsigned             *caret_count /* IN/OUT */,
                            hb_position_t        *caret_array /* OUT */) const
@@ -371,7 +372,7 @@ struct LigCaretList
   unsigned int get_lig_carets (hb_font_t *font,
                                hb_direction_t direction,
                                hb_codepoint_t glyph_id,
-                               const VariationStore &var_store,
+                               const ItemVariationStore &var_store,
                                unsigned int start_offset,
                                unsigned int *caret_count /* IN/OUT */,
                                hb_position_t *caret_array /* OUT */) const
@@ -441,6 +442,20 @@ struct MarkGlyphSetsFormat1
   bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
   { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
 
+  void collect_used_mark_sets (const hb_set_t& glyph_set,
+                               hb_set_t& used_mark_sets /* OUT */) const
+  {
+    unsigned i = 0;
+    for (const auto &offset : coverage)
+     {
+       const auto &cov = this+offset;
+       if (cov.intersects (&glyph_set))
+         used_mark_sets.add (i);
+
+       i++;
+     }
+  }
+
   template <typename set_t>
   void collect_coverage (hb_vector_t<set_t> &sets) const
   {
@@ -461,6 +476,7 @@ struct MarkGlyphSetsFormat1
     bool ret = true;
     for (const Offset32To<Coverage>& offset : coverage.iter ())
     {
+      auto snap = c->serializer->snapshot ();
       auto *o = out->coverage.serialize_append (c->serializer);
       if (unlikely (!o))
       {
@@ -468,11 +484,17 @@ struct MarkGlyphSetsFormat1
         break;
       }
 
-      //not using o->serialize_subset (c, offset, this, out) here because
-      //OTS doesn't allow null offset.
-      //See issue: https://github.com/khaledhosny/ots/issues/172
+      //skip empty coverage
       c->serializer->push ();
-      c->dispatch (this+offset);
+      bool res = false;
+      if (offset) res = c->dispatch (this+offset);
+      if (!res)
+      {
+        c->serializer->pop_discard ();
+        c->serializer->revert (snap);
+        (out->coverage.len)--;
+        continue;
+      }
       c->serializer->add_link (*o, c->serializer->pop_pack ());
     }
 
@@ -513,6 +535,15 @@ struct MarkGlyphSets
     }
   }
 
+  void collect_used_mark_sets (const hb_set_t& glyph_set,
+                               hb_set_t& used_mark_sets /* OUT */) const
+  {
+    switch (u.format) {
+    case 1: u.format1.collect_used_mark_sets (glyph_set, used_mark_sets); return;
+    default:return;
+    }
+  }
+
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
@@ -526,6 +557,7 @@ struct MarkGlyphSets
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
+    hb_barrier ();
     switch (u.format) {
     case 1: return_trace (u.format1.sanitize (c));
     default:return_trace (true);
@@ -577,7 +609,7 @@ struct GDEFVersion1_2
                                          * definitions--from beginning of GDEF
                                          * header (may be NULL).  Introduced
                                          * in version 0x00010002. */
-  Offset32To<VariationStore>
+  Offset32To<ItemVariationStore>
                 varStore;               /* Offset to the table of Item Variation
                                          * Store--from beginning of GDEF
                                          * header (may be NULL).  Introduced
@@ -600,8 +632,9 @@ struct GDEFVersion1_2
                   attachList.sanitize (c, this) &&
                   ligCaretList.sanitize (c, this) &&
                   markAttachClassDef.sanitize (c, this) &&
-                  (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
-                  (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
+                  hb_barrier () &&
+                  ((version.to_int () < 0x00010002u && hb_barrier ()) || markGlyphSetsDef.sanitize (c, this)) &&
+                  ((version.to_int () < 0x00010003u && hb_barrier ()) || varStore.sanitize (c, this)));
   }
 
   static void remap_varidx_after_instantiation (const hb_map_t& varidx_map,
@@ -627,23 +660,23 @@ struct GDEFVersion1_2
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    auto *out = c->serializer->embed (*this);
-    if (unlikely (!out)) return_trace (false);
-
-    bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);
-    bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
-    bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
-    bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true);
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
 
-    bool subset_markglyphsetsdef = false;
-    if (version.to_int () >= 0x00010002u)
-    {
-      subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this);
-    }
+    // Push var store first (if it's needed) so that it's last in the
+    // serialization order. Some font consumers assume that varstore runs to
+    // the end of the GDEF table.
+    // See: https://github.com/harfbuzz/harfbuzz/issues/4636
+    auto snapshot_version0 = c->serializer->snapshot ();
+    if (unlikely (version.to_int () >= 0x00010002u && hb_barrier () && !c->serializer->embed (markGlyphSetsDef)))
+      return_trace (false);
 
     bool subset_varstore = false;
-    if (version.to_int () >= 0x00010003u)
+    unsigned varstore_index = (unsigned) -1;
+    auto snapshot_version2 = c->serializer->snapshot ();
+    if (version.to_int () >= 0x00010003u && hb_barrier ())
     {
+      if (unlikely (!c->serializer->embed (varStore))) return_trace (false);
       if (c->plan->all_axes_pinned)
         out->varStore = 0;
       else if (c->plan->normalized_coords)
@@ -652,27 +685,56 @@ struct GDEFVersion1_2
         {
           item_variations_t item_vars;
           if (item_vars.instantiate (this+varStore, c->plan, true, true,
-                                     c->plan->gdef_varstore_inner_maps.as_array ()))
+                                     c->plan->gdef_varstore_inner_maps.as_array ())) {
             subset_varstore = out->varStore.serialize_serialize (c->serializer,
                                                                  item_vars.has_long_word (),
                                                                  c->plan->axis_tags,
                                                                  item_vars.get_region_list (),
                                                                  item_vars.get_vardata_encodings ());
+            varstore_index = c->serializer->last_added_child_index();
+          }
           remap_varidx_after_instantiation (item_vars.get_varidx_map (),
                                             c->plan->layout_variation_idx_delta_map);
         }
       }
       else
+      {
         subset_varstore = out->varStore.serialize_subset (c, varStore, this, c->plan->gdef_varstore_inner_maps.as_array ());
+        varstore_index = c->serializer->last_added_child_index();
+      }
+    }
+
+    out->version.major = version.major;
+    out->version.minor = version.minor;
+
+    if (!subset_varstore && version.to_int () >= 0x00010002u) {
+      c->serializer->revert (snapshot_version2);
+    }
+
+    bool subset_markglyphsetsdef = false;
+    if (version.to_int () >= 0x00010002u && hb_barrier ())
+    {
+      subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this);
     }
 
     if (subset_varstore)
     {
       out->version.minor = 3;
+      c->plan->has_gdef_varstore = true;
     } else if (subset_markglyphsetsdef) {
       out->version.minor = 2;
     } else  {
       out->version.minor = 0;
+      c->serializer->revert (snapshot_version0);
+    }
+
+    bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);
+    bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
+    bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true);
+    bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
+
+    if (subset_varstore && varstore_index != (unsigned) -1) {
+      c->serializer->repack_last(varstore_index);
     }
 
     return_trace (subset_glyphclassdef || subset_attachlist ||
@@ -709,6 +771,7 @@ struct GDEF
   {
     TRACE_SANITIZE (this);
     if (unlikely (!u.version.sanitize (c))) return_trace (false);
+    hb_barrier ();
     switch (u.version.major) {
     case 1: return_trace (u.version1.sanitize (c));
 #ifndef HB_NO_BEYOND_64K
@@ -812,7 +875,7 @@ struct GDEF
   bool has_mark_glyph_sets () const
   {
     switch (u.version.major) {
-    case 1: return u.version.to_int () >= 0x00010002u && u.version1.markGlyphSetsDef != 0;
+    case 1: return u.version.to_int () >= 0x00010002u && hb_barrier () && u.version1.markGlyphSetsDef != 0;
 #ifndef HB_NO_BEYOND_64K
     case 2: return u.version2.markGlyphSetsDef != 0;
 #endif
@@ -822,7 +885,7 @@ struct GDEF
   const MarkGlyphSets &get_mark_glyph_sets () const
   {
     switch (u.version.major) {
-    case 1: return u.version.to_int () >= 0x00010002u ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets);
+    case 1: return u.version.to_int () >= 0x00010002u && hb_barrier () ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets);
 #ifndef HB_NO_BEYOND_64K
     case 2: return this+u.version2.markGlyphSetsDef;
 #endif
@@ -832,21 +895,21 @@ struct GDEF
   bool has_var_store () const
   {
     switch (u.version.major) {
-    case 1: return u.version.to_int () >= 0x00010003u && u.version1.varStore != 0;
+    case 1: return u.version.to_int () >= 0x00010003u && hb_barrier () && u.version1.varStore != 0;
 #ifndef HB_NO_BEYOND_64K
     case 2: return u.version2.varStore != 0;
 #endif
     default: return false;
     }
   }
-  const VariationStore &get_var_store () const
+  const ItemVariationStore &get_var_store () const
   {
     switch (u.version.major) {
-    case 1: return u.version.to_int () >= 0x00010003u ? this+u.version1.varStore : Null(VariationStore);
+    case 1: return u.version.to_int () >= 0x00010003u && hb_barrier () ? this+u.version1.varStore : Null(ItemVariationStore);
 #ifndef HB_NO_BEYOND_64K
     case 2: return this+u.version2.varStore;
 #endif
-    default: return Null(VariationStore);
+    default: return Null(ItemVariationStore);
     }
   }
 
@@ -959,47 +1022,6 @@ struct GDEF
   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
   { get_lig_caret_list ().collect_variation_indices (c); }
 
-  void remap_layout_variation_indices (const hb_set_t *layout_variation_indices,
-                                       const hb_vector_t<int>& normalized_coords,
-                                       bool calculate_delta, /* not pinned at default */
-                                       bool no_variations, /* all axes pinned */
-                                       hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map /* OUT */) const
-  {
-    if (!has_var_store ()) return;
-    const VariationStore &var_store = get_var_store ();
-    float *store_cache = var_store.create_cache ();
-
-    unsigned new_major = 0, new_minor = 0;
-    unsigned last_major = (layout_variation_indices->get_min ()) >> 16;
-    for (unsigned idx : layout_variation_indices->iter ())
-    {
-      int delta = 0;
-      if (calculate_delta)
-        delta = roundf (var_store.get_delta (idx, normalized_coords.arrayZ,
-                                             normalized_coords.length, store_cache));
-
-      if (no_variations)
-      {
-        layout_variation_idx_delta_map->set (idx, hb_pair_t<unsigned, int> (HB_OT_LAYOUT_NO_VARIATIONS_INDEX, delta));
-        continue;
-      }
-
-      uint16_t major = idx >> 16;
-      if (major >= var_store.get_sub_table_count ()) break;
-      if (major != last_major)
-      {
-        new_minor = 0;
-        ++new_major;
-      }
-
-      unsigned new_idx = (new_major << 16) + new_minor;
-      layout_variation_idx_delta_map->set (idx, hb_pair_t<unsigned, int> (new_idx, delta));
-      ++new_minor;
-      last_major = major;
-    }
-    var_store.destroy_cache (store_cache);
-  }
-
   protected:
   union {
   FixedVersion<>                version;        /* Version identifier */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Anchor.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Anchor.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Anchor.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Anchor.hh	2025-06-27 08:03:14.000000000 +0000
@@ -25,6 +25,7 @@ struct Anchor
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
+    hb_barrier ();
     switch (u.format) {
     case 1: return_trace (u.format1.sanitize (c));
     case 2: return_trace (u.format2.sanitize (c));
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorFormat3.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorFormat3.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorFormat3.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorFormat3.hh	2025-06-27 08:03:14.000000000 +0000
@@ -38,9 +38,15 @@ struct AnchorFormat3
     *y = font->em_fscale_y (yCoordinate);
 
     if ((font->x_ppem || font->num_coords) && xDeviceTable.sanitize (&c->sanitizer, this))
+    {
+      hb_barrier ();
       *x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache);
+    }
     if ((font->y_ppem || font->num_coords) && yDeviceTable.sanitize (&c->sanitizer, this))
+    {
+      hb_barrier ();
       *y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
+    }
   }
 
   bool subset (hb_subset_context_t *c) const
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorMatrix.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorMatrix.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorMatrix.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorMatrix.hh	2025-06-27 08:03:14.000000000 +0000
@@ -8,7 +8,7 @@ namespace GPOS_impl {
 struct AnchorMatrix
 {
   HBUINT16      rows;                   /* Number of rows */
-  UnsizedArrayOf<Offset16To<Anchor>>
+  UnsizedArrayOf<Offset16To<Anchor, AnchorMatrix>>
                 matrixZ;                /* Matrix of offsets to Anchor tables--
                                          * from beginning of AnchorMatrix table */
   public:
@@ -18,6 +18,7 @@ struct AnchorMatrix
   {
     TRACE_SANITIZE (this);
     if (!c->check_struct (this)) return_trace (false);
+    hb_barrier ();
     if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
     unsigned int count = rows * cols;
     if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
@@ -25,6 +26,7 @@ struct AnchorMatrix
     if (c->lazy_some_gpos)
       return_trace (true);
 
+    hb_barrier ();
     for (unsigned int i = 0; i < count; i++)
       if (!matrixZ[i].sanitize (c, this)) return_trace (false);
     return_trace (true);
@@ -38,6 +40,7 @@ struct AnchorMatrix
     if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
     auto &offset = matrixZ[row * cols + col];
     if (unlikely (!offset.sanitize (&c->sanitizer, this))) return Null (Anchor);
+    hb_barrier ();
     *found = !offset.is_null ();
     return this+offset;
   }
@@ -65,15 +68,14 @@ struct AnchorMatrix
     if (unlikely (!c->serializer->extend_min (out)))  return_trace (false);
 
     out->rows = num_rows;
-    bool ret = false;
     for (const unsigned i : index_iter)
     {
       auto *offset = c->serializer->embed (matrixZ[i]);
       if (!offset) return_trace (false);
-      ret |= offset->serialize_subset (c, matrixZ[i], this);
+      offset->serialize_subset (c, matrixZ[i], this);
     }
 
-    return_trace (ret);
+    return_trace (true);
   }
 };
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Common.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Common.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Common.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Common.hh	2025-06-27 08:03:14.000000000 +0000
@@ -23,7 +23,7 @@ static void SinglePos_serialize (hb_seri
                                  const SrcLookup *src,
                                  Iterator it,
                                  const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
-                                 bool all_axes_pinned);
+                                 unsigned new_format);
 
 
 }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/CursivePosFormat1.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/CursivePosFormat1.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/CursivePosFormat1.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/CursivePosFormat1.hh	2025-06-27 08:03:14.000000000 +0000
@@ -11,21 +11,21 @@ struct EntryExitRecord
 {
   friend struct CursivePosFormat1;
 
-  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const struct CursivePosFormat1 *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
   }
 
   void collect_variation_indices (hb_collect_variation_indices_context_t *c,
-                                  const void *src_base) const
+                                  const struct CursivePosFormat1 *src_base) const
   {
     (src_base+entryAnchor).collect_variation_indices (c);
     (src_base+exitAnchor).collect_variation_indices (c);
   }
 
   bool subset (hb_subset_context_t *c,
-               const void *src_base) const
+               const struct CursivePosFormat1 *src_base) const
   {
     TRACE_SERIALIZE (this);
     auto *out = c->serializer->embed (this);
@@ -38,11 +38,11 @@ struct EntryExitRecord
   }
 
   protected:
-  Offset16To<Anchor>
+  Offset16To<Anchor, struct CursivePosFormat1>
                 entryAnchor;            /* Offset to EntryAnchor table--from
                                          * beginning of CursivePos
                                          * subtable--may be NULL */
-  Offset16To<Anchor>
+  Offset16To<Anchor, struct CursivePosFormat1>
                 exitAnchor;             /* Offset to ExitAnchor table--from
                                          * beginning of CursivePos
                                          * subtable--may be NULL */
@@ -128,6 +128,7 @@ struct CursivePosFormat1
     const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage  (buffer->cur().codepoint)];
     if (!this_record.entryAnchor ||
         unlikely (!this_record.entryAnchor.sanitize (&c->sanitizer, this))) return_trace (false);
+    hb_barrier ();
 
     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset_fast (buffer->idx);
@@ -145,6 +146,7 @@ struct CursivePosFormat1
       buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
       return_trace (false);
     }
+    hb_barrier ();
 
     unsigned int i = skippy_iter.idx;
     unsigned int j = buffer->idx;
@@ -262,7 +264,7 @@ struct CursivePosFormat1
             hb_requires (hb_is_iterator (Iterator))>
   void serialize (hb_subset_context_t *c,
                   Iterator it,
-                  const void *src_base)
+                  const struct CursivePosFormat1 *src_base)
   {
     if (unlikely (!c->serializer->extend_min ((*this)))) return;
     this->format = 1;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/MarkMarkPosFormat1.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/MarkMarkPosFormat1.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/MarkMarkPosFormat1.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/MarkMarkPosFormat1.hh	2025-06-27 08:03:14.000000000 +0000
@@ -42,6 +42,7 @@ struct MarkMarkPosFormat1_2
                   mark1Coverage.sanitize (c, this) &&
                   mark2Coverage.sanitize (c, this) &&
                   mark1Array.sanitize (c, this) &&
+                  hb_barrier () &&
                   mark2Array.sanitize (c, this, (unsigned int) classCount));
   }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh	2025-06-27 08:03:14.000000000 +0000
@@ -36,6 +36,7 @@ struct PairPosFormat1_3
     TRACE_SANITIZE (this);
 
     if (!c->check_struct (this)) return_trace (false);
+    hb_barrier ();
 
     unsigned int len1 = valueFormat[0].get_len ();
     unsigned int len2 = valueFormat[1].get_len ();
@@ -102,12 +103,50 @@ struct PairPosFormat1_3
 
   const Coverage &get_coverage () const { return this+coverage; }
 
-  bool apply (hb_ot_apply_context_t *c) const
+  unsigned cache_cost () const
+  {
+    return (this+coverage).cost ();
+  }
+  static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
+  {
+    switch (op)
+    {
+      case hb_ot_lookup_cache_op_t::CREATE:
+      {
+        hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) hb_malloc (sizeof (hb_ot_lookup_cache_t));
+        if (likely (cache))
+          cache->clear ();
+        return cache;
+      }
+      case hb_ot_lookup_cache_op_t::ENTER:
+        return (void *) true;
+      case hb_ot_lookup_cache_op_t::LEAVE:
+        return nullptr;
+      case hb_ot_lookup_cache_op_t::DESTROY:
+      {
+        hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) p;
+        hb_free (cache);
+        return nullptr;
+      }
+    }
+    return nullptr;
+  }
+
+  bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
+  bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
+  bool _apply (hb_ot_apply_context_t *c, bool cached) const
   {
     TRACE_APPLY (this);
+
     hb_buffer_t *buffer = c->buffer;
+
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+    hb_ot_lookup_cache_t *cache = cached ? (hb_ot_lookup_cache_t *) c->lookup_accel->cache : nullptr;
+    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint, cache);
+#else
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
+#endif
+    if (index == NOT_COVERED) return_trace (false);
 
     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset_fast (buffer->idx);
@@ -131,21 +170,34 @@ struct PairPosFormat1_3
     auto *out = c->serializer->start_embed (*this);
     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
     out->format = format;
-    out->valueFormat[0] = valueFormat[0];
-    out->valueFormat[1] = valueFormat[1];
-    if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
-    {
-      hb_pair_t<unsigned, unsigned> newFormats = compute_effective_value_formats (glyphset);
-      out->valueFormat[0] = newFormats.first;
-      out->valueFormat[1] = newFormats.second;
-    }
 
-    if (c->plan->all_axes_pinned)
+    hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat[0], valueFormat[1]);
+
+    if (c->plan->normalized_coords)
+    {
+      /* all device flags will be dropped when full instancing, no need to strip
+       * hints, also do not strip emtpy cause we don't compute the new default
+       * value during stripping */
+      newFormats = compute_effective_value_formats (glyphset, false, false, &c->plan->layout_variation_idx_delta_map);
+    }
+    /* do not strip hints for VF */
+    else if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
     {
-      out->valueFormat[0] = out->valueFormat[0].drop_device_table_flags ();
-      out->valueFormat[1] = out->valueFormat[1].drop_device_table_flags ();
+      hb_blob_t* blob = hb_face_reference_table (c->plan->source, HB_TAG ('f','v','a','r'));
+      bool has_fvar = (blob != hb_blob_get_empty ());
+      hb_blob_destroy (blob);
+
+      bool strip = !has_fvar;
+      /* special case: strip hints when a VF has no GDEF varstore after
+       * subsetting*/
+      if (has_fvar && !c->plan->has_gdef_varstore)
+        strip = true;
+      newFormats = compute_effective_value_formats (glyphset, strip, true);
     }
 
+    out->valueFormat[0] = newFormats.first;
+    out->valueFormat[1] = newFormats.second;
+
     hb_sorted_vector_t<hb_codepoint_t> new_coverage;
 
     + hb_zip (this+coverage, pairSet)
@@ -175,7 +227,9 @@ struct PairPosFormat1_3
   }
 
 
-  hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset) const
+  hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset,
+                                                                 bool strip_hints, bool strip_empty,
+                                                                 const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map = nullptr) const
   {
     unsigned record_size = PairSet::get_size (valueFormat);
 
@@ -195,8 +249,8 @@ struct PairPosFormat1_3
       {
         if (record->intersects (glyphset))
         {
-          format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 ());
-          format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0]));
+          format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 (), strip_hints, strip_empty, &set, varidx_delta_map);
+          format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0]), strip_hints, strip_empty, &set, varidx_delta_map);
         }
         record = &StructAtOffset<const PairValueRecord> (record, record_size);
       }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat2.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat2.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat2.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat2.hh	2025-06-27 08:03:14.000000000 +0000
@@ -8,7 +8,7 @@ namespace Layout {
 namespace GPOS_impl {
 
 template <typename Types>
-struct PairPosFormat2_4
+struct PairPosFormat2_4 : ValueBase
 {
   protected:
   HBUINT16      format;                 /* Format identifier--format = 2 */
@@ -123,12 +123,61 @@ struct PairPosFormat2_4
 
   const Coverage &get_coverage () const { return this+coverage; }
 
-  bool apply (hb_ot_apply_context_t *c) const
+  struct pair_pos_cache_t
+  {
+    hb_ot_lookup_cache_t coverage;
+    hb_ot_lookup_cache_t first;
+    hb_ot_lookup_cache_t second;
+  };
+
+  unsigned cache_cost () const
+  {
+    return (this+coverage).cost () + (this+classDef1).cost () + (this+classDef2).cost ();
+  }
+  static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
+  {
+    switch (op)
+    {
+      case hb_ot_lookup_cache_op_t::CREATE:
+      {
+        pair_pos_cache_t *cache = (pair_pos_cache_t *) hb_malloc (sizeof (pair_pos_cache_t));
+        if (likely (cache))
+        {
+          cache->coverage.clear ();
+          cache->first.clear ();
+          cache->second.clear ();
+        }
+        return cache;
+      }
+      case hb_ot_lookup_cache_op_t::ENTER:
+        return (void *) true;
+      case hb_ot_lookup_cache_op_t::LEAVE:
+        return nullptr;
+      case hb_ot_lookup_cache_op_t::DESTROY:
+        {
+          pair_pos_cache_t *cache = (pair_pos_cache_t *) p;
+          hb_free (cache);
+          return nullptr;
+        }
+    }
+    return nullptr;
+  }
+
+  bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
+  bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
+  bool _apply (hb_ot_apply_context_t *c, bool cached) const
   {
     TRACE_APPLY (this);
+
     hb_buffer_t *buffer = c->buffer;
+
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+    pair_pos_cache_t *cache = cached ? (pair_pos_cache_t *) c->lookup_accel->cache : nullptr;
+    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
+#else
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
+#endif
+    if (index == NOT_COVERED) return_trace (false);
 
     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset_fast (buffer->idx);
@@ -139,14 +188,13 @@ struct PairPosFormat2_4
       return_trace (false);
     }
 
-    unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
-    if (!klass2)
-    {
-      buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
-      return_trace (false);
-    }
-
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+    unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint, cache ? &cache->first : nullptr);
+    unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint, cache ? &cache->second : nullptr);
+#else
     unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
+    unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
+#endif
     if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
     {
       buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
@@ -287,18 +335,31 @@ struct PairPosFormat2_4
     unsigned len2 = valueFormat2.get_len ();
 
     hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2);
-    if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
-      newFormats = compute_effective_value_formats (klass1_map, klass2_map);
 
-    out->valueFormat1 = newFormats.first;
-    out->valueFormat2 = newFormats.second;
-
-    if (c->plan->all_axes_pinned)
+    if (c->plan->normalized_coords)
     {
-      out->valueFormat1 = out->valueFormat1.drop_device_table_flags ();
-      out->valueFormat2 = out->valueFormat2.drop_device_table_flags ();
+      /* in case of full instancing, all var device flags will be dropped so no
+       * need to strip hints here */
+      newFormats = compute_effective_value_formats (klass1_map, klass2_map, false, false, &c->plan->layout_variation_idx_delta_map);
+    }
+    /* do not strip hints for VF */
+    else if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+    {
+      hb_blob_t* blob = hb_face_reference_table (c->plan->source, HB_TAG ('f','v','a','r'));
+      bool has_fvar = (blob != hb_blob_get_empty ());
+      hb_blob_destroy (blob);
+
+      bool strip = !has_fvar;
+      /* special case: strip hints when a VF has no GDEF varstore after
+       * subsetting*/
+      if (has_fvar && !c->plan->has_gdef_varstore)
+        strip = true;
+      newFormats = compute_effective_value_formats (klass1_map, klass2_map, strip, true);
     }
 
+    out->valueFormat1 = newFormats.first;
+    out->valueFormat2 = newFormats.second;
+
     unsigned total_len = len1 + len2;
     hb_vector_t<unsigned> class2_idxs (+ hb_range ((unsigned) class2Count) | hb_filter (klass2_map));
     for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
@@ -311,22 +372,15 @@ struct PairPosFormat2_4
       }
     }
 
-    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
-    const hb_map_t &glyph_map = *c->plan->glyph_map;
-
-    auto it =
-    + hb_iter (this+coverage)
-    | hb_filter (glyphset)
-    | hb_map_retains_sorting (glyph_map)
-    ;
-
-    out->coverage.serialize_serialize (c->serializer, it);
-    return_trace (out->class1Count && out->class2Count && bool (it));
+    bool ret = out->coverage.serialize_subset(c, coverage, this);
+    return_trace (out->class1Count && out->class2Count && ret);
   }
 
 
   hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_map_t& klass1_map,
-                                                                 const hb_map_t& klass2_map) const
+                                                                 const hb_map_t& klass2_map,
+                                                                 bool strip_hints, bool strip_empty,
+                                                                 const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map = nullptr) const
   {
     unsigned len1 = valueFormat1.get_len ();
     unsigned len2 = valueFormat2.get_len ();
@@ -340,8 +394,8 @@ struct PairPosFormat2_4
       for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
       {
         unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_size;
-        format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
-        format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
+        format1 = format1 | valueFormat1.get_effective_format (&values[idx], strip_hints, strip_empty, this, varidx_delta_map);
+        format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1], strip_hints, strip_empty, this, varidx_delta_map);
       }
 
       if (format1 == valueFormat1 && format2 == valueFormat2)
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairSet.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairSet.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairSet.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairSet.hh	2025-06-27 08:03:14.000000000 +0000
@@ -9,7 +9,7 @@ namespace GPOS_impl {
 
 
 template <typename Types>
-struct PairSet
+struct PairSet : ValueBase
 {
   template <typename Types2>
   friend struct PairPosFormat1_3;
@@ -45,10 +45,12 @@ struct PairSet
   bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
   {
     TRACE_SANITIZE (this);
-    if (!(c->check_struct (this)
-       && c->check_range (&firstPairValueRecord,
+    if (!(c->check_struct (this) &&
+          hb_barrier () &&
+          c->check_range (&firstPairValueRecord,
                           len,
                           closure->stride))) return_trace (false);
+    hb_barrier ();
 
     unsigned int count = len;
     const PairValueRecord *record = &firstPairValueRecord;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairValueRecord.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairValueRecord.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairValueRecord.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairValueRecord.hh	2025-06-27 08:03:14.000000000 +0000
@@ -29,7 +29,7 @@ struct PairValueRecord
 
   struct context_t
   {
-    const void          *base;
+    const ValueBase     *base;
     const ValueFormat   *valueFormats;
     const ValueFormat   *newFormats;
     unsigned            len1; /* valueFormats[0].get_len() */
@@ -62,7 +62,7 @@ struct PairValueRecord
 
   void collect_variation_indices (hb_collect_variation_indices_context_t *c,
                                   const ValueFormat *valueFormats,
-                                  const void *base) const
+                                  const ValueBase *base) const
   {
     unsigned record1_len = valueFormats[0].get_len ();
     unsigned record2_len = valueFormats[1].get_len ();
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePos.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePos.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePos.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePos.hh	2025-06-27 08:03:14.000000000 +0000
@@ -39,14 +39,12 @@ struct SinglePos
                   const SrcLookup* src,
                   Iterator glyph_val_iter_pairs,
                   const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
-                  bool all_axes_pinned)
+                  unsigned newFormat)
   {
     if (unlikely (!c->extend_min (u.format))) return;
     unsigned format = 2;
-    ValueFormat new_format = src->get_value_format ();
-
-    if (all_axes_pinned)
-      new_format = new_format.drop_device_table_flags ();
+    ValueFormat new_format;
+    new_format = newFormat;
 
     if (glyph_val_iter_pairs)
       format = get_format (glyph_val_iter_pairs);
@@ -89,8 +87,8 @@ SinglePos_serialize (hb_serialize_contex
                      const SrcLookup *src,
                      Iterator it,
                      const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
-                     bool all_axes_pinned)
-{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_delta_map, all_axes_pinned); }
+                     unsigned new_format)
+{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_delta_map, new_format); }
 
 
 }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat1.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat1.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat1.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat1.hh	2025-06-27 08:03:14.000000000 +0000
@@ -8,7 +8,7 @@ namespace OT {
 namespace Layout {
 namespace GPOS_impl {
 
-struct SinglePosFormat1
+struct SinglePosFormat1 : ValueBase
 {
   protected:
   HBUINT16      format;                 /* Format identifier--format = 1 */
@@ -28,6 +28,7 @@ struct SinglePosFormat1
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
                   coverage.sanitize (c, this) &&
+                  hb_barrier () &&
                   /* The coverage  table may use a range to represent a set
                    * of glyphs, which means a small number of bytes can
                    * generate a large glyph set. Manually modify the
@@ -66,7 +67,7 @@ struct SinglePosFormat1
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
+    if (index == NOT_COVERED) return_trace (false);
 
     if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
     {
@@ -146,6 +147,30 @@ struct SinglePosFormat1
     hb_set_t intersection;
     (this+coverage).intersect_set (glyphset, intersection);
 
+    unsigned new_format = valueFormat;
+
+    if (c->plan->normalized_coords)
+    {
+      new_format = valueFormat.get_effective_format (values.arrayZ, false, false, this, &c->plan->layout_variation_idx_delta_map);
+    }
+    /* do not strip hints for VF */
+    else if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+    {
+      hb_blob_t* blob = hb_face_reference_table (c->plan->source, HB_TAG ('f','v','a','r'));
+      bool has_fvar = (blob != hb_blob_get_empty ());
+      hb_blob_destroy (blob);
+
+      bool strip = !has_fvar;
+      /* special case: strip hints when a VF has no GDEF varstore after
+       * subsetting*/
+      if (has_fvar && !c->plan->has_gdef_varstore)
+        strip = true;
+      new_format = valueFormat.get_effective_format (values.arrayZ,
+                                                     strip, /* strip hints */
+                                                     true, /* strip empty */
+                                                     this, nullptr);
+    }
+
     auto it =
     + hb_iter (intersection)
     | hb_map_retains_sorting (glyph_map)
@@ -153,7 +178,7 @@ struct SinglePosFormat1
     ;
 
     bool ret = bool (it);
-    SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
+    SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, new_format);
     return_trace (ret);
   }
 };
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat2.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat2.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat2.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat2.hh	2025-06-27 08:03:14.000000000 +0000
@@ -7,7 +7,7 @@ namespace OT {
 namespace Layout {
 namespace GPOS_impl {
 
-struct SinglePosFormat2
+struct SinglePosFormat2 : ValueBase
 {
   protected:
   HBUINT16      format;                 /* Format identifier--format = 2 */
@@ -66,7 +66,7 @@ struct SinglePosFormat2
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
+    if (index == NOT_COVERED) return_trace (false);
 
     if (unlikely (index >= valueCount)) return_trace (false);
 
@@ -143,6 +143,37 @@ struct SinglePosFormat2
     coverage.serialize_serialize (c, glyphs);
   }
 
+  template<typename Iterator,
+      hb_requires (hb_is_iterator (Iterator))>
+  unsigned compute_effective_format (const hb_face_t *face,
+                                     Iterator it,
+                                     bool is_instancing, bool strip_hints,
+                                     bool has_gdef_varstore,
+                                     const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map) const
+  {
+    hb_blob_t* blob = hb_face_reference_table (face, HB_TAG ('f','v','a','r'));
+    bool has_fvar = (blob != hb_blob_get_empty ());
+    hb_blob_destroy (blob);
+
+    unsigned new_format = 0;
+    if (is_instancing)
+    {
+      new_format = new_format | valueFormat.get_effective_format (+ it | hb_map (hb_second), false, false, this, varidx_delta_map);
+    }
+    /* do not strip hints for VF */
+    else if (strip_hints)
+    {
+      bool strip = !has_fvar;
+      if (has_fvar && !has_gdef_varstore)
+        strip = true;
+      new_format = new_format | valueFormat.get_effective_format (+ it | hb_map (hb_second), strip, true, this, nullptr);
+    }
+    else
+      new_format = valueFormat;
+
+    return new_format;
+  }
+
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
@@ -163,8 +194,13 @@ struct SinglePosFormat2
                               })
     ;
 
+    unsigned new_format = compute_effective_format (c->plan->source, it,
+                                                    bool (c->plan->normalized_coords),
+                                                    bool (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING),
+                                                    c->plan->has_gdef_varstore,
+                                                    &c->plan->layout_variation_idx_delta_map);
     bool ret = bool (it);
-    SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
+    SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, new_format);
     return_trace (ret);
   }
 };
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/ValueFormat.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/ValueFormat.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/ValueFormat.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/ValueFormat.hh	2025-06-27 08:03:14.000000000 +0000
@@ -9,6 +9,8 @@ namespace GPOS_impl {
 
 typedef HBUINT16 Value;
 
+struct ValueBase {}; // Dummy base class tag for OffsetTo<Value> bases.
+
 typedef UnsizedArrayOf<Value> ValueRecord;
 
 struct ValueFormat : HBUINT16
@@ -78,7 +80,7 @@ struct ValueFormat : HBUINT16
   }
 
   bool apply_value (hb_ot_apply_context_t *c,
-                    const void            *base,
+                    const ValueBase       *base,
                     const Value           *values,
                     hb_glyph_position_t   &glyph_pos) const
   {
@@ -114,7 +116,7 @@ struct ValueFormat : HBUINT16
 
     if (!use_x_device && !use_y_device) return ret;
 
-    const VariationStore &store = c->var_store;
+    const ItemVariationStore &store = c->var_store;
     auto *cache = c->var_store_cache;
 
     /* pixel -> fractional pixel */
@@ -142,11 +144,29 @@ struct ValueFormat : HBUINT16
     return ret;
   }
 
-  unsigned int get_effective_format (const Value *values) const
+  unsigned int get_effective_format (const Value *values, bool strip_hints, bool strip_empty, const ValueBase *base,
+                                     const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map) const
   {
     unsigned int format = *this;
     for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) {
-      if (format & flag) should_drop (*values++, (Flags) flag, &format);
+      if (format & flag)
+      {
+        if (strip_hints && flag >= xPlaDevice)
+        {
+          format = format & ~flag;
+          values++;
+          continue;
+        }
+        if (varidx_delta_map && flag >= xPlaDevice)
+        {
+          update_var_flag (values++, (Flags) flag, &format, base, varidx_delta_map);
+          continue;
+        }
+        /* do not strip empty when instancing, cause we don't know whether the new
+         * default value is 0 or not */
+        if (strip_empty) should_drop (*values, (Flags) flag, &format);
+        values++;
+      }
     }
 
     return format;
@@ -154,18 +174,19 @@ struct ValueFormat : HBUINT16
 
   template<typename Iterator,
       hb_requires (hb_is_iterator (Iterator))>
-  unsigned int get_effective_format (Iterator it) const {
+  unsigned int get_effective_format (Iterator it, bool strip_hints, bool strip_empty, const ValueBase *base,
+                                     const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map) const {
     unsigned int new_format = 0;
 
     for (const hb_array_t<const Value>& values : it)
-      new_format = new_format | get_effective_format (&values);
+      new_format = new_format | get_effective_format (&values, strip_hints, strip_empty, base, varidx_delta_map);
 
     return new_format;
   }
 
   void copy_values (hb_serialize_context_t *c,
                     unsigned int new_format,
-                    const void *base,
+                    const ValueBase *base,
                     const Value *values,
                     const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
   {
@@ -217,7 +238,7 @@ struct ValueFormat : HBUINT16
   }
 
   void collect_variation_indices (hb_collect_variation_indices_context_t *c,
-                                  const void *base,
+                                  const ValueBase *base,
                                   const hb_array_t<const Value>& values) const
   {
     unsigned format = *this;
@@ -251,17 +272,8 @@ struct ValueFormat : HBUINT16
     }
   }
 
-  unsigned drop_device_table_flags () const
-  {
-    unsigned format = *this;
-    for (unsigned flag = xPlaDevice; flag <= yAdvDevice; flag = flag << 1)
-      format = format & ~flag;
-
-    return format;
-  }
-
   private:
-  bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
+  bool sanitize_value_devices (hb_sanitize_context_t *c, const ValueBase *base, const Value *values) const
   {
     unsigned int format = *this;
 
@@ -278,17 +290,17 @@ struct ValueFormat : HBUINT16
     return true;
   }
 
-  static inline Offset16To<Device>& get_device (Value* value)
+  static inline Offset16To<Device, ValueBase>& get_device (Value* value)
   {
-    return *static_cast<Offset16To<Device> *> (value);
+    return *static_cast<Offset16To<Device, ValueBase> *> (value);
   }
-  static inline const Offset16To<Device>& get_device (const Value* value)
+  static inline const Offset16To<Device, ValueBase>& get_device (const Value* value)
   {
-    return *static_cast<const Offset16To<Device> *> (value);
+    return *static_cast<const Offset16To<Device, ValueBase> *> (value);
   }
   static inline const Device& get_device (const Value* value,
                                           bool *worked,
-                                          const void *base,
+                                          const ValueBase *base,
                                           hb_sanitize_context_t &c)
   {
     if (worked) *worked |= bool (*value);
@@ -296,12 +308,13 @@ struct ValueFormat : HBUINT16
 
     if (unlikely (!offset.sanitize (&c, base)))
       return Null(Device);
+    hb_barrier ();
 
     return base + offset;
   }
 
   void add_delta_to_value (HBINT16 *value,
-                           const void *base,
+                           const ValueBase *base,
                            const Value *src_value,
                            const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
   {
@@ -313,7 +326,8 @@ struct ValueFormat : HBUINT16
     *value += hb_second (*varidx_delta);
   }
 
-  bool copy_device (hb_serialize_context_t *c, const void *base,
+  bool copy_device (hb_serialize_context_t *c,
+                    const ValueBase *base,
                     const Value *src_value,
                     const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
                     unsigned int new_format, Flags flag) const
@@ -354,7 +368,7 @@ struct ValueFormat : HBUINT16
     return (format & devices) != 0;
   }
 
-  bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
+  bool sanitize_value (hb_sanitize_context_t *c, const ValueBase *base, const Value *values) const
   {
     TRACE_SANITIZE (this);
 
@@ -366,7 +380,7 @@ struct ValueFormat : HBUINT16
     return_trace (!has_device () || sanitize_value_devices (c, base, values));
   }
 
-  bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
+  bool sanitize_values (hb_sanitize_context_t *c, const ValueBase *base, const Value *values, unsigned int count) const
   {
     TRACE_SANITIZE (this);
     unsigned size = get_size ();
@@ -376,11 +390,12 @@ struct ValueFormat : HBUINT16
     if (c->lazy_some_gpos)
       return_trace (true);
 
+    hb_barrier ();
     return_trace (sanitize_values_stride_unsafe (c, base, values, count, size));
   }
 
   /* Just sanitize referenced Device tables.  Doesn't check the values themselves. */
-  bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
+  bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const ValueBase *base, const Value *values, unsigned int count, unsigned int stride) const
   {
     TRACE_SANITIZE (this);
 
@@ -403,6 +418,20 @@ struct ValueFormat : HBUINT16
     *format = *format & ~flag;
   }
 
+  void update_var_flag (const Value* value, Flags flag,
+                        unsigned int* format, const ValueBase *base,
+                        const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map) const
+  {
+    if (*value)
+    {
+      unsigned varidx = (base + get_device (value)).get_variation_index ();
+      hb_pair_t<unsigned, int> *varidx_delta;
+      if (varidx_delta_map->has (varidx, &varidx_delta) &&
+          varidx_delta->first != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
+        return;
+    }
+    *format = *format & ~flag;
+  }
 };
 
 }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/AlternateSubstFormat1.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/AlternateSubstFormat1.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/AlternateSubstFormat1.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/AlternateSubstFormat1.hh	2025-06-27 08:03:14.000000000 +0000
@@ -74,7 +74,7 @@ struct AlternateSubstFormat1_2
     TRACE_APPLY (this);
 
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
+    if (index == NOT_COVERED) return_trace (false);
 
     return_trace ((this+alternateSet[index]).apply (c));
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/Ligature.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/Ligature.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/Ligature.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/Ligature.hh	2025-06-27 08:03:14.000000000 +0000
@@ -90,8 +90,17 @@ struct Ligature
 
     unsigned int total_component_count = 0;
 
+    if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return false;
+    unsigned match_positions_stack[4];
+    unsigned *match_positions = match_positions_stack;
+    if (unlikely (count > ARRAY_LENGTH (match_positions_stack)))
+    {
+      match_positions = (unsigned *) hb_malloc (hb_max (count, 1u) * sizeof (unsigned));
+      if (unlikely (!match_positions))
+        return_trace (false);
+    }
+
     unsigned int match_end = 0;
-    unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
 
     if (likely (!match_input (c, count,
                               &component[1],
@@ -102,6 +111,8 @@ struct Ligature
                               &total_component_count)))
     {
       c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
+      if (match_positions != match_positions_stack)
+        hb_free (match_positions);
       return_trace (false);
     }
 
@@ -145,6 +156,8 @@ struct Ligature
                           pos);
     }
 
+    if (match_positions != match_positions_stack)
+      hb_free (match_positions);
     return_trace (true);
   }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSubstFormat1.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSubstFormat1.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSubstFormat1.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSubstFormat1.hh	2025-06-27 08:03:14.000000000 +0000
@@ -78,12 +78,49 @@ struct LigatureSubstFormat1_2
     return lig_set.would_apply (c);
   }
 
-  bool apply (hb_ot_apply_context_t *c) const
+  unsigned cache_cost () const
+  {
+    return (this+coverage).cost ();
+  }
+  static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
+  {
+    switch (op)
+    {
+      case hb_ot_lookup_cache_op_t::CREATE:
+      {
+        hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) hb_malloc (sizeof (hb_ot_lookup_cache_t));
+        if (likely (cache))
+          cache->clear ();
+        return cache;
+      }
+      case hb_ot_lookup_cache_op_t::ENTER:
+        return (void *) true;
+      case hb_ot_lookup_cache_op_t::LEAVE:
+        return nullptr;
+      case hb_ot_lookup_cache_op_t::DESTROY:
+      {
+        hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) p;
+        hb_free (cache);
+        return nullptr;
+      }
+    }
+    return nullptr;
+  }
+
+  bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
+  bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
+  bool _apply (hb_ot_apply_context_t *c, bool cached) const
   {
     TRACE_APPLY (this);
+    hb_buffer_t *buffer = c->buffer;
 
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+    hb_ot_lookup_cache_t *cache = cached ? (hb_ot_lookup_cache_t *) c->lookup_accel->cache : nullptr;
+    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint, cache);
+#else
+    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
+#endif
+    if (index == NOT_COVERED) return_trace (false);
 
     const auto &lig_set = this+ligatureSet[index];
     return_trace (lig_set.apply (c));
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/MultipleSubstFormat1.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/MultipleSubstFormat1.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/MultipleSubstFormat1.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/MultipleSubstFormat1.hh	2025-06-27 08:03:14.000000000 +0000
@@ -66,7 +66,7 @@ struct MultipleSubstFormat1_2
     TRACE_APPLY (this);
 
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
+    if (index == NOT_COVERED) return_trace (false);
 
     return_trace ((this+sequence[index]).apply (c));
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh	2025-06-27 08:03:14.000000000 +0000
@@ -33,9 +33,11 @@ struct ReverseChainSingleSubstFormat1
     TRACE_SANITIZE (this);
     if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
       return_trace (false);
+    hb_barrier ();
     const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
     if (!lookahead.sanitize (c, this))
       return_trace (false);
+    hb_barrier ();
     const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
     return_trace (substitute.sanitize (c));
   }
@@ -109,12 +111,12 @@ struct ReverseChainSingleSubstFormat1
   bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
+    if (index == NOT_COVERED) return_trace (false);
+
     if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
       return_trace (false); /* No chaining to this type */
 
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
     const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
     const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat1.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat1.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat1.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat1.hh	2025-06-27 08:03:14.000000000 +0000
@@ -128,7 +128,7 @@ struct SingleSubstFormat1_3
     TRACE_APPLY (this);
     hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
     unsigned int index = (this+coverage).get_coverage (glyph_id);
-    if (likely (index == NOT_COVERED)) return_trace (false);
+    if (index == NOT_COVERED) return_trace (false);
 
     hb_codepoint_t d = deltaGlyphID;
     hb_codepoint_t mask = get_mask ();
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat2.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat2.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat2.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat2.hh	2025-06-27 08:03:14.000000000 +0000
@@ -104,7 +104,7 @@ struct SingleSubstFormat2_4
   {
     TRACE_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
+    if (index == NOT_COVERED) return_trace (false);
 
     if (unlikely (index >= substitute.len)) return_trace (false);
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/types.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/types.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/types.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Layout/types.hh	2025-06-27 08:03:14.000000000 +0000
@@ -29,6 +29,9 @@
 #ifndef OT_LAYOUT_TYPES_HH
 #define OT_LAYOUT_TYPES_HH
 
+using hb_ot_lookup_cache_t = hb_cache_t<15, 8, 7>;
+static_assert (sizeof (hb_ot_lookup_cache_t) == 256, "");
+
 namespace OT {
 namespace Layout {
 
@@ -38,8 +41,8 @@ struct SmallTypes {
   using HBUINT = HBUINT16;
   using HBGlyphID = HBGlyphID16;
   using Offset = Offset16;
-  template <typename Type, bool has_null=true>
-  using OffsetTo = OT::Offset16To<Type, has_null>;
+  template <typename Type, typename BaseType=void, bool has_null=true>
+  using OffsetTo = OT::Offset16To<Type, BaseType, has_null>;
   template <typename Type>
   using ArrayOf = OT::Array16Of<Type>;
   template <typename Type>
@@ -52,8 +55,8 @@ struct MediumTypes {
   using HBUINT = HBUINT24;
   using HBGlyphID = HBGlyphID24;
   using Offset = Offset24;
-  template <typename Type, bool has_null=true>
-  using OffsetTo = OT::Offset24To<Type, has_null>;
+  template <typename Type, typename BaseType=void, bool has_null=true>
+  using OffsetTo = OT::Offset24To<Type, BaseType, has_null>;
   template <typename Type>
   using ArrayOf = OT::Array24Of<Type>;
   template <typename Type>
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,218 @@
+#ifndef OT_VAR_VARC_VARC_HH
+#define OT_VAR_VARC_VARC_HH
+
+#include "../../../hb-decycler.hh"
+#include "../../../hb-geometry.hh"
+#include "../../../hb-ot-layout-common.hh"
+#include "../../../hb-ot-glyf-table.hh"
+#include "../../../hb-ot-cff2-table.hh"
+#include "../../../hb-ot-cff1-table.hh"
+
+#include "coord-setter.hh"
+
+namespace OT {
+
+//namespace Var {
+
+/*
+ * VARC -- Variable Composites
+ * https://github.com/harfbuzz/boring-expansion-spec/blob/main/VARC.md
+ */
+
+#ifndef HB_NO_VAR_COMPOSITES
+
+struct VarComponent
+{
+  enum class flags_t : uint32_t
+  {
+    RESET_UNSPECIFIED_AXES      = 1u << 0,
+    HAVE_AXES                   = 1u << 1,
+    AXIS_VALUES_HAVE_VARIATION  = 1u << 2,
+    TRANSFORM_HAS_VARIATION     = 1u << 3,
+    HAVE_TRANSLATE_X            = 1u << 4,
+    HAVE_TRANSLATE_Y            = 1u << 5,
+    HAVE_ROTATION               = 1u << 6,
+    HAVE_CONDITION              = 1u << 7,
+    HAVE_SCALE_X                = 1u << 8,
+    HAVE_SCALE_Y                = 1u << 9,
+    HAVE_TCENTER_X              = 1u << 10,
+    HAVE_TCENTER_Y              = 1u << 11,
+    GID_IS_24BIT                = 1u << 12,
+    HAVE_SKEW_X                 = 1u << 13,
+    HAVE_SKEW_Y                 = 1u << 14,
+    RESERVED_MASK               = ~((1u << 15) - 1),
+  };
+
+  HB_INTERNAL hb_ubytes_t
+  get_path_at (hb_font_t *font,
+               hb_codepoint_t parent_gid,
+               hb_draw_session_t &draw_session,
+               hb_array_t<const int> 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,
+               hb_array_t<const int> 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)
+  {
+    while (record)
+    {
+      const VarComponent &comp = * (const VarComponent *) (record.arrayZ);
+      record = comp.get_path_at (font, glyph,
+                                 draw_session, coords, transform,
+                                 record,
+                                 decycler, edges_left, depth_left, scratch, cache);
+    }
+  }
+};
+
+HB_MARK_AS_FLAG_T (VarComponent::flags_t);
+
+struct VARC
+{
+  friend struct VarComponent;
+
+  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,
+               hb_array_t<const int> 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;
+
+  bool
+  get_path (hb_font_t *font,
+            hb_codepoint_t gid,
+            hb_draw_session_t &draw_session,
+            hb_glyf_scratch_t &scratch) const
+  {
+    hb_decycler_t decycler;
+    signed edges = HB_MAX_GRAPH_EDGE_COUNT;
+
+    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);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+                  hb_barrier () &&
+                  version.major == 1 &&
+                  coverage.sanitize (c, this) &&
+                  varStore.sanitize (c, this) &&
+                  conditionList.sanitize (c, this) &&
+                  axisIndicesList.sanitize (c, this) &&
+                  glyphRecords.sanitize (c, this));
+  }
+
+  struct accelerator_t
+  {
+    friend struct VarComponent;
+
+    accelerator_t (hb_face_t *face)
+    {
+      table = hb_sanitize_context_t ().reference_table<VARC> (face);
+    }
+    ~accelerator_t ()
+    {
+      auto *scratch = cached_scratch.get_relaxed ();
+      if (scratch)
+      {
+        scratch->~hb_glyf_scratch_t ();
+        hb_free (scratch);
+      }
+
+      table.destroy ();
+    }
+
+    bool
+    get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
+    {
+      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;
+        }
+      }
+
+      bool ret = table->get_path (font, gid, draw_session, *scratch);
+
+      // Put it back.
+      if (!cached_scratch.cmpexch (nullptr, scratch))
+      {
+        scratch->~hb_glyf_scratch_t ();
+        hb_free (scratch);
+      }
+
+      return ret;
+    }
+
+    private:
+    hb_blob_ptr_t<VARC> table;
+    hb_atomic_ptr_t<hb_glyf_scratch_t> cached_scratch;
+  };
+
+  bool has_data () const { return version.major != 0; }
+
+  protected:
+  FixedVersion<> version; /* Version identifier */
+  Offset32To<Coverage> coverage;
+  Offset32To<MultiItemVariationStore> varStore;
+  Offset32To<ConditionList> conditionList;
+  Offset32To<TupleList> axisIndicesList;
+  Offset32To<CFF2Index/*Of<VarCompositeGlyph>*/> glyphRecords;
+  public:
+  DEFINE_SIZE_STATIC (24);
+};
+
+struct VARC_accelerator_t : VARC::accelerator_t {
+  VARC_accelerator_t (hb_face_t *face) : VARC::accelerator_t (face) {}
+};
+
+#endif
+
+//}
+
+}
+
+#endif  /* OT_VAR_VARC_VARC_HH */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/coord-setter.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/coord-setter.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/coord-setter.hh	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/coord-setter.hh	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,63 @@
+#ifndef OT_VAR_VARC_COORD_SETTER_HH
+#define OT_VAR_VARC_COORD_SETTER_HH
+
+
+#include "../../../hb.hh"
+
+
+namespace OT {
+//namespace Var {
+
+
+struct coord_setter_t
+{
+  coord_setter_t (hb_array_t<const int> coords_)
+  {
+    length = coords_.length;
+    if (length <= ARRAY_LENGTH (static_coords))
+      hb_memcpy (static_coords, coords_.arrayZ, length * sizeof (int));
+    else
+      dynamic_coords.extend (coords_);
+  }
+
+  int& operator [] (unsigned idx)
+  {
+    if (unlikely (idx >= HB_VAR_COMPOSITE_MAX_AXES))
+      return Crap(int);
+
+    if (length <= ARRAY_LENGTH (static_coords))
+    {
+      if (idx < ARRAY_LENGTH (static_coords))
+      {
+        while (length <= idx)
+          static_coords[length++] = 0;
+        return static_coords[idx];
+      }
+      else
+        dynamic_coords.extend (hb_array (static_coords, length));
+    }
+
+    if (dynamic_coords.length <= idx)
+    {
+      if (unlikely (!dynamic_coords.resize (idx + 1)))
+        return Crap(int);
+      length = idx + 1;
+    }
+    return dynamic_coords.arrayZ[idx];
+  }
+
+  hb_array_t<int> get_coords ()
+  { return length <= ARRAY_LENGTH (static_coords) ? hb_array (static_coords, length) : dynamic_coords.as_array (); }
+
+  private:
+  hb_vector_t<int> dynamic_coords;
+  unsigned length;
+  int static_coords[sizeof (void *) * 8];
+};
+
+
+//} // namespace Var
+
+} // namespace OT
+
+#endif /* OT_VAR_VARC_COORD_SETTER_HH */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/CompositeGlyph.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/CompositeGlyph.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/CompositeGlyph.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/CompositeGlyph.hh	2025-06-27 08:03:14.000000000 +0000
@@ -143,7 +143,7 @@ struct CompositeGlyphRecord
     float matrix[4];
     contour_point_t trans;
     get_transformation (matrix, trans);
-    if (unlikely (!points.alloc (points.length + 4))) return false; // For phantom points
+    if (unlikely (!points.alloc (points.length + 1 + 4))) return false; // For phantom points
     points.push (trans);
     return true;
   }
@@ -240,7 +240,8 @@ struct CompositeGlyphRecord
     }
     if (is_anchored ()) tx = ty = 0;
 
-    trans.init ((float) tx, (float) ty);
+    /* set is_end_point flag to true, used by IUP delta optimization */
+    trans.init ((float) tx, (float) ty, true);
 
     {
       const F2DOT14 *points = (const F2DOT14 *) p;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/Glyph.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/Glyph.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/Glyph.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/Glyph.hh	2025-06-27 08:03:14.000000000 +0000
@@ -7,8 +7,6 @@
 #include "GlyphHeader.hh"
 #include "SimpleGlyph.hh"
 #include "CompositeGlyph.hh"
-#include "VarCompositeGlyph.hh"
-#include "coord-setter.hh"
 
 
 namespace OT {
@@ -33,9 +31,6 @@ struct Glyph
     EMPTY,
     SIMPLE,
     COMPOSITE,
-#ifndef HB_NO_VAR_COMPOSITES
-    VAR_COMPOSITE,
-#endif
   };
 
   public:
@@ -44,22 +39,10 @@ struct Glyph
     if (type != COMPOSITE) return composite_iter_t ();
     return CompositeGlyph (*header, bytes).iter ();
   }
-  var_composite_iter_t get_var_composite_iterator () const
-  {
-#ifndef HB_NO_VAR_COMPOSITES
-    if (type != VAR_COMPOSITE) return var_composite_iter_t ();
-    return VarCompositeGlyph (*header, bytes).iter ();
-#else
-    return var_composite_iter_t ();
-#endif
-  }
 
   const hb_bytes_t trim_padding () const
   {
     switch (type) {
-#ifndef HB_NO_VAR_COMPOSITES
-    case VAR_COMPOSITE: return VarCompositeGlyph (*header, bytes).trim_padding ();
-#endif
     case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
     case SIMPLE:    return SimpleGlyph (*header, bytes).trim_padding ();
     case EMPTY:     return bytes;
@@ -70,9 +53,6 @@ struct Glyph
   void drop_hints ()
   {
     switch (type) {
-#ifndef HB_NO_VAR_COMPOSITES
-    case VAR_COMPOSITE: return; // No hinting
-#endif
     case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
     case SIMPLE:    SimpleGlyph (*header, bytes).drop_hints (); return;
     case EMPTY:     return;
@@ -82,9 +62,6 @@ struct Glyph
   void set_overlaps_flag ()
   {
     switch (type) {
-#ifndef HB_NO_VAR_COMPOSITES
-    case VAR_COMPOSITE: return; // No overlaps flag
-#endif
     case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
     case SIMPLE:    SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
     case EMPTY:     return;
@@ -94,15 +71,15 @@ struct Glyph
   void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
   {
     switch (type) {
-#ifndef HB_NO_VAR_COMPOSITES
-    case VAR_COMPOSITE: return; // No hinting
-#endif
     case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
     case SIMPLE:    SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
     case EMPTY:     return;
     }
   }
 
+  bool is_composite () const
+  { return type == COMPOSITE; }
+
   bool get_all_points_without_var (const hb_face_t *face,
                                    contour_point_vector_t &points /* OUT */) const
   {
@@ -117,14 +94,6 @@ struct Glyph
         if (unlikely (!item.get_points (points))) return false;
       break;
     }
-#ifndef HB_NO_VAR_COMPOSITES
-    case VAR_COMPOSITE:
-    {
-      for (auto &item : get_var_composite_iterator ())
-        if (unlikely (!item.get_points (points))) return false;
-      break;
-    }
-#endif
     case EMPTY:
       break;
     }
@@ -282,7 +251,8 @@ struct Glyph
       composite_contours_p = nullptr;
     }
 
-    if (!get_points (font, glyf, all_points, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false))
+    hb_glyf_scratch_t scratch;
+    if (!get_points (font, glyf, all_points, scratch, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false))
       return false;
 
     // .notdef, set type to empty so we only update metrics and don't compile bytes for
@@ -300,13 +270,6 @@ struct Glyph
     {
       switch (type)
       {
-#ifndef HB_NO_VAR_COMPOSITES
-      case VAR_COMPOSITE:
-        // TODO
-        dest_end = hb_bytes_t ();
-        break;
-#endif
-
       case COMPOSITE:
         if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start,
                                                                         points_with_deltas,
@@ -343,27 +306,23 @@ struct Glyph
   template <typename accelerator_t>
   bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
                    contour_point_vector_t &all_points /* OUT */,
+                   hb_glyf_scratch_t &scratch,
                    contour_point_vector_t *points_with_deltas = nullptr, /* OUT */
                    head_maxp_info_t * head_maxp_info = nullptr, /* OUT */
                    unsigned *composite_contours = nullptr, /* OUT */
                    bool shift_points_hori = true,
                    bool use_my_metrics = true,
                    bool phantom_only = false,
-                   hb_array_t<int> coords = hb_array_t<int> (),
-                   hb_map_t *current_glyphs = nullptr,
+                   hb_array_t<const int> coords = hb_array_t<const int> (),
                    unsigned int depth = 0,
                    unsigned *edge_count = nullptr) const
   {
     if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
     unsigned stack_edge_count = 0;
     if (!edge_count) edge_count = &stack_edge_count;
-    if (unlikely (*edge_count > HB_GLYF_MAX_EDGE_COUNT)) return false;
+    if (unlikely (*edge_count > HB_MAX_GRAPH_EDGE_COUNT)) return false;
     (*edge_count)++;
 
-    hb_map_t current_glyphs_stack;
-    if (current_glyphs == nullptr)
-      current_glyphs = &current_glyphs_stack;
-
     if (head_maxp_info)
     {
       head_maxp_info->maxComponentDepth = hb_max (head_maxp_info->maxComponentDepth, depth);
@@ -372,8 +331,7 @@ struct Glyph
     if (!coords)
       coords = hb_array (font->coords, font->num_coords);
 
-    contour_point_vector_t stack_points;
-    contour_point_vector_t &points = type == SIMPLE ? all_points : stack_points;
+    contour_point_vector_t &points = type == SIMPLE ? all_points : scratch.comp_points;
     unsigned old_length = points.length;
 
     switch (type) {
@@ -391,14 +349,6 @@ struct Glyph
         if (unlikely (!item.get_points (points))) return false;
       break;
     }
-#ifndef HB_NO_VAR_COMPOSITES
-    case VAR_COMPOSITE:
-    {
-      for (auto &item : get_var_composite_iterator ())
-        if (unlikely (!item.get_points (points))) return false;
-      break;
-    }
-#endif
     case EMPTY:
       break;
     }
@@ -434,36 +384,53 @@ struct Glyph
 
 #ifndef HB_NO_VAR
     if (coords)
-      glyf_accelerator.gvar->apply_deltas_to_points (gid,
-                                                     coords,
-                                                     points.as_array ().sub_array (old_length),
-                                                     phantom_only && type == SIMPLE);
+    {
+#ifndef HB_NO_BEYOND_64K
+      if (glyf_accelerator.GVAR->has_data ())
+        glyf_accelerator.GVAR->apply_deltas_to_points (gid,
+                                                       coords,
+                                                       points.as_array ().sub_array (old_length),
+                                                       scratch,
+                                                       phantom_only && type == SIMPLE);
+      else
+#endif
+        glyf_accelerator.gvar->apply_deltas_to_points (gid,
+                                                       coords,
+                                                       points.as_array ().sub_array (old_length),
+                                                       scratch,
+                                                       phantom_only && type == SIMPLE);
+    }
 #endif
 
     // mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
     // with child glyphs' points
     if (points_with_deltas != nullptr && depth == 0 && type == COMPOSITE)
     {
-      if (unlikely (!points_with_deltas->resize (points.length))) return false;
+      assert (old_length == 0);
       *points_with_deltas = points;
     }
 
+    float shift = 0;
     switch (type) {
     case SIMPLE:
       if (depth == 0 && head_maxp_info)
         head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, all_points.length - old_length - 4);
+      shift = phantoms[PHANTOM_LEFT].x;
       break;
     case COMPOSITE:
     {
+      hb_decycler_node_t decycler_node (scratch.decycler);
+
       unsigned int comp_index = 0;
       for (auto &item : get_composite_iterator ())
       {
         hb_codepoint_t item_gid = item.get_gid ();
 
-        if (unlikely (current_glyphs->has (item_gid)))
+        if (unlikely (!decycler_node.visit (item_gid)))
+        {
+          comp_index++;
           continue;
-
-        current_glyphs->add (item_gid);
+        }
 
         unsigned old_count = all_points.length;
 
@@ -472,6 +439,7 @@ struct Glyph
                                        .get_points (font,
                                                     glyf_accelerator,
                                                     all_points,
+                                                    scratch,
                                                     points_with_deltas,
                                                     head_maxp_info,
                                                     composite_contours,
@@ -479,14 +447,16 @@ struct Glyph
                                                     use_my_metrics,
                                                     phantom_only,
                                                     coords,
-                                                    current_glyphs,
                                                     depth + 1,
                                                     edge_count)))
         {
-          current_glyphs->del (item_gid);
+          points.resize (old_length);
           return false;
         }
 
+        // points might have been reallocated. Relocate phantoms.
+        phantoms = points.as_array ().sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
+
         auto comp_points = all_points.as_array ().sub_array (old_count);
 
         /* Copy phantom points from component if USE_MY_METRICS flag set */
@@ -501,7 +471,7 @@ struct Glyph
           item.get_transformation (matrix, default_trans);
 
           /* Apply component transformation & translation (with deltas applied) */
-          item.transform_points (comp_points, matrix, points[comp_index]);
+          item.transform_points (comp_points, matrix, points[old_length + comp_index]);
         }
 
         if (item.is_anchored () && !phantom_only)
@@ -522,12 +492,11 @@ struct Glyph
 
         if (all_points.length > HB_GLYF_MAX_POINTS)
         {
-          current_glyphs->del (item_gid);
+          points.resize (old_length);
           return false;
         }
 
         comp_index++;
-        current_glyphs->del (item_gid);
       }
 
       if (head_maxp_info && depth == 0)
@@ -538,84 +507,13 @@ struct Glyph
         head_maxp_info->maxComponentElements = hb_max (head_maxp_info->maxComponentElements, comp_index);
       }
       all_points.extend (phantoms);
+      shift = phantoms[PHANTOM_LEFT].x;
+      points.resize (old_length);
     } break;
-#ifndef HB_NO_VAR_COMPOSITES
-    case VAR_COMPOSITE:
-    {
-      hb_array_t<contour_point_t> points_left = points.as_array ();
-      for (auto &item : get_var_composite_iterator ())
-      {
-        hb_codepoint_t item_gid = item.get_gid ();
-
-        if (unlikely (current_glyphs->has (item_gid)))
-          continue;
-
-        current_glyphs->add (item_gid);
-
-        unsigned item_num_points = item.get_num_points ();
-        hb_array_t<contour_point_t> record_points = points_left.sub_array (0, item_num_points);
-        assert (record_points.length == item_num_points);
-
-        auto component_coords = coords;
-        /* Copying coords is expensive; so we have put an arbitrary
-         * limit on the max number of coords for now. */
-        if (item.is_reset_unspecified_axes () ||
-            coords.length > HB_GLYF_VAR_COMPOSITE_MAX_AXES)
-          component_coords = hb_array<int> ();
-
-        coord_setter_t coord_setter (component_coords);
-        item.set_variations (coord_setter, record_points);
-
-        unsigned old_count = all_points.length;
-
-        if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) &&
-                      !glyf_accelerator.glyph_for_gid (item_gid)
-                                       .get_points (font,
-                                                    glyf_accelerator,
-                                                    all_points,
-                                                    points_with_deltas,
-                                                    head_maxp_info,
-                                                    nullptr,
-                                                    shift_points_hori,
-                                                    use_my_metrics,
-                                                    phantom_only,
-                                                    coord_setter.get_coords (),
-                                                    current_glyphs,
-                                                    depth + 1,
-                                                    edge_count)))
-        {
-          current_glyphs->del (item_gid);
-          return false;
-        }
-
-        auto comp_points = all_points.as_array ().sub_array (old_count);
-
-        /* Apply component transformation */
-        if (comp_points) // Empty in case of phantom_only
-          item.transform_points (record_points, comp_points);
-
-        /* Copy phantom points from component if USE_MY_METRICS flag set */
-        if (use_my_metrics && item.is_use_my_metrics ())
-          for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
-            phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
-
-        all_points.resize (all_points.length - PHANTOM_COUNT);
-
-        if (all_points.length > HB_GLYF_MAX_POINTS)
-        {
-          current_glyphs->del (item_gid);
-          return false;
-        }
-
-        points_left += item_num_points;
-
-        current_glyphs->del (item_gid);
-      }
-      all_points.extend (phantoms);
-    } break;
-#endif
     case EMPTY:
       all_points.extend (phantoms);
+      shift = phantoms[PHANTOM_LEFT].x;
+      points.resize (old_length);
       break;
     }
 
@@ -624,10 +522,9 @@ struct Glyph
       /* Undocumented rasterizer behavior:
        * Shift points horizontally by the updated left side bearing
        */
-      int v = -phantoms[PHANTOM_LEFT].x;
-      if (v)
+      if (shift)
         for (auto &point : all_points)
-          point.x += v;
+          point.x -= shift;
     }
 
     return !all_points.in_error ();
@@ -658,10 +555,7 @@ struct Glyph
     int num_contours = header->numberOfContours;
     if (unlikely (num_contours == 0)) type = EMPTY;
     else if (num_contours > 0) type = SIMPLE;
-    else if (num_contours == -1) type = COMPOSITE;
-#ifndef HB_NO_VAR_COMPOSITES
-    else if (num_contours == -2) type = VAR_COMPOSITE;
-#endif
+    else if (num_contours <= -1) type = COMPOSITE;
     else type = EMPTY; // Spec deviation; Spec says COMPOSITE, but not seen in the wild.
   }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/SimpleGlyph.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/SimpleGlyph.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/SimpleGlyph.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/SimpleGlyph.hh	2025-06-27 08:03:14.000000000 +0000
@@ -127,19 +127,20 @@ struct SimpleGlyph
                           hb_array_t<contour_point_t> points_ /* IN/OUT */,
                           const HBUINT8 *end)
   {
+    auto *points = points_.arrayZ;
     unsigned count = points_.length;
     for (unsigned int i = 0; i < count;)
     {
       if (unlikely (p + 1 > end)) return false;
       uint8_t flag = *p++;
-      points_.arrayZ[i++].flag = flag;
+      points[i++].flag = flag;
       if (flag & FLAG_REPEAT)
       {
         if (unlikely (p + 1 > end)) return false;
         unsigned int repeat_count = *p++;
         unsigned stop = hb_min (i + repeat_count, count);
         for (; i < stop; i++)
-          points_.arrayZ[i].flag = flag;
+          points[i].flag = flag;
       }
     }
     return true;
@@ -160,10 +161,7 @@ struct SimpleGlyph
       if (flag & short_flag)
       {
         if (unlikely (p + 1 > end)) return false;
-        if (flag & same_flag)
-          v += *p++;
-        else
-          v -= *p++;
+        v += (bool(flag & same_flag) * 2 - 1) * *p++;
       }
       else
       {
@@ -190,7 +188,7 @@ struct SimpleGlyph
     unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
 
     unsigned old_length = points.length;
-    points.alloc (points.length + num_points + 4, true); // Allocate for phantom points, to avoid a possible copy
+    points.alloc (points.length + num_points + 4); // Allocate for phantom points, to avoid a possible copy
     if (unlikely (!points.resize (points.length + num_points, false))) return false;
     auto points_ = points.as_array ().sub_array (old_length);
     if (!phantom_only)
@@ -281,9 +279,9 @@ struct SimpleGlyph
     unsigned num_points = all_points.length - 4;
 
     hb_vector_t<uint8_t> flags, x_coords, y_coords;
-    if (unlikely (!flags.alloc (num_points, true))) return false;
-    if (unlikely (!x_coords.alloc (2*num_points, true))) return false;
-    if (unlikely (!y_coords.alloc (2*num_points, true))) return false;
+    if (unlikely (!flags.alloc_exact (num_points))) return false;
+    if (unlikely (!x_coords.alloc_exact (2*num_points))) return false;
+    if (unlikely (!y_coords.alloc_exact (2*num_points))) return false;
 
     unsigned lastflag = 255, repeat = 0;
     int prev_x = 0, prev_y = 0;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/SubsetGlyph.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/SubsetGlyph.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/SubsetGlyph.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/SubsetGlyph.hh	2025-06-27 08:03:14.000000000 +0000
@@ -53,23 +53,12 @@ struct SubsetGlyph
       if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
         const_cast<CompositeGlyphRecord &> (_).set_gid (new_gid);
     }
-#ifndef HB_NO_VAR_COMPOSITES
-    for (auto &_ : Glyph (dest_glyph).get_var_composite_iterator ())
-    {
-      hb_codepoint_t new_gid;
-      if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
-        const_cast<VarCompositeGlyphRecord &> (_).set_gid (new_gid);
-    }
-#endif
 
 #ifndef HB_NO_BEYOND_64K
     auto it = Glyph (dest_glyph).get_composite_iterator ();
     if (it)
     {
-      /* lower GID24 to GID16 in components if possible.
-       *
-       * TODO: VarComposite. Not as critical, since VarComposite supports
-       * gid24 from the first version. */
+      /* lower GID24 to GID16 in components if possible. */
       char *p = it ? (char *) &*it : nullptr;
       char *q = p;
       const char *end = dest_glyph.arrayZ + dest_glyph.length;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/VarCompositeGlyph.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/VarCompositeGlyph.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/VarCompositeGlyph.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/VarCompositeGlyph.hh	1970-01-01 00:00:00.000000000 +0000
@@ -1,401 +0,0 @@
-#ifndef OT_GLYF_VARCOMPOSITEGLYPH_HH
-#define OT_GLYF_VARCOMPOSITEGLYPH_HH
-
-
-#include "../../hb-open-type.hh"
-#include "coord-setter.hh"
-
-
-namespace OT {
-namespace glyf_impl {
-
-
-struct VarCompositeGlyphRecord
-{
-  protected:
-  enum var_composite_glyph_flag_t
-  {
-    USE_MY_METRICS              = 0x0001,
-    AXIS_INDICES_ARE_SHORT      = 0x0002,
-    UNIFORM_SCALE               = 0x0004,
-    HAVE_TRANSLATE_X            = 0x0008,
-    HAVE_TRANSLATE_Y            = 0x0010,
-    HAVE_ROTATION               = 0x0020,
-    HAVE_SCALE_X                = 0x0040,
-    HAVE_SCALE_Y                = 0x0080,
-    HAVE_SKEW_X                 = 0x0100,
-    HAVE_SKEW_Y                 = 0x0200,
-    HAVE_TCENTER_X              = 0x0400,
-    HAVE_TCENTER_Y              = 0x0800,
-    GID_IS_24BIT                = 0x1000,
-    AXES_HAVE_VARIATION         = 0x2000,
-    RESET_UNSPECIFIED_AXES      = 0x4000,
-  };
-
-  public:
-
-  unsigned int get_size () const
-  {
-    unsigned fl = flags;
-    unsigned int size = min_size;
-
-    unsigned axis_width = (fl & AXIS_INDICES_ARE_SHORT) ? 4 : 3;
-    size += numAxes * axis_width;
-
-    if (fl & GID_IS_24BIT)      size += 1;
-
-    // 2 bytes each for the following flags
-    fl = fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y |
-               HAVE_ROTATION |
-               HAVE_SCALE_X | HAVE_SCALE_Y |
-               HAVE_SKEW_X | HAVE_SKEW_Y |
-               HAVE_TCENTER_X | HAVE_TCENTER_Y);
-    size += hb_popcount (fl) * 2;
-
-    return size;
-  }
-
-  bool has_more () const { return true; }
-
-  bool is_use_my_metrics () const { return flags & USE_MY_METRICS; }
-  bool is_reset_unspecified_axes () const { return flags & RESET_UNSPECIFIED_AXES; }
-
-  hb_codepoint_t get_gid () const
-  {
-    if (flags & GID_IS_24BIT)
-      return * (const HBGlyphID24 *) &pad;
-    else
-      return * (const HBGlyphID16 *) &pad;
-  }
-
-  void set_gid (hb_codepoint_t gid)
-  {
-    if (flags & GID_IS_24BIT)
-      * (HBGlyphID24 *) &pad = gid;
-    else
-      * (HBGlyphID16 *) &pad = gid;
-  }
-
-  unsigned get_numAxes () const
-  {
-    return numAxes;
-  }
-
-  unsigned get_num_points () const
-  {
-    unsigned fl = flags;
-    unsigned num = 0;
-    if (fl & AXES_HAVE_VARIATION)                       num += numAxes;
-
-    /* Hopefully faster code, relying on the value of the flags. */
-    fl = (((fl & (HAVE_TRANSLATE_Y | HAVE_SCALE_Y | HAVE_SKEW_Y | HAVE_TCENTER_Y)) >> 1) | fl) &
-         (HAVE_TRANSLATE_X | HAVE_ROTATION | HAVE_SCALE_X | HAVE_SKEW_X | HAVE_TCENTER_X);
-    num += hb_popcount (fl);
-    return num;
-
-    /* Slower but more readable code. */
-    if (fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y))     num++;
-    if (fl & HAVE_ROTATION)                             num++;
-    if (fl & (HAVE_SCALE_X | HAVE_SCALE_Y))             num++;
-    if (fl & (HAVE_SKEW_X | HAVE_SKEW_Y))               num++;
-    if (fl & (HAVE_TCENTER_X | HAVE_TCENTER_Y))         num++;
-    return num;
-  }
-
-  void transform_points (hb_array_t<const contour_point_t> record_points,
-                         hb_array_t<contour_point_t> points) const
-  {
-    float matrix[4];
-    contour_point_t trans;
-
-    get_transformation_from_points (record_points.arrayZ, matrix, trans);
-
-    auto arrayZ = points.arrayZ;
-    unsigned count = points.length;
-
-    if (matrix[0] != 1.f || matrix[1] != 0.f ||
-        matrix[2] != 0.f || matrix[3] != 1.f)
-      for (unsigned i = 0; i < count; i++)
-        arrayZ[i].transform (matrix);
-
-    if (trans.x != 0.f || trans.y != 0.f)
-      for (unsigned i = 0; i < count; i++)
-        arrayZ[i].translate (trans);
-  }
-
-  static inline void transform (float (&matrix)[4], contour_point_t &trans,
-                                float (other)[6])
-  {
-    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L268
-    float xx1 = other[0];
-    float xy1 = other[1];
-    float yx1 = other[2];
-    float yy1 = other[3];
-    float dx1 = other[4];
-    float dy1 = other[5];
-    float xx2 = matrix[0];
-    float xy2 = matrix[1];
-    float yx2 = matrix[2];
-    float yy2 = matrix[3];
-    float dx2 = trans.x;
-    float dy2 = trans.y;
-
-    matrix[0] = xx1*xx2 + xy1*yx2;
-    matrix[1] = xx1*xy2 + xy1*yy2;
-    matrix[2] = yx1*xx2 + yy1*yx2;
-    matrix[3] = yx1*xy2 + yy1*yy2;
-    trans.x = xx2*dx1 + yx2*dy1 + dx2;
-    trans.y = xy2*dx1 + yy2*dy1 + dy2;
-  }
-
-  static void translate (float (&matrix)[4], contour_point_t &trans,
-                         float translateX, float translateY)
-  {
-    if (!translateX && !translateY)
-      return;
-
-    trans.x += matrix[0] * translateX + matrix[2] * translateY;
-    trans.y += matrix[1] * translateX + matrix[3] * translateY;
-  }
-
-  static void scale (float (&matrix)[4], contour_point_t &trans,
-                     float scaleX, float scaleY)
-  {
-    if (scaleX == 1.f && scaleY == 1.f)
-      return;
-
-    matrix[0] *= scaleX;
-    matrix[1] *= scaleX;
-    matrix[2] *= scaleY;
-    matrix[3] *= scaleY;
-  }
-
-  static void rotate (float (&matrix)[4], contour_point_t &trans,
-                      float rotation)
-  {
-    if (!rotation)
-      return;
-
-    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
-    rotation = rotation * HB_PI;
-    float c;
-    float s;
-#ifdef HAVE_SINCOSF
-    sincosf (rotation, &s, &c);
-#else
-    c = cosf (rotation);
-    s = sinf (rotation);
-#endif
-    float other[6] = {c, s, -s, c, 0.f, 0.f};
-    transform (matrix, trans, other);
-  }
-
-  static void skew (float (&matrix)[4], contour_point_t &trans,
-                    float skewX, float skewY)
-  {
-    if (!skewX && !skewY)
-      return;
-
-    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
-    skewX = skewX * HB_PI;
-    skewY = skewY * HB_PI;
-    float other[6] = {1.f,
-                      skewY ? tanf (skewY) : 0.f,
-                      skewX ? tanf (skewX) : 0.f,
-                      1.f,
-                      0.f, 0.f};
-    transform (matrix, trans, other);
-  }
-
-  bool get_points (contour_point_vector_t &points) const
-  {
-    unsigned num_points = get_num_points ();
-
-    points.alloc (points.length + num_points + 4); // For phantom points
-    if (unlikely (!points.resize (points.length + num_points, false))) return false;
-    contour_point_t *rec_points = points.arrayZ + (points.length - num_points);
-    hb_memset (rec_points, 0, num_points * sizeof (rec_points[0]));
-
-    unsigned fl = flags;
-
-    unsigned num_axes = numAxes;
-    unsigned axis_width = (fl & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
-    unsigned axes_size = num_axes * axis_width;
-
-    const F2DOT14 *q = (const F2DOT14 *) (axes_size +
-                                          (fl & GID_IS_24BIT ? 3 : 2) +
-                                          (const HBUINT8 *) &pad);
-
-    unsigned count = num_axes;
-    if (fl & AXES_HAVE_VARIATION)
-    {
-      for (unsigned i = 0; i < count; i++)
-        rec_points++->x = q++->to_int ();
-    }
-    else
-      q += count;
-
-    const HBUINT16 *p = (const HBUINT16 *) q;
-
-    if (fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y))
-    {
-      int translateX = (fl & HAVE_TRANSLATE_X) ? * (const FWORD *) p++ : 0;
-      int translateY = (fl & HAVE_TRANSLATE_Y) ? * (const FWORD *) p++ : 0;
-      rec_points->x = translateX;
-      rec_points->y = translateY;
-      rec_points++;
-    }
-    if (fl & HAVE_ROTATION)
-    {
-      int rotation = (fl & HAVE_ROTATION) ? ((const F4DOT12 *) p++)->to_int () : 0;
-      rec_points->x = rotation;
-      rec_points++;
-    }
-    if (fl & (HAVE_SCALE_X | HAVE_SCALE_Y))
-    {
-      int scaleX = (fl & HAVE_SCALE_X) ? ((const F6DOT10 *) p++)->to_int () : 1 << 10;
-      int scaleY = (fl & HAVE_SCALE_Y) ? ((const F6DOT10 *) p++)->to_int () : 1 << 10;
-      if ((fl & UNIFORM_SCALE) && !(fl & HAVE_SCALE_Y))
-        scaleY = scaleX;
-      rec_points->x = scaleX;
-      rec_points->y = scaleY;
-      rec_points++;
-    }
-    if (fl & (HAVE_SKEW_X | HAVE_SKEW_Y))
-    {
-      int skewX = (fl & HAVE_SKEW_X) ? ((const F4DOT12 *) p++)->to_int () : 0;
-      int skewY = (fl & HAVE_SKEW_Y) ? ((const F4DOT12 *) p++)->to_int () : 0;
-      rec_points->x = skewX;
-      rec_points->y = skewY;
-      rec_points++;
-    }
-    if (fl & (HAVE_TCENTER_X | HAVE_TCENTER_Y))
-    {
-      int tCenterX = (fl & HAVE_TCENTER_X) ? * (const FWORD *) p++ : 0;
-      int tCenterY = (fl & HAVE_TCENTER_Y) ? * (const FWORD *) p++ : 0;
-      rec_points->x = tCenterX;
-      rec_points->y = tCenterY;
-      rec_points++;
-    }
-
-    return true;
-  }
-
-  void get_transformation_from_points (const contour_point_t *rec_points,
-                                       float (&matrix)[4], contour_point_t &trans) const
-  {
-    unsigned fl = flags;
-
-    if (fl & AXES_HAVE_VARIATION)
-      rec_points += numAxes;
-
-    matrix[0] = matrix[3] = 1.f;
-    matrix[1] = matrix[2] = 0.f;
-    trans.init (0.f, 0.f);
-
-    float translateX = 0.f;
-    float translateY = 0.f;
-    float rotation = 0.f;
-    float scaleX = 1.f;
-    float scaleY = 1.f;
-    float skewX = 0.f;
-    float skewY = 0.f;
-    float tCenterX = 0.f;
-    float tCenterY = 0.f;
-
-    if (fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y))
-    {
-      translateX = rec_points->x;
-      translateY = rec_points->y;
-      rec_points++;
-    }
-    if (fl & HAVE_ROTATION)
-    {
-      rotation = rec_points->x / (1 << 12);
-      rec_points++;
-    }
-    if (fl & (HAVE_SCALE_X | HAVE_SCALE_Y))
-    {
-      scaleX = rec_points->x / (1 << 10);
-      scaleY = rec_points->y / (1 << 10);
-      rec_points++;
-    }
-    if (fl & (HAVE_SKEW_X | HAVE_SKEW_Y))
-    {
-      skewX = rec_points->x / (1 << 12);
-      skewY = rec_points->y / (1 << 12);
-      rec_points++;
-    }
-    if (fl & (HAVE_TCENTER_X | HAVE_TCENTER_Y))
-    {
-      tCenterX = rec_points->x;
-      tCenterY = rec_points->y;
-      rec_points++;
-    }
-
-    translate (matrix, trans, translateX + tCenterX, translateY + tCenterY);
-    rotate (matrix, trans, rotation);
-    scale (matrix, trans, scaleX, scaleY);
-    skew (matrix, trans, -skewX, skewY);
-    translate (matrix, trans, -tCenterX, -tCenterY);
-  }
-
-  void set_variations (coord_setter_t &setter,
-                       hb_array_t<contour_point_t> rec_points) const
-  {
-    bool have_variations = flags & AXES_HAVE_VARIATION;
-    unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
-    unsigned num_axes = numAxes;
-
-    const HBUINT8  *p = (const HBUINT8 *)  (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2));
-    const HBUINT16 *q = (const HBUINT16 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2));
-
-    const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + num_axes) : (HBUINT8 *) (q + num_axes)));
-
-    unsigned count = num_axes;
-    for (unsigned i = 0; i < count; i++)
-    {
-      unsigned axis_index = axis_width == 1 ? (unsigned) *p++ : (unsigned) *q++;
-
-      signed v = have_variations ? rec_points.arrayZ[i].x : a++->to_int ();
-
-      v = hb_clamp (v, -(1<<14), (1<<14));
-      setter[axis_index] = v;
-    }
-  }
-
-  protected:
-  HBUINT16      flags;
-  HBUINT8       numAxes;
-  HBUINT16      pad;
-  public:
-  DEFINE_SIZE_MIN (5);
-};
-
-using var_composite_iter_t = composite_iter_tmpl<VarCompositeGlyphRecord>;
-
-struct VarCompositeGlyph
-{
-  const GlyphHeader &header;
-  hb_bytes_t bytes;
-  VarCompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
-    header (header_), bytes (bytes_) {}
-
-  var_composite_iter_t iter () const
-  { return var_composite_iter_t (bytes, &StructAfter<VarCompositeGlyphRecord, GlyphHeader> (header)); }
-
-  const hb_bytes_t trim_padding () const
-  {
-    unsigned length = GlyphHeader::static_size;
-    for (auto &comp : iter ())
-      length += comp.get_size ();
-    return bytes.sub_array (0, length);
-  }
-};
-
-
-} /* namespace glyf_impl */
-} /* namespace OT */
-
-
-#endif /* OT_GLYF_VARCOMPOSITEGLYPH_HH */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/coord-setter.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/coord-setter.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/coord-setter.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/coord-setter.hh	1970-01-01 00:00:00.000000000 +0000
@@ -1,36 +0,0 @@
-#ifndef OT_GLYF_COORD_SETTER_HH
-#define OT_GLYF_COORD_SETTER_HH
-
-
-#include "../../hb.hh"
-
-
-namespace OT {
-namespace glyf_impl {
-
-
-struct coord_setter_t
-{
-  coord_setter_t (hb_array_t<int> coords) :
-    coords (coords) {}
-
-  int& operator [] (unsigned idx)
-  {
-    if (unlikely (idx >= HB_GLYF_VAR_COMPOSITE_MAX_AXES))
-      return Crap(int);
-    if (coords.length < idx + 1)
-      coords.resize (idx + 1);
-    return coords[idx];
-  }
-
-  hb_array_t<int> get_coords ()
-  { return coords.as_array (); }
-
-  hb_vector_t<int> coords;
-};
-
-
-} /* namespace glyf_impl */
-} /* namespace OT */
-
-#endif /* OT_GLYF_COORD_SETTER_HH */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf-helpers.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf-helpers.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf-helpers.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf-helpers.hh	2025-06-27 08:03:14.000000000 +0000
@@ -38,7 +38,7 @@ _write_loca (IteratorIn&& it,
 
     unsigned padded_size = *it++;
     offset += padded_size;
-    DEBUG_MSG (SUBSET, nullptr, "loca entry gid %u offset %u padded-size %u", gid, offset, padded_size);
+    DEBUG_MSG (SUBSET, nullptr, "loca entry gid %" PRIu32 " offset %u padded-size %u", gid, offset, padded_size);
     value = offset >> right_shift;
     *dest++ = value;
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh	2025-06-27 08:03:14.000000000 +0000
@@ -94,7 +94,7 @@ struct glyf
     }
 
     hb_vector_t<unsigned> padded_offsets;
-    if (unlikely (!padded_offsets.alloc (c->plan->new_to_old_gid_list.length, true)))
+    if (unlikely (!padded_offsets.alloc_exact (c->plan->new_to_old_gid_list.length)))
       return_trace (false);
 
     hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
@@ -172,6 +172,9 @@ struct glyf_accelerator_t
     glyf_table = nullptr;
 #ifndef HB_NO_VAR
     gvar = nullptr;
+#ifndef HB_NO_BEYOND_64K
+    GVAR = nullptr;
+#endif
 #endif
     hmtx = nullptr;
 #ifndef HB_NO_VERTICAL
@@ -187,6 +190,9 @@ struct glyf_accelerator_t
     glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
 #ifndef HB_NO_VAR
     gvar = face->table.gvar;
+#ifndef HB_NO_BEYOND_64K
+    GVAR = face->table.GVAR;
+#endif
 #endif
     hmtx = face->table.hmtx;
 #ifndef HB_NO_VERTICAL
@@ -198,6 +204,13 @@ struct glyf_accelerator_t
   }
   ~glyf_accelerator_t ()
   {
+    auto *scratch = cached_scratch.get_relaxed ();
+    if (scratch)
+    {
+      scratch->~hb_glyf_scratch_t ();
+      hb_free (scratch);
+    }
+
     glyf_table.destroy ();
   }
 
@@ -205,18 +218,17 @@ struct glyf_accelerator_t
 
   protected:
   template<typename T>
-  bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
+  bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer,
+                   hb_array_t<const int> coords,
+                   hb_glyf_scratch_t &scratch) const
   {
     if (gid >= num_glyphs) return false;
 
-    /* Making this allocfree is not that easy
-       https://github.com/harfbuzz/harfbuzz/issues/2095
-       mostly because of gvar handling in VF fonts,
-       perhaps a separate path for non-VF fonts can be considered */
-    contour_point_vector_t all_points;
+    auto &all_points = scratch.all_points;
+    all_points.resize (0);
 
     bool phantom_only = !consumer.is_consuming_contour_points ();
-    if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only)))
+    if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, scratch, nullptr, nullptr, nullptr, true, true, phantom_only, coords)))
       return false;
 
     unsigned count = all_points.length;
@@ -225,8 +237,61 @@ struct glyf_accelerator_t
 
     if (consumer.is_consuming_contour_points ())
     {
-      for (auto &point : all_points.as_array ().sub_array (0, count))
-        consumer.consume_point (point);
+      auto *points = all_points.arrayZ;
+
+      if (false)
+      {
+        /* Our path-builder was designed to work with this simple loop.
+         * But FreeType and CoreText do it differently, so we match those
+         * with the other, more complicated, code branch below. */
+        for (unsigned i = 0; i < count; i++)
+        {
+          consumer.consume_point (points[i]);
+          if (points[i].is_end_point)
+            consumer.contour_end ();
+        }
+      }
+      else
+      {
+        for (unsigned i = 0; i < count; i++)
+        {
+          // Start of a contour.
+          if (points[i].flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE)
+          {
+            // First point is on-curve. Draw the contour.
+            for (; i < count; i++)
+            {
+              consumer.consume_point (points[i]);
+              if (points[i].is_end_point)
+              {
+                consumer.contour_end ();
+                break;
+              }
+            }
+          }
+          else
+          {
+            unsigned start = i;
+
+            // Find end of the contour.
+            for (; i < count; i++)
+              if (points[i].is_end_point)
+                break;
+
+            unsigned end = i;
+
+            // Enough to start from the end. Our path-builder takes care of the rest.
+            if (likely (end < count)) // Can only fail in case of alloc failure *maybe*.
+              consumer.consume_point (points[end]);
+
+            for (i = start; i < end; i++)
+              consumer.consume_point (points[i]);
+
+            consumer.contour_end ();
+          }
+        }
+      }
+
       consumer.points_end ();
     }
 
@@ -299,6 +364,7 @@ struct glyf_accelerator_t
 
     HB_ALWAYS_INLINE
     void consume_point (const contour_point_t &point) { bounds.add (point); }
+    void contour_end () {}
     void points_end () { bounds.get_extents (font, extents, scaled); }
 
     bool is_consuming_contour_points () { return extents; }
@@ -314,7 +380,12 @@ struct glyf_accelerator_t
 
     contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
     if (font->num_coords)
-      success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false));
+    {
+      hb_glyf_scratch_t scratch;
+      success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false),
+                            hb_array (font->coords, font->num_coords),
+                            scratch);
+    }
 
     if (unlikely (!success))
       return
@@ -334,9 +405,11 @@ struct glyf_accelerator_t
     if (unlikely (gid >= num_glyphs)) return false;
 
     hb_glyph_extents_t extents;
-
+    hb_glyf_scratch_t scratch;
     contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
-    if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms, false))))
+    if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms, false),
+                               hb_array (font->coords, font->num_coords),
+                               scratch)))
       return false;
 
     *lsb = is_vertical
@@ -362,20 +435,16 @@ struct glyf_accelerator_t
 
 #ifndef HB_NO_VAR
     if (font->num_coords)
-      return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true));
+    {
+      hb_glyf_scratch_t scratch;
+      return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true),
+                         hb_array (font->coords, font->num_coords),
+                         scratch);
+    }
 #endif
     return glyph_for_gid (gid).get_extents_without_var_scaled (font, *this, extents);
   }
 
-  bool paint_glyph (hb_font_t *font, hb_codepoint_t gid, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
-  {
-    funcs->push_clip_glyph (data, gid, font);
-    funcs->color (data, true, foreground);
-    funcs->pop_clip (data);
-
-    return true;
-  }
-
   const glyf_impl::Glyph
   glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
   {
@@ -406,10 +475,52 @@ struct glyf_accelerator_t
 
   bool
   get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
-  { return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session)); }
+  {
+    if (!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;
+      }
+    }
+
+    bool ret = get_points (font, gid, glyf_impl::path_builder_t (font, draw_session),
+                           hb_array (font->coords, font->num_coords),
+                           *scratch);
+
+    // Put it back.
+    if (!cached_scratch.cmpexch (nullptr, scratch))
+    {
+      scratch->~hb_glyf_scratch_t ();
+      hb_free (scratch);
+    }
+
+    return ret;
+  }
+
+  bool
+  get_path_at (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session,
+               hb_array_t<const int> coords,
+               hb_glyf_scratch_t &scratch) const
+  {
+    if (!has_data ()) return false;
+    return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session),
+                       coords,
+                       scratch);
+  }
 
 #ifndef HB_NO_VAR
   const gvar_accelerator_t *gvar;
+#ifndef HB_NO_BEYOND_64K
+  const GVAR_accelerator_t *GVAR;
+#endif
 #endif
   const hmtx_accelerator_t *hmtx;
 #ifndef HB_NO_VERTICAL
@@ -421,6 +532,7 @@ struct glyf_accelerator_t
   unsigned int num_glyphs;
   hb_blob_ptr_t<loca> loca_table;
   hb_blob_ptr_t<glyf> glyf_table;
+  hb_atomic_ptr_t<hb_glyf_scratch_t> cached_scratch;
 };
 
 
@@ -430,7 +542,7 @@ glyf::_populate_subset_glyphs (const hb_
                                hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const
 {
   OT::glyf_accelerator_t glyf (plan->source);
-  if (!glyphs.alloc (plan->new_to_old_gid_list.length, true)) return false;
+  if (!glyphs.alloc_exact (plan->new_to_old_gid_list.length)) return false;
 
   for (const auto &pair : plan->new_to_old_gid_list)
   {
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/path-builder.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/path-builder.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/path-builder.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/glyf/path-builder.hh	2025-06-27 08:03:14.000000000 +0000
@@ -42,7 +42,7 @@ struct path_builder_t
   {
     bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
 #ifdef HB_NO_CUBIC_GLYF
-    bool is_cubic = false;
+    constexpr bool is_cubic = false;
 #else
     bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC);
 #endif
@@ -124,58 +124,60 @@ struct path_builder_t
       }
     }
 
-    if (unlikely (point.is_end_point))
-    {
-      if (first_offcurve && last_offcurve)
-      {
-        optional_point_t mid = last_offcurve.mid (first_offcurve2 ?
-                                                  first_offcurve2 :
-                                                  first_offcurve);
-        if (last_offcurve2)
-          draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
-                                  last_offcurve.x, last_offcurve.y,
-                                  mid.x, mid.y);
-        else
-          draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
-                                     mid.x, mid.y);
-        last_offcurve = optional_point_t ();
-      }
-      /* now check the rest */
+  }
 
-      if (first_offcurve && first_oncurve)
-      {
-        if (first_offcurve2)
-          draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y,
-                                  first_offcurve.x, first_offcurve.y,
-                                  first_oncurve.x, first_oncurve.y);
-        else
-          draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
-                                     first_oncurve.x, first_oncurve.y);
-      }
-      else if (last_offcurve && first_oncurve)
-      {
-        if (last_offcurve2)
-          draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
-                                  last_offcurve.x, last_offcurve.y,
-                                  first_oncurve.x, first_oncurve.y);
-        else
-          draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
-                                     first_oncurve.x, first_oncurve.y);
-      }
-      else if (first_oncurve)
-        draw_session->line_to (first_oncurve.x, first_oncurve.y);
-      else if (first_offcurve)
-      {
-        float x = first_offcurve.x, y = first_offcurve.y;
-        draw_session->move_to (x, y);
-        draw_session->quadratic_to (x, y, x, y);
-      }
+  void contour_end ()
+  {
+    if (first_offcurve && last_offcurve)
+    {
+      optional_point_t mid = last_offcurve.mid (first_offcurve2 ?
+                                                first_offcurve2 :
+                                                first_offcurve);
+      if (last_offcurve2)
+        draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
+                                last_offcurve.x, last_offcurve.y,
+                                mid.x, mid.y);
+      else
+        draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+                                   mid.x, mid.y);
+      last_offcurve = optional_point_t ();
+    }
+    /* now check the rest */
 
-      /* Getting ready for the next contour */
-      first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
-      draw_session->close_path ();
+    if (first_offcurve && first_oncurve)
+    {
+      if (first_offcurve2)
+        draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y,
+                                first_offcurve.x, first_offcurve.y,
+                                first_oncurve.x, first_oncurve.y);
+      else
+        draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
+                                   first_oncurve.x, first_oncurve.y);
     }
+    else if (last_offcurve && first_oncurve)
+    {
+      if (last_offcurve2)
+        draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
+                                last_offcurve.x, last_offcurve.y,
+                                first_oncurve.x, first_oncurve.y);
+      else
+        draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+                                   first_oncurve.x, first_oncurve.y);
+    }
+    else if (first_oncurve)
+      draw_session->line_to (first_oncurve.x, first_oncurve.y);
+    else if (first_offcurve)
+    {
+      float x = first_offcurve.x, y = first_offcurve.y;
+      draw_session->move_to (x, y);
+      draw_session->quadratic_to (x, y, x, y);
+    }
+
+    /* Getting ready for the next contour */
+    first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
+    draw_session->close_path ();
   }
+
   void points_end () {}
 
   bool is_consuming_contour_points () { return true; }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/name/name.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/name/name.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/OT/name/name.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/OT/name/name.hh	2025-06-27 08:03:14.000000000 +0000
@@ -242,7 +242,9 @@ struct NameRecord
   bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && offset.sanitize (c, base, length));
+    return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
+                  offset.sanitize (c, base, length));
   }
 
   HBUINT16      platformID;     /* Platform ID. */
@@ -465,6 +467,7 @@ struct name
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   likely (format == 0 || format == 1) &&
                   c->check_array (nameRecordZ.arrayZ, count) &&
                   c->check_range (this, stringOffset) &&
@@ -482,7 +485,7 @@ struct name
       const hb_array_t<const NameRecord> all_names (this->table->nameRecordZ.arrayZ,
                                                     this->table->count);
 
-      this->names.alloc (all_names.length, true);
+      this->names.alloc_exact (all_names.length);
 
       for (unsigned int i = 0; i < all_names.length; i++)
       {
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/UPDATING.txt 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/UPDATING.txt
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/UPDATING.txt	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/UPDATING.txt	2025-06-27 08:03:14.000000000 +0000
@@ -53,9 +53,9 @@ STEP 2: BUILD CHANGES INCREMENTALLY
 
 STEP 3: COMPILER WARNINGS AND SETTING FLAGS
 -------------------------------------------
-- Update make parameters in Awt2DLibraries.gmk
+- Update make parameters in make/modules/java.desktop/lib/ClientLibraries.gmk
   Since we don't use configure we need to manually specify the options
-  we need in the Harfbuzz section of Awt2DLibraries.gmk.
+  we need in the Harfbuzz section of ClientLibraries.gmk.
   As well as adding new options, we may need to clean up obsolete options.
   Note there may be platform variations in the flags.
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/graph/classdef-graph.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/graph/classdef-graph.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/graph/classdef-graph.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/graph/classdef-graph.hh	2025-06-27 08:03:14.000000000 +0000
@@ -39,6 +39,7 @@ struct ClassDefFormat1 : public OT::Clas
     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
     constexpr unsigned min_size = OT::ClassDefFormat1_3<SmallTypes>::min_size;
     if (vertex_len < min_size) return false;
+    hb_barrier ();
     return vertex_len >= min_size + classValue.get_size () - classValue.len.get_size ();
   }
 };
@@ -50,6 +51,7 @@ struct ClassDefFormat2 : public OT::Clas
     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
     constexpr unsigned min_size = OT::ClassDefFormat2_4<SmallTypes>::min_size;
     if (vertex_len < min_size) return false;
+    hb_barrier ();
     return vertex_len >= min_size + rangeRecord.get_size () - rangeRecord.len.get_size ();
   }
 };
@@ -114,6 +116,7 @@ struct ClassDef : public OT::ClassDef
   {
     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
     if (vertex_len < OT::ClassDef::min_size) return false;
+    hb_barrier ();
     switch (u.format)
     {
     case 1: return ((ClassDefFormat1*)this)->sanitize (vertex);
@@ -131,20 +134,23 @@ struct ClassDef : public OT::ClassDef
 
 struct class_def_size_estimator_t
 {
+  // TODO(garretrieger): update to support beyond64k coverage/classdef tables.
+  constexpr static unsigned class_def_format1_base_size = 6;
+  constexpr static unsigned class_def_format2_base_size = 4;
+  constexpr static unsigned coverage_base_size = 4;
+  constexpr static unsigned bytes_per_range = 6;
+  constexpr static unsigned bytes_per_glyph = 2;
+
   template<typename It>
   class_def_size_estimator_t (It glyph_and_class)
-      : gids_consecutive (true), num_ranges_per_class (), glyphs_per_class ()
+      : num_ranges_per_class (), glyphs_per_class ()
   {
-    unsigned last_gid = (unsigned) -1;
+    reset();
     for (auto p : + glyph_and_class)
     {
       unsigned gid = p.first;
       unsigned klass = p.second;
 
-      if (last_gid != (unsigned) -1 && gid != last_gid + 1)
-        gids_consecutive = false;
-      last_gid = gid;
-
       hb_set_t* glyphs;
       if (glyphs_per_class.has (klass, &glyphs) && glyphs) {
         glyphs->add (gid);
@@ -174,28 +180,54 @@ struct class_def_size_estimator_t
     }
   }
 
-  // Incremental increase in the Coverage and ClassDef table size
-  // (worst case) if all glyphs associated with 'klass' were added.
-  unsigned incremental_coverage_size (unsigned klass) const
+  void reset() {
+    class_def_1_size = class_def_format1_base_size;
+    class_def_2_size = class_def_format2_base_size;
+    included_glyphs.clear();
+    included_classes.clear();
+  }
+
+  // Compute the size of coverage for all glyphs added via 'add_class_def_size'.
+  unsigned coverage_size () const
   {
-    // Coverage takes 2 bytes per glyph worst case,
-    return 2 * glyphs_per_class.get (klass).get_population ();
+    unsigned format1_size = coverage_base_size + bytes_per_glyph * included_glyphs.get_population();
+    unsigned format2_size = coverage_base_size + bytes_per_range * num_glyph_ranges();
+    return hb_min(format1_size, format2_size);
   }
 
-  // Incremental increase in the Coverage and ClassDef table size
-  // (worst case) if all glyphs associated with 'klass' were added.
-  unsigned incremental_class_def_size (unsigned klass) const
+  // Compute the new size of the ClassDef table if all glyphs associated with 'klass' were added.
+  unsigned add_class_def_size (unsigned klass)
   {
-    // ClassDef takes 6 bytes per range
-    unsigned class_def_2_size = 6 * num_ranges_per_class.get (klass);
-    if (gids_consecutive)
-    {
-      // ClassDef1 takes 2 bytes per glyph, but only can be used
-      // when gids are consecutive.
-      return hb_min (2 * glyphs_per_class.get (klass).get_population (), class_def_2_size);
+    if (!included_classes.has(klass)) {
+      hb_set_t* glyphs = nullptr;
+      if (glyphs_per_class.has(klass, &glyphs)) {
+        included_glyphs.union_(*glyphs);
+      }
+
+      class_def_1_size = class_def_format1_base_size;
+      if (!included_glyphs.is_empty()) {
+        unsigned min_glyph = included_glyphs.get_min();
+        unsigned max_glyph = included_glyphs.get_max();
+        class_def_1_size += bytes_per_glyph * (max_glyph - min_glyph + 1);
+      }
+
+      class_def_2_size += bytes_per_range * num_ranges_per_class.get (klass);
+
+      included_classes.add(klass);
     }
 
-    return class_def_2_size;
+    return hb_min (class_def_1_size, class_def_2_size);
+  }
+
+  unsigned num_glyph_ranges() const {
+    hb_codepoint_t start = HB_SET_VALUE_INVALID;
+    hb_codepoint_t end = HB_SET_VALUE_INVALID;
+
+    unsigned count = 0;
+    while (included_glyphs.next_range (&start, &end)) {
+        count++;
+    }
+    return count;
   }
 
   bool in_error ()
@@ -211,9 +243,12 @@ struct class_def_size_estimator_t
   }
 
  private:
-  bool gids_consecutive;
   hb_hashmap_t<unsigned, unsigned> num_ranges_per_class;
   hb_hashmap_t<unsigned, hb_set_t> glyphs_per_class;
+  hb_set_t included_classes;
+  hb_set_t included_glyphs;
+  unsigned class_def_1_size;
+  unsigned class_def_2_size;
 };
 
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/graph/coverage-graph.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/graph/coverage-graph.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/graph/coverage-graph.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/graph/coverage-graph.hh	2025-06-27 08:03:14.000000000 +0000
@@ -39,6 +39,7 @@ struct CoverageFormat1 : public OT::Layo
     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
     constexpr unsigned min_size = OT::Layout::Common::CoverageFormat1_3<SmallTypes>::min_size;
     if (vertex_len < min_size) return false;
+    hb_barrier ();
     return vertex_len >= min_size + glyphArray.get_size () - glyphArray.len.get_size ();
   }
 };
@@ -50,6 +51,7 @@ struct CoverageFormat2 : public OT::Layo
     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
     constexpr unsigned min_size = OT::Layout::Common::CoverageFormat2_4<SmallTypes>::min_size;
     if (vertex_len < min_size) return false;
+    hb_barrier ();
     return vertex_len >= min_size + rangeRecord.get_size () - rangeRecord.len.get_size ();
   }
 };
@@ -138,6 +140,7 @@ struct Coverage : public OT::Layout::Com
   {
     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
     if (vertex_len < OT::Layout::Common::Coverage::min_size) return false;
+    hb_barrier ();
     switch (u.format)
     {
     case 1: return ((CoverageFormat1*)this)->sanitize (vertex);
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/graph/graph.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/graph/graph.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/graph/graph.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/graph/graph.hh	2025-06-27 08:03:14.000000000 +0000
@@ -195,6 +195,15 @@ struct graph_t
       return incoming_edges_;
     }
 
+    unsigned incoming_edges_from_parent (unsigned parent_index) const {
+      if (single_parent != (unsigned) -1) {
+        return single_parent == parent_index ? 1 : 0;
+      }
+
+      unsigned* count;
+      return  parents.has(parent_index, &count) ? *count : 0;
+    }
+
     void reset_parents ()
     {
       incoming_edges_ = 0;
@@ -334,6 +343,16 @@ struct graph_t
       return true;
     }
 
+    bool give_max_priority ()
+    {
+      bool result = false;
+      while (!has_max_priority()) {
+        result = true;
+        priority++;
+      }
+      return result;
+    }
+
     bool has_max_priority () const {
       return priority >= 3;
     }
@@ -349,7 +368,7 @@ struct graph_t
       // it's parent where possible.
 
       int64_t modified_distance =
-          hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFFF);
+          hb_clamp (distance + distance_modifier (), (int64_t) 0, 0x7FFFFFFFFFF);
       if (has_max_priority ()) {
         modified_distance = 0;
       }
@@ -567,6 +586,7 @@ struct graph_t
     update_distances ();
 
     hb_priority_queue_t<int64_t> queue;
+    queue.alloc (vertices_.length);
     hb_vector_t<vertex_t> &sorted_graph = vertices_scratch_;
     if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
     hb_vector_t<unsigned> id_map;
@@ -1022,6 +1042,11 @@ struct graph_t
    * Creates a copy of child and re-assigns the link from
    * parent to the clone. The copy is a shallow copy, objects
    * linked from child are not duplicated.
+   *
+   * Returns the index of the newly created duplicate.
+   *
+   * If the child_idx only has incoming edges from parent_idx, this
+   * will do nothing and return the original child_idx.
    */
   unsigned duplicate_if_shared (unsigned parent_idx, unsigned child_idx)
   {
@@ -1035,18 +1060,20 @@ struct graph_t
    * Creates a copy of child and re-assigns the link from
    * parent to the clone. The copy is a shallow copy, objects
    * linked from child are not duplicated.
+   *
+   * Returns the index of the newly created duplicate.
+   *
+   * If the child_idx only has incoming edges from parent_idx,
+   * duplication isn't possible and this will return -1.
    */
   unsigned duplicate (unsigned parent_idx, unsigned child_idx)
   {
     update_parents ();
 
-    unsigned links_to_child = 0;
-    for (const auto& l : vertices_[parent_idx].obj.all_links ())
-    {
-      if (l.objidx == child_idx) links_to_child++;
-    }
+    const auto& child = vertices_[child_idx];
+    unsigned links_to_child = child.incoming_edges_from_parent(parent_idx);
 
-    if (vertices_[child_idx].incoming_edges () <= links_to_child)
+    if (child.incoming_edges () <= links_to_child)
     {
       // Can't duplicate this node, doing so would orphan the original one as all remaining links
       // to child are from parent.
@@ -1059,7 +1086,7 @@ struct graph_t
                parent_idx, child_idx);
 
     unsigned clone_idx = duplicate (child_idx);
-    if (clone_idx == (unsigned) -1) return false;
+    if (clone_idx == (unsigned) -1) return -1;
     // duplicate shifts the root node idx, so if parent_idx was root update it.
     if (parent_idx == clone_idx) parent_idx++;
 
@@ -1075,6 +1102,62 @@ struct graph_t
     return clone_idx;
   }
 
+  /*
+   * Creates a copy of child and re-assigns the links from
+   * parents to the clone. The copy is a shallow copy, objects
+   * linked from child are not duplicated.
+   *
+   * Returns the index of the newly created duplicate.
+   *
+   * If the child_idx only has incoming edges from parents,
+   * duplication isn't possible or duplication fails and this will
+   * return -1.
+   */
+  unsigned duplicate (const hb_set_t* parents, unsigned child_idx)
+  {
+    if (parents->is_empty()) {
+      return -1;
+    }
+
+    update_parents ();
+
+    const auto& child = vertices_[child_idx];
+    unsigned links_to_child = 0;
+    unsigned last_parent = parents->get_max();
+    unsigned first_parent = parents->get_min();
+    for (unsigned parent_idx : *parents) {
+      links_to_child += child.incoming_edges_from_parent(parent_idx);
+    }
+
+    if (child.incoming_edges () <= links_to_child)
+    {
+      // Can't duplicate this node, doing so would orphan the original one as all remaining links
+      // to child are from parent.
+      DEBUG_MSG (SUBSET_REPACK, nullptr, "  Not duplicating %u, ..., %u => %u", first_parent, last_parent, child_idx);
+      return -1;
+    }
+
+    DEBUG_MSG (SUBSET_REPACK, nullptr, "  Duplicating %u, ..., %u => %u", first_parent, last_parent, child_idx);
+
+    unsigned clone_idx = duplicate (child_idx);
+    if (clone_idx == (unsigned) -1) return false;
+
+    for (unsigned parent_idx : *parents) {
+      // duplicate shifts the root node idx, so if parent_idx was root update it.
+      if (parent_idx == clone_idx) parent_idx++;
+      auto& parent = vertices_[parent_idx];
+      for (auto& l : parent.obj.all_links_writer ())
+      {
+        if (l.objidx != child_idx)
+          continue;
+
+        reassign_link (l, parent_idx, clone_idx);
+      }
+    }
+
+    return clone_idx;
+  }
+
 
   /*
    * Adds a new node to the graph, not connected to anything.
@@ -1370,6 +1453,7 @@ struct graph_t
     vertices_.tail ().distance = 0;
 
     hb_priority_queue_t<int64_t> queue;
+    queue.alloc (count);
     queue.insert (0, vertices_.length - 1);
 
     hb_vector_t<bool> visited;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/graph/gsubgpos-graph.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/graph/gsubgpos-graph.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/graph/gsubgpos-graph.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/graph/gsubgpos-graph.hh	2025-06-27 08:03:14.000000000 +0000
@@ -76,6 +76,7 @@ struct Lookup : public OT::Lookup
   {
     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
     if (vertex_len < OT::Lookup::min_size) return false;
+    hb_barrier ();
     return vertex_len >= this->get_size ();
   }
 
@@ -351,6 +352,7 @@ struct LookupList : public OT::LookupLis
   {
     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
     if (vertex_len < OT::LookupList<T>::min_size) return false;
+    hb_barrier ();
     return vertex_len >= OT::LookupList<T>::item_size * this->len;
   }
 };
@@ -364,6 +366,7 @@ struct GSTAR : public OT::GSUBGPOS
     GSTAR* gstar = (GSTAR*) r.obj.head;
     if (!gstar || !gstar->sanitize (r))
       return nullptr;
+    hb_barrier ();
 
     return gstar;
   }
@@ -383,6 +386,7 @@ struct GSTAR : public OT::GSUBGPOS
   {
     int64_t len = vertex.obj.tail - vertex.obj.head;
     if (len < OT::GSUBGPOS::min_size) return false;
+    hb_barrier ();
     return len >= get_size ();
   }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/graph/markbasepos-graph.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/graph/markbasepos-graph.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/graph/markbasepos-graph.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/graph/markbasepos-graph.hh	2025-06-27 08:03:14.000000000 +0000
@@ -40,6 +40,7 @@ struct AnchorMatrix : public OT::Layout:
   {
     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
     if (vertex_len < AnchorMatrix::min_size) return false;
+    hb_barrier ();
 
     return vertex_len >= AnchorMatrix::min_size +
         OT::Offset16::static_size * class_count * this->rows;
@@ -128,6 +129,7 @@ struct MarkArray : public OT::Layout::GP
     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
     unsigned min_size = MarkArray::min_size;
     if (vertex_len < min_size) return false;
+    hb_barrier ();
 
     return vertex_len >= get_size ();
   }
@@ -495,6 +497,7 @@ struct MarkBasePos : public OT::Layout::
   {
     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
     if (vertex_len < u.format.get_size ()) return false;
+    hb_barrier ();
 
     switch (u.format) {
     case 1:
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/graph/pairpos-graph.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/graph/pairpos-graph.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/graph/pairpos-graph.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/graph/pairpos-graph.hh	2025-06-27 08:03:14.000000000 +0000
@@ -42,6 +42,7 @@ struct PairPosFormat1 : public OT::Layou
     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
     unsigned min_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size;
     if (vertex_len < min_size) return false;
+    hb_barrier ();
 
     return vertex_len >=
         min_size + pairSet.get_size () - pairSet.len.get_size();
@@ -198,6 +199,7 @@ struct PairPosFormat2 : public OT::Layou
     size_t vertex_len = vertex.table_size ();
     unsigned min_size = OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>::min_size;
     if (vertex_len < min_size) return false;
+    hb_barrier ();
 
     const unsigned class1_count = class1Count;
     return vertex_len >=
@@ -245,8 +247,8 @@ struct PairPosFormat2 : public OT::Layou
     for (unsigned i = 0; i < class1_count; i++)
     {
       unsigned accumulated_delta = class1_record_size;
-      coverage_size += estimator.incremental_coverage_size (i);
-      class_def_1_size += estimator.incremental_class_def_size (i);
+      class_def_1_size = estimator.add_class_def_size (i);
+      coverage_size = estimator.coverage_size ();
       max_coverage_size = hb_max (max_coverage_size, coverage_size);
       max_class_def_1_size = hb_max (max_class_def_1_size, class_def_1_size);
 
@@ -278,8 +280,10 @@ struct PairPosFormat2 : public OT::Layou
         split_points.push (i);
         // split does not include i, so add the size for i when we reset the size counters.
         accumulated = base_size + accumulated_delta;
-        coverage_size = 4 + estimator.incremental_coverage_size (i);
-        class_def_1_size = 4 + estimator.incremental_class_def_size (i);
+
+        estimator.reset();
+        class_def_1_size = estimator.add_class_def_size(i);
+        coverage_size = estimator.coverage_size();
         visited.clear (); // node sharing isn't allowed between splits.
       }
     }
@@ -625,6 +629,7 @@ struct PairPos : public OT::Layout::GPOS
   {
     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
     if (vertex_len < u.format.get_size ()) return false;
+    hb_barrier ();
 
     switch (u.format) {
     case 1:
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-ankr-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-ankr-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-ankr-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-ankr-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -75,6 +75,7 @@ struct ankr
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
                           version == 0 &&
                           c->check_range (this, anchorData) &&
                           lookupTable.sanitize (c, this, &(this+anchorData))));
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-bsln-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-bsln-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-bsln-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-bsln-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -123,6 +123,7 @@ struct bsln
     TRACE_SANITIZE (this);
     if (unlikely (!(c->check_struct (this) && defaultBaseline < 32)))
       return_trace (false);
+    hb_barrier ();
 
     switch (format)
     {
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh	2025-06-27 08:03:14.000000000 +0000
@@ -30,6 +30,10 @@
 #include "hb-aat-layout.hh"
 #include "hb-aat-map.hh"
 #include "hb-open-type.hh"
+#include "hb-cache.hh"
+#include "hb-bit-set.hh"
+#include "hb-bit-page.hh"
+
 
 namespace OT {
 struct GDEF;
@@ -39,15 +43,18 @@ namespace AAT {
 
 using namespace OT;
 
-
 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_apply_context_t :
        hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
 {
   const char *get_name () { return "APPLY"; }
-  template <typename T>
-  return_t dispatch (const T &obj) { return obj.apply (this); }
+  template <typename T, typename ...Ts>
+  return_t dispatch (const T &obj, Ts&&... ds)
+  { return obj.apply (this, std::forward<Ts> (ds)...); }
   static return_t default_return_value () { return false; }
   bool stop_sublookup_iteration (return_t r) const { return r; }
 
@@ -59,6 +66,12 @@ struct hb_aat_apply_context_t :
   const ankr *ankr_table;
   const OT::GDEF *gdef_table;
   const hb_sorted_vector_t<hb_aat_map_t::range_flags_t> *range_flags = nullptr;
+  bool using_buffer_glyph_set = false;
+  hb_bit_set_t buffer_glyph_set;
+  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;
+  hb_aat_class_cache_t *machine_class_cache = nullptr;
   hb_mask_t subtable_flags = 0;
 
   /* Unused. For debug tracing only. */
@@ -74,6 +87,25 @@ struct hb_aat_apply_context_t :
   HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
 
   void set_lookup_index (unsigned int i) { lookup_index = i; }
+
+  void setup_buffer_glyph_set ()
+  {
+    using_buffer_glyph_set = buffer->len >= 4;
+
+    if (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);
+
+    // Faster for shorter buffers.
+    for (unsigned i = 0; i < buffer->len; i++)
+      if (machine_glyph_set->has (buffer->info[i].codepoint))
+        return true;
+    return false;
+  }
 };
 
 
@@ -81,6 +113,8 @@ struct hb_aat_apply_context_t :
  * Lookup Table
  */
 
+enum { DELETED_GLYPH = 0xFFFF };
+
 template <typename T> struct Lookup;
 
 template <typename T>
@@ -95,6 +129,19 @@ struct LookupFormat0
     return &arrayZ[glyph_id];
   }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &glyphs, unsigned num_glyphs) const
+  {
+    glyphs.add_range (0, num_glyphs - 1);
+  }
+  template <typename set_t, typename filter_t>
+  void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const
+  {
+    for (unsigned i = 0; i < num_glyphs; i++)
+      if (filter (arrayZ[i]))
+        glyphs.add (i);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -123,6 +170,19 @@ struct LookupSegmentSingle
   int cmp (hb_codepoint_t g) const
   { return g < first ? -1 : g <= last ? 0 : +1 ; }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &glyphs) const
+  {
+    if (first == DELETED_GLYPH) return;
+    glyphs.add_range (first, last);
+  }
+  template <typename set_t, typename filter_t>
+  void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
+  {
+    if (!filter (value)) return;
+    glyphs.add_range (first, last);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -153,6 +213,21 @@ struct LookupFormat2
     return v ? &v->value : nullptr;
   }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &glyphs) const
+  {
+    unsigned count = segments.get_length ();
+    for (unsigned int i = 0; i < count; i++)
+      segments[i].collect_glyphs (glyphs);
+  }
+  template <typename set_t, typename filter_t>
+  void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
+  {
+    unsigned count = segments.get_length ();
+    for (unsigned int i = 0; i < count; i++)
+      segments[i].collect_glyphs_filtered (glyphs, filter);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -184,6 +259,21 @@ struct LookupSegmentArray
     return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
   }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &glyphs) const
+  {
+    if (first == DELETED_GLYPH) return;
+    glyphs.add_range (first, last);
+  }
+  template <typename set_t, typename filter_t>
+  void collect_glyphs_filtered (set_t &glyphs, const void *base, const filter_t &filter) const
+  {
+    const auto &values = base+valuesZ;
+    for (hb_codepoint_t i = first; i <= last; i++)
+      if (filter (values[i - first]))
+        glyphs.add (i);
+  }
+
   int cmp (hb_codepoint_t g) const
   { return g < first ? -1 : g <= last ? 0 : +1; }
 
@@ -191,6 +281,7 @@ struct LookupSegmentArray
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   first <= last &&
                   valuesZ.sanitize (c, base, last - first + 1));
   }
@@ -199,6 +290,7 @@ struct LookupSegmentArray
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   first <= last &&
                   valuesZ.sanitize (c, base, last - first + 1, std::forward<Ts> (ds)...));
   }
@@ -224,6 +316,21 @@ struct LookupFormat4
     return v ? v->get_value (glyph_id, this) : nullptr;
   }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &glyphs) const
+  {
+    unsigned count = segments.get_length ();
+    for (unsigned i = 0; i < count; i++)
+      segments[i].collect_glyphs (glyphs);
+  }
+  template <typename set_t, typename filter_t>
+  void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
+  {
+    unsigned count = segments.get_length ();
+    for (unsigned i = 0; i < count; i++)
+      segments[i].collect_glyphs_filtered (glyphs, this, filter);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -252,6 +359,19 @@ struct LookupSingle
 
   int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &glyphs) const
+  {
+    if (glyph == DELETED_GLYPH) return;
+    glyphs.add (glyph);
+  }
+  template <typename set_t, typename filter_t>
+  void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
+  {
+    if (!filter (value)) return;
+    glyphs.add (glyph);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -281,6 +401,21 @@ struct LookupFormat6
     return v ? &v->value : nullptr;
   }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &glyphs) const
+  {
+    unsigned count = entries.get_length ();
+    for (unsigned i = 0; i < count; i++)
+      entries[i].collect_glyphs (glyphs);
+  }
+  template <typename set_t, typename filter_t>
+  void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
+  {
+    unsigned count = entries.get_length ();
+    for (unsigned i = 0; i < count; i++)
+      entries[i].collect_glyphs_filtered (glyphs, filter);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -312,6 +447,24 @@ struct LookupFormat8
            &valueArrayZ[glyph_id - firstGlyph] : nullptr;
   }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &glyphs) const
+  {
+    if (unlikely (!glyphCount)) return;
+    if (firstGlyph == DELETED_GLYPH) return;
+    glyphs.add_range (firstGlyph, firstGlyph + glyphCount - 1);
+  }
+  template <typename set_t, typename filter_t>
+  void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
+  {
+    if (unlikely (!glyphCount)) return;
+    if (firstGlyph == DELETED_GLYPH) return;
+    const T *p = valueArrayZ.arrayZ;
+    for (unsigned i = 0; i < glyphCount; i++)
+      if (filter (p[i]))
+        glyphs.add (firstGlyph + i);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -356,10 +509,19 @@ struct LookupFormat10
     return v;
   }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &glyphs) const
+  {
+    if (unlikely (!glyphCount)) return;
+    if (firstGlyph == DELETED_GLYPH) return;
+    glyphs.add_range (firstGlyph, firstGlyph + glyphCount - 1);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   valueSize <= 4 &&
                   valueArrayZ.sanitize (c, glyphCount * valueSize));
   }
@@ -383,11 +545,11 @@ struct Lookup
   const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
   {
     switch (u.format) {
-    case 0: return u.format0.get_value (glyph_id, num_glyphs);
-    case 2: return u.format2.get_value (glyph_id);
-    case 4: return u.format4.get_value (glyph_id);
-    case 6: return u.format6.get_value (glyph_id);
-    case 8: return u.format8.get_value (glyph_id);
+    case 0: hb_barrier (); return u.format0.get_value (glyph_id, num_glyphs);
+    case 2: hb_barrier (); return u.format2.get_value (glyph_id);
+    case 4: hb_barrier (); return u.format4.get_value (glyph_id);
+    case 6: hb_barrier (); return u.format6.get_value (glyph_id);
+    case 8: hb_barrier (); return u.format8.get_value (glyph_id);
     default:return nullptr;
     }
   }
@@ -396,13 +558,39 @@ struct Lookup
   {
     switch (u.format) {
       /* Format 10 cannot return a pointer. */
-      case 10: return u.format10.get_value_or_null (glyph_id);
+      case 10: hb_barrier (); return u.format10.get_value_or_null (glyph_id);
       default:
       const T *v = get_value (glyph_id, num_glyphs);
       return v ? *v : Null (T);
     }
   }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &glyphs, unsigned int num_glyphs) const
+  {
+    switch (u.format) {
+    case 0: hb_barrier (); u.format0.collect_glyphs (glyphs, num_glyphs); return;
+    case 2: hb_barrier (); u.format2.collect_glyphs (glyphs); return;
+    case 4: hb_barrier (); u.format4.collect_glyphs (glyphs); return;
+    case 6: hb_barrier (); u.format6.collect_glyphs (glyphs); return;
+    case 8: hb_barrier (); u.format8.collect_glyphs (glyphs); return;
+    case 10: hb_barrier (); u.format10.collect_glyphs (glyphs); return;
+    default:return;
+    }
+  }
+  template <typename set_t, typename filter_t>
+  void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const
+  {
+    switch (u.format) {
+    case 0: hb_barrier (); u.format0.collect_glyphs_filtered (glyphs, num_glyphs, filter); return;
+    case 2: hb_barrier (); u.format2.collect_glyphs_filtered (glyphs, filter); return;
+    case 4: hb_barrier (); u.format4.collect_glyphs_filtered (glyphs, filter); return;
+    case 6: hb_barrier (); u.format6.collect_glyphs_filtered (glyphs, filter); return;
+    case 8: hb_barrier (); u.format8.collect_glyphs_filtered (glyphs, filter); return;
+    default:return;
+    }
+  }
+
   typename T::type get_class (hb_codepoint_t glyph_id,
                               unsigned int num_glyphs,
                               unsigned int outOfRange) const
@@ -415,13 +603,14 @@ struct Lookup
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
+    hb_barrier ();
     switch (u.format) {
-    case 0: return_trace (u.format0.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    case 4: return_trace (u.format4.sanitize (c));
-    case 6: return_trace (u.format6.sanitize (c));
-    case 8: return_trace (u.format8.sanitize (c));
-    case 10: return_trace (u.format10.sanitize (c));
+    case 0: hb_barrier (); return_trace (u.format0.sanitize (c));
+    case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
+    case 4: hb_barrier (); return_trace (u.format4.sanitize (c));
+    case 6: hb_barrier (); return_trace (u.format6.sanitize (c));
+    case 8: hb_barrier (); return_trace (u.format8.sanitize (c));
+    case 10: hb_barrier (); return_trace (u.format10.sanitize (c));
     default:return_trace (true);
     }
   }
@@ -429,12 +618,13 @@ struct Lookup
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
+    hb_barrier ();
     switch (u.format) {
-    case 0: return_trace (u.format0.sanitize (c, base));
-    case 2: return_trace (u.format2.sanitize (c, base));
-    case 4: return_trace (u.format4.sanitize (c, base));
-    case 6: return_trace (u.format6.sanitize (c, base));
-    case 8: return_trace (u.format8.sanitize (c, base));
+    case 0: hb_barrier (); return_trace (u.format0.sanitize (c, base));
+    case 2: hb_barrier (); return_trace (u.format2.sanitize (c, base));
+    case 4: hb_barrier (); return_trace (u.format4.sanitize (c, base));
+    case 6: hb_barrier (); return_trace (u.format6.sanitize (c, base));
+    case 8: hb_barrier (); return_trace (u.format8.sanitize (c, base));
     case 10: return_trace (false); /* We don't support format10 here currently. */
     default:return_trace (true);
     }
@@ -455,8 +645,6 @@ struct Lookup
 };
 DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (AAT, Lookup, 2);
 
-enum { DELETED_GLYPH = 0xFFFF };
-
 /*
  * (Extended) State Table
  */
@@ -464,7 +652,7 @@ enum { DELETED_GLYPH = 0xFFFF };
 template <typename T>
 struct Entry
 {
-  // This does seem like it's ever called.
+  // This doesn't seem like it's ever called.
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -507,6 +695,14 @@ struct Entry<void>
   DEFINE_SIZE_STATIC (4);
 };
 
+enum Class
+{
+  CLASS_END_OF_TEXT = 0,
+  CLASS_OUT_OF_BOUNDS = 1,
+  CLASS_DELETED_GLYPH = 2,
+  CLASS_END_OF_LINE = 3,
+};
+
 template <typename Types, typename Extra>
 struct StateTable
 {
@@ -519,21 +715,53 @@ struct StateTable
     STATE_START_OF_TEXT = 0,
     STATE_START_OF_LINE = 1,
   };
-  enum Class
+
+  template <typename set_t>
+  void collect_glyphs (set_t &glyphs, unsigned num_glyphs) const
   {
-    CLASS_END_OF_TEXT = 0,
-    CLASS_OUT_OF_BOUNDS = 1,
-    CLASS_DELETED_GLYPH = 2,
-    CLASS_END_OF_LINE = 3,
-  };
+    (this+classTable).collect_glyphs (glyphs, num_glyphs);
+  }
+  template <typename set_t, typename table_t>
+  void collect_initial_glyphs (set_t &glyphs, unsigned num_glyphs, const table_t &table) const
+  {
+    unsigned num_classes = nClasses;
+
+    if (unlikely (num_classes > hb_bit_page_t::BITS))
+    {
+      (this+classTable).collect_glyphs (glyphs, num_glyphs);
+      return;
+    }
+
+    // Collect all classes going out from the start state.
+    hb_bit_page_t filter;
+
+    for (unsigned i = 0; i < num_classes; i++)
+    {
+      const auto &entry = get_entry (STATE_START_OF_TEXT, i);
+      if (new_state (entry.newState) == STATE_START_OF_TEXT &&
+          !table.is_action_initiable (entry) && !table.is_actionable (entry))
+        continue;
+
+      filter.add (i);
+    }
+
+    // And glyphs in those classes.
+    (this+classTable).collect_glyphs_filtered (glyphs, num_glyphs, filter);
+  }
 
   int new_state (unsigned int newState) const
   { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
 
-  unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+  unsigned int get_class (hb_codepoint_t glyph_id,
+                          unsigned int num_glyphs,
+                          hb_aat_class_cache_t *cache = nullptr) const
   {
+    unsigned klass;
+    if (cache && cache->get (glyph_id, &klass)) return klass;
     if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
-    return (this+classTable).get_class (glyph_id, num_glyphs, 1);
+    klass = (this+classTable).get_class (glyph_id, num_glyphs, CLASS_OUT_OF_BOUNDS);
+    if (cache) cache->set (glyph_id, klass);
+    return klass;
   }
 
   const Entry<Extra> *get_entries () const
@@ -541,13 +769,14 @@ struct StateTable
 
   const Entry<Extra> &get_entry (int state, unsigned int klass) const
   {
-    if (unlikely (klass >= nClasses))
-      klass = StateTable::CLASS_OUT_OF_BOUNDS;
+    unsigned n_classes = nClasses;
+    if (unlikely (klass >= n_classes))
+      klass = CLASS_OUT_OF_BOUNDS;
 
     const HBUSHORT *states = (this+stateArrayTable).arrayZ;
     const Entry<Extra> *entries = (this+entryTable).arrayZ;
 
-    unsigned int entry = states[state * nClasses + klass];
+    unsigned int entry = states[state * n_classes + klass];
     DEBUG_MSG (APPLY, nullptr, "e%u", entry);
 
     return entries[entry];
@@ -558,6 +787,7 @@ struct StateTable
   {
     TRACE_SANITIZE (this);
     if (unlikely (!(c->check_struct (this) &&
+                    hb_barrier () &&
                     nClasses >= 4 /* Ensure pre-defined classes fit.  */ &&
                     classTable.sanitize (c, this)))) return_trace (false);
 
@@ -684,6 +914,22 @@ struct ClassTable
   {
     return get_class (glyph_id, outOfRange);
   }
+
+  template <typename set_t>
+  void collect_glyphs (set_t &glyphs, unsigned num_glyphs) const
+  {
+    for (unsigned i = 0; i < classArray.len; i++)
+      if (classArray.arrayZ[i] != CLASS_OUT_OF_BOUNDS)
+        glyphs.add (firstGlyph + i);
+  }
+  template <typename set_t, typename filter_t>
+  void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const
+  {
+    for (unsigned i = 0; i < classArray.len; i++)
+      if (filter (classArray.arrayZ[i]))
+        glyphs.add (firstGlyph + i);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -697,6 +943,38 @@ struct ClassTable
   DEFINE_SIZE_ARRAY (4, classArray);
 };
 
+struct SubtableGlyphCoverage
+{
+  bool sanitize (hb_sanitize_context_t *c, unsigned subtable_count) const
+  {
+    TRACE_SANITIZE (this);
+
+    if (unlikely (!c->check_array (&subtableOffsets, subtable_count)))
+      return_trace (false);
+
+    unsigned bytes = (c->get_num_glyphs () + CHAR_BIT - 1) / CHAR_BIT;
+    for (unsigned i = 0; i < subtable_count; i++)
+    {
+      uint32_t offset = (uint32_t) subtableOffsets[i];
+      if (offset == 0 || offset == 0xFFFFFFFF)
+        continue;
+      if (unlikely (!subtableOffsets[i].sanitize (c, this, bytes)))
+        return_trace (false);
+    }
+
+    return_trace (true);
+  }
+  protected:
+  UnsizedArrayOf<NNOffset32To<UnsizedArrayOf<HBUINT8>>> subtableOffsets;
+                                            /* Array of offsets from the beginning of the
+                                             * subtable glyph coverage table to the glyph
+                                             * coverage bitfield for a given subtable; there
+                                             * is one offset for each subtable in the chain */
+  /* UnsizedArrayOf<HBUINT8> coverageBitfields; *//* The individual coverage bitfields. */
+  public:
+  DEFINE_SIZE_ARRAY (0, subtableOffsets);
+};
+
 struct ObsoleteTypes
 {
   static constexpr bool extended = false;
@@ -766,22 +1044,22 @@ struct ExtendedTypes
   }
 };
 
-template <typename Types, typename EntryData>
+template <typename Types, typename EntryData, typename Flags>
 struct StateTableDriver
 {
   using StateTableT = StateTable<Types, EntryData>;
   using EntryT = Entry<EntryData>;
 
   StateTableDriver (const StateTableT &machine_,
-                    hb_buffer_t *buffer_,
                     hb_face_t *face_) :
               machine (machine_),
-              buffer (buffer_),
               num_glyphs (face_->get_num_glyphs ()) {}
 
   template <typename context_t>
   void drive (context_t *c, hb_aat_apply_context_t *ac)
   {
+    hb_buffer_t *buffer = ac->buffer;
+
     if (!c->in_place)
       buffer->clear_output ();
 
@@ -816,9 +1094,9 @@ struct StateTableDriver
         }
       }
 
-      unsigned int klass = buffer->idx < buffer->len ?
-                           machine.get_class (buffer->cur().codepoint, num_glyphs) :
-                           (unsigned) StateTableT::CLASS_END_OF_TEXT;
+      unsigned int klass = likely (buffer->idx < buffer->len) ?
+                           machine.get_class (buffer->cur().codepoint, num_glyphs, ac->machine_class_cache) :
+                           (unsigned) CLASS_END_OF_TEXT;
       DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
       const EntryT &entry = machine.get_entry (state, klass);
       const int next_state = machine.new_state (entry.newState);
@@ -851,44 +1129,39 @@ struct StateTableDriver
        *
        *   https://github.com/harfbuzz/harfbuzz/issues/2860
        */
-
-      const auto is_safe_to_break_extra = [&]()
-      {
-          /* 2c. */
-          const auto wouldbe_entry = machine.get_entry(StateTableT::STATE_START_OF_TEXT, klass);
-
-          /* 2c'. */
-          if (c->is_actionable (this, wouldbe_entry))
-              return false;
-
-          /* 2c". */
-          return next_state == machine.new_state(wouldbe_entry.newState)
-              && (entry.flags & context_t::DontAdvance) == (wouldbe_entry.flags & context_t::DontAdvance);
-      };
-
-      const auto is_safe_to_break = [&]()
-      {
+      const EntryT *wouldbe_entry;
+      bool is_safe_to_break =
+      (
           /* 1. */
-          if (c->is_actionable (this, entry))
-              return false;
+          !c->table->is_actionable (entry) &&
 
           /* 2. */
           // This one is meh, I know...
-          const auto ok =
+          (
                  state == StateTableT::STATE_START_OF_TEXT
-              || ((entry.flags & context_t::DontAdvance) && next_state == StateTableT::STATE_START_OF_TEXT)
-              || is_safe_to_break_extra();
-          if (!ok)
-              return false;
+              || ((entry.flags & Flags::DontAdvance) && next_state == StateTableT::STATE_START_OF_TEXT)
+              || (
+                    /* 2c. */
+                    wouldbe_entry = &machine.get_entry(StateTableT::STATE_START_OF_TEXT, klass)
+                    ,
+                    /* 2c'. */
+                    !c->table->is_actionable (*wouldbe_entry) &&
+                    /* 2c". */
+                    (
+                      next_state == machine.new_state(wouldbe_entry->newState) &&
+                      (entry.flags & Flags::DontAdvance) == (wouldbe_entry->flags & Flags::DontAdvance)
+                    )
+                 )
+          ) &&
 
           /* 3. */
-          return !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT));
-      };
+          !c->table->is_actionable (machine.get_entry (state, CLASS_END_OF_TEXT))
+      );
 
-      if (!is_safe_to_break () && buffer->backtrack_len () && buffer->idx < buffer->len)
+      if (!is_safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
         buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
 
-      c->transition (this, entry);
+      c->transition (buffer, this, entry);
 
       state = next_state;
       DEBUG_MSG (APPLY, nullptr, "s%d", state);
@@ -896,7 +1169,7 @@ struct StateTableDriver
       if (buffer->idx == buffer->len || unlikely (!buffer->successful))
         break;
 
-      if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
+      if (!(entry.flags & Flags::DontAdvance) || buffer->max_ops-- <= 0)
         (void) buffer->next_glyph ();
     }
 
@@ -906,7 +1179,6 @@ struct StateTableDriver
 
   public:
   const StateTableT &machine;
-  hb_buffer_t *buffer;
   unsigned int num_glyphs;
 };
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-feat-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-feat-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-feat-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-feat-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -138,6 +138,7 @@ struct FeatureName
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
                           (base+settingTableZ).sanitize (c, nSettings)));
   }
 
@@ -200,6 +201,7 @@ struct feat
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
                           version.major == 1 &&
                           namesZ.sanitize (c, featureNameCount, this)));
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-just-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-just-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-just-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-just-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -185,15 +185,16 @@ struct ActionSubrecord
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
       return_trace (false);
+    hb_barrier ();
 
     switch (u.header.actionType)
     {
-    case 0:  return_trace (u.decompositionAction.sanitize (c));
-    case 1:  return_trace (u.unconditionalAddGlyphAction.sanitize (c));
-    case 2:  return_trace (u.conditionalAddGlyphAction.sanitize (c));
-    // case 3: return_trace (u.stretchGlyphAction.sanitize (c));
-    case 4:  return_trace (u.decompositionAction.sanitize (c));
-    case 5:  return_trace (u.decompositionAction.sanitize (c));
+    case 0: hb_barrier ();  return_trace (u.decompositionAction.sanitize (c));
+    case 1: hb_barrier ();  return_trace (u.unconditionalAddGlyphAction.sanitize (c));
+    case 2: hb_barrier ();  return_trace (u.conditionalAddGlyphAction.sanitize (c));
+    // case 3: hb_barrier (); return_trace (u.stretchGlyphAction.sanitize (c));
+    case 4: hb_barrier ();  return_trace (u.decompositionAction.sanitize (c));
+    case 5: hb_barrier ();  return_trace (u.decompositionAction.sanitize (c));
     default: return_trace (true);
     }
   }
@@ -220,6 +221,7 @@ struct PostcompensationActionChain
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
       return_trace (false);
+    hb_barrier ();
 
     unsigned int offset = min_size;
     for (unsigned int i = 0; i < count; i++)
@@ -389,6 +391,7 @@ struct just
     TRACE_SANITIZE (this);
 
     return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
                           version.major == 1 &&
                           horizData.sanitize (c, this, this) &&
                           vertData.sanitize (c, this, this)));
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -30,6 +30,7 @@
 
 #include "hb-kern.hh"
 #include "hb-aat-layout-ankr-table.hh"
+#include "hb-set-digest.hh"
 
 /*
  * kerx -- Extended Kerning
@@ -54,6 +55,7 @@ kerxTupleKern (int value,
   unsigned int offset = value;
   const FWORD *pv = &StructAtOffset<FWORD> (base, offset);
   if (unlikely (!c->sanitizer.check_array (pv, tupleCount))) return 0;
+  hb_barrier ();
   return *pv;
 }
 
@@ -81,7 +83,7 @@ struct KernPair
     return_trace (c->check_struct (this));
   }
 
-  protected:
+  public:
   HBGlyphID16   left;
   HBGlyphID16   right;
   FWORD         value;
@@ -105,10 +107,10 @@ struct KerxSubTableFormat0
     TRACE_APPLY (this);
 
     if (!c->plan->requested_kerning)
-      return false;
+      return_trace (false);
 
     if (header.coverage & header.Backwards)
-      return false;
+      return_trace (false);
 
     accelerator_t accel (*this, c);
     hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
@@ -117,6 +119,16 @@ struct KerxSubTableFormat0
     return_trace (true);
   }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
+  {
+    for (const KernPair& pair : pairs)
+    {
+      left_set.add (pair.left);
+      right_set.add (pair.right);
+    }
+  }
+
   struct accelerator_t
   {
     const KerxSubTableFormat0 &table;
@@ -127,7 +139,10 @@ struct KerxSubTableFormat0
                      table (table_), c (c_) {}
 
     int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
-    { return table.get_kerning (left, right, c); }
+    {
+      if (!(*c->left_set)[left] || !(*c->right_set)[right]) return 0;
+      return table.get_kerning (left, right, c);
+    }
   };
 
 
@@ -192,6 +207,9 @@ struct Format1Entry<false>
 
   typedef void EntryData;
 
+  static bool initiateAction (const Entry<EntryData> &entry)
+  { return entry.flags & Push; }
+
   static bool performAction (const Entry<EntryData> &entry)
   { return entry.flags & Offset; }
 
@@ -208,13 +226,23 @@ struct KerxSubTableFormat1
   typedef Format1Entry<Types::extended> Format1EntryT;
   typedef typename Format1EntryT::EntryData EntryData;
 
+  enum Flags
+  {
+    DontAdvance = Format1EntryT::DontAdvance,
+  };
+
+  bool is_action_initiable (const Entry<EntryData> &entry) const
+  {
+    return Format1EntryT::initiateAction (entry);
+  }
+  bool is_actionable (const Entry<EntryData> &entry) const
+  {
+    return Format1EntryT::performAction (entry);
+  }
+
   struct driver_context_t
   {
     static constexpr bool in_place = true;
-    enum
-    {
-      DontAdvance       = Format1EntryT::DontAdvance,
-    };
 
     driver_context_t (const KerxSubTableFormat1 *table_,
                       hb_aat_apply_context_t *c_) :
@@ -227,13 +255,10 @@ struct KerxSubTableFormat1
         depth (0),
         crossStream (table->header.coverage & table->header.CrossStream) {}
 
-    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
-                        const Entry<EntryData> &entry)
-    { return Format1EntryT::performAction (entry); }
-    void transition (StateTableDriver<Types, EntryData> *driver,
+    void transition (hb_buffer_t *buffer,
+                     StateTableDriver<Types, EntryData, Flags> *driver,
                      const Entry<EntryData> &entry)
     {
-      hb_buffer_t *buffer = driver->buffer;
       unsigned int flags = entry.flags;
 
       if (flags & Format1EntryT::Reset)
@@ -259,6 +284,7 @@ struct KerxSubTableFormat1
           depth = 0;
           return;
         }
+        hb_barrier ();
 
         hb_mask_t kern_mask = c->plan->kern_mask;
 
@@ -330,9 +356,10 @@ struct KerxSubTableFormat1
       }
     }
 
-    private:
+    public:
     hb_aat_apply_context_t *c;
     const KerxSubTableFormat1 *table;
+    private:
     const UnsizedArrayOf<FWORD> &kernAction;
     unsigned int stack[8];
     unsigned int depth;
@@ -349,7 +376,8 @@ struct KerxSubTableFormat1
 
     driver_context_t dc (this, c);
 
-    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
+    StateTableDriver<Types, EntryData, Flags> driver (machine, c->font->face);
+
     driver.drive (&dc, c);
 
     return_trace (true);
@@ -363,12 +391,21 @@ struct KerxSubTableFormat1
                           machine.sanitize (c)));
   }
 
+  template <typename set_t>
+  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);
+  }
+
   protected:
   KernSubTableHeader                            header;
   StateTable<Types, EntryData>                  machine;
   NNOffsetTo<UnsizedArrayOf<FWORD>, HBUINT>     kernAction;
   public:
-  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 5 * sizeof (HBUINT));
+  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + (StateTable<Types, EntryData>::static_size + HBUINT::static_size));
 };
 
 template <typename KernSubTableHeader>
@@ -389,6 +426,7 @@ struct KerxSubTableFormat2
     kern_idx = Types::offsetToIndex (kern_idx, this, arrayZ.arrayZ);
     const FWORD *v = &arrayZ[kern_idx];
     if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
+    hb_barrier ();
 
     return kerxTupleKern (*v, header.tuple_count (), this, c);
   }
@@ -398,10 +436,10 @@ struct KerxSubTableFormat2
     TRACE_APPLY (this);
 
     if (!c->plan->requested_kerning)
-      return false;
+      return_trace (false);
 
     if (header.coverage & header.Backwards)
-      return false;
+      return_trace (false);
 
     accelerator_t accel (*this, c);
     hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
@@ -410,6 +448,13 @@ struct KerxSubTableFormat2
     return_trace (true);
   }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
+  {
+    (this+leftClassTable).collect_glyphs (left_set, num_glyphs);
+    (this+rightClassTable).collect_glyphs (right_set, num_glyphs);
+  }
+
   struct accelerator_t
   {
     const KerxSubTableFormat2 &table;
@@ -420,7 +465,10 @@ struct KerxSubTableFormat2
                      table (table_), c (c_) {}
 
     int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
-    { return table.get_kerning (left, right, c); }
+    {
+      if (!(*c->left_set)[left] || !(*c->right_set)[right]) return 0;
+      return table.get_kerning (left, right, c);
+    }
   };
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -429,6 +477,7 @@ struct KerxSubTableFormat2
     return_trace (likely (c->check_struct (this) &&
                           leftClassTable.sanitize (c, this) &&
                           rightClassTable.sanitize (c, this) &&
+                          hb_barrier () &&
                           c->check_range (this, array)));
   }
 
@@ -461,17 +510,26 @@ struct KerxSubTableFormat4
     DEFINE_SIZE_STATIC (2);
   };
 
-  struct driver_context_t
+  enum Flags
   {
-    static constexpr bool in_place = true;
-    enum Flags
-    {
-      Mark              = 0x8000,       /* If set, remember this glyph as the marked glyph. */
-      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph before
+    Mark                = 0x8000,       /* If set, remember this glyph as the marked glyph. */
+    DontAdvance         = 0x4000,       /* If set, don't advance to the next glyph before
                                          * going to the new state. */
-      Reserved          = 0x3FFF,       /* Not used; set to 0. */
-    };
+    Reserved            = 0x3FFF,       /* Not used; set to 0. */
+  };
+
+  bool is_action_initiable (const Entry<EntryData> &entry) const
+  {
+    return (entry.flags & Mark);
+  }
+  bool is_actionable (const Entry<EntryData> &entry) const
+  {
+    return entry.data.ankrActionIndex != 0xFFFF;
+  }
 
+  struct driver_context_t
+  {
+    static constexpr bool in_place = true;
     enum SubTableFlags
     {
       ActionType        = 0xC0000000,   /* A two-bit field containing the action type. */
@@ -481,22 +539,19 @@ struct KerxSubTableFormat4
                                          * point table. */
     };
 
-    driver_context_t (const KerxSubTableFormat4 *table,
+    driver_context_t (const KerxSubTableFormat4 *table_,
                       hb_aat_apply_context_t *c_) :
         c (c_),
+        table (table_),
         action_type ((table->flags & ActionType) >> 30),
         ankrData ((HBUINT16 *) ((const char *) &table->machine + (table->flags & Offset))),
         mark_set (false),
         mark (0) {}
 
-    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
-                        const Entry<EntryData> &entry)
-    { return entry.data.ankrActionIndex != 0xFFFF; }
-    void transition (StateTableDriver<Types, EntryData> *driver,
+    void transition (hb_buffer_t *buffer,
+                     StateTableDriver<Types, EntryData, Flags> *driver,
                      const Entry<EntryData> &entry)
     {
-      hb_buffer_t *buffer = driver->buffer;
-
       if (mark_set && entry.data.ankrActionIndex != 0xFFFF && buffer->idx < buffer->len)
       {
         hb_glyph_position_t &o = buffer->cur_pos();
@@ -509,6 +564,7 @@ struct KerxSubTableFormat4
                double the ankrActionIndex to get the correct offset here. */
             const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex * 2];
             if (!c->sanitizer.check_array (data, 2)) return;
+            hb_barrier ();
             unsigned int markControlPoint = *data++;
             unsigned int currControlPoint = *data++;
             hb_position_t markX = 0;
@@ -537,6 +593,7 @@ struct KerxSubTableFormat4
                double the ankrActionIndex to get the correct offset here. */
             const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex * 2];
             if (!c->sanitizer.check_array (data, 2)) return;
+            hb_barrier ();
             unsigned int markAnchorPoint = *data++;
             unsigned int currAnchorPoint = *data++;
             const Anchor &markAnchor = c->ankr_table->get_anchor (c->buffer->info[mark].codepoint,
@@ -557,6 +614,7 @@ struct KerxSubTableFormat4
                by 4 to get the correct offset for the given action. */
             const FWORD *data = (const FWORD *) &ankrData[entry.data.ankrActionIndex * 4];
             if (!c->sanitizer.check_array (data, 4)) return;
+            hb_barrier ();
             int markX = *data++;
             int markY = *data++;
             int currX = *data++;
@@ -579,8 +637,10 @@ struct KerxSubTableFormat4
       }
     }
 
-    private:
+    public:
     hb_aat_apply_context_t *c;
+    const KerxSubTableFormat4 *table;
+    private:
     unsigned int action_type;
     const HBUINT16 *ankrData;
     bool mark_set;
@@ -593,7 +653,8 @@ struct KerxSubTableFormat4
 
     driver_context_t dc (this, c);
 
-    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
+    StateTableDriver<Types, EntryData, Flags> driver (machine, c->font->face);
+
     driver.drive (&dc, c);
 
     return_trace (true);
@@ -607,12 +668,21 @@ struct KerxSubTableFormat4
                           machine.sanitize (c)));
   }
 
+  template <typename set_t>
+  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);
+  }
+
   protected:
   KernSubTableHeader            header;
   StateTable<Types, EntryData>  machine;
   HBUINT32                      flags;
   public:
-  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 20);
+  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + (StateTable<Types, EntryData>::static_size + HBUINT32::static_size));
 };
 
 template <typename KernSubTableHeader>
@@ -631,7 +701,7 @@ struct KerxSubTableFormat6
     unsigned int num_glyphs = c->sanitizer.get_num_glyphs ();
     if (is_long ())
     {
-      const typename U::Long &t = u.l;
+      const auto &t = u.l;
       unsigned int l = (this+t.rowIndexTable).get_value_or_null (left, num_glyphs);
       unsigned int r = (this+t.columnIndexTable).get_value_or_null (right, num_glyphs);
       unsigned int offset = l + r;
@@ -639,16 +709,18 @@ struct KerxSubTableFormat6
       if (unlikely (hb_unsigned_mul_overflows (offset, sizeof (FWORD32)))) return 0;
       const FWORD32 *v = &StructAtOffset<FWORD32> (&(this+t.array), offset * sizeof (FWORD32));
       if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
+      hb_barrier ();
       return kerxTupleKern (*v, header.tuple_count (), &(this+vector), c);
     }
     else
     {
-      const typename U::Short &t = u.s;
+      const auto &t = u.s;
       unsigned int l = (this+t.rowIndexTable).get_value_or_null (left, num_glyphs);
       unsigned int r = (this+t.columnIndexTable).get_value_or_null (right, num_glyphs);
       unsigned int offset = l + r;
       const FWORD *v = &StructAtOffset<FWORD> (&(this+t.array), offset * sizeof (FWORD));
       if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
+      hb_barrier ();
       return kerxTupleKern (*v, header.tuple_count (), &(this+vector), c);
     }
   }
@@ -658,10 +730,10 @@ struct KerxSubTableFormat6
     TRACE_APPLY (this);
 
     if (!c->plan->requested_kerning)
-      return false;
+      return_trace (false);
 
     if (header.coverage & header.Backwards)
-      return false;
+      return_trace (false);
 
     accelerator_t accel (*this, c);
     hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
@@ -674,6 +746,7 @@ struct KerxSubTableFormat6
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
                           (is_long () ?
                            (
                              u.l.rowIndexTable.sanitize (c, this) &&
@@ -688,6 +761,23 @@ struct KerxSubTableFormat6
                            c->check_range (this, vector))));
   }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
+  {
+    if (is_long ())
+    {
+      const auto &t = u.l;
+      (this+t.rowIndexTable).collect_glyphs (left_set, num_glyphs);
+      (this+t.columnIndexTable).collect_glyphs (right_set, num_glyphs);
+    }
+    else
+    {
+      const auto &t = u.s;
+      (this+t.rowIndexTable).collect_glyphs (left_set, num_glyphs);
+      (this+t.columnIndexTable).collect_glyphs (right_set, num_glyphs);
+    }
+  }
+
   struct accelerator_t
   {
     const KerxSubTableFormat6 &table;
@@ -698,7 +788,10 @@ struct KerxSubTableFormat6
                      table (table_), c (c_) {}
 
     int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
-    { return table.get_kerning (left, right, c); }
+    {
+      if (!(*c->left_set)[left] || !(*c->right_set)[right]) return 0;
+      return table.get_kerning (left, right, c);
+    }
   };
 
   protected:
@@ -784,12 +877,27 @@ struct KerxSubTable
     }
   }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
+  {
+    unsigned int subtable_type = get_type ();
+    switch (subtable_type) {
+    case 0:     u.format0.collect_glyphs (left_set, right_set, num_glyphs); return;
+    case 1:     u.format1.collect_glyphs (left_set, right_set, num_glyphs); return;
+    case 2:     u.format2.collect_glyphs (left_set, right_set, num_glyphs); return;
+    case 4:     u.format4.collect_glyphs (left_set, right_set, num_glyphs); return;
+    case 6:     u.format6.collect_glyphs (left_set, right_set, num_glyphs); return;
+    default:    return;
+    }
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!u.header.sanitize (c) ||
-        u.header.length <= u.header.static_size ||
-        !c->check_range (this, u.header.length))
+    if (!(u.header.sanitize (c) &&
+          hb_barrier () &&
+          u.header.length >= u.header.static_size &&
+          c->check_range (this, u.header.length)))
       return_trace (false);
 
     return_trace (dispatch (c));
@@ -813,6 +921,8 @@ struct KerxSubTable
  * The 'kerx' Table
  */
 
+using kern_accelerator_data_t = hb_vector_t<hb_pair_t<hb_bit_set_t, hb_bit_set_t>>;
+
 template <typename T>
 struct KerxTable
 {
@@ -829,6 +939,9 @@ struct KerxTable
     {
       if (st->get_type () == 1)
         return true;
+
+      // TODO: What about format 4? What's this API used for anyway?
+
       st = &StructAfter<SubTable> (*st);
     }
     return false;
@@ -867,7 +980,8 @@ struct KerxTable
     return v;
   }
 
-  bool apply (AAT::hb_aat_apply_context_t *c) const
+  bool apply (AAT::hb_aat_apply_context_t *c,
+              const kern_accelerator_data_t &accel_data) const
   {
     c->buffer->unsafe_to_concat ();
 
@@ -914,6 +1028,9 @@ 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);
@@ -936,9 +1053,10 @@ struct KerxTable
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!thiz()->version.sanitize (c) ||
-                  (unsigned) thiz()->version < (unsigned) T::minVersion ||
-                  !thiz()->tableCount.sanitize (c)))
+    if (unlikely (!(thiz()->version.sanitize (c) &&
+                    hb_barrier () &&
+                    (unsigned) thiz()->version >= (unsigned) T::minVersion &&
+                    thiz()->tableCount.sanitize (c))))
       return_trace (false);
 
     typedef typename T::SubTable SubTable;
@@ -949,6 +1067,7 @@ struct KerxTable
     {
       if (unlikely (!st->u.header.sanitize (c)))
         return_trace (false);
+      hb_barrier ();
       /* OpenType kern table has 2-byte subtable lengths.  That's limiting.
        * MS implementation also only supports one subtable, of format 0,
        * anyway.  Certain versions of some fonts, like Calibry, contain
@@ -964,8 +1083,61 @@ struct KerxTable
       st = &StructAfter<SubTable> (*st);
     }
 
+    unsigned majorVersion = thiz()->version;
+    if (sizeof (thiz()->version) == 4)
+      majorVersion = majorVersion >> 16;
+    if (majorVersion >= 3)
+    {
+      const SubtableGlyphCoverage *coverage = (const SubtableGlyphCoverage *) st;
+      if (!coverage->sanitize (c, count))
+        return_trace (false);
+    }
+
     return_trace (true);
   }
+
+  kern_accelerator_data_t create_accelerator_data (unsigned num_glyphs) const
+  {
+    kern_accelerator_data_t accel_data;
+
+    typedef typename T::SubTable SubTable;
+
+    const SubTable *st = &thiz()->firstSubTable;
+    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));
+      st = &StructAfter<SubTable> (*st);
+    }
+
+    return accel_data;
+  }
+
+  struct accelerator_t
+  {
+    accelerator_t (hb_face_t *face)
+    {
+      hb_sanitize_context_t sc;
+      this->table = sc.reference_table<T> (face);
+      this->accel_data = this->table->create_accelerator_data (face->get_num_glyphs ());
+    }
+    ~accelerator_t ()
+    {
+      this->table.destroy ();
+    }
+
+    hb_blob_t *get_blob () const { return table.get_blob (); }
+
+    bool apply (AAT::hb_aat_apply_context_t *c) const
+    {
+      return table->apply (c, accel_data);
+    }
+
+    hb_blob_ptr_t<T> table;
+    kern_accelerator_data_t accel_data;
+  };
 };
 
 struct kerx : KerxTable<kerx>
@@ -994,8 +1166,10 @@ struct kerx : KerxTable<kerx>
   DEFINE_SIZE_MIN (8);
 };
 
+struct kerx_accelerator_t : kerx::accelerator_t {
+  kerx_accelerator_t (hb_face_t *face) : kerx::accelerator_t (face) {}
+};
 
 } /* namespace AAT */
 
-
 #endif /* HB_AAT_LAYOUT_KERX_TABLE_HH */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -29,6 +29,7 @@
 
 #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"
@@ -53,36 +54,42 @@ struct RearrangementSubtable
 
   typedef void EntryData;
 
-  struct driver_context_t
+  enum Flags
   {
-    static constexpr bool in_place = true;
-    enum Flags
-    {
-      MarkFirst         = 0x8000,       /* If set, make the current glyph the first
+    MarkFirst           = 0x8000,       /* If set, make the current glyph the first
                                          * glyph to be rearranged. */
-      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph
+    DontAdvance         = 0x4000,       /* If set, don't advance to the next glyph
                                          * before going to the new state. This means
                                          * that the glyph index doesn't change, even
                                          * if the glyph at that index has changed. */
-      MarkLast          = 0x2000,       /* If set, make the current glyph the last
+    MarkLast            = 0x2000,       /* If set, make the current glyph the last
                                          * glyph to be rearranged. */
-      Reserved          = 0x1FF0,       /* These bits are reserved and should be set to 0. */
-      Verb              = 0x000F,       /* The type of rearrangement specified. */
-    };
+    Reserved            = 0x1FF0,       /* These bits are reserved and should be set to 0. */
+    Verb                = 0x000F,       /* The type of rearrangement specified. */
+  };
+
+  bool is_action_initiable (const Entry<EntryData> &entry) const
+  {
+    return (entry.flags & MarkFirst);
+  }
+  bool is_actionable (const Entry<EntryData> &entry) const
+  {
+    return (entry.flags & Verb);
+  }
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = true;
 
-    driver_context_t (const RearrangementSubtable *table HB_UNUSED) :
+    driver_context_t (const RearrangementSubtable *table_) :
         ret (false),
+        table (table_),
         start (0), end (0) {}
 
-    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
-                        const Entry<EntryData> &entry)
-    {
-      return (entry.flags & Verb) && start < end;
-    }
-    void transition (StateTableDriver<Types, EntryData> *driver,
+    void transition (hb_buffer_t *buffer,
+                     StateTableDriver<Types, EntryData, Flags> *driver,
                      const Entry<EntryData> &entry)
     {
-      hb_buffer_t *buffer = driver->buffer;
       unsigned int flags = entry.flags;
 
       if (flags & MarkFirst)
@@ -157,6 +164,7 @@ struct RearrangementSubtable
 
     public:
     bool ret;
+    const RearrangementSubtable *table;
     private:
     unsigned int start;
     unsigned int end;
@@ -168,7 +176,14 @@ struct RearrangementSubtable
 
     driver_context_t dc (this);
 
-    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+    StateTableDriver<Types, EntryData, Flags> 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);
@@ -180,10 +195,10 @@ struct RearrangementSubtable
     return_trace (machine.sanitize (c));
   }
 
-  protected:
+  public:
   StateTable<Types, EntryData>  machine;
   public:
-  DEFINE_SIZE_STATIC (16);
+  DEFINE_SIZE_STATIC ((StateTable<Types, EntryData>::static_size));
 };
 
 template <typename Types>
@@ -201,43 +216,42 @@ struct ContextualSubtable
     DEFINE_SIZE_STATIC (4);
   };
 
+  enum Flags
+  {
+    SetMark             = 0x8000,       /* If set, make the current glyph the marked glyph. */
+    DontAdvance         = 0x4000,       /* If set, don't advance to the next glyph before
+                                         * going to the new state. */
+    Reserved            = 0x3FFF,       /* These bits are reserved and should be set to 0. */
+  };
+
+  bool is_action_initiable (const Entry<EntryData> &entry) const
+  {
+    return (entry.flags & SetMark);
+  }
+  bool is_actionable (const Entry<EntryData> &entry) const
+  {
+    return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
+  }
+
   struct driver_context_t
   {
     static constexpr bool in_place = true;
-    enum Flags
-    {
-      SetMark           = 0x8000,       /* If set, make the current glyph the marked glyph. */
-      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph before
-                                         * going to the new state. */
-      Reserved          = 0x3FFF,       /* These bits are reserved and should be set to 0. */
-    };
 
     driver_context_t (const ContextualSubtable *table_,
                              hb_aat_apply_context_t *c_) :
         ret (false),
         c (c_),
+        table (table_),
         gdef (*c->gdef_table),
         mark_set (false),
         has_glyph_classes (gdef.has_glyph_classes ()),
         mark (0),
-        table (table_),
         subs (table+table->substitutionTables) {}
 
-    bool is_actionable (StateTableDriver<Types, EntryData> *driver,
-                        const Entry<EntryData> &entry)
-    {
-      hb_buffer_t *buffer = driver->buffer;
-
-      if (buffer->idx == buffer->len && !mark_set)
-        return false;
-
-      return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
-    }
-    void transition (StateTableDriver<Types, EntryData> *driver,
+    void transition (hb_buffer_t *buffer,
+                     StateTableDriver<Types, EntryData, Flags> *driver,
                      const Entry<EntryData> &entry)
     {
-      hb_buffer_t *buffer = driver->buffer;
-
       /* Looks like CoreText applies neither mark nor current substitution for
        * end-of-text if mark was not explicitly set. */
       if (buffer->idx == buffer->len && !mark_set)
@@ -259,13 +273,17 @@ struct ContextualSubtable
         unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint;
         const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) subs;
         replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
-        if (!replacement->sanitize (&c->sanitizer) || !*replacement)
+        if (!(replacement->sanitize (&c->sanitizer) &&
+              hb_barrier () &&
+              *replacement))
           replacement = nullptr;
       }
       if (replacement)
       {
         buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len));
-        buffer->info[mark].codepoint = *replacement;
+        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));
@@ -287,12 +305,16 @@ struct ContextualSubtable
         unsigned int offset = entry.data.currentIndex + buffer->info[idx].codepoint;
         const UnsizedArrayOf<HBGlyphID16> &subs_old = (const UnsizedArrayOf<HBGlyphID16> &) subs;
         replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
-        if (!replacement->sanitize (&c->sanitizer) || !*replacement)
+        if (!(replacement->sanitize (&c->sanitizer) &&
+              hb_barrier () &&
+              *replacement))
           replacement = nullptr;
       }
       if (replacement)
       {
-        buffer->info[idx].codepoint = *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));
@@ -308,14 +330,14 @@ struct ContextualSubtable
 
     public:
     bool ret;
-    private:
     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 ContextualSubtable *table;
-    const UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, false> &subs;
+    const UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, void, false> &subs;
   };
 
   bool apply (hb_aat_apply_context_t *c) const
@@ -324,7 +346,14 @@ struct ContextualSubtable
 
     driver_context_t dc (this, c);
 
-    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+    StateTableDriver<Types, EntryData, Flags> 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);
@@ -336,6 +365,7 @@ struct ContextualSubtable
 
     unsigned int num_entries = 0;
     if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false);
+    hb_barrier ();
 
     if (!Types::extended)
       return_trace (substitutionTables.sanitize (c, this, 0));
@@ -356,13 +386,14 @@ struct ContextualSubtable
     return_trace (substitutionTables.sanitize (c, this, num_lookups));
   }
 
-  protected:
+  public:
   StateTable<Types, EntryData>
                 machine;
-  NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, false>, HBUINT>
+  protected:
+  NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, void, false>, HBUINT>
                 substitutionTables;
   public:
-  DEFINE_SIZE_STATIC (20);
+  DEFINE_SIZE_STATIC ((StateTable<Types, EntryData>::static_size + HBUINT::static_size));
 };
 
 
@@ -372,6 +403,16 @@ struct LigatureEntry;
 template <>
 struct LigatureEntry<true>
 {
+
+  struct EntryData
+  {
+    HBUINT16    ligActionIndex; /* Index to the first ligActionTable entry
+                                 * for processing this group, if indicated
+                                 * by the flags. */
+    public:
+    DEFINE_SIZE_STATIC (2);
+  };
+
   enum Flags
   {
     SetComponent        = 0x8000,       /* Push this glyph onto the component stack for
@@ -383,14 +424,8 @@ struct LigatureEntry<true>
     Reserved            = 0x1FFF,       /* These bits are reserved and should be set to 0. */
   };
 
-  struct EntryData
-  {
-    HBUINT16    ligActionIndex; /* Index to the first ligActionTable entry
-                                 * for processing this group, if indicated
-                                 * by the flags. */
-    public:
-    DEFINE_SIZE_STATIC (2);
-  };
+  static bool initiateAction (const Entry<EntryData> &entry)
+  { return entry.flags & SetComponent; }
 
   static bool performAction (const Entry<EntryData> &entry)
   { return entry.flags & PerformAction; }
@@ -401,6 +436,8 @@ struct LigatureEntry<true>
 template <>
 struct LigatureEntry<false>
 {
+  typedef void EntryData;
+
   enum Flags
   {
     SetComponent        = 0x8000,       /* Push this glyph onto the component stack for
@@ -412,7 +449,8 @@ struct LigatureEntry<false>
                                          * multiple of 4. */
   };
 
-  typedef void EntryData;
+  static bool initiateAction (const Entry<EntryData> &entry)
+  { return entry.flags & SetComponent; }
 
   static bool performAction (const Entry<EntryData> &entry)
   { return entry.flags & Offset; }
@@ -430,13 +468,23 @@ struct LigatureSubtable
   typedef LigatureEntry<Types::extended> LigatureEntryT;
   typedef typename LigatureEntryT::EntryData EntryData;
 
+  enum Flags
+  {
+    DontAdvance = LigatureEntryT::DontAdvance,
+  };
+
+  bool is_action_initiable (const Entry<EntryData> &entry) const
+  {
+    return LigatureEntryT::initiateAction (entry);
+  }
+  bool is_actionable (const Entry<EntryData> &entry) const
+  {
+    return LigatureEntryT::performAction (entry);
+  }
+
   struct driver_context_t
   {
     static constexpr bool in_place = false;
-    enum
-    {
-      DontAdvance       = LigatureEntryT::DontAdvance,
-    };
     enum LigActionFlags
     {
       LigActionLast     = 0x80000000,   /* This is the last action in the list. This also
@@ -459,16 +507,10 @@ struct LigatureSubtable
         ligature (table+table->ligature),
         match_length (0) {}
 
-    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
-                        const Entry<EntryData> &entry)
-    {
-      return LigatureEntryT::performAction (entry);
-    }
-    void transition (StateTableDriver<Types, EntryData> *driver,
+    void transition (hb_buffer_t *buffer,
+                     StateTableDriver<Types, EntryData, Flags> *driver,
                      const Entry<EntryData> &entry)
     {
-      hb_buffer_t *buffer = driver->buffer;
-
       DEBUG_MSG (APPLY, nullptr, "Ligature transition at %u", buffer->idx);
       if (entry.flags & LigatureEntryT::SetComponent)
       {
@@ -513,6 +555,7 @@ struct LigatureSubtable
           if (unlikely (!buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]))) return;
 
           if (unlikely (!actionData->sanitize (&c->sanitizer))) break;
+          hb_barrier ();
           action = *actionData;
 
           uint32_t uoffset = action & LigActionOffset;
@@ -523,6 +566,7 @@ struct LigatureSubtable
           component_idx = Types::wordOffsetToIndex (component_idx, table, component.arrayZ);
           const HBUINT16 &componentData = component[component_idx];
           if (unlikely (!componentData.sanitize (&c->sanitizer))) break;
+          hb_barrier ();
           ligature_idx += componentData;
 
           DEBUG_MSG (APPLY, nullptr, "Action store %d last %d",
@@ -533,6 +577,7 @@ struct LigatureSubtable
             ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ);
             const HBGlyphID16 &ligatureData = ligature[ligature_idx];
             if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break;
+            hb_barrier ();
             hb_codepoint_t lig = ligatureData;
 
             DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
@@ -544,6 +589,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;
             }
 
@@ -560,9 +606,9 @@ struct LigatureSubtable
 
     public:
     bool ret;
-    private:
     hb_aat_apply_context_t *c;
     const LigatureSubtable *table;
+    private:
     const UnsizedArrayOf<HBUINT32> &ligAction;
     const UnsizedArrayOf<HBUINT16> &component;
     const UnsizedArrayOf<HBGlyphID16> &ligature;
@@ -576,7 +622,14 @@ struct LigatureSubtable
 
     driver_context_t dc (this, c);
 
-    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+    StateTableDriver<Types, EntryData, Flags> 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);
@@ -587,12 +640,14 @@ struct LigatureSubtable
     TRACE_SANITIZE (this);
     /* The rest of array sanitizations are done at run-time. */
     return_trace (c->check_struct (this) && machine.sanitize (c) &&
+                  hb_barrier () &&
                   ligAction && component && ligature);
   }
 
-  protected:
+  public:
   StateTable<Types, EntryData>
                 machine;
+  protected:
   NNOffsetTo<UnsizedArrayOf<HBUINT32>, HBUINT>
                 ligAction;      /* Offset to the ligature action table. */
   NNOffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT>
@@ -600,7 +655,7 @@ struct LigatureSubtable
   NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, HBUINT>
                 ligature;       /* Offset to the actual ligature lists. */
   public:
-  DEFINE_SIZE_STATIC (28);
+  DEFINE_SIZE_STATIC ((StateTable<Types, EntryData>::static_size + 3 * HBUINT::static_size));
 };
 
 template <typename Types>
@@ -610,6 +665,12 @@ 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 ();
 
@@ -642,7 +703,9 @@ struct NoncontextualSubtable
       const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
       if (replacement)
       {
-        info[i].codepoint = *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));
@@ -653,6 +716,12 @@ struct NoncontextualSubtable
     return_trace (ret);
   }
 
+  template <typename set_t>
+  void collect_initial_glyphs (set_t &glyphs, unsigned num_glyphs) const
+  {
+    substitute.collect_glyphs (glyphs, num_glyphs);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -686,74 +755,80 @@ struct InsertionSubtable
     DEFINE_SIZE_STATIC (4);
   };
 
+  enum Flags
+  {
+    SetMark             = 0x8000,     /* If set, mark the current glyph. */
+    DontAdvance         = 0x4000,     /* If set, don't advance to the next glyph before
+                                       * going to the new state.  This does not mean
+                                       * that the glyph pointed to is the same one as
+                                       * before. If you've made insertions immediately
+                                       * downstream of the current glyph, the next glyph
+                                       * processed would in fact be the first one
+                                       * inserted. */
+    CurrentIsKashidaLike= 0x2000,     /* If set, and the currentInsertList is nonzero,
+                                       * then the specified glyph list will be inserted
+                                       * as a kashida-like insertion, either before or
+                                       * after the current glyph (depending on the state
+                                       * of the currentInsertBefore flag). If clear, and
+                                       * the currentInsertList is nonzero, then the
+                                       * specified glyph list will be inserted as a
+                                       * split-vowel-like insertion, either before or
+                                       * after the current glyph (depending on the state
+                                       * of the currentInsertBefore flag). */
+    MarkedIsKashidaLike= 0x1000,      /* If set, and the markedInsertList is nonzero,
+                                       * then the specified glyph list will be inserted
+                                       * as a kashida-like insertion, either before or
+                                       * after the marked glyph (depending on the state
+                                       * of the markedInsertBefore flag). If clear, and
+                                       * the markedInsertList is nonzero, then the
+                                       * specified glyph list will be inserted as a
+                                       * split-vowel-like insertion, either before or
+                                       * after the marked glyph (depending on the state
+                                       * of the markedInsertBefore flag). */
+    CurrentInsertBefore= 0x0800,      /* If set, specifies that insertions are to be made
+                                       * to the left of the current glyph. If clear,
+                                       * they're made to the right of the current glyph. */
+    MarkedInsertBefore= 0x0400,       /* If set, specifies that insertions are to be
+                                       * made to the left of the marked glyph. If clear,
+                                       * they're made to the right of the marked glyph. */
+    CurrentInsertCount= 0x3E0,        /* This 5-bit field is treated as a count of the
+                                       * number of glyphs to insert at the current
+                                       * position. Since zero means no insertions, the
+                                       * largest number of insertions at any given
+                                       * current location is 31 glyphs. */
+    MarkedInsertCount= 0x001F,        /* This 5-bit field is treated as a count of the
+                                       * number of glyphs to insert at the marked
+                                       * position. Since zero means no insertions, the
+                                       * largest number of insertions at any given
+                                       * marked location is 31 glyphs. */
+  };
+
+  bool is_action_initiable (const Entry<EntryData> &entry) const
+  {
+    return (entry.flags & SetMark);
+  }
+  bool is_actionable (const Entry<EntryData> &entry) const
+  {
+    return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) &&
+           (entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF);
+  }
+
   struct driver_context_t
   {
     static constexpr bool in_place = false;
-    enum Flags
-    {
-      SetMark           = 0x8000,       /* If set, mark the current glyph. */
-      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph before
-                                         * going to the new state.  This does not mean
-                                         * that the glyph pointed to is the same one as
-                                         * before. If you've made insertions immediately
-                                         * downstream of the current glyph, the next glyph
-                                         * processed would in fact be the first one
-                                         * inserted. */
-      CurrentIsKashidaLike= 0x2000,     /* If set, and the currentInsertList is nonzero,
-                                         * then the specified glyph list will be inserted
-                                         * as a kashida-like insertion, either before or
-                                         * after the current glyph (depending on the state
-                                         * of the currentInsertBefore flag). If clear, and
-                                         * the currentInsertList is nonzero, then the
-                                         * specified glyph list will be inserted as a
-                                         * split-vowel-like insertion, either before or
-                                         * after the current glyph (depending on the state
-                                         * of the currentInsertBefore flag). */
-      MarkedIsKashidaLike= 0x1000,      /* If set, and the markedInsertList is nonzero,
-                                         * then the specified glyph list will be inserted
-                                         * as a kashida-like insertion, either before or
-                                         * after the marked glyph (depending on the state
-                                         * of the markedInsertBefore flag). If clear, and
-                                         * the markedInsertList is nonzero, then the
-                                         * specified glyph list will be inserted as a
-                                         * split-vowel-like insertion, either before or
-                                         * after the marked glyph (depending on the state
-                                         * of the markedInsertBefore flag). */
-      CurrentInsertBefore= 0x0800,      /* If set, specifies that insertions are to be made
-                                         * to the left of the current glyph. If clear,
-                                         * they're made to the right of the current glyph. */
-      MarkedInsertBefore= 0x0400,       /* If set, specifies that insertions are to be
-                                         * made to the left of the marked glyph. If clear,
-                                         * they're made to the right of the marked glyph. */
-      CurrentInsertCount= 0x3E0,        /* This 5-bit field is treated as a count of the
-                                         * number of glyphs to insert at the current
-                                         * position. Since zero means no insertions, the
-                                         * largest number of insertions at any given
-                                         * current location is 31 glyphs. */
-      MarkedInsertCount= 0x001F,        /* This 5-bit field is treated as a count of the
-                                         * number of glyphs to insert at the marked
-                                         * position. Since zero means no insertions, the
-                                         * largest number of insertions at any given
-                                         * marked location is 31 glyphs. */
-    };
 
-    driver_context_t (const InsertionSubtable *table,
+    driver_context_t (const InsertionSubtable *table_,
                       hb_aat_apply_context_t *c_) :
         ret (false),
         c (c_),
+        table (table_),
         mark (0),
         insertionAction (table+table->insertionAction) {}
 
-    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
-                        const Entry<EntryData> &entry)
-    {
-      return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) &&
-             (entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF);
-    }
-    void transition (StateTableDriver<Types, EntryData> *driver,
+    void transition (hb_buffer_t *buffer,
+                     StateTableDriver<Types, EntryData, Flags> *driver,
                      const Entry<EntryData> &entry)
     {
-      hb_buffer_t *buffer = driver->buffer;
       unsigned int flags = entry.flags;
 
       unsigned mark_loc = buffer->out_len;
@@ -765,6 +840,7 @@ struct InsertionSubtable
         unsigned int start = entry.data.markedInsertIndex;
         const HBGlyphID16 *glyphs = &insertionAction[start];
         if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
+        hb_barrier ();
 
         bool before = flags & MarkedInsertBefore;
 
@@ -775,6 +851,9 @@ struct InsertionSubtable
           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]);
+        ret = true;
         if (buffer->idx < buffer->len && !before)
           buffer->skip_glyph ();
 
@@ -793,6 +872,7 @@ struct InsertionSubtable
         unsigned int start = entry.data.currentInsertIndex;
         const HBGlyphID16 *glyphs = &insertionAction[start];
         if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
+        hb_barrier ();
 
         bool before = flags & CurrentInsertBefore;
 
@@ -826,8 +906,9 @@ struct InsertionSubtable
 
     public:
     bool ret;
-    private:
     hb_aat_apply_context_t *c;
+    const InsertionSubtable *table;
+    private:
     unsigned int mark;
     const UnsizedArrayOf<HBGlyphID16> &insertionAction;
   };
@@ -838,7 +919,14 @@ struct InsertionSubtable
 
     driver_context_t dc (this, c);
 
-    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+    StateTableDriver<Types, EntryData, Flags> 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);
@@ -849,17 +937,19 @@ struct InsertionSubtable
     TRACE_SANITIZE (this);
     /* The rest of array sanitizations are done at run-time. */
     return_trace (c->check_struct (this) && machine.sanitize (c) &&
+                  hb_barrier () &&
                   insertionAction);
   }
 
-  protected:
+  public:
   StateTable<Types, EntryData>
                 machine;
+  protected:
   NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, HBUINT>
                 insertionAction;        /* Byte offset from stateHeader to the start of
                                          * the insertion glyph table. */
   public:
-  DEFINE_SIZE_STATIC (20);
+  DEFINE_SIZE_STATIC ((StateTable<Types, EntryData>::static_size + HBUINT::static_size));
 };
 
 
@@ -883,6 +973,107 @@ struct Feature
   DEFINE_SIZE_STATIC (12);
 };
 
+
+struct hb_accelerate_subtables_context_t :
+       hb_dispatch_context_t<hb_accelerate_subtables_context_t>
+{
+  struct hb_applicable_t
+  {
+    friend struct hb_accelerate_subtables_context_t;
+    friend struct hb_aat_layout_lookup_accelerator_t;
+
+    public:
+    hb_bit_set_t glyph_set;
+    mutable hb_aat_class_cache_t class_cache;
+
+    template <typename T>
+    auto init_ (const T &obj_, unsigned num_glyphs, hb_priority<1>) HB_AUTO_RETURN
+    (
+      obj_.machine.collect_initial_glyphs (glyph_set, num_glyphs, obj_)
+    )
+
+    template <typename T>
+    void init_ (const T &obj_, unsigned num_glyphs, hb_priority<0>)
+    {
+      obj_.collect_initial_glyphs (glyph_set, num_glyphs);
+    }
+
+    template <typename T>
+    void init (const T &obj_, unsigned num_glyphs)
+    {
+      glyph_set.init ();
+      init_ (obj_, num_glyphs, hb_prioritize);
+      class_cache.clear ();
+    }
+
+    void
+    fini ()
+    {
+      glyph_set.fini ();
+    }
+  };
+
+  /* Dispatch interface. */
+  template <typename T>
+  return_t dispatch (const T &obj)
+  {
+    hb_applicable_t *entry = &array[i++];
+
+    entry->init (obj, num_glyphs);
+
+    return hb_empty_t ();
+  }
+  static return_t default_return_value () { return hb_empty_t (); }
+
+  bool stop_sublookup_iteration (return_t r) const { return false; }
+
+  hb_accelerate_subtables_context_t (hb_applicable_t *array_, unsigned num_glyphs_) :
+                                     hb_dispatch_context_t<hb_accelerate_subtables_context_t> (),
+                                     array (array_), num_glyphs (num_glyphs_) {}
+
+  hb_applicable_t *array;
+  unsigned num_glyphs;
+  unsigned i = 0;
+};
+
+struct hb_aat_layout_chain_accelerator_t
+{
+  template <typename TChain>
+  static hb_aat_layout_chain_accelerator_t *create (const TChain &chain, unsigned num_glyphs)
+  {
+    unsigned count = chain.get_subtable_count ();
+
+    unsigned size = sizeof (hb_aat_layout_chain_accelerator_t) -
+                    HB_VAR_ARRAY * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t) +
+                    count * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t);
+
+    /* The following is a calloc because when we are collecting subtables,
+     * some of them might be invalid and hence not collect; as a result,
+     * we might not fill in all the count entries of the subtables array.
+     * Zeroing it allows the set digest to gatekeep it without having to
+     * initialize it further. */
+    auto *thiz = (hb_aat_layout_chain_accelerator_t *) hb_calloc (1, size);
+    if (unlikely (!thiz))
+      return nullptr;
+
+    thiz->count = count;
+
+    hb_accelerate_subtables_context_t c_accelerate_subtables (thiz->subtables, num_glyphs);
+    chain.dispatch (&c_accelerate_subtables);
+
+    return thiz;
+  }
+
+  void destroy ()
+  {
+    for (unsigned i = 0; i < count; i++)
+      subtables[i].fini ();
+  }
+
+  unsigned count;
+  hb_accelerate_subtables_context_t::hb_applicable_t subtables[HB_VAR_ARRAY];
+};
+
 template <typename Types>
 struct ChainSubtable
 {
@@ -937,19 +1128,22 @@ struct ChainSubtable
   bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    hb_sanitize_with_object_t with (&c->sanitizer, this);
+    // Disabled for https://github.com/harfbuzz/harfbuzz/issues/4873
+    //hb_sanitize_with_object_t with (&c->sanitizer, this);
     return_trace (dispatch (c));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!length.sanitize (c) ||
-        length <= min_size ||
-        !c->check_range (this, length))
+    if (!(length.sanitize (c) &&
+          hb_barrier () &&
+          length >= min_size &&
+          c->check_range (this, length)))
       return_trace (false);
 
-    hb_sanitize_with_object_t with (c, this);
+    // Disabled for https://github.com/harfbuzz/harfbuzz/issues/4873
+    //hb_sanitize_with_object_t with (c, this);
     return_trace (dispatch (c));
   }
 
@@ -973,6 +1167,8 @@ struct Chain
 {
   typedef typename Types::HBUINT HBUINT;
 
+  unsigned get_subtable_count () const { return subtableCount; }
+
   hb_mask_t compile_flags (const hb_aat_map_builder_t *map) const
   {
     hb_mask_t flags = defaultFlags;
@@ -1013,7 +1209,8 @@ struct Chain
     return flags;
   }
 
-  void apply (hb_aat_apply_context_t *c) const
+  void apply (hb_aat_apply_context_t *c,
+              const hb_aat_layout_chain_accelerator_t *accel) const
   {
     const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount));
     unsigned int count = subtableCount;
@@ -1021,14 +1218,19 @@ struct Chain
     {
       bool reverse;
 
+      auto coverage = subtable->get_coverage ();
+
+      hb_mask_t subtable_flags = subtable->subFeatureFlags;
       if (hb_none (hb_iter (c->range_flags) |
-                   hb_map ([&subtable] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable->subFeatureFlags & (_.flags); })))
+                   hb_map ([subtable_flags] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable_flags & (_.flags); })))
         goto skip;
-      c->subtable_flags = subtable->subFeatureFlags;
+      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;
 
-      if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) &&
+      if (!(coverage & ChainSubtable<Types>::AllDirections) &&
           HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
-          bool (subtable->get_coverage() & ChainSubtable<Types>::Vertical))
+          bool (coverage & ChainSubtable<Types>::Vertical))
         goto skip;
 
       /* Buffer contents is always in logical direction.  Determine if
@@ -1058,9 +1260,9 @@ struct Chain
                                 (the order opposite that of the characters, which
                                 may be right-to-left or left-to-right).
        */
-      reverse = subtable->get_coverage () & ChainSubtable<Types>::Logical ?
-                bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) :
-                bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) !=
+      reverse = coverage & ChainSubtable<Types>::Logical ?
+                bool (coverage & ChainSubtable<Types>::Backwards) :
+                bool (coverage & ChainSubtable<Types>::Backwards) !=
                 HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
 
       if (!c->buffer->message (c->font, "start chainsubtable %u", c->lookup_index))
@@ -1086,12 +1288,28 @@ struct Chain
 
   unsigned int get_size () const { return length; }
 
-  bool sanitize (hb_sanitize_context_t *c, unsigned int version HB_UNUSED) const
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+  {
+    const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount));
+    unsigned int count = subtableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      typename context_t::return_t ret = subtable->dispatch (c, std::forward<Ts> (ds)...);
+      if (c->stop_sublookup_iteration (ret))
+        return ret;
+      subtable = &StructAfter<ChainSubtable<Types>> (*subtable);
+    }
+    return c->default_return_value ();
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int version) const
   {
     TRACE_SANITIZE (this);
-    if (!length.sanitize (c) ||
-        length < min_size ||
-        !c->check_range (this, length))
+    if (!(length.sanitize (c) &&
+          hb_barrier () &&
+          length >= min_size &&
+          c->check_range (this, length)))
       return_trace (false);
 
     if (!c->check_array (featureZ.arrayZ, featureCount))
@@ -1103,9 +1321,17 @@ struct Chain
     {
       if (!subtable->sanitize (c))
         return_trace (false);
+      hb_barrier ();
       subtable = &StructAfter<ChainSubtable<Types>> (*subtable);
     }
 
+    if (version >= 3)
+    {
+      const SubtableGlyphCoverage *coverage = (const SubtableGlyphCoverage *) subtable;
+      if (!coverage->sanitize (c, count))
+        return_trace (false);
+    }
+
     return_trace (true);
   }
 
@@ -1117,7 +1343,7 @@ struct Chain
 
   UnsizedArrayOf<Feature>       featureZ;       /* Features. */
 /*ChainSubtable firstSubtable;*//* Subtables. */
-/*subtableGlyphCoverageArray*/  /* Only if version >= 3. We don't use. */
+/*SubtableGlyphCoverage coverages*//* Only if version >= 3. */
 
   public:
   DEFINE_SIZE_MIN (8 + 2 * sizeof (HBUINT));
@@ -1128,13 +1354,79 @@ struct Chain
  * The 'mort'/'morx' Table
  */
 
-template <typename Types, hb_tag_t TAG>
+template <typename T, typename Types, hb_tag_t TAG>
 struct mortmorx
 {
   static constexpr hb_tag_t tableTag = TAG;
 
   bool has_data () const { return version != 0; }
 
+  struct accelerator_t
+  {
+    accelerator_t (hb_face_t *face)
+    {
+      hb_sanitize_context_t sc;
+      this->table = sc.reference_table<T> (face);
+
+      if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
+      {
+        hb_blob_destroy (this->table.get_blob ());
+        this->table = hb_blob_get_empty ();
+      }
+
+      this->chain_count = table->get_chain_count ();
+
+      this->accels = (hb_atomic_ptr_t<hb_aat_layout_chain_accelerator_t> *) hb_calloc (this->chain_count, sizeof (*accels));
+      if (unlikely (!this->accels))
+      {
+        this->chain_count = 0;
+        this->table.destroy ();
+        this->table = hb_blob_get_empty ();
+      }
+    }
+    ~accelerator_t ()
+    {
+      for (unsigned int i = 0; i < this->chain_count; i++)
+      {
+        if (this->accels[i])
+          this->accels[i]->destroy ();
+        hb_free (this->accels[i]);
+      }
+      hb_free (this->accels);
+      this->table.destroy ();
+    }
+
+    hb_blob_t *get_blob () const { return table.get_blob (); }
+
+    template <typename Chain>
+    hb_aat_layout_chain_accelerator_t *get_accel (unsigned chain_index, const Chain &chain, unsigned num_glyphs) const
+    {
+      if (unlikely (chain_index >= chain_count)) return nullptr;
+
+    retry:
+      auto *accel = accels[chain_index].get_acquire ();
+      if (unlikely (!accel))
+      {
+        accel = hb_aat_layout_chain_accelerator_t::create (chain, num_glyphs);
+        if (unlikely (!accel))
+          return nullptr;
+
+        if (unlikely (!accels[chain_index].cmpexch (nullptr, accel)))
+        {
+          hb_free (accel);
+          goto retry;
+        }
+      }
+
+      return accel;
+    }
+
+    hb_blob_ptr_t<T> table;
+    unsigned int chain_count;
+    hb_atomic_ptr_t<hb_aat_layout_chain_accelerator_t> *accels;
+  };
+
+
   void compile_flags (const hb_aat_map_builder_t *mapper,
                       hb_aat_map_t *map) const
   {
@@ -1151,20 +1443,28 @@ struct mortmorx
     }
   }
 
+  unsigned get_chain_count () const
+  {
+    return chainCount;
+  }
   void apply (hb_aat_apply_context_t *c,
-              const hb_aat_map_t &map) const
+              const hb_aat_map_t &map,
+              const accelerator_t &accel) const
   {
     if (unlikely (!c->buffer->successful)) return;
 
     c->buffer->unsafe_to_concat ();
 
+    c->setup_buffer_glyph_set ();
+
     c->set_lookup_index (0);
     const Chain<Types> *chain = &firstChain;
     unsigned int count = chainCount;
     for (unsigned int i = 0; i < count; i++)
     {
+      auto *chain_accel = accel.get_accel (i, *chain, c->face->get_num_glyphs ());
       c->range_flags = &map.chain_flags[i];
-      chain->apply (c);
+      chain->apply (c, chain_accel);
       if (unlikely (!c->buffer->successful)) return;
       chain = &StructAfter<Chain<Types>> (*chain);
     }
@@ -1173,7 +1473,10 @@ struct mortmorx
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!version.sanitize (c) || !version || !chainCount.sanitize (c))
+    if (!(version.sanitize (c) &&
+          hb_barrier () &&
+          version &&
+          chainCount.sanitize (c)))
       return_trace (false);
 
     const Chain<Types> *chain = &firstChain;
@@ -1182,6 +1485,7 @@ struct mortmorx
     {
       if (!chain->sanitize (c, version))
         return_trace (false);
+      hb_barrier ();
       chain = &StructAfter<Chain<Types>> (*chain);
     }
 
@@ -1200,8 +1504,24 @@ struct mortmorx
   DEFINE_SIZE_MIN (8);
 };
 
-struct morx : mortmorx<ExtendedTypes, HB_AAT_TAG_morx> {};
-struct mort : mortmorx<ObsoleteTypes, HB_AAT_TAG_mort> {};
+struct morx : mortmorx<morx, ExtendedTypes, HB_AAT_TAG_morx>
+{
+  HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
+                                   hb_face_t *face) const;
+};
+
+struct mort : mortmorx<mort, ObsoleteTypes, HB_AAT_TAG_mort>
+{
+  HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
+                                   hb_face_t *face) const;
+};
+
+struct morx_accelerator_t : morx::accelerator_t {
+  morx_accelerator_t (hb_face_t *face) : morx::accelerator_t (face) {}
+};
+struct mort_accelerator_t : mort::accelerator_t {
+  mort_accelerator_t (hb_face_t *face) : mort::accelerator_t (face) {}
+};
 
 
 } /* namespace AAT */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-opbd-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-opbd-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-opbd-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-opbd-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -133,8 +133,8 @@ struct opbd
   {
     switch (format)
     {
-    case 0: return u.format0.get_bounds (font, glyph_id, extents, this);
-    case 1: return u.format1.get_bounds (font, glyph_id, extents, this);
+    case 0: hb_barrier (); return u.format0.get_bounds (font, glyph_id, extents, this);
+    case 1: hb_barrier (); return u.format1.get_bounds (font, glyph_id, extents, this);
     default:return false;
     }
   }
@@ -144,11 +144,12 @@ struct opbd
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this) || version.major != 1))
       return_trace (false);
+    hb_barrier ();
 
     switch (format)
     {
-    case 0: return_trace (u.format0.sanitize (c, this));
-    case 1: return_trace (u.format1.sanitize (c, this));
+    case 0: hb_barrier (); return_trace (u.format0.sanitize (c, this));
+    case 1: hb_barrier (); return_trace (u.format1.sanitize (c, this));
     default:return_trace (true);
     }
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -48,17 +48,69 @@ struct TrackTableEntry
 
   float get_track_value () const { return track.to_float (); }
 
-  int get_value (const void *base, unsigned int index,
-                 unsigned int table_size) const
-  { return (base+valuesZ).as_array (table_size)[index]; }
+  float interpolate_at (unsigned int idx,
+                        float ptem,
+                        const void *base,
+                        hb_array_t<const F16DOT16> size_table) const
+  {
+    const FWORD *values = (base+valuesZ).arrayZ;
+
+    float s0 = size_table[idx].to_float ();
+    float s1 = size_table[idx + 1].to_float ();
+    int v0 = values[idx];
+    int v1 = values[idx + 1];
+
+    // Deal with font bugs.
+    if (unlikely (s1 < s0))
+    { hb_swap (s0, s1); hb_swap (v0, v1); }
+    if (unlikely (ptem < s0)) return v0;
+    if (unlikely (ptem > s1)) return v1;
+    if (unlikely (s0 == s1)) return (v0 + v1) * 0.5f;
+
+    float t = (ptem - s0) / (s1 - s0);
+    return v0 + t * (v1 - v0);
+  }
+
+  float get_value (float ptem,
+                   const void *base,
+                   hb_array_t<const F16DOT16> size_table) const
+  {
+    const FWORD *values = (base+valuesZ).arrayZ;
+
+    unsigned int n_sizes = size_table.length;
+
+    /*
+     * Choose size.
+     */
+    if (!n_sizes) return 0.f;
+    if (n_sizes == 1) return values[0];
+
+    // At least two entries.
+
+    unsigned i;
+    for (i = 0; i < n_sizes; i++)
+      if (size_table[i].to_float () >= ptem)
+        break;
+
+    // Boundary conditions.
+    if (i == 0)       return values[0];
+    if (i == n_sizes) return values[n_sizes - 1];
+
+    // Exact match.
+    if (size_table[i].to_float () == ptem) return values[i];
+
+    // Interpolate.
+    return interpolate_at (i - 1, ptem, base, size_table);
+  }
 
   public:
-  bool sanitize (hb_sanitize_context_t *c, const void *base,
-                 unsigned int table_size) const
+  bool sanitize (hb_sanitize_context_t *c,
+                 const void *base,
+                 unsigned int n_sizes) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
-                          (valuesZ.sanitize (c, base, table_size))));
+                          (valuesZ.sanitize (c, base, n_sizes))));
   }
 
   protected:
@@ -76,64 +128,45 @@ struct TrackTableEntry
 
 struct TrackData
 {
-  float interpolate_at (unsigned int idx,
-                        float target_size,
-                        const TrackTableEntry &trackTableEntry,
-                        const void *base) const
+  float get_tracking (const void *base, float ptem, float track = 0.f) const
   {
-    unsigned int sizes = nSizes;
-    hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes);
+    unsigned count = nTracks;
+    hb_array_t<const F16DOT16> size_table = (base+sizeTable).as_array (nSizes);
 
-    float s0 = size_table[idx].to_float ();
-    float s1 = size_table[idx + 1].to_float ();
-    float t = unlikely (s0 == s1) ? 0.f : (target_size - s0) / (s1 - s0);
-    return t * trackTableEntry.get_value (base, idx + 1, sizes) +
-           (1.f - t) * trackTableEntry.get_value (base, idx, sizes);
-  }
+    if (!count) return 0.f;
+    if (count == 1) return trackTable[0].get_value (ptem, base, size_table);
 
-  int get_tracking (const void *base, float ptem) const
-  {
-    /*
-     * Choose track.
-     */
-    const TrackTableEntry *trackTableEntry = nullptr;
-    unsigned int count = nTracks;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      /* Note: Seems like the track entries are sorted by values.  But the
-       * spec doesn't explicitly say that.  It just mentions it in the example. */
-
-      /* For now we only seek for track entries with zero tracking value */
-
-      if (trackTable[i].get_track_value () == 0.f)
-      {
-        trackTableEntry = &trackTable[i];
-        break;
-      }
-    }
-    if (!trackTableEntry) return 0;
+    // At least two entries.
 
-    /*
-     * Choose size.
-     */
-    unsigned int sizes = nSizes;
-    if (!sizes) return 0;
-    if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes);
-
-    hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes);
-    unsigned int size_index;
-    for (size_index = 0; size_index < sizes - 1; size_index++)
-      if (size_table[size_index].to_float () >= ptem)
-        break;
+    unsigned i = 0;
+    unsigned j = count - 1;
+
+    // Find the two entries that track is between.
+    while (i + 1 < count && trackTable[i + 1].get_track_value () < track)
+      i++;
+    while (j > 0 && trackTable[j - 1].get_track_value () > track)
+      j--;
+
+    // Exact match.
+    if (i == j) return trackTable[i].get_value (ptem, base, size_table);
+
+    // Interpolate.
+
+    float t0 = trackTable[i].get_track_value ();
+    float t1 = trackTable[j].get_track_value ();
+
+    float t = (track - t0) / (t1 - t0);
 
-    return roundf (interpolate_at (size_index ? size_index - 1 : 0, ptem,
-                                   *trackTableEntry, base));
+    float a = trackTable[i].get_value (ptem, base, size_table);
+    float b = trackTable[j].get_value (ptem, base, size_table);
+    return a + t * (b - a);
   }
 
   bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
                           sizeTable.sanitize (c, base, nSizes) &&
                           trackTable.sanitize (c, nTracks, base, nSizes)));
   }
@@ -157,45 +190,15 @@ struct trak
 
   bool has_data () const { return version.to_int (); }
 
-  bool apply (hb_aat_apply_context_t *c) const
+  hb_position_t get_h_tracking (hb_font_t *font, float track = 0.f) const
   {
-    TRACE_APPLY (this);
-
-    hb_mask_t trak_mask = c->plan->trak_mask;
-
-    const float ptem = c->font->ptem;
-    if (unlikely (ptem <= 0.f))
-      return_trace (false);
-
-    hb_buffer_t *buffer = c->buffer;
-    if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
-    {
-      const TrackData &trackData = this+horizData;
-      int tracking = trackData.get_tracking (this, ptem);
-      hb_position_t offset_to_add = c->font->em_scalef_x (tracking / 2);
-      hb_position_t advance_to_add = c->font->em_scalef_x (tracking);
-      foreach_grapheme (buffer, start, end)
-      {
-        if (!(buffer->info[start].mask & trak_mask)) continue;
-        buffer->pos[start].x_advance += advance_to_add;
-        buffer->pos[start].x_offset += offset_to_add;
-      }
-    }
-    else
-    {
-      const TrackData &trackData = this+vertData;
-      int tracking = trackData.get_tracking (this, ptem);
-      hb_position_t offset_to_add = c->font->em_scalef_y (tracking / 2);
-      hb_position_t advance_to_add = c->font->em_scalef_y (tracking);
-      foreach_grapheme (buffer, start, end)
-      {
-        if (!(buffer->info[start].mask & trak_mask)) continue;
-        buffer->pos[start].y_advance += advance_to_add;
-        buffer->pos[start].y_offset += offset_to_add;
-      }
-    }
-
-    return_trace (true);
+    float ptem = font->ptem > 0.f ? font->ptem : HB_CORETEXT_DEFAULT_FONT_SIZE;
+    return font->em_scalef_x ((this+horizData).get_tracking (this, ptem, track));
+  }
+  hb_position_t get_v_tracking (hb_font_t *font, float track = 0.f) const
+  {
+    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));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -203,6 +206,7 @@ struct trak
     TRACE_SANITIZE (this);
 
     return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
                           version.major == 1 &&
                           horizData.sanitize (c, this, this) &&
                           vertData.sanitize (c, this, this)));
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc	2025-06-27 08:03:14.000000000 +0000
@@ -34,9 +34,12 @@
 #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"
+#include "hb-aat-layout-trak-table.hh" // Just so we compile it; unused otherwise.
 #include "hb-aat-ltag-table.hh"
 
+#include "hb-ot-layout-gsub-table.hh"
+#include "hb-ot-layout-gdef-table.hh"
+
 
 /*
  * hb_aat_apply_context_t
@@ -207,18 +210,48 @@ hb_aat_layout_find_feature_mapping (hb_t
  */
 
 
+bool
+AAT::morx::is_blocklisted (hb_blob_t *blob,
+                           hb_face_t *face) const
+{
+#ifdef HB_NO_AAT_LAYOUT_BLOCKLIST
+  return false;
+#endif
+
+  switch HB_CODEPOINT_ENCODE3 (blob->length,
+                               face->table.GSUB->table.get_length (),
+                               face->table.GDEF->table.get_length ())
+  {
+    /* https://github.com/harfbuzz/harfbuzz/issues/4108
+       sha1sum:a71ca6813b7e56a772cffff7c24a5166b087197c  AALMAGHRIBI.ttf */
+    case HB_CODEPOINT_ENCODE3 (19892, 2794, 340):
+      return true;
+  }
+  return false;
+}
+
+bool
+AAT::mort::is_blocklisted (hb_blob_t *blob,
+                           hb_face_t *face) const
+{
+#ifdef HB_NO_AAT_LAYOUT_BLOCKLIST
+  return false;
+#endif
+  return false;
+}
+
 void
 hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
                            hb_aat_map_t *map)
 {
-  const AAT::morx& morx = *mapper->face->table.morx;
+  const AAT::morx& morx = *mapper->face->table.morx->table;
   if (morx.has_data ())
   {
     morx.compile_flags (mapper, map);
     return;
   }
 
-  const AAT::mort& mort = *mapper->face->table.mort;
+  const AAT::mort& mort = *mapper->face->table.mort->table;
   if (mort.has_data ())
   {
     mort.compile_flags (mapper, map);
@@ -243,8 +276,8 @@ hb_aat_layout_compile_map (const hb_aat_
 hb_bool_t
 hb_aat_layout_has_substitution (hb_face_t *face)
 {
-  return face->table.morx->has_data () ||
-         face->table.mort->has_data ();
+  return face->table.morx->table->has_data () ||
+         face->table.mort->table->has_data ();
 }
 
 void
@@ -260,26 +293,30 @@ hb_aat_layout_substitute (const hb_ot_sh
   hb_aat_map_t map;
   builder.compile (map);
 
-  hb_blob_t *morx_blob = font->face->table.morx.get_blob ();
-  const AAT::morx& morx = *morx_blob->as<AAT::morx> ();
-  if (morx.has_data ())
   {
-    AAT::hb_aat_apply_context_t c (plan, font, buffer, morx_blob);
-    if (!buffer->message (font, "start table morx")) return;
-    morx.apply (&c, map);
-    (void) buffer->message (font, "end table morx");
-    return;
+    auto &accel = *font->face->table.morx;
+    const AAT::morx& morx = *accel.table;
+    if (morx.has_data ())
+    {
+      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);
+      (void) buffer->message (font, "end table morx");
+      return;
+    }
   }
 
-  hb_blob_t *mort_blob = font->face->table.mort.get_blob ();
-  const AAT::mort& mort = *mort_blob->as<AAT::mort> ();
-  if (mort.has_data ())
   {
-    AAT::hb_aat_apply_context_t c (plan, font, buffer, mort_blob);
-    if (!buffer->message (font, "start table mort")) return;
-    mort.apply (&c, map);
-    (void) buffer->message (font, "end table mort");
-    return;
+    auto &accel = *font->face->table.mort;
+    const AAT::mort& mort = *accel.table;
+    if (mort.has_data ())
+    {
+      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);
+      (void) buffer->message (font, "end table mort");
+      return;
+    }
   }
 }
 
@@ -322,7 +359,7 @@ hb_aat_layout_remove_deleted_glyphs (hb_
 hb_bool_t
 hb_aat_layout_has_positioning (hb_face_t *face)
 {
-  return face->table.kerx->has_data ();
+  return face->table.kerx->table->has_data ();
 }
 
 void
@@ -330,13 +367,12 @@ hb_aat_layout_position (const hb_ot_shap
                         hb_font_t *font,
                         hb_buffer_t *buffer)
 {
-  hb_blob_t *kerx_blob = font->face->table.kerx.get_blob ();
-  const AAT::kerx& kerx = *kerx_blob->as<AAT::kerx> ();
+  auto &accel = *font->face->table.kerx;
 
-  AAT::hb_aat_apply_context_t c (plan, font, buffer, kerx_blob);
+  AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
   if (!buffer->message (font, "start table kerx")) return;
   c.set_ankr_table (font->face->table.ankr.get ());
-  kerx.apply (&c);
+  accel.apply (&c);
   (void) buffer->message (font, "end table kerx");
 }
 
@@ -358,17 +394,6 @@ hb_aat_layout_has_tracking (hb_face_t *f
   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 -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.h 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.h
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.h	2025-06-27 08:03:14.000000000 +0000
@@ -40,7 +40,7 @@ HB_BEGIN_DECLS
  * @HB_AAT_LAYOUT_FEATURE_TYPE_INVALID: Initial, unset feature type
  * @HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC: [All Typographic Features](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type0)
  * @HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES: [Ligatures](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type1)
- * @HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION: [Cursive Connection](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type2)
+ * @HB_AAT_LAYOUT_FEATURE_TYPE_CURSIVE_CONNECTION: [Cursive Connection](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type2)
  * @HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE: [Letter Case](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type3)
  * @HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION: [Vertical Substitution](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type4)
  * @HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT: [Linguistic Rearrangement](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type5)
@@ -88,7 +88,7 @@ typedef enum
 
   HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC                    = 0,
   HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES                          = 1,
-  HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION                 = 2,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CURSIVE_CONNECTION                 = 2,
   HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE                        = 3,
   HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION              = 4,
   HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT           = 5,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh	2025-06-27 08:03:14.000000000 +0000
@@ -32,6 +32,9 @@
 #include "hb-ot-shape.hh"
 #include "hb-aat-ltag-table.hh"
 
+/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
+#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
+
 struct hb_aat_feature_mapping_t
 {
   hb_tag_t otFeatureTag;
@@ -68,10 +71,5 @@ hb_aat_layout_position (const hb_ot_shap
                         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 -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-ltag-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-ltag-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-ltag-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-ltag-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -46,7 +46,9 @@ struct FTStringRange
   bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && (base+tag).sanitize (c, length));
+    return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
+                  (base+tag).sanitize (c, length));
   }
 
   protected:
@@ -73,6 +75,7 @@ struct ltag
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
                           version >= 1 &&
                           tagRanges.sanitize (c, this)));
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc	2025-06-27 08:03:14.000000000 +0000
@@ -88,22 +88,23 @@ hb_aat_map_builder_t::compile (hb_aat_ma
 
   /* Sort features by start/end events. */
   hb_vector_t<feature_event_t> feature_events;
+  feature_events.alloc_exact (features.length * 2 + 1);
   for (unsigned int i = 0; i < features.length; i++)
   {
-    auto &feature = features[i];
+    auto &feature = features.arrayZ[i];
 
-    if (features[i].start == features[i].end)
+    if (feature.start == feature.end)
       continue;
 
     feature_event_t *event;
 
     event = feature_events.push ();
-    event->index = features[i].start;
+    event->index = feature.start;
     event->start = true;
     event->feature = feature.info;
 
     event = feature_events.push ();
-    event->index = features[i].end;
+    event->index = feature.end;
     event->start = false;
     event->feature = feature.info;
   }
@@ -139,12 +140,12 @@ hb_aat_map_builder_t::compile (hb_aat_ma
         current_features.qsort ();
         unsigned int j = 0;
         for (unsigned int i = 1; i < current_features.length; i++)
-          if (current_features[i].type != current_features[j].type ||
+          if (current_features.arrayZ[i].type != current_features.arrayZ[j].type ||
               /* Nonexclusive feature selectors come in even/odd pairs to turn a setting on/off
                * respectively, so we mask out the low-order bit when checking for "duplicates"
                * (selectors referring to the same feature setting) here. */
-              (!current_features[i].is_exclusive && ((current_features[i].setting & ~1) != (current_features[j].setting & ~1))))
-            current_features[++j] = current_features[i];
+              (!current_features.arrayZ[i].is_exclusive && ((current_features.arrayZ[i].setting & ~1) != (current_features.arrayZ[j].setting & ~1))))
+            current_features.arrayZ[++j] = current_features.arrayZ[i];
         current_features.shrink (j + 1);
       }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-algs.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-algs.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-algs.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-algs.hh	2025-06-27 08:03:14.000000000 +0000
@@ -202,8 +202,12 @@ struct BEInt<Type, 4>
 /* Floats. */
 
 /* We want our rounding towards +infinity. */
+static inline double
+_hb_roundf (double x) { return floor (x + .5); }
+
 static inline float
 _hb_roundf (float x) { return floorf (x + .5f); }
+
 #define roundf(x) _hb_roundf(x)
 
 
@@ -282,7 +286,7 @@ HB_FUNCOBJ (hb_bool);
 
 // Compression function for Merkle-Damgard construction.
 // This function is generated using the framework provided.
-#define mix(h) (                                        \
+#define fasthash_mix(h) (                                       \
                         (void) ((h) ^= (h) >> 23),              \
                         (void) ((h) *= 0x2127599bf4325c37ULL),  \
                         (h) ^= (h) >> 47)
@@ -306,7 +310,7 @@ static inline uint64_t fasthash64(const
 #pragma GCC diagnostic ignored "-Wcast-align"
             v  = * (const uint64_t *) (pos++);
 #pragma GCC diagnostic pop
-            h ^= mix(v);
+            h ^= fasthash_mix(v);
             h *= m;
           }
         }
@@ -316,7 +320,7 @@ static inline uint64_t fasthash64(const
           while (pos != end)
           {
             v  = pos++->v;
-            h ^= mix(v);
+            h ^= fasthash_mix(v);
             h *= m;
           }
         }
@@ -332,11 +336,11 @@ static inline uint64_t fasthash64(const
         case 3: v ^= (uint64_t)pos2[2] << 16; HB_FALLTHROUGH;
         case 2: v ^= (uint64_t)pos2[1] <<  8; HB_FALLTHROUGH;
         case 1: v ^= (uint64_t)pos2[0];
-                h ^= mix(v);
+                h ^= fasthash_mix(v);
                 h *= m;
         }
 
-        return mix(h);
+        return fasthash_mix(h);
 }
 
 static inline uint32_t fasthash32(const void *buf, size_t len, uint32_t seed)
@@ -671,7 +675,7 @@ struct hb_pair_t
     return 0;
   }
 
-  friend void swap (hb_pair_t& a, hb_pair_t& b)
+  friend void swap (hb_pair_t& a, hb_pair_t& b) noexcept
   {
     hb_swap (a.first, b.first);
     hb_swap (a.second, b.second);
@@ -1053,6 +1057,18 @@ _hb_cmp_method (const void *pkey, const
   return val.cmp (key, ds...);
 }
 
+template <typename K, typename V>
+static int
+_hb_cmp_operator (const void *pkey, const void *pval)
+{
+  const K& key = * (const K*) pkey;
+  const V& val = * (const V*) pval;
+
+  if (key < val) return -1;
+  if (key > val) return  1;
+  return 0;
+}
+
 template <typename V, typename K, typename ...Ts>
 static inline bool
 hb_bsearch_impl (unsigned *pos, /* Out */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-array.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-array.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-array.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-array.hh	2025-06-27 08:03:14.000000000 +0000
@@ -47,6 +47,8 @@ enum hb_not_found_t
 template <typename Type>
 struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
 {
+  static constexpr bool realloc_move = true;
+
   /*
    * Constructors.
    */
@@ -249,7 +251,8 @@ struct hb_array_t : hb_iter_with_fallbac
     if (end < start + 2)
       return;
 
-    for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--)
+    unsigned stop = start + (end - start) / 2;
+    for (unsigned lhs = start, rhs = end - 1; lhs < stop; lhs++, rhs--)
       hb_swap (arrayZ[rhs], arrayZ[lhs]);
   }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh	2025-06-27 08:03:14.000000000 +0000
@@ -118,12 +118,12 @@ _hb_atomic_ptr_impl_cmplexch (const void
  */
 #ifndef _hb_compiler_memory_r_barrier
 #if defined(__ATOMIC_ACQUIRE) // gcc-like
-#define _hb_compiler_memory_r_barrier() asm volatile("": : :"memory")
+static inline void _hb_compiler_memory_r_barrier () { asm volatile("": : :"memory"); }
 #elif !defined(_MSC_VER)
 #include <atomic>
 #define _hb_compiler_memory_r_barrier() std::atomic_signal_fence (std::memory_order_acquire)
 #else
-#define _hb_compiler_memory_r_barrier() do {} while (0)
+static inline void _hb_compiler_memory_r_barrier () {}
 #endif
 #endif
 
@@ -212,11 +212,18 @@ struct hb_atomic_ptr_t
   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_); }
 
+  operator bool () const { return get_acquire () != nullptr; }
   T * operator -> () const                    { return get_acquire (); }
   template <typename C> operator C * () const { return get_acquire (); }
 
   T *v = nullptr;
 };
 
+static inline bool hb_barrier ()
+{
+  _hb_compiler_memory_r_barrier ();
+  return true;
+}
+
 
 #endif /* HB_ATOMIC_HH */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-bit-page.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-bit-page.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-bit-page.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-bit-page.hh	2025-06-27 08:03:14.000000000 +0000
@@ -78,6 +78,28 @@ struct hb_vector_size_t
   hb_vector_size_t operator ~ () const
   { return process (hb_bitwise_neg); }
 
+  operator bool () const
+  {
+    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+      if (v[i])
+        return true;
+    return false;
+  }
+  operator unsigned int () const
+  {
+    unsigned int r = 0;
+    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+      r += hb_popcount (v[i]);
+    return r;
+  }
+  bool operator == (const hb_vector_size_t &o) const
+  {
+    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
+      if (v[i] != o.v[i])
+        return false;
+    return true;
+  }
+
   hb_array_t<const elt_t> iter () const
   { return hb_array (v); }
 
@@ -89,6 +111,8 @@ struct hb_vector_size_t
 
 struct hb_bit_page_t
 {
+  hb_bit_page_t () { init0 (); }
+
   void init0 () { v.init0 (); population = 0; }
   void init1 () { v.init1 (); population = PAGE_BITS; }
 
@@ -101,10 +125,9 @@ struct hb_bit_page_t
   bool is_empty () const
   {
     if (has_population ()) return !population;
-    return
-    + hb_iter (v)
-    | hb_none
-    ;
+    bool empty = !v;
+    if (empty) population = 0;
+    return empty;
   }
   uint32_t hash () const
   {
@@ -115,6 +138,10 @@ struct hb_bit_page_t
   void del (hb_codepoint_t g) { elt (g) &= ~mask (g); dirty (); }
   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 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)
   {
@@ -220,13 +247,17 @@ struct hb_bit_page_t
   }
 
   bool operator == (const hb_bit_page_t &other) const { return is_equal (other); }
-  bool is_equal (const hb_bit_page_t &other) const
+  bool is_equal (const hb_bit_page_t &other) const { return v == other.v; }
+  bool intersects (const hb_bit_page_t &other) const
   {
     for (unsigned i = 0; i < len (); i++)
-      if (v[i] != other.v[i])
-        return false;
-    return true;
+      if (v[i] & other.v[i])
+        return true;
+    return false;
   }
+  bool may_intersect (const hb_bit_page_t &other) const
+  { return intersects (other); }
+
   bool operator <= (const hb_bit_page_t &larger_page) const { return is_subset (larger_page); }
   bool is_subset (const hb_bit_page_t &larger_page) const
   {
@@ -241,14 +272,10 @@ struct hb_bit_page_t
   }
 
   bool has_population () const { return population != UINT_MAX; }
-  unsigned int get_population () const
+  unsigned get_population () const
   {
     if (has_population ()) return population;
-    population =
-    + hb_iter (v)
-    | hb_reduce ([] (unsigned pop, const elt_t &_) { return pop + hb_popcount (_); }, 0u)
-    ;
-    return population;
+    return population = v;
   }
 
   bool next (hb_codepoint_t *codepoint) const
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-bit-set-invertible.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-bit-set-invertible.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-bit-set-invertible.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-bit-set-invertible.hh	2025-06-27 08:03:14.000000000 +0000
@@ -39,10 +39,10 @@ struct hb_bit_set_invertible_t
 
   hb_bit_set_invertible_t () = default;
   hb_bit_set_invertible_t (const hb_bit_set_invertible_t& o) = default;
-  hb_bit_set_invertible_t (hb_bit_set_invertible_t&& other) : hb_bit_set_invertible_t () { hb_swap (*this, other); }
+  hb_bit_set_invertible_t (hb_bit_set_invertible_t&& other)  noexcept : hb_bit_set_invertible_t () { hb_swap (*this, other); }
   hb_bit_set_invertible_t& operator= (const hb_bit_set_invertible_t& o) = default;
-  hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& other) { hb_swap (*this, other); return *this; }
-  friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b)
+  hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& other)  noexcept { hb_swap (*this, other); return *this; }
+  friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b) noexcept
   {
     if (likely (!a.s.successful || !b.s.successful))
       return;
@@ -126,6 +126,7 @@ struct hb_bit_set_invertible_t
   { unlikely (inverted) ? (void) s.add_range (a, b) : s.del_range (a, b); }
 
   bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; }
+  bool may_have (hb_codepoint_t g) const { return get (g); }
 
   /* Has interface. */
   bool operator [] (hb_codepoint_t k) const { return get (k); }
@@ -139,6 +140,9 @@ struct hb_bit_set_invertible_t
   hb_bit_set_invertible_t& operator << (const hb_codepoint_pair_t& range)
   { add_range (range.first, range.second); return *this; }
 
+  bool may_intersect (const hb_bit_set_invertible_t &other) const
+  { return inverted || other.inverted || s.intersects (other.s); }
+
   bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
   {
     hb_codepoint_t c = first - 1;
@@ -359,8 +363,8 @@ struct hb_bit_set_invertible_t
     typedef hb_codepoint_t __item_t__;
     hb_codepoint_t __item__ () const { return v; }
     bool __more__ () const { return v != INVALID; }
-    void __next__ () { s->next (&v); if (l) l--; }
-    void __prev__ () { s->previous (&v); }
+    void __next__ () { s->next (&v); if (likely (l)) l--; }
+    void __prev__ () { s->previous (&v); l++; }
     unsigned __len__ () const { return l; }
     iter_t end () const { return iter_t (*s, false); }
     bool operator != (const iter_t& o) const
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh	2025-06-27 08:03:14.000000000 +0000
@@ -38,10 +38,10 @@ struct hb_bit_set_t
   ~hb_bit_set_t () = default;
 
   hb_bit_set_t (const hb_bit_set_t& other) : hb_bit_set_t () { set (other, true); }
-  hb_bit_set_t ( hb_bit_set_t&& other) : hb_bit_set_t () { hb_swap (*this, other); }
+  hb_bit_set_t ( hb_bit_set_t&& other)  noexcept : hb_bit_set_t () { hb_swap (*this, other); }
   hb_bit_set_t& operator= (const hb_bit_set_t& other) { set (other); return *this; }
-  hb_bit_set_t& operator= (hb_bit_set_t&& other) { hb_swap (*this, other); return *this; }
-  friend void swap (hb_bit_set_t &a, hb_bit_set_t &b)
+  hb_bit_set_t& operator= (hb_bit_set_t&& other)  noexcept { hb_swap (*this, other); return *this; }
+  friend void swap (hb_bit_set_t &a, hb_bit_set_t &b) noexcept
   {
     if (likely (!a.successful || !b.successful))
       return;
@@ -88,10 +88,11 @@ struct hb_bit_set_t
   {
     if (unlikely (!successful)) return false;
 
-    if (pages.length == 0 && count == 1)
+    if (pages.length < count && count <= 2)
       exact_size = true; // Most sets are small and local
 
-    if (unlikely (!pages.resize (count, clear, exact_size) || !page_map.resize (count, clear, exact_size)))
+    if (unlikely (!pages.resize (count, clear, exact_size) ||
+        !page_map.resize (count, clear)))
     {
       pages.resize (page_map.length, clear, exact_size);
       successful = false;
@@ -297,9 +298,9 @@ struct hb_bit_set_t
       unsigned int write_index = 0;
       for (unsigned int i = 0; i < page_map.length; i++)
       {
-        int m = (int) page_map[i].major;
+        int m = (int) page_map.arrayZ[i].major;
         if (m < ds || de < m)
-          page_map[write_index++] = page_map[i];
+          page_map.arrayZ[write_index++] = page_map.arrayZ[i];
       }
       compact (compact_workspace, write_index);
       resize (write_index);
@@ -345,6 +346,7 @@ struct hb_bit_set_t
       return false;
     return page->get (g);
   }
+  bool may_have (hb_codepoint_t g) const { return get (g); }
 
   /* Has interface. */
   bool operator [] (hb_codepoint_t k) const { return get (k); }
@@ -358,6 +360,31 @@ struct hb_bit_set_t
   hb_bit_set_t& operator << (const hb_codepoint_pair_t& range)
   { add_range (range.first, range.second); return *this; }
 
+  bool intersects (const hb_bit_set_t &other) const
+  {
+    unsigned int na = pages.length;
+    unsigned int nb = other.pages.length;
+
+    unsigned int a = 0, b = 0;
+    for (; a < na && b < nb; )
+    {
+      if (page_map.arrayZ[a].major == other.page_map.arrayZ[b].major)
+      {
+        if (page_at (a).intersects (other.page_at (b)))
+          return true;
+        a++;
+        b++;
+      }
+      else if (page_map.arrayZ[a].major < other.page_map.arrayZ[b].major)
+        a++;
+      else
+        b++;
+    }
+    return false;
+  }
+  bool may_intersect (const hb_bit_set_t &other) const
+  { return intersects (other); }
+
   bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
   {
     hb_codepoint_t c = first - 1;
@@ -389,7 +416,7 @@ struct hb_bit_set_t
     {
       if (page_at (a).is_empty ()) { a++; continue; }
       if (other.page_at (b).is_empty ()) { b++; continue; }
-      if (page_map[a].major != other.page_map[b].major ||
+      if (page_map.arrayZ[a].major != other.page_map.arrayZ[b].major ||
           !page_at (a).is_equal (other.page_at (b)))
         return false;
       a++;
@@ -412,8 +439,8 @@ struct hb_bit_set_t
     uint32_t spi = 0;
     for (uint32_t lpi = 0; spi < page_map.length && lpi < larger_set.page_map.length; lpi++)
     {
-      uint32_t spm = page_map[spi].major;
-      uint32_t lpm = larger_set.page_map[lpi].major;
+      uint32_t spm = page_map.arrayZ[spi].major;
+      uint32_t lpm = larger_set.page_map.arrayZ[lpi].major;
       auto sp = page_at (spi);
 
       if (spm < lpm && !sp.is_empty ())
@@ -503,7 +530,7 @@ struct hb_bit_set_t
 
     for (; a < na && b < nb; )
     {
-      if (page_map[a].major == other.page_map[b].major)
+      if (page_map.arrayZ[a].major == other.page_map.arrayZ[b].major)
       {
         if (!passthru_left)
         {
@@ -512,7 +539,7 @@ struct hb_bit_set_t
           // passthru_left is set since no left side pages will be removed
           // in that case.
           if (write_index < a)
-            page_map[write_index] = page_map[a];
+            page_map.arrayZ[write_index] = page_map.arrayZ[a];
           write_index++;
         }
 
@@ -520,7 +547,7 @@ struct hb_bit_set_t
         a++;
         b++;
       }
-      else if (page_map[a].major < other.page_map[b].major)
+      else if (page_map.arrayZ[a].major < other.page_map.arrayZ[b].major)
       {
         if (passthru_left)
           count++;
@@ -765,8 +792,8 @@ struct hb_bit_set_t
     unsigned int initial_size = size;
     for (unsigned int i = start_page; i < page_map.length && size; i++)
     {
-      uint32_t base = major_start (page_map[i].major);
-      unsigned int n = pages[page_map[i].index].write (base, start_page_value, out, size);
+      uint32_t base = major_start (page_map.arrayZ[i].major);
+      unsigned int n = pages[page_map.arrayZ[i].index].write (base, start_page_value, out, size);
       out += n;
       size -= n;
       start_page_value = 0;
@@ -814,8 +841,8 @@ struct hb_bit_set_t
     hb_codepoint_t next_value = codepoint + 1;
     for (unsigned int i=start_page; i<page_map.length && size; i++)
     {
-      uint32_t base = major_start (page_map[i].major);
-      unsigned int n = pages[page_map[i].index].write_inverted (base, start_page_value, out, size, &next_value);
+      uint32_t base = major_start (page_map.arrayZ[i].major);
+      unsigned int n = pages[page_map.arrayZ[i].index].write_inverted (base, start_page_value, out, size, &next_value);
       out += n;
       size -= n;
       start_page_value = 0;
@@ -846,8 +873,8 @@ struct hb_bit_set_t
     unsigned count = pages.length;
     for (unsigned i = 0; i < count; i++)
     {
-      const auto& map = page_map[i];
-      const auto& page = pages[map.index];
+      const auto& map = page_map.arrayZ[i];
+      const auto& page = pages.arrayZ[map.index];
 
       if (!page.is_empty ())
         return map.major * page_t::PAGE_BITS + page.get_min ();
@@ -859,8 +886,8 @@ struct hb_bit_set_t
     unsigned count = pages.length;
     for (signed i = count - 1; i >= 0; i--)
     {
-      const auto& map = page_map[(unsigned) i];
-      const auto& page = pages[map.index];
+      const auto& map = page_map.arrayZ[(unsigned) i];
+      const auto& page = pages.arrayZ[map.index];
 
       if (!page.is_empty ())
         return map.major * page_t::PAGE_BITS + page.get_max ();
@@ -961,7 +988,7 @@ struct hb_bit_set_t
       return nullptr;
 
     last_page_lookup = i;
-    return &pages.arrayZ[page_map[i].index];
+    return &pages.arrayZ[page_map.arrayZ[i].index];
   }
   page_t &page_at (unsigned int i)
   {
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-blob.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-blob.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-blob.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-blob.cc	2025-06-27 08:03:14.000000000 +0000
@@ -598,6 +598,11 @@ _open_resource_fork (const char *file_na
  * Creates a new blob containing the data from the
  * specified binary font file.
  *
+ * The filename is passed directly to the system on all platforms,
+ * except on Windows, where the filename is interpreted as UTF-8.
+ * Only if the filename is not valid UTF-8, it will be interpreted
+ * according to the system codepage.
+ *
  * Returns: An #hb_blob_t pointer with the content of the file,
  * or hb_blob_get_empty() if failed.
  *
@@ -612,10 +617,14 @@ hb_blob_create_from_file (const char *fi
 
 /**
  * hb_blob_create_from_file_or_fail:
- * @file_name: A font filename
+ * @file_name: A filename
  *
- * Creates a new blob containing the data from the
- * specified binary font file.
+ * Creates a new blob containing the data from the specified file.
+ *
+ * The filename is passed directly to the system on all platforms,
+ * except on Windows, where the filename is interpreted as UTF-8.
+ * Only if the filename is not valid UTF-8, it will be interpreted
+ * according to the system codepage.
  *
  * Returns: An #hb_blob_t pointer with the content of the file,
  * or `NULL` if failed.
@@ -672,10 +681,19 @@ fail_without_close:
   if (unlikely (!file)) return nullptr;
 
   HANDLE fd;
+  int conversion;
   unsigned int size = strlen (file_name) + 1;
   wchar_t * wchar_file_name = (wchar_t *) hb_malloc (sizeof (wchar_t) * size);
   if (unlikely (!wchar_file_name)) goto fail_without_close;
-  mbstowcs (wchar_file_name, file_name, size);
+
+  /* Assume file name is given in UTF-8 encoding */
+  conversion = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, file_name, -1, wchar_file_name, size);
+  if (conversion <= 0)
+  {
+    /* Conversion failed due to invalid UTF-8 characters,
+       Repeat conversion based on system code page */
+    mbstowcs(wchar_file_name, file_name, size);
+  }
 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
   {
     CREATEFILE2_EXTENDED_PARAMETERS ceparams = { 0 };
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh	2025-06-27 08:03:14.000000000 +0000
@@ -34,36 +34,36 @@
 
 #line 36 "hb-buffer-deserialize-json.hh"
 static const unsigned char _deserialize_json_trans_keys[] = {
-        0u, 0u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u,
-        48u, 57u, 9u, 125u, 9u, 125u, 9u, 93u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u,
+        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, 123u, 0u, 0u, 0
+        9u, 93u, 9u, 123u, 0u, 0u, 0
 };
 
 static const char _deserialize_json_key_spans[] = {
-        0, 115, 26, 21, 2, 1, 50, 49,
-        10, 117, 117, 85, 117, 1, 50, 49,
+        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,
-        115, 0
+        85, 115, 0
 };
 
 static const short _deserialize_json_index_offsets[] = {
-        0, 0, 116, 143, 165, 168, 170, 221,
-        271, 282, 400, 518, 604, 722, 724, 775,
-        825, 836, 954, 1072, 1074, 1076, 1127, 1177,
-        1295, 1413, 1416, 1418, 1469, 1519, 1530, 1648,
-        1766, 1768, 1819, 1869, 1880, 1998, 2116, 2118,
-        2120, 2171, 2221, 2339, 2457, 2459, 2510, 2560,
-        2620, 2738, 2798, 2916, 3034, 3036, 3087, 3137,
-        3255, 3371
+        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
 };
 
 static const char _deserialize_json_indicies[] = {
@@ -77,51 +77,51 @@ static const char _deserialize_json_indi
         1, 1, 1, 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, 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, 2, 1, 3, 3, 3,
-        3, 3, 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, 3, 1, 4, 1,
-        5, 1, 6, 7, 1, 8, 9, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 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, 20, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 21, 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, 1, 1, 1, 1, 1, 1, 22,
-        1, 23, 23, 23, 23, 23, 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, 1, 1, 1, 1, 21, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        23, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 3, 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,
@@ -131,94 +131,99 @@ static const char _deserialize_json_indi
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 24, 1, 25,
-        25, 25, 25, 25, 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, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 25, 1,
+        1, 1, 1, 1, 24, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 26, 1, 1, 1, 1, 1,
+        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, 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, 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, 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, 22, 1, 28, 1, 28, 28, 28,
-        28, 28, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 28, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 29, 1,
-        29, 29, 29, 29, 29, 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, 29,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 30, 1, 1, 31,
-        32, 32, 32, 32, 32, 32, 32, 32,
-        32, 1, 33, 34, 34, 34, 34, 34,
-        34, 34, 34, 34, 1, 35, 35, 35,
-        35, 35, 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, 35, 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,
-        36, 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, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 37, 1, 35, 35, 35, 35, 35,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 35, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 36, 1,
-        1, 1, 34, 34, 34, 34, 34, 34,
-        34, 34, 34, 34, 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, 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, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 1, 37,
-        1, 38, 1, 39, 1, 39, 39, 39,
-        39, 39, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 39, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 40, 1,
-        40, 40, 40, 40, 40, 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, 40,
+        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,
+        41, 41, 41, 41, 41, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 41,
-        42, 42, 42, 42, 42, 42, 42, 42,
-        42, 1, 43, 43, 43, 43, 43, 1,
         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, 43, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 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,
@@ -227,15 +232,14 @@ static const char _deserialize_json_indi
         1, 1, 1, 1, 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, 1, 45, 1,
-        43, 43, 43, 43, 43, 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, 43,
+        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, 44, 1, 1, 1, 46,
-        46, 46, 46, 46, 46, 46, 46, 46,
-        46, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
@@ -243,26 +247,26 @@ static const char _deserialize_json_indi
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 45, 1, 47, 48,
-        1, 49, 1, 49, 49, 49, 49, 49,
+        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,
-        1, 1, 49, 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, 1, 1, 50, 1, 50, 50,
-        50, 50, 50, 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, 1, 1, 50, 1, 1,
+        1, 1, 1, 48, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 51, 1, 1, 52, 53, 53,
-        53, 53, 53, 53, 53, 53, 53, 1,
-        54, 55, 55, 55, 55, 55, 55, 55,
-        55, 55, 1, 56, 56, 56, 56, 56,
+        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,
-        1, 1, 56, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 57, 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,
@@ -272,14 +276,13 @@ static const char _deserialize_json_indi
         1, 1, 1, 1, 1, 1, 1, 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, 56, 56, 56, 56, 56, 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,
-        56, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 57, 1, 1, 1,
-        55, 55, 55, 55, 55, 55, 55, 55,
-        55, 55, 1, 1, 1, 1, 1, 1,
+        1, 1, 55, 1, 1, 1, 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,
@@ -287,119 +290,120 @@ static const char _deserialize_json_indi
         1, 1, 1, 1, 1, 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, 59,
-        1, 59, 59, 59, 59, 59, 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,
-        59, 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, 60, 1, 60, 60, 60, 60,
-        60, 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, 60, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        61, 1, 1, 62, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 1, 64, 65,
-        65, 65, 65, 65, 65, 65, 65, 65,
-        1, 66, 66, 66, 66, 66, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        66, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 67, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 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, 68, 1, 66,
-        66, 66, 66, 66, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 66, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 67, 1, 1, 1, 65, 65,
-        65, 65, 65, 65, 65, 65, 65, 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, 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,
-        1, 1, 1, 68, 1, 69, 1, 70,
-        1, 70, 70, 70, 70, 70, 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,
-        70, 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, 71, 1, 71, 71, 71, 71,
-        71, 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, 71, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 72, 73, 73, 73, 73,
-        73, 73, 73, 73, 73, 1, 74, 74,
-        74, 74, 74, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 74, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 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,
+        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, 76, 1, 74, 74, 74, 74,
-        74, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 74, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 1, 75,
-        1, 1, 1, 77, 77, 77, 77, 77,
-        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, 1, 1, 1, 1, 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,
-        76, 1, 78, 1, 78, 78, 78, 78,
-        78, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 78, 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, 1, 79, 1, 79,
-        79, 79, 79, 79, 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, 83, 81, 84, 84, 84, 84, 84,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 79, 1,
-        80, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 81, 82,
-        82, 82, 82, 82, 82, 82, 82, 82,
-        1, 84, 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,
-        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, 85, 83, 86, 86, 86,
-        86, 86, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 86, 1, 1, 1,
+        1, 1, 84, 1, 1, 1, 1, 1,
+        1, 1, 1, 1, 1, 1, 85, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        87, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
@@ -408,20 +412,21 @@ static const char _deserialize_json_indi
         1, 1, 1, 1, 1, 1, 1, 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, 1, 1, 1, 1, 1, 1, 1,
-        1, 88, 1, 83, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 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,
+        87, 87, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 83, 1, 89,
-        89, 89, 89, 89, 1, 1, 1, 1,
+        1, 1, 1, 1, 87, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 89, 1,
+        88, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 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, 1, 1, 1,
@@ -430,97 +435,107 @@ static const char _deserialize_json_indi
         1, 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, 91, 1, 89, 89, 89,
-        89, 89, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 89, 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, 1, 1,
-        90, 1, 1, 1, 92, 92, 92, 92,
-        92, 92, 92, 92, 92, 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, 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, 91, 1, 93, 1, 93, 93, 93,
-        93, 93, 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, 93, 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, 1, 94, 1,
-        94, 94, 94, 94, 94, 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, 94,
+        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, 95,
-        96, 96, 96, 96, 96, 96, 96, 96,
-        96, 1, 89, 89, 89, 89, 89, 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,
+        95, 95, 95, 95, 95, 95, 95, 95,
+        95, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 89, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 90, 1, 1,
-        1, 97, 97, 97, 97, 97, 97, 97,
-        97, 97, 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, 1, 1, 1, 1,
         1, 1, 1, 1, 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, 1, 91, 1,
-        0, 0, 0, 0, 0, 1, 1, 1,
+        1, 1, 1, 1, 1, 96, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 1, 0,
+        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, 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, 1, 1,
         1, 1, 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, 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, 1, 1, 1, 1, 1,
+        1, 1, 1, 1, 1, 1, 1, 1,
+        1, 1, 1, 1, 1, 1, 3, 1,
+        1, 0
 };
 
 static const char _deserialize_json_trans_targs[] = {
-        1, 0, 2, 2, 3, 4, 19, 25,
-        38, 44, 52, 5, 13, 6, 7, 8,
-        9, 12, 9, 12, 10, 2, 11, 10,
-        11, 11, 56, 57, 14, 15, 16, 17,
-        18, 17, 18, 10, 2, 11, 20, 21,
-        22, 23, 24, 10, 2, 11, 24, 26,
-        32, 27, 28, 29, 30, 31, 30, 31,
-        10, 2, 11, 33, 34, 35, 36, 37,
-        36, 37, 10, 2, 11, 39, 40, 41,
-        42, 43, 10, 2, 11, 43, 45, 46,
-        47, 50, 51, 47, 48, 49, 10, 2,
-        11, 10, 2, 11, 51, 53, 54, 50,
-        55, 55
+        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
 };
 
 static const char _deserialize_json_trans_actions[] = {
-        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, 0, 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, 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
 };
 
 static const int deserialize_json_start = 1;
@@ -545,22 +560,17 @@ _hb_buffer_deserialize_json (hb_buffer_t
   /* 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 *tok = nullptr;
   int cs;
   hb_glyph_info_t info = {0};
   hb_glyph_position_t pos = {0};
 
-#line 559 "hb-buffer-deserialize-json.hh"
+#line 569 "hb-buffer-deserialize-json.hh"
         {
         cs = deserialize_json_start;
         }
 
-#line 564 "hb-buffer-deserialize-json.hh"
+#line 574 "hb-buffer-deserialize-json.hh"
         {
         int _slen;
         int _trans;
@@ -772,7 +782,7 @@ _resume:
         *end_ptr = p;
 }
         break;
-#line 776 "hb-buffer-deserialize-json.hh"
+#line 786 "hb-buffer-deserialize-json.hh"
         }
 
 _again:
@@ -784,7 +794,7 @@ _again:
         _out: {}
         }
 
-#line 137 "hb-buffer-deserialize-json.rl"
+#line 132 "hb-buffer-deserialize-json.rl"
 
 
   *end_ptr = p;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc	2025-06-27 08:03:14.000000000 +0000
@@ -149,7 +149,7 @@ buffer_verify_unsafe_to_break (hb_buffer
     }
     assert (text_start < text_end);
 
-    if (0)
+    if (false)
       printf("start %u end %u text start %u end %u\n", start, end, text_start, text_end);
 
     hb_buffer_clear_contents (fragment);
@@ -288,7 +288,7 @@ buffer_verify_unsafe_to_concat (hb_buffe
       }
       assert (text_start < text_end);
 
-      if (0)
+      if (false)
         printf("start %u end %u text start %u end %u\n", start, end, text_start, text_end);
 
 #if 0
@@ -412,7 +412,7 @@ hb_buffer_t::verify (hb_buffer_t
                                    &len,
                                    HB_BUFFER_SERIALIZE_FORMAT_TEXT,
                                    HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS);
-      buffer_verify_error (this, font, BUFFER_VERIFY_ERROR "text was: %s.", bytes.arrayZ);
+      buffer_verify_error (this, font, BUFFER_VERIFY_ERROR "text was: %s.", bytes.arrayZ ? bytes.arrayZ : "");
     }
 #endif
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc	2025-06-27 08:03:14.000000000 +0000
@@ -271,6 +271,7 @@ hb_buffer_t::similar (const hb_buffer_t
   replacement = src.replacement;
   invisible = src.invisible;
   not_found = src.not_found;
+  not_found_variation_selector = src.not_found_variation_selector;
 }
 
 void
@@ -283,6 +284,7 @@ hb_buffer_t::reset ()
   replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
   invisible = 0;
   not_found = 0;
+  not_found_variation_selector = HB_CODEPOINT_INVALID;
 
   clear ();
 }
@@ -309,6 +311,7 @@ hb_buffer_t::clear ()
 
   deallocate_var_all ();
   serial = 0;
+  random_state = 1;
   scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
 }
 
@@ -704,6 +707,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
   HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
   0, /* invisible */
   0, /* not_found */
+  HB_CODEPOINT_INVALID, /* not_found_variation_selector */
 
 
   HB_BUFFER_CONTENT_TYPE_INVALID,
@@ -1359,6 +1363,89 @@ hb_buffer_get_not_found_glyph (const hb_
   return buffer->not_found;
 }
 
+/**
+ * hb_buffer_set_not_found_variation_selector_glyph:
+ * @buffer: An #hb_buffer_t
+ * @not_found_variation_selector: the not-found-variation-selector #hb_codepoint_t
+ *
+ * Sets the #hb_codepoint_t that replaces variation-selector characters not resolved
+ * in the font during shaping.
+ *
+ * The not-found-variation-selector glyph defaults to #HB_CODEPOINT_INVALID,
+ * in which case an unresolved variation-selector will be removed from the glyph
+ * string during shaping. This API allows for changing that and retaining a glyph,
+ * such that the situation can be detected by the client and handled accordingly
+ * (e.g. by using a different font).
+ *
+ * Since: 10.0.0
+ **/
+void
+hb_buffer_set_not_found_variation_selector_glyph (hb_buffer_t    *buffer,
+                                                  hb_codepoint_t  not_found_variation_selector)
+{
+  buffer->not_found_variation_selector = not_found_variation_selector;
+}
+
+/**
+ * hb_buffer_get_not_found_variation_selector_glyph:
+ * @buffer: An #hb_buffer_t
+ *
+ * See hb_buffer_set_not_found_variation_selector_glyph().
+ *
+ * Return value:
+ * The @buffer not-found-variation-selector #hb_codepoint_t
+ *
+ * Since: 10.0.0
+ **/
+hb_codepoint_t
+hb_buffer_get_not_found_variation_selector_glyph (const hb_buffer_t *buffer)
+{
+  return buffer->not_found_variation_selector;
+}
+
+/**
+ * hb_buffer_set_random_state:
+ * @buffer: An #hb_buffer_t
+ * @state: the new random state
+ *
+ * Sets the random state of the buffer. The state changes
+ * every time a glyph uses randomness (eg. the `rand`
+ * OpenType feature). This function together with
+ * hb_buffer_get_random_state() allow for transferring
+ * the current random state to a subsequent buffer, to
+ * get better randomness distribution.
+ *
+ * Defaults to 1 and when buffer contents are cleared.
+ * A value of 0 disables randomness during shaping.
+ *
+ * Since: 8.4.0
+ **/
+void
+hb_buffer_set_random_state (hb_buffer_t    *buffer,
+                            unsigned        state)
+{
+  if (unlikely (hb_object_is_immutable (buffer)))
+    return;
+
+  buffer->random_state = state;
+}
+
+/**
+ * hb_buffer_get_random_state:
+ * @buffer: An #hb_buffer_t
+ *
+ * See hb_buffer_set_random_state().
+ *
+ * Return value:
+ * The @buffer random state
+ *
+ * Since: 8.4.0
+ **/
+unsigned
+hb_buffer_get_random_state (const hb_buffer_t *buffer)
+{
+  return buffer->random_state;
+}
 
 /**
  * hb_buffer_clear_contents:
@@ -1896,7 +1983,7 @@ hb_buffer_add_codepoints (hb_buffer_t
  * @buffer: An #hb_buffer_t
  * @source: source #hb_buffer_t
  * @start: start index into source buffer to copy.  Use 0 to copy from start of buffer.
- * @end: end index into source buffer to copy.  Use @HB_FEATURE_GLOBAL_END to copy to end of buffer.
+ * @end: end index into source buffer to copy.  Use @UINT_MAX (or ((unsigned int) -1)) to copy to end of buffer.
  *
  * Append (part of) contents of another buffer to this buffer.
  *
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-buffer.h 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-buffer.h
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-buffer.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-buffer.h	2025-06-27 08:03:14.000000000 +0000
@@ -487,6 +487,19 @@ hb_buffer_set_not_found_glyph (hb_buffer
 HB_EXTERN hb_codepoint_t
 hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer);
 
+HB_EXTERN void
+hb_buffer_set_not_found_variation_selector_glyph (hb_buffer_t    *buffer,
+                                                  hb_codepoint_t  not_found_variation_selector);
+
+HB_EXTERN hb_codepoint_t
+hb_buffer_get_not_found_variation_selector_glyph (const hb_buffer_t *buffer);
+
+HB_EXTERN void
+hb_buffer_set_random_state (hb_buffer_t    *buffer,
+                            unsigned        state);
+
+HB_EXTERN unsigned
+hb_buffer_get_random_state (const hb_buffer_t *buffer);
 
 /*
  * Content API.
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh	2025-06-27 08:03:14.000000000 +0000
@@ -32,7 +32,6 @@
 
 #include "hb.hh"
 #include "hb-unicode.hh"
-#include "hb-set-digest.hh"
 
 
 static_assert ((sizeof (hb_glyph_info_t) == 20), "");
@@ -52,6 +51,7 @@ enum hb_buffer_scratch_flags_t {
   HB_BUFFER_SCRATCH_FLAG_HAS_CGJ                        = 0x00000010u,
   HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS                = 0x00000020u,
   HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE            = 0x00000040u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK= 0x00000080u,
 
   /* Reserved for shapers' internal use. */
   HB_BUFFER_SCRATCH_FLAG_SHAPER0                        = 0x01000000u,
@@ -80,6 +80,7 @@ struct hb_buffer_t
   hb_codepoint_t replacement; /* U+FFFD or something else. */
   hb_codepoint_t invisible; /* 0 or something else. */
   hb_codepoint_t not_found; /* 0 or something else. */
+  hb_codepoint_t not_found_variation_selector; /* HB_CODEPOINT_INVALID or something else. */
 
   /*
    * Buffer contents
@@ -116,6 +117,7 @@ struct hb_buffer_t
 
   uint8_t allocated_var_bits;
   uint8_t serial;
+  uint32_t random_state;
   hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
   unsigned int max_len; /* Maximum allowed len. */
   int max_ops; /* Maximum allowed operations. */
@@ -179,22 +181,24 @@ struct hb_buffer_t
     allocated_var_bits = 0;
   }
 
+  HB_ALWAYS_INLINE
   hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
+  HB_ALWAYS_INLINE
   hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
 
+  HB_ALWAYS_INLINE
   hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
+  HB_ALWAYS_INLINE
   hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
 
+  HB_ALWAYS_INLINE
   hb_glyph_info_t &prev ()      { return out_info[out_len ? out_len - 1 : 0]; }
+  HB_ALWAYS_INLINE
   hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
 
-  hb_set_digest_t digest () const
-  {
-    hb_set_digest_t d;
-    d.init ();
-    d.add_array (&info[0].codepoint, len, sizeof (info[0]));
-    return d;
-  }
+  template <typename set_t>
+  void collect_codepoints (set_t &d) const
+  { d.clear (); d.add_array (&info[0].codepoint, len, sizeof (info[0])); }
 
   HB_INTERNAL void similar (const hb_buffer_t &src);
   HB_INTERNAL void reset ();
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-common.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-common.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-common.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-common.hh	2025-06-27 08:03:14.000000000 +0000
@@ -522,7 +522,7 @@ struct parsed_values_t
 
   void alloc (unsigned n)
   {
-    values.alloc (n, true);
+    values.alloc_exact (n);
   }
 
   void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t (), const VAL &v = VAL ())
@@ -624,7 +624,6 @@ struct opset_t
         } else {
           /* invalid unknown operator */
           env.clear_args ();
-          env.set_error ();
         }
         break;
     }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-dict-common.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-dict-common.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-dict-common.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-dict-common.hh	2025-06-27 08:03:14.000000000 +0000
@@ -54,8 +54,8 @@ struct top_dict_values_t : dict_values_t
   }
   void fini () { dict_values_t<OPSTR>::fini (); }
 
-  unsigned int  charStringsOffset;
-  unsigned int  FDArrayOffset;
+  int  charStringsOffset;
+  int  FDArrayOffset;
 };
 
 struct dict_opset_t : opset_t<number_t>
@@ -84,7 +84,7 @@ struct dict_opset_t : opset_t<number_t>
 
     enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END };
 
-    char buf[32];
+    char buf[32] = {0};
     unsigned char byte = 0;
     for (unsigned i = 0, count = 0; count < ARRAY_LENGTH (buf); ++i, ++count)
     {
@@ -157,11 +157,11 @@ struct top_dict_opset_t : dict_opset_t
   {
     switch (op) {
       case OpCode_CharStrings:
-        dictval.charStringsOffset = env.argStack.pop_uint ();
+        dictval.charStringsOffset = env.argStack.pop_int ();
         env.clear_args ();
         break;
       case OpCode_FDArray:
-        dictval.FDArrayOffset = env.argStack.pop_uint ();
+        dictval.FDArrayOffset = env.argStack.pop_int ();
         env.clear_args ();
         break;
       case OpCode_FontMatrix:
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh	2025-06-27 08:03:14.000000000 +0000
@@ -76,16 +76,12 @@ struct cff2_cs_interp_env_t : cs_interp_
     coords = coords_;
     num_coords = num_coords_;
     varStore = acc.varStore;
-    seen_blend = false;
-    seen_vsindex_ = false;
-    scalars.init ();
     do_blend = num_coords && coords && varStore->size;
     set_ivs (acc.privateDicts[fd].ivs);
   }
 
   void fini ()
   {
-    scalars.fini ();
     SUPER::fini ();
   }
 
@@ -168,13 +164,13 @@ struct cff2_cs_interp_env_t : cs_interp_
   protected:
   const int     *coords;
   unsigned int  num_coords;
-  const  CFF2VariationStore *varStore;
+  const  CFF2ItemVariationStore *varStore;
   unsigned int  region_count;
   unsigned int  ivs;
   hb_vector_t<float>  scalars;
   bool    do_blend;
-  bool    seen_vsindex_;
-  bool    seen_blend;
+  bool    seen_vsindex_ = false;
+  bool    seen_blend = false;
 
   typedef cs_interp_env_t<ELEM, CFF2Subrs> SUPER;
 };
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-common.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-common.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-common.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-common.cc	2025-06-27 08:03:14.000000000 +0000
@@ -625,6 +625,9 @@ hb_script_get_horizontal_direction (hb_s
     /* Unicode-14.0 additions */
     case HB_SCRIPT_OLD_UYGHUR:
 
+    /* Unicode-16.0 additions */
+    case HB_SCRIPT_GARAY:
+
       return HB_DIRECTION_RTL;
 
 
@@ -996,7 +999,7 @@ hb_feature_to_string (hb_feature_t *feat
   if (feature->value > 1)
   {
     s[len++] = '=';
-    len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
+    len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%" PRIu32, feature->value));
   }
   assert (len < ARRAY_LENGTH (s));
   len = hb_min (len, size - 1);
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-common.h 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-common.h
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-common.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-common.h	2025-06-27 08:03:14.000000000 +0000
@@ -47,14 +47,10 @@
 # endif /* !__cplusplus */
 #endif
 
-#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \
-    defined (_sgi) || defined (__sun) || defined (sun) || \
-    defined (__digital__) || defined (__HP_cc)
-#  include <inttypes.h>
-#elif defined (_AIX)
+#if defined (_AIX)
 #  include <sys/inttypes.h>
 #elif defined (_MSC_VER) && _MSC_VER < 1600
-/* VS 2010 (_MSC_VER 1600) has stdint.h */
+/* VS 2010 (_MSC_VER 1600) has stdint.h   */
 typedef __int8 int8_t;
 typedef unsigned __int8 uint8_t;
 typedef __int16 int16_t;
@@ -63,10 +59,11 @@ typedef __int32 int32_t;
 typedef unsigned __int32 uint32_t;
 typedef __int64 int64_t;
 typedef unsigned __int64 uint64_t;
-#elif defined (__KERNEL__)
-#  include <linux/types.h>
-#else
+#elif defined (_MSC_VER) && _MSC_VER < 1800
+/* VS 2013 (_MSC_VER 1800) has inttypes.h */
 #  include <stdint.h>
+#else
+#  include <inttypes.h>
 #endif
 
 #if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
@@ -507,6 +504,13 @@ hb_language_matches (hb_language_t langu
  * @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
@@ -734,6 +738,17 @@ typedef enum
   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,
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-config.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-config.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-config.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-config.hh	2025-06-27 08:03:14.000000000 +0000
@@ -56,7 +56,6 @@
 
 #ifdef HB_LEAN
 #define HB_DISABLE_DEPRECATED
-#define HB_NDEBUG
 #define HB_NO_ATEXIT
 #define HB_NO_BUFFER_MESSAGE
 #define HB_NO_BUFFER_SERIALIZE
@@ -69,8 +68,6 @@
 #define HB_NO_FACE_COLLECT_UNICODES
 #define HB_NO_GETENV
 #define HB_NO_HINTING
-#define HB_NO_LANGUAGE_LONG
-#define HB_NO_LANGUAGE_PRIVATE_SUBTAG
 #define HB_NO_LAYOUT_FEATURE_PARAMS
 #define HB_NO_LAYOUT_COLLECT_GLYPHS
 #define HB_NO_LAYOUT_RARELY_USED
@@ -118,6 +115,10 @@
 #define HB_NO_VAR_COMPOSITES
 #endif
 
+#ifdef HB_NO_VAR
+#define HB_NO_VAR_COMPOSITES
+#endif
+
 #ifdef HB_DISABLE_DEPRECATED
 #define HB_IF_NOT_DEPRECATED(x)
 #else
@@ -156,6 +157,7 @@
 #define HB_NO_FALLBACK_SHAPE
 #define HB_NO_OT_KERN
 #define HB_NO_OT_LAYOUT_BLOCKLIST
+#define HB_NO_AAT_LAYOUT_BLOCKLIST
 #define HB_NO_OT_SHAPE_FALLBACK
 #endif
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-cplusplus.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-cplusplus.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-cplusplus.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-cplusplus.hh	2025-06-27 08:03:14.000000000 +0000
@@ -27,9 +27,6 @@
 
 #include "hb.h"
 
-HB_BEGIN_DECLS
-HB_END_DECLS
-
 #ifdef __cplusplus
 
 #include <functional>
@@ -56,15 +53,15 @@ struct shared_ptr
 
   explicit shared_ptr (T *p = nullptr) : p (p) {}
   shared_ptr (const shared_ptr &o) : p (v::reference (o.p)) {}
-  shared_ptr (shared_ptr &&o) : p (o.p) { o.p = nullptr; }
+  shared_ptr (shared_ptr &&o)  noexcept : p (o.p) { o.p = nullptr; }
   shared_ptr& operator = (const shared_ptr &o) { if (p != o.p) { destroy (); p = o.p; reference (); } return *this; }
-  shared_ptr& operator = (shared_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; }
+  shared_ptr& operator = (shared_ptr &&o)  noexcept { v::destroy (p); p = o.p; o.p = nullptr; return *this; }
   ~shared_ptr () { v::destroy (p); p = nullptr; }
 
   T* get() const { return p; }
 
-  void swap (shared_ptr &o) { std::swap (p, o.p); }
-  friend void swap (shared_ptr &a, shared_ptr &b) { std::swap (a.p, b.p); }
+  void swap (shared_ptr &o)  noexcept { std::swap (p, o.p); }
+  friend void swap (shared_ptr &a, shared_ptr &b)  noexcept { std::swap (a.p, b.p); }
 
   operator T * () const { return p; }
   T& operator * () const { return *get (); }
@@ -98,16 +95,16 @@ struct unique_ptr
 
   explicit unique_ptr (T *p = nullptr) : p (p) {}
   unique_ptr (const unique_ptr &o) = delete;
-  unique_ptr (unique_ptr &&o) : p (o.p) { o.p = nullptr; }
+  unique_ptr (unique_ptr &&o)  noexcept : p (o.p) { o.p = nullptr; }
   unique_ptr& operator = (const unique_ptr &o) = delete;
-  unique_ptr& operator = (unique_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; }
+  unique_ptr& operator = (unique_ptr &&o)  noexcept { v::destroy (p); p = o.p; o.p = nullptr; return *this; }
   ~unique_ptr () { v::destroy (p); p = nullptr; }
 
   T* get() const { return p; }
   T* release () { T* v = p; p = nullptr; return v; }
 
-  void swap (unique_ptr &o) { std::swap (p, o.p); }
-  friend void swap (unique_ptr &a, unique_ptr &b) { std::swap (a.p, b.p); }
+  void swap (unique_ptr &o)  noexcept { std::swap (p, o.p); }
+  friend void swap (unique_ptr &a, unique_ptr &b)  noexcept { std::swap (a.p, b.p); }
 
   operator T * () const { return p; }
   T& operator * () const { return *get (); }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-decycler.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-decycler.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-decycler.hh	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-decycler.hh	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,164 @@
+/*
+ * Copyright © 2025 Behdad Esfahbod
+ *
+ *  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_DECYCLER_HH
+#define HB_DECYCLER_HH
+
+#include "hb.hh"
+
+/*
+ * hb_decycler_t is an efficient cycle detector for graph traversal.
+ * It's a simple tortoise-and-hare algorithm with a twist: it's
+ * designed to detect cycles while traversing a graph in a DFS manner,
+ * instead of just a linked list.
+ *
+ * For Floyd's tortoise and hare algorithm, see:
+ * https://en.wikipedia.org/wiki/Cycle_detection#Floyd's_tortoise_and_hare
+ *
+ * hb_decycler_t is O(n) in the number of nodes in the DFS traversal
+ * if there are no cycles. Unlike Floyd's algorithm, hb_decycler_t
+ * can be used in a DFS traversal, where the graph is not a simple
+ * linked list, but a tree with possible cycles.  Like Floyd's algorithm,
+ * it is constant-memory (~three  pointers).
+ *
+ * The decycler works by creating an implicit linked-list on the stack,
+ * of the path from the root to the current node, and apply Floyd's
+ * algorithm on that list as it goes.
+ *
+ * The decycler is malloc-free, and as such, much faster to use than a
+ * hb_set_t or hb_map_t equivalent.
+ *
+ * The decycler detects cycles in the graph *eventually*, not *immediately*.
+ * That is, it may not detect a cycle until the cycle is fully traversed,
+ * even multiple times. See Floyd's algorithm analysis for details.
+ *
+ * The implementation saves a pointer storage on the stack by combining
+ * this->u.decycler and this->u.next into a union.  This is possible because
+ * at any point we only need one of those values. The invariant is that
+ * after construction, and before destruction, of a node, the u.decycler
+ * field is always valid. The u.next field is only valid when the node is
+ * in the traversal path, parent to another node.
+ *
+ * There are three method's:
+ *
+ *   - hb_decycler_node_t() constructor: Creates a new node in the traversal.
+ *     The constructor takes a reference to the decycler object and inserts
+ *     itself as the latest node in the traversal path, by advancing the hare
+ *     pointer, and for every other descent, advancing the tortoise pointer.
+ *
+ *   - ~hb_decycler_node_t() destructor: Restores the decycler object to its
+ *      previous state by removing the node from the traversal path.
+ *
+ *   - bool visit(uintptr_t value): Called on every node in the graph.  Returns
+ *     true if the node is not part of a cycle, and false if it is.  The value
+ *     parameter is used to detect cycles.  It's the caller's responsibility
+ *     to ensure that the value is unique for each node in the graph.
+ *     The cycle detection is as simple as comparing the value to the value
+ *     held by the tortoise pointer, which is the Floyd's algorithm.
+ *
+ * For usage examples see test-decycler.cc.
+ */
+
+struct hb_decycler_node_t;
+
+struct hb_decycler_t
+{
+  friend struct hb_decycler_node_t;
+
+  private:
+  bool tortoise_awake = false;
+  hb_decycler_node_t *tortoise = nullptr;
+  hb_decycler_node_t *hare = nullptr;
+};
+
+struct hb_decycler_node_t
+{
+  hb_decycler_node_t (hb_decycler_t &decycler)
+  {
+    u.decycler = &decycler;
+
+    decycler.tortoise_awake = !decycler.tortoise_awake;
+
+    if (!decycler.tortoise)
+    {
+      // First node.
+      assert (decycler.tortoise_awake);
+      assert (!decycler.hare);
+      decycler.tortoise = decycler.hare = this;
+      return;
+    }
+
+    if (decycler.tortoise_awake)
+      decycler.tortoise = decycler.tortoise->u.next; // Time to move.
+
+    this->prev = decycler.hare;
+    decycler.hare->u.next = this;
+    decycler.hare = this;
+  }
+
+  ~hb_decycler_node_t ()
+  {
+    hb_decycler_t &decycler = *u.decycler;
+
+    // Inverse of the constructor.
+
+    assert (decycler.hare == this);
+    decycler.hare = prev;
+    if (prev)
+      prev->u.decycler = &decycler;
+
+    assert (decycler.tortoise);
+    if (decycler.tortoise_awake)
+      decycler.tortoise = decycler.tortoise->prev;
+
+    decycler.tortoise_awake = !decycler.tortoise_awake;
+  }
+
+  bool visit (uintptr_t value_)
+  {
+    value = value_;
+
+    hb_decycler_t &decycler = *u.decycler;
+
+    if (decycler.tortoise == this)
+      return true; // First node; not a cycle.
+
+    if (decycler.tortoise->value == value)
+      return false; // Cycle detected.
+
+    return true;
+  }
+
+  private:
+  union {
+    hb_decycler_t *decycler;
+    hb_decycler_node_t *next;
+  } u = {nullptr};
+  hb_decycler_node_t *prev = nullptr;
+  uintptr_t value = 0;
+};
+
+#endif /* HB_DECYCLER_HH */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h	2025-06-27 08:03:14.000000000 +0000
@@ -56,7 +56,7 @@ HB_BEGIN_DECLS
 /**
  * HB_SCRIPT_CANADIAN_ABORIGINAL:
  *
- * Use #HB_SCRIPT_CANADIAN_SYLLABICS instead:
+ * Use #HB_SCRIPT_CANADIAN_SYLLABICS instead.
  *
  * Deprecated: 0.9.20
  */
@@ -301,6 +301,15 @@ hb_font_get_glyph_shape (hb_font_t *font
                          hb_draw_funcs_t *dfuncs, void *draw_data);
 
 
+/**
+ * HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION:
+ *
+ * Use #HB_AAT_LAYOUT_FEATURE_TYPE_CURSIVE_CONNECTION instead.
+ *
+ * Deprecated: 8.3.0
+ */
+#define HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION HB_AAT_LAYOUT_FEATURE_TYPE_CURSIVE_CONNECTION
+
 #endif
 
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-draw.h 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-draw.h
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-draw.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-draw.h	2025-06-27 08:03:14.000000000 +0000
@@ -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.}}
+#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}}
 
 
 /**
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-draw.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-draw.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-draw.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-draw.hh	2025-06-27 08:03:14.000000000 +0000
@@ -232,7 +232,7 @@ struct hb_draw_session_t
     funcs->close_path (draw_data, st);
   }
 
-  protected:
+  public:
   float slant;
   bool not_slanted;
   hb_draw_funcs_t *funcs;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-face-builder.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-face-builder.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-face-builder.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-face-builder.cc	2025-06-27 08:03:14.000000000 +0000
@@ -42,7 +42,7 @@
 struct face_table_info_t
 {
   hb_blob_t* data;
-  signed order;
+  unsigned order;
 };
 
 struct hb_face_builder_data_t
@@ -153,6 +153,50 @@ _hb_face_builder_reference_table (hb_fac
   return hb_blob_reference (data->tables[tag].data);
 }
 
+static unsigned
+_hb_face_builder_get_table_tags (const hb_face_t *face HB_UNUSED,
+                                 unsigned int start_offset,
+                                 unsigned int *table_count,
+                                 hb_tag_t *table_tags,
+                                 void *user_data)
+{
+  hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
+
+  unsigned population = data->tables.get_population ();
+
+  if (!table_count)
+    return population;
+
+  if (unlikely (start_offset >= population))
+  {
+    if (table_count)
+      *table_count = 0;
+    return population;
+  }
+
+  // Sort the tags.
+  hb_vector_t<hb_tag_t> sorted_tags;
+  data->tables.keys () | hb_sink (sorted_tags);
+  if (unlikely (sorted_tags.in_error ()))
+  {
+    // Not much to do...
+  }
+  sorted_tags.qsort ([] (const void* a, const void* b) {
+    return * (hb_tag_t *) a <  * (hb_tag_t *) b ? -1 :
+           * (hb_tag_t *) a == * (hb_tag_t *) b ?  0 :
+                                                  +1;
+  });
+
+  auto array = sorted_tags.as_array ().sub_array (start_offset, table_count);
+  auto out = hb_array (table_tags, *table_count);
+
+  + array.iter ()
+  | hb_sink (out)
+  ;
+
+  return population;
+}
+
 
 /**
  * hb_face_builder_create:
@@ -171,9 +215,16 @@ hb_face_builder_create ()
   hb_face_builder_data_t *data = _hb_face_builder_data_create ();
   if (unlikely (!data)) return hb_face_get_empty ();
 
-  return hb_face_create_for_tables (_hb_face_builder_reference_table,
-                                    data,
-                                    _hb_face_builder_data_destroy);
+  hb_face_t *face = hb_face_create_for_tables (_hb_face_builder_reference_table,
+                                               data,
+                                               _hb_face_builder_data_destroy);
+
+  hb_face_set_get_table_tags_func (face,
+                                   _hb_face_builder_get_table_tags,
+                                   data,
+                                   nullptr);
+
+  return face;
 }
 
 /**
@@ -199,7 +250,7 @@ hb_face_builder_add_table (hb_face_t *fa
   hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
 
   hb_blob_t* previous = data->tables.get (tag).data;
-  if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), -1}))
+  if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), (unsigned) -1}))
   {
     hb_blob_destroy (blob);
     return false;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-face.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-face.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-face.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-face.cc	2025-06-27 08:03:14.000000000 +0000
@@ -90,10 +90,6 @@ DEFINE_NULL_INSTANCE (hb_face_t) =
 {
   HB_OBJECT_HEADER_STATIC,
 
-  nullptr, /* reference_table_func */
-  nullptr, /* user_data */
-  nullptr, /* destroy */
-
   0,    /* index */
   1000, /* upem */
   0,    /* num_glyphs */
@@ -110,8 +106,9 @@ DEFINE_NULL_INSTANCE (hb_face_t) =
  *
  * Variant of hb_face_create(), built for those cases where it is more
  * convenient to provide data for individual tables instead of the whole font
- * data. With the caveat that hb_face_get_table_tags() does not currently work
- * with faces created this way.
+ * data. With the caveat that hb_face_get_table_tags() would not work
+ * with faces created this way. You can address that by calling the
+ * hb_face_set_get_table_tags_func() function and setting the appropriate callback.
  *
  * Creates a new face object from the specified @user_data and @reference_table_func,
  * with the @destroy callback.
@@ -194,6 +191,22 @@ _hb_face_for_data_reference_table (hb_fa
   return blob;
 }
 
+static unsigned
+_hb_face_for_data_get_table_tags (const hb_face_t *face HB_UNUSED,
+                                  unsigned int start_offset,
+                                  unsigned int *table_count,
+                                  hb_tag_t *table_tags,
+                                  void *user_data)
+{
+  hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
+
+  const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
+  const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
+
+  return ot_face.get_table_tags (start_offset, table_count, table_tags);
+}
+
+
 /**
  * hb_face_create:
  * @blob: #hb_blob_t to work upon
@@ -240,6 +253,10 @@ hb_face_create (hb_blob_t    *blob,
   face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
                                     closure,
                                     _hb_face_for_data_closure_destroy);
+  hb_face_set_get_table_tags_func (face,
+                                   _hb_face_for_data_get_table_tags,
+                                   closure,
+                                   nullptr);
 
   face->index = index;
 
@@ -247,6 +264,63 @@ hb_face_create (hb_blob_t    *blob,
 }
 
 /**
+ * hb_face_create_or_fail:
+ * @blob: #hb_blob_t to work upon
+ * @index: The index of the face within @blob
+ *
+ * Like hb_face_create(), but returns `NULL` if the blob data
+ * contains no usable font face at the specified index.
+ *
+ * Return value: (transfer full): The new face object, or `NULL` if
+ * no face is found at the specified index.
+ *
+ * Since: 10.1.0
+ **/
+hb_face_t *
+hb_face_create_or_fail (hb_blob_t    *blob,
+                        unsigned int  index)
+{
+  unsigned num_faces = hb_face_count (blob);
+  if (index >= num_faces)
+    return nullptr;
+
+  hb_face_t *face = hb_face_create (blob, index);
+  if (hb_object_is_immutable (face))
+    return nullptr;
+
+  return face;
+}
+
+#ifndef HB_NO_OPEN
+/**
+ * hb_face_create_from_file_or_fail:
+ * @file_name: A font filename
+ * @index: The index of the face within the file
+ *
+ * A thin wrapper around hb_blob_create_from_file_or_fail()
+ * followed by hb_face_create_or_fail().
+ *
+ * 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.
+ *
+ * Since: 10.1.0
+ **/
+HB_EXTERN hb_face_t *
+hb_face_create_from_file_or_fail (const char   *file_name,
+                                  unsigned int  index)
+{
+  hb_blob_t *blob = hb_blob_create_from_file_or_fail (file_name);
+  if (unlikely (!blob))
+    return nullptr;
+
+  hb_face_t *face = hb_face_create_or_fail (blob, index);
+  hb_blob_destroy (blob);
+
+  return face;
+}
+#endif
+
+/**
  * hb_face_get_empty:
  *
  * Fetches the singleton empty face object.
@@ -306,6 +380,9 @@ hb_face_destroy (hb_face_t *face)
   face->data.fini ();
   face->table.fini ();
 
+  if (face->get_table_tags_destroy)
+    face->get_table_tags_destroy (face->get_table_tags_user_data);
+
   if (face->destroy)
     face->destroy (face->user_data);
 
@@ -395,7 +472,8 @@ hb_face_is_immutable (const hb_face_t *f
  * @tag: The #hb_tag_t of the table to query
  *
  * Fetches a reference to the specified table within
- * the specified face.
+ * the specified face. Returns an empty blob if referencing table data is not
+ * possible.
  *
  * Return value: (transfer full): A pointer to the @tag table within @face
  *
@@ -415,9 +493,10 @@ hb_face_reference_table (const hb_face_t
  * hb_face_reference_blob:
  * @face: A face object
  *
- * Fetches a pointer to the binary blob that contains the
- * specified face. Returns an empty blob if referencing face data is not
- * possible.
+ * Fetches a pointer to the binary blob that contains the specified face.
+ * If referencing the face data is not possible, this function creates a blob
+ * out of individual table blobs if hb_face_get_table_tags() works with this
+ * face, otherwise it returns an empty blob.
  *
  * Return value: (transfer full): A pointer to the blob for @face
  *
@@ -426,7 +505,41 @@ hb_face_reference_table (const hb_face_t
 hb_blob_t *
 hb_face_reference_blob (hb_face_t *face)
 {
-  return face->reference_table (HB_TAG_NONE);
+  hb_blob_t *blob = face->reference_table (HB_TAG_NONE);
+
+  if (blob == hb_blob_get_empty ())
+  {
+    // If referencing the face blob is not possible (e.g. not implemented by the
+    // font functions), use face builder to create a blob out of individual
+    // table blobs.
+    unsigned total_count = hb_face_get_table_tags (face, 0, nullptr, nullptr);
+    if (total_count)
+    {
+      hb_tag_t tags[64];
+      unsigned count = ARRAY_LENGTH (tags);
+      hb_face_t* builder = hb_face_builder_create ();
+
+      for (unsigned offset = 0; offset < total_count; offset += count)
+      {
+        hb_face_get_table_tags (face, offset, &count, tags);
+        if (unlikely (!count))
+          break; // Allocation error
+        for (unsigned i = 0; i < count; i++)
+        {
+          if (unlikely (!tags[i]))
+            continue;
+          hb_blob_t *table = hb_face_reference_table (face, tags[i]);
+          hb_face_builder_add_table (builder, tags[i], table);
+          hb_blob_destroy (table);
+        }
+      }
+
+      blob = hb_face_reference_blob (builder);
+      hb_face_destroy (builder);
+    }
+  }
+
+  return blob;
 }
 
 /**
@@ -548,6 +661,38 @@ hb_face_get_glyph_count (const hb_face_t
 }
 
 /**
+ * hb_face_set_get_table_tags_func:
+ * @face: A face object
+ * @func: (closure user_data) (destroy destroy) (scope notified): The table-tag-fetching function
+ * @user_data: A pointer to the user data, to be destroyed by @destroy when not needed anymore
+ * @destroy: (nullable): A callback to call when @func is not needed anymore
+ *
+ * Sets the table-tag-fetching function for the specified face object.
+ *
+ * Since: 10.0.0
+ */
+HB_EXTERN void
+hb_face_set_get_table_tags_func (hb_face_t *face,
+                                 hb_get_table_tags_func_t func,
+                                 void                    *user_data,
+                                 hb_destroy_func_t        destroy)
+{
+  if (hb_object_is_immutable (face))
+  {
+    if (destroy)
+      destroy (user_data);
+    return;
+  }
+
+  if (face->get_table_tags_destroy)
+    face->get_table_tags_destroy (face->get_table_tags_user_data);
+
+  face->get_table_tags_func = func;
+  face->get_table_tags_user_data = user_data;
+  face->get_table_tags_destroy = destroy;
+}
+
+/**
  * hb_face_get_table_tags:
  * @face: A face object
  * @start_offset: The index of first table tag to retrieve
@@ -568,19 +713,14 @@ hb_face_get_table_tags (const hb_face_t
                         unsigned int *table_count, /* IN/OUT */
                         hb_tag_t     *table_tags /* OUT */)
 {
-  if (face->destroy != (hb_destroy_func_t) _hb_face_for_data_closure_destroy)
+  if (!face->get_table_tags_func)
   {
     if (table_count)
       *table_count = 0;
     return 0;
   }
 
-  hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data;
-
-  const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
-  const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
-
-  return ot_face.get_table_tags (start_offset, table_count, table_tags);
+  return face->get_table_tags_func (face, start_offset, table_count, table_tags, face->get_table_tags_user_data);
 }
 
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-face.h 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-face.h
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-face.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-face.h	2025-06-27 08:03:14.000000000 +0000
@@ -59,15 +59,28 @@ HB_EXTERN hb_face_t *
 hb_face_create (hb_blob_t    *blob,
                 unsigned int  index);
 
+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_from_file_or_fail (const char   *file_name,
+                                  unsigned int  index);
+
 /**
  * hb_reference_table_func_t:
  * @face: an #hb_face_t to reference table for
  * @tag: the tag of the table to reference
  * @user_data: User data pointer passed by the caller
  *
- * Callback function for hb_face_create_for_tables().
+ * Callback function for hb_face_create_for_tables(). The @tag is the tag of the
+ * table to reference, and the special tag #HB_TAG_NONE is used to reference the
+ * blob of the face itself. If referencing the face blob is not possible, it is
+ * recommended to set hb_get_table_tags_func_t on the @face to allow
+ * hb_face_reference_blob() to create a face blob out of individual table blobs.
  *
- * Return value: (transfer full): A pointer to the @tag table within @face
+ * Return value: (transfer full): A pointer to the @tag table within @face or
+ * `NULL` if the table is not found or cannot be referenced.
  *
  * Since: 0.9.2
  */
@@ -135,6 +148,34 @@ hb_face_set_glyph_count (hb_face_t    *f
 HB_EXTERN unsigned int
 hb_face_get_glyph_count (const hb_face_t *face);
 
+
+/**
+ * hb_get_table_tags_func_t:
+ * @face: A face object
+ * @start_offset: The index of first table tag to retrieve
+ * @table_count: (inout): Input = the maximum number of table tags to return;
+ *                Output = the actual number of table tags returned (may be zero)
+ * @table_tags: (out) (array length=table_count): The array of table tags found
+ * @user_data: User data pointer passed by the caller
+ *
+ * Callback function for hb_face_get_table_tags().
+ *
+ * Return value: Total number of tables, or zero if it is not possible to list
+ *
+ * Since: 10.0.0
+ */
+typedef unsigned int (*hb_get_table_tags_func_t) (const hb_face_t *face,
+                                                  unsigned int  start_offset,
+                                                  unsigned int *table_count, /* IN/OUT */
+                                                  hb_tag_t     *table_tags /* OUT */,
+                                                  void         *user_data);
+
+HB_EXTERN void
+hb_face_set_get_table_tags_func (hb_face_t *face,
+                                 hb_get_table_tags_func_t func,
+                                 void                    *user_data,
+                                 hb_destroy_func_t        destroy);
+
 HB_EXTERN unsigned int
 hb_face_get_table_tags (const hb_face_t *face,
                         unsigned int  start_offset,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-face.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-face.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-face.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-face.hh	2025-06-27 08:03:14.000000000 +0000
@@ -48,13 +48,17 @@ 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. */
+
   hb_reference_table_func_t  reference_table_func;
   void                      *user_data;
   hb_destroy_func_t          destroy;
 
-  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. */
+  hb_get_table_tags_func_t   get_table_tags_func;
+  void                      *get_table_tags_user_data;
+  hb_destroy_func_t          get_table_tags_destroy;
 
   hb_shaper_object_dataset_t<hb_face_t> data;/* Various shaper data. */
   hb_ot_face_t table;                   /* All the face's tables. */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-font.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-font.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-font.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-font.cc	2025-06-27 08:03:14.000000000 +0000
@@ -231,7 +231,7 @@ hb_font_get_glyph_v_advance_nil (hb_font
                                  void           *user_data HB_UNUSED)
 {
   /* TODO use font_extents.ascender+descender */
-  return font->y_scale;
+  return -font->y_scale;
 }
 
 static hb_position_t
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-font.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-font.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-font.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-font.hh	2025-06-27 08:03:14.000000000 +0000
@@ -651,7 +651,7 @@ struct hb_font_t
   {
     if (get_glyph_name (glyph, s, size)) return;
 
-    if (size && snprintf (s, size, "gid%u", glyph) < 0)
+    if (size && snprintf (s, size, "gid%" PRIu32, glyph) < 0)
       *s = '\0';
   }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ft.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ft.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ft.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ft.cc	2025-06-27 08:03:14.000000000 +0000
@@ -37,10 +37,15 @@
 #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"
 
+#include FT_MODULE_H
 #include FT_ADVANCES_H
 #include FT_MULTIPLE_MASTERS_H
 #include FT_OUTLINE_H
@@ -225,7 +230,7 @@ _hb_ft_hb_font_check_changed (hb_font_t
  * Sets the FT_Load_Glyph load flags for the specified #hb_font_t.
  *
  * For more information, see
- * https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#ft_load_xxx
+ * <https://freetype.org/freetype2/docs/reference/ft2-glyph_retrieval.html#ft_load_xxx>
  *
  * This function works with #hb_font_t objects created by
  * hb_ft_font_create() or hb_ft_font_create_referenced().
@@ -253,7 +258,7 @@ hb_ft_font_set_load_flags (hb_font_t *fo
  * Fetches the FT_Load_Glyph load flags of the specified #hb_font_t.
  *
  * For more information, see
- * https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#ft_load_xxx
+ * <https://freetype.org/freetype2/docs/reference/ft2-glyph_retrieval.html#ft_load_xxx>
  *
  * This function works with #hb_font_t objects created by
  * hb_ft_font_create() or hb_ft_font_create_referenced().
@@ -274,7 +279,7 @@ hb_ft_font_get_load_flags (hb_font_t *fo
 }
 
 /**
- * hb_ft_font_get_face: (skip)
+ * hb_ft_font_get_ft_face: (skip)
  * @font: #hb_font_t to work upon
  *
  * Fetches the FT_Face associated with the specified #hb_font_t
@@ -285,10 +290,10 @@ hb_ft_font_get_load_flags (hb_font_t *fo
  *
  * Return value: (nullable): the FT_Face found or `NULL`
  *
- * Since: 0.9.2
+ * Since: 10.4.0
  **/
 FT_Face
-hb_ft_font_get_face (hb_font_t *font)
+hb_ft_font_get_ft_face (hb_font_t *font)
 {
   if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
     return nullptr;
@@ -298,6 +303,31 @@ hb_ft_font_get_face (hb_font_t *font)
   return ft_font->ft_face;
 }
 
+#ifndef HB_DISABLE_DEPRECATED
+
+/**
+ * hb_ft_font_get_face: (skip)
+ * @font: #hb_font_t to work upon
+ *
+ * Fetches the FT_Face associated with the specified #hb_font_t
+ * font object.
+ *
+ * This function works with #hb_font_t objects created by
+ * hb_ft_font_create() or hb_ft_font_create_referenced().
+ *
+ * Return value: (nullable): the FT_Face found or `NULL`
+ *
+ * Since: 0.9.2
+ * Deprecated: 10.4.0: Use hb_ft_font_get_ft_face() instead.
+ **/
+FT_Face
+hb_ft_font_get_face (hb_font_t *font)
+{
+  return hb_ft_font_get_ft_face (font);
+}
+
+#endif
+
 /**
  * hb_ft_font_lock_face: (skip)
  * @font: #hb_font_t to work upon
@@ -501,6 +531,26 @@ hb_ft_get_glyph_h_advances (hb_font_t* f
       first_advance = &StructAtOffsetUnaligned<hb_position_t> (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<hb_codepoint_t> (first_glyph, glyph_stride);
+      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+    }
+  }
+#endif
 }
 
 #ifndef HB_NO_VERTICAL
@@ -537,7 +587,20 @@ hb_ft_get_glyph_v_advance (hb_font_t *fo
    * have a Y growing upward.  Hence the extra negation. */
 
   hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength;
-  return ((-v + (1<<9)) >> 10) + (font->embolden_in_place ? 0 : 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;
 }
 #endif
 
@@ -930,11 +993,15 @@ hb_ft_paint_glyph (hb_font_t *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;
+#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21301
+  load_flags |= FT_LOAD_NO_SVG;
+#endif
+
   /* We release the lock before calling into glyph callbacks, such that
    * eg. draw API can call back into the face.*/
 
-  if (unlikely (FT_Load_Glyph (ft_face, gid,
-                               ft_font->load_flags | FT_LOAD_COLOR)))
+  if (unlikely (FT_Load_Glyph (ft_face, gid, load_flags)))
     return;
 
   if (ft_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
@@ -1104,6 +1171,45 @@ _hb_ft_reference_table (hb_face_t *face
                          buffer, hb_free);
 }
 
+static unsigned
+_hb_ft_get_table_tags (const hb_face_t *face HB_UNUSED,
+                       unsigned int start_offset,
+                       unsigned int *table_count,
+                       hb_tag_t *table_tags,
+                       void *user_data)
+{
+  FT_Face ft_face = (FT_Face) user_data;
+
+  FT_ULong population = 0;
+  FT_Sfnt_Table_Info (ft_face,
+                      0, // table_index; ignored
+                      nullptr,
+                      &population);
+
+  if (!table_count)
+    return population;
+  else
+    *table_count = 0;
+
+  if (unlikely (start_offset >= population))
+    return population;
+
+  unsigned end_offset = hb_min (start_offset + *table_count, (unsigned) population);
+  if (unlikely (end_offset < start_offset))
+    return population;
+
+  *table_count = end_offset - start_offset;
+  for (unsigned i = start_offset; i < end_offset; i++)
+  {
+    FT_ULong tag = 0, length;
+    FT_Sfnt_Table_Info (ft_face, i, &tag, &length);
+    table_tags[i - start_offset] = tag;
+  }
+
+  return population;
+}
+
+
 /**
  * hb_ft_face_create:
  * @ft_face: (destroy destroy) (scope notified): FT_Face to work upon
@@ -1145,6 +1251,7 @@ hb_ft_face_create (FT_Face           ft_
     hb_blob_destroy (blob);
   } else {
     face = hb_face_create_for_tables (_hb_ft_reference_table, ft_face, destroy);
+    hb_face_set_get_table_tags_func (face, _hb_ft_get_table_tags, ft_face, nullptr);
   }
 
   hb_face_set_index (face, ft_face->face_index);
@@ -1215,7 +1322,7 @@ hb_ft_face_finalize (void *arg)
 hb_face_t *
 hb_ft_face_create_cached (FT_Face ft_face)
 {
-  if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != (FT_Generic_Finalizer) hb_ft_face_finalize))
+  if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != hb_ft_face_finalize))
   {
     if (ft_face->generic.finalizer)
       ft_face->generic.finalizer (ft_face);
@@ -1245,7 +1352,7 @@ hb_ft_face_create_cached (FT_Face ft_fac
  *
  * If you know you have valid reasons not to use hb_ft_font_create_referenced(),
  * then it is the client program's responsibility to destroy @ft_face
- * after the #hb_font_t font object has been destroyed.
+ * only after the #hb_font_t font object has been destroyed.
  *
  * HarfBuzz will use the @destroy callback on the #hb_font_t font object
  * if it is supplied when you use this function. However, even if @destroy
@@ -1392,6 +1499,24 @@ hb_ft_font_create_referenced (FT_Face ft
   return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
 }
 
+
+static void * _hb_ft_alloc (FT_Memory memory, long size)
+{ return hb_malloc (size); }
+
+static void _hb_ft_free (FT_Memory memory, void *block)
+{ hb_free (block); }
+
+static void * _hb_ft_realloc (FT_Memory memory, long cur_size, long new_size, void *block)
+{ return hb_realloc (block, new_size); }
+
+static FT_MemoryRec_ m =
+{
+  nullptr,
+  _hb_ft_alloc,
+  _hb_ft_free,
+  _hb_ft_realloc
+};
+
 static inline void free_static_ft_library ();
 
 static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<FT_Library>,
@@ -1400,16 +1525,19 @@ static struct hb_ft_library_lazy_loader_
   static FT_Library create ()
   {
     FT_Library l;
-    if (FT_Init_FreeType (&l))
+    if (FT_New_Library (&m, &l))
       return nullptr;
 
+    FT_Add_Default_Modules (l);
+    FT_Set_Default_Properties (l);
+
     hb_atexit (free_static_ft_library);
 
     return l;
   }
   static void destroy (FT_Library l)
   {
-    FT_Done_FreeType (l);
+    FT_Done_Library (l);
   }
   static FT_Library get_null ()
   {
@@ -1424,9 +1552,76 @@ void free_static_ft_library ()
 }
 
 static FT_Library
-get_ft_library ()
+reference_ft_library ()
+{
+  FT_Library l = static_ft_library.get_unconst ();
+  if (unlikely (FT_Reference_Library (l)))
+  {
+    DEBUG_MSG (FT, l, "FT_Reference_Library() failed");
+    return nullptr;
+  }
+  return l;
+}
+
+static hb_user_data_key_t ft_library_key = {0};
+
+static void
+finalize_ft_library (void *arg)
+{
+  FT_Face ft_face = (FT_Face) arg;
+  FT_Done_Library ((FT_Library) ft_face->generic.data);
+}
+
+static void
+destroy_ft_library (void *arg)
+{
+  FT_Done_Library ((FT_Library) arg);
+}
+
+/**
+ * hb_ft_face_create_from_file_or_fail:
+ * @file_name: A font filename
+ * @index: The index of the face within the file
+ *
+ * Creates an #hb_face_t face object from the specified
+ * 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.
+ *
+ * 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.
+ *
+ * Since: 10.1.0
+ */
+hb_face_t *
+hb_ft_face_create_from_file_or_fail (const char   *file_name,
+                                     unsigned int  index)
 {
-  return static_ft_library.get_unconst ();
+  FT_Library ft_library = reference_ft_library ();
+  if (unlikely (!ft_library))
+  {
+    DEBUG_MSG (FT, ft_library, "reference_ft_library failed");
+    return nullptr;
+  }
+
+  FT_Face ft_face;
+  if (unlikely (FT_New_Face (ft_library,
+                             file_name,
+                             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;
+
+  return face;
 }
 
 static void
@@ -1465,32 +1660,47 @@ _release_blob (void *arg)
 void
 hb_ft_font_set_funcs (hb_font_t *font)
 {
+  // In case of failure...
+  hb_font_set_funcs (font,
+                     hb_font_funcs_get_empty (),
+                     nullptr, nullptr);
+
   hb_blob_t *blob = hb_face_reference_blob (font->face);
   unsigned int blob_length;
   const char *blob_data = hb_blob_get_data (blob, &blob_length);
   if (unlikely (!blob_length))
     DEBUG_MSG (FT, font, "Font face has empty blob");
 
-  FT_Face ft_face = nullptr;
-  FT_Error err = FT_New_Memory_Face (get_ft_library (),
-                                     (const FT_Byte *) blob_data,
-                                     blob_length,
-                                     hb_face_get_index (font->face),
-                                     &ft_face);
+  FT_Library ft_library = reference_ft_library ();
+  if (unlikely (!ft_library))
+  {
+    hb_blob_destroy (blob);
+    DEBUG_MSG (FT, font, "reference_ft_library failed");
+    return;
+  }
 
-  if (unlikely (err)) {
+  FT_Face ft_face = nullptr;
+  if (unlikely (FT_New_Memory_Face (ft_library,
+                                    (const FT_Byte *) blob_data,
+                                    blob_length,
+                                    hb_face_get_index (font->face),
+                                    &ft_face)))
+  {
     hb_blob_destroy (blob);
-    DEBUG_MSG (FT, font, "Font face FT_New_Memory_Face() failed");
+    DEBUG_MSG (FT, font, "FT_New_Memory_Face() failed");
     return;
   }
 
   if (FT_Select_Charmap (ft_face, FT_ENCODING_MS_SYMBOL))
     FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE);
 
-
+  // Hook the blob to the FT_Face
   ft_face->generic.data = blob;
   ft_face->generic.finalizer = _release_blob;
 
+  // And the FT_Library to the blob
+  hb_blob_set_user_data (blob, &ft_library_key, ft_library, destroy_ft_library, true);
+
   _hb_ft_font_set_funcs (font, ft_face, true);
   hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING);
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ft.h 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ft.h
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ft.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ft.h	2025-06-27 08:03:14.000000000 +0000
@@ -84,6 +84,9 @@ hb_ft_face_create_cached (FT_Face ft_fac
 HB_EXTERN hb_face_t *
 hb_ft_face_create_referenced (FT_Face ft_face);
 
+HB_EXTERN hb_face_t *
+hb_ft_face_create_from_file_or_fail (const char   *file_name,
+                                     unsigned int  index);
 
 /*
  * hb-font from ft-face.
@@ -108,7 +111,7 @@ HB_EXTERN hb_font_t *
 hb_ft_font_create_referenced (FT_Face ft_face);
 
 HB_EXTERN FT_Face
-hb_ft_font_get_face (hb_font_t *font);
+hb_ft_font_get_ft_face (hb_font_t *font);
 
 HB_EXTERN FT_Face
 hb_ft_font_lock_face (hb_font_t *font);
@@ -139,6 +142,13 @@ hb_ft_hb_font_changed (hb_font_t *font);
 HB_EXTERN void
 hb_ft_font_set_funcs (hb_font_t *font);
 
+#ifndef HB_DISABLE_DEPRECATED
+
+HB_DEPRECATED_FOR (hb_ft_font_get_ft_face)
+HB_EXTERN FT_Face
+hb_ft_font_get_face (hb_font_t *font);
+
+#endif
 
 HB_END_DECLS
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,293 @@
+/*
+ * Copyright © 2022 Behdad Esfahbod
+ *
+ *  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.
+ */
+#ifndef HB_GEOMETRY_HH
+#define HB_GEOMETRY_HH
+
+#include "hb.hh"
+
+
+struct hb_extents_t
+{
+  hb_extents_t () {}
+  hb_extents_t (float xmin, float ymin, float xmax, float ymax) :
+    xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {}
+
+  bool is_empty () const { return xmin >= xmax || ymin >= ymax; }
+  bool is_void () const { return xmin > xmax; }
+
+  void union_ (const hb_extents_t &o)
+  {
+    xmin = hb_min (xmin, o.xmin);
+    ymin = hb_min (ymin, o.ymin);
+    xmax = hb_max (xmax, o.xmax);
+    ymax = hb_max (ymax, o.ymax);
+  }
+
+  void intersect (const hb_extents_t &o)
+  {
+    xmin = hb_max (xmin, o.xmin);
+    ymin = hb_max (ymin, o.ymin);
+    xmax = hb_min (xmax, o.xmax);
+    ymax = hb_min (ymax, o.ymax);
+  }
+
+  void
+  add_point (float x, float y)
+  {
+    if (unlikely (is_void ()))
+    {
+      xmin = xmax = x;
+      ymin = ymax = y;
+    }
+    else
+    {
+      xmin = hb_min (xmin, x);
+      ymin = hb_min (ymin, y);
+      xmax = hb_max (xmax, x);
+      ymax = hb_max (ymax, y);
+    }
+  }
+
+  float xmin = 0.f;
+  float ymin = 0.f;
+  float xmax = -1.f;
+  float ymax = -1.f;
+};
+
+struct hb_transform_t
+{
+  hb_transform_t () {}
+  hb_transform_t (float xx, float yx,
+                  float xy, float yy,
+                  float x0, float y0) :
+    xx (xx), yx (yx), xy (xy), yy (yy), x0 (x0), y0 (y0) {}
+
+  bool is_identity () const
+  {
+    return xx == 1.f && yx == 0.f &&
+           xy == 0.f && yy == 1.f &&
+           x0 == 0.f && y0 == 0.f;
+  }
+
+  void multiply (const hb_transform_t &o)
+  {
+    /* Copied from cairo, with "o" being "a" there and "this" being "b" there. */
+    hb_transform_t r;
+
+    r.xx = o.xx * xx + o.yx * xy;
+    r.yx = o.xx * yx + o.yx * yy;
+
+    r.xy = o.xy * xx + o.yy * xy;
+    r.yy = o.xy * yx + o.yy * yy;
+
+    r.x0 = o.x0 * xx + o.y0 * xy + x0;
+    r.y0 = o.x0 * yx + o.y0 * yy + y0;
+
+    *this = r;
+  }
+
+  void transform_distance (float &dx, float &dy) const
+  {
+    float new_x = xx * dx + xy * dy;
+    float new_y = yx * dx + yy * dy;
+    dx = new_x;
+    dy = new_y;
+  }
+
+  void transform_point (float &x, float &y) const
+  {
+    transform_distance (x, y);
+    x += x0;
+    y += y0;
+  }
+
+  void transform_extents (hb_extents_t &extents) const
+  {
+    float quad_x[4], quad_y[4];
+
+    quad_x[0] = extents.xmin;
+    quad_y[0] = extents.ymin;
+    quad_x[1] = extents.xmin;
+    quad_y[1] = extents.ymax;
+    quad_x[2] = extents.xmax;
+    quad_y[2] = extents.ymin;
+    quad_x[3] = extents.xmax;
+    quad_y[3] = extents.ymax;
+
+    extents = hb_extents_t {};
+    for (unsigned i = 0; i < 4; i++)
+    {
+      transform_point (quad_x[i], quad_y[i]);
+      extents.add_point (quad_x[i], quad_y[i]);
+    }
+  }
+
+  void transform (const hb_transform_t &o) { multiply (o); }
+
+  void translate (float x, float y)
+  {
+    if (x == 0.f && y == 0.f)
+      return;
+
+    x0 += xx * x + xy * y;
+    y0 += yx * x + yy * y;
+  }
+
+  void scale (float scaleX, float scaleY)
+  {
+    if (scaleX == 1.f && scaleY == 1.f)
+      return;
+
+    xx *= scaleX;
+    yx *= scaleX;
+    xy *= scaleY;
+    yy *= scaleY;
+  }
+
+  void rotate (float rotation)
+  {
+    if (rotation == 0.f)
+      return;
+
+    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
+    rotation = rotation * HB_PI;
+    float c;
+    float s;
+#ifdef HAVE_SINCOSF
+    sincosf (rotation, &s, &c);
+#else
+    c = cosf (rotation);
+    s = sinf (rotation);
+#endif
+    auto other = hb_transform_t{c, s, -s, c, 0.f, 0.f};
+    transform (other);
+  }
+
+  void skew (float skewX, float skewY)
+  {
+    if (skewX == 0.f && skewY == 0.f)
+      return;
+
+    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
+    skewX = skewX * HB_PI;
+    skewY = skewY * HB_PI;
+    auto other = hb_transform_t{1.f,
+                                skewY ? tanf (skewY) : 0.f,
+                                skewX ? tanf (skewX) : 0.f,
+                                1.f,
+                                0.f, 0.f};
+    transform (other);
+  }
+
+  float xx = 1.f;
+  float yx = 0.f;
+  float xy = 0.f;
+  float yy = 1.f;
+  float x0 = 0.f;
+  float y0 = 0.f;
+};
+
+#define HB_TRANSFORM_IDENTITY hb_transform_t{1.f, 0.f, 0.f, 1.f, 0.f, 0.f}
+
+struct hb_bounds_t
+{
+  enum status_t {
+    UNBOUNDED,
+    BOUNDED,
+    EMPTY,
+  };
+
+  hb_bounds_t (status_t status) : status (status) {}
+  hb_bounds_t (const hb_extents_t &extents) :
+    status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {}
+
+  void union_ (const hb_bounds_t &o)
+  {
+    if (o.status == UNBOUNDED)
+      status = UNBOUNDED;
+    else if (o.status == BOUNDED)
+    {
+      if (status == EMPTY)
+        *this = o;
+      else if (status == BOUNDED)
+        extents.union_ (o.extents);
+    }
+  }
+
+  void intersect (const hb_bounds_t &o)
+  {
+    if (o.status == EMPTY)
+      status = EMPTY;
+    else if (o.status == BOUNDED)
+    {
+      if (status == UNBOUNDED)
+        *this = o;
+      else if (status == BOUNDED)
+      {
+        extents.intersect (o.extents);
+        if (extents.is_empty ())
+          status = EMPTY;
+      }
+    }
+  }
+
+  status_t status;
+  hb_extents_t extents;
+};
+
+struct hb_transform_decomposed_t
+{
+  float translateX = 0;
+  float translateY = 0;
+  float rotation = 0;  // in degrees, counter-clockwise
+  float scaleX = 1;
+  float scaleY = 1;
+  float skewX = 0;  // in degrees, counter-clockwise
+  float skewY = 0;  // in degrees, counter-clockwise
+  float tCenterX = 0;
+  float tCenterY = 0;
+
+  operator bool () const
+  {
+    return translateX || translateY ||
+           rotation ||
+           scaleX != 1 || scaleY != 1 ||
+           skewX || skewY ||
+           tCenterX || tCenterY;
+  }
+
+  hb_transform_t to_transform () const
+  {
+    hb_transform_t t;
+    t.translate (translateX + tCenterX, translateY + tCenterY);
+    t.rotate (rotation);
+    t.scale (scaleX, scaleY);
+    t.skew (-skewX, skewY);
+    t.translate (-tCenterX, -tCenterY);
+    return t;
+  }
+};
+
+
+#endif /* HB_GEOMETRY_HH */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-iter.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-iter.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-iter.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-iter.hh	2025-06-27 08:03:14.000000000 +0000
@@ -324,6 +324,16 @@ struct hb_is_sink_of
         (hb_is_source_of(Iter, Item) && Iter::is_sorted_iterator)
 
 
+struct
+{
+  template <typename Iterable,
+            hb_requires (hb_is_iterable (Iterable))>
+  unsigned operator () (const Iterable &_) const { return hb_len (hb_iter (_)); }
+
+  unsigned operator () (unsigned _) const { return _; }
+}
+HB_FUNCOBJ (hb_len_of);
+
 /* Range-based 'for' for iterables. */
 
 template <typename Iterable,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-limits.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-limits.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-limits.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-limits.hh	2025-06-27 08:03:14.000000000 +0000
@@ -88,25 +88,24 @@
 #define HB_MAX_LOOKUP_VISIT_COUNT 35000
 #endif
 
-
-#ifndef HB_GLYF_VAR_COMPOSITE_MAX_AXES
-#define HB_GLYF_VAR_COMPOSITE_MAX_AXES 4096
+#ifndef HB_MAX_GRAPH_EDGE_COUNT
+#define HB_MAX_GRAPH_EDGE_COUNT 2048
 #endif
 
-#ifndef HB_GLYF_MAX_POINTS
-#define HB_GLYF_MAX_POINTS 20000
+#ifndef HB_VAR_COMPOSITE_MAX_AXES
+#define HB_VAR_COMPOSITE_MAX_AXES 4096
 #endif
 
-#ifndef HB_GLYF_MAX_EDGE_COUNT
-#define HB_GLYF_MAX_EDGE_COUNT 1024
+#ifndef HB_GLYF_MAX_POINTS
+#define HB_GLYF_MAX_POINTS 200000
 #endif
 
 #ifndef HB_CFF_MAX_OPS
-#define HB_CFF_MAX_OPS 10000
+#define HB_CFF_MAX_OPS 200000
 #endif
 
-#ifndef HB_COLRV1_MAX_EDGE_COUNT
-#define HB_COLRV1_MAX_EDGE_COUNT 65536
+#ifndef HB_MAX_COMPOSITE_OPERATIONS_PER_GLYPH
+#define HB_MAX_COMPOSITE_OPERATIONS_PER_GLYPH 64
 #endif
 
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-map.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-map.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-map.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-map.hh	2025-06-27 08:03:14.000000000 +0000
@@ -42,13 +42,37 @@ template <typename K, typename V,
           bool minus_one = false>
 struct hb_hashmap_t
 {
+  static constexpr bool realloc_move = true;
+
   hb_hashmap_t ()  { init (); }
   ~hb_hashmap_t () { fini (); }
 
-  hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { alloc (o.population); hb_copy (o, *this); }
-  hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); }
+  hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t ()
+  {
+    if (unlikely (!o.mask)) return;
+
+    if (item_t::is_trivial)
+    {
+      items = (item_t *) hb_malloc (sizeof (item_t) * (o.mask + 1));
+      if (unlikely (!items))
+      {
+        successful = false;
+        return;
+      }
+      population = o.population;
+      occupancy = o.occupancy;
+      mask = o.mask;
+      prime = o.prime;
+      max_chain_length = o.max_chain_length;
+      memcpy (items, o.items, sizeof (item_t) * (mask + 1));
+      return;
+    }
+
+    alloc (o.population); hb_copy (o, *this);
+  }
+  hb_hashmap_t (hb_hashmap_t&& o)  noexcept : hb_hashmap_t () { hb_swap (*this, o); }
   hb_hashmap_t& operator= (const hb_hashmap_t& o)  { reset (); alloc (o.population); hb_copy (o, *this); return *this; }
-  hb_hashmap_t& operator= (hb_hashmap_t&& o)  { hb_swap (*this, o); return *this; }
+  hb_hashmap_t& operator= (hb_hashmap_t&& o)   noexcept { hb_swap (*this, o); return *this; }
 
   hb_hashmap_t (std::initializer_list<hb_pair_t<K, V>> lst) : hb_hashmap_t ()
   {
@@ -113,26 +137,23 @@ struct hb_hashmap_t
   };
 
   hb_object_header_t header;
-  unsigned int successful : 1; /* Allocations successful */
-  unsigned int population : 31; /* Not including tombstones. */
+  bool successful; /* Allocations successful */
+  unsigned short max_chain_length;
+  unsigned int population; /* Not including tombstones. */
   unsigned int occupancy; /* Including tombstones. */
   unsigned int mask;
   unsigned int prime;
-  unsigned int max_chain_length;
   item_t *items;
 
-  friend void swap (hb_hashmap_t& a, hb_hashmap_t& b)
+  friend void swap (hb_hashmap_t& a, hb_hashmap_t& b) noexcept
   {
     if (unlikely (!a.successful || !b.successful))
       return;
-    unsigned tmp = a.population;
-    a.population = b.population;
-    b.population = tmp;
-    //hb_swap (a.population, b.population);
+    hb_swap (a.max_chain_length, b.max_chain_length);
+    hb_swap (a.population, b.population);
     hb_swap (a.occupancy, b.occupancy);
     hb_swap (a.mask, b.mask);
     hb_swap (a.prime, b.prime);
-    hb_swap (a.max_chain_length, b.max_chain_length);
     hb_swap (a.items, b.items);
   }
   void init ()
@@ -140,10 +161,10 @@ struct hb_hashmap_t
     hb_object_init (this);
 
     successful = true;
+    max_chain_length = 0;
     population = occupancy = 0;
     mask = 0;
     prime = 0;
-    max_chain_length = 0;
     items = nullptr;
   }
   void fini ()
@@ -209,9 +230,10 @@ struct hb_hashmap_t
                        old_items[i].hash,
                        std::move (old_items[i].value));
       }
-      if (!item_t::is_trivial)
-        old_items[i].~item_t ();
     }
+    if (!item_t::is_trivial)
+      for (unsigned int i = 0; i < old_size; i++)
+        old_items[i].~item_t ();
 
     hb_free (old_items);
 
@@ -285,7 +307,7 @@ struct hb_hashmap_t
   const V& get_with_hash (const K &key, uint32_t hash) const
   {
     if (!items) return item_t::default_value ();
-    auto *item = fetch_item (key, hb_hash (key));
+    auto *item = fetch_item (key, hash);
     if (item)
       return item->value;
     return item_t::default_value ();
@@ -533,7 +555,7 @@ struct hb_map_t : hb_hashmap_t<hb_codepo
   ~hb_map_t () = default;
   hb_map_t () : hashmap () {}
   hb_map_t (const hb_map_t &o) : hashmap ((hashmap &) o) {}
-  hb_map_t (hb_map_t &&o) : hashmap (std::move ((hashmap &) o)) {}
+  hb_map_t (hb_map_t &&o)  noexcept : hashmap (std::move ((hashmap &) o)) {}
   hb_map_t& operator= (const hb_map_t&) = default;
   hb_map_t& operator= (hb_map_t&&) = default;
   hb_map_t (std::initializer_list<hb_codepoint_pair_t> lst) : hashmap (lst) {}
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-null.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-null.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-null.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-null.hh	2025-06-27 08:03:14.000000000 +0000
@@ -176,7 +176,7 @@ template <typename Type>
 static inline Type& Crap () {
   static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
   Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
-  memcpy (obj, std::addressof (Null (Type)), sizeof (*obj));
+  memcpy (reinterpret_cast<void*>(obj), std::addressof (Null (Type)), sizeof (*obj));
   return *obj;
 }
 template <typename QType>
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-object.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-object.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-object.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-object.hh	2025-06-27 08:03:14.000000000 +0000
@@ -325,7 +325,7 @@ retry:
   hb_user_data_array_t *user_data = obj->header.user_data.get_acquire ();
   if (unlikely (!user_data))
   {
-    user_data = (hb_user_data_array_t *) hb_calloc (sizeof (hb_user_data_array_t), 1);
+    user_data = (hb_user_data_array_t *) hb_calloc (1, sizeof (hb_user_data_array_t));
     if (unlikely (!user_data))
       return false;
     user_data->init ();
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-open-file.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-open-file.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-open-file.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-open-file.hh	2025-06-27 08:03:14.000000000 +0000
@@ -250,7 +250,7 @@ struct TTCHeader
   {
     switch (u.header.version.major) {
     case 2: /* version 2 is compatible with version 1 */
-    case 1: return u.version1.get_face_count ();
+    case 1: hb_barrier (); return u.version1.get_face_count ();
     default:return 0;
     }
   }
@@ -258,7 +258,7 @@ struct TTCHeader
   {
     switch (u.header.version.major) {
     case 2: /* version 2 is compatible with version 1 */
-    case 1: return u.version1.get_face (i);
+    case 1: hb_barrier (); return u.version1.get_face (i);
     default:return Null (OpenTypeFontFace);
     }
   }
@@ -267,9 +267,10 @@ struct TTCHeader
   {
     TRACE_SANITIZE (this);
     if (unlikely (!u.header.version.sanitize (c))) return_trace (false);
+    hb_barrier ();
     switch (u.header.version.major) {
     case 2: /* version 2 is compatible with version 1 */
-    case 1: return_trace (u.version1.sanitize (c));
+    case 1: hb_barrier (); return_trace (u.version1.sanitize (c));
     default:return_trace (true);
     }
   }
@@ -302,6 +303,7 @@ struct ResourceRecord
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
                   offset.sanitize (c, data_base) &&
+                  hb_barrier () &&
                   get_face (data_base).sanitize (c));
   }
 
@@ -337,6 +339,7 @@ struct ResourceTypeRecord
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   resourcesZ.sanitize (c, type_base,
                                        get_resource_count (),
                                        data_base));
@@ -385,6 +388,7 @@ struct ResourceMap
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   typeList.sanitize (c, this,
                                      &(this+typeList),
                                      data_base));
@@ -428,6 +432,7 @@ struct ResourceForkHeader
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   data.sanitize (c, this, dataLen) &&
                   map.sanitize (c, this, &(this+data)));
   }
@@ -508,6 +513,7 @@ struct OpenTypeFontFile
   {
     TRACE_SANITIZE (this);
     if (unlikely (!u.tag.sanitize (c))) return_trace (false);
+    hb_barrier ();
     switch (u.tag) {
     case CFFTag:        /* All the non-collection tags */
     case TrueTag:
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh	2025-06-27 08:03:14.000000000 +0000
@@ -87,20 +87,11 @@ struct IntType
     return pb->cmp (*pa);
   }
   template <typename Type2,
-            hb_enable_if (std::is_integral<Type2>::value &&
-                          sizeof (Type2) < sizeof (int) &&
-                          sizeof (Type) < sizeof (int))>
-  int cmp (Type2 a) const
-  {
-    Type b = v;
-    return (int) a - (int) b;
-  }
-  template <typename Type2,
             hb_enable_if (hb_is_convertible (Type2, Type))>
   int cmp (Type2 a) const
   {
     Type b = v;
-    return a < b ? -1 : a == b ? 0 : +1;
+    return (a > b) - (a < b);
   }
   bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -132,6 +123,89 @@ struct HBUINT15 : HBUINT16
   DEFINE_SIZE_STATIC (2);
 };
 
+/* 32-bit unsigned integer with variable encoding. */
+struct HBUINT32VAR
+{
+  unsigned get_size () const
+  {
+    unsigned b0 = v[0];
+    if (b0 < 0x80)
+      return 1;
+    else if (b0 < 0xC0)
+      return 2;
+    else if (b0 < 0xE0)
+      return 3;
+    else if (b0 < 0xF0)
+      return 4;
+    else
+      return 5;
+  }
+
+  static unsigned get_size (uint32_t v)
+  {
+    if (v < 0x80)
+      return 1;
+    else if (v < 0x4000)
+      return 2;
+    else if (v < 0x200000)
+      return 3;
+    else if (v < 0x10000000)
+      return 4;
+    else
+      return 5;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_range (v, 1) &&
+                  hb_barrier () &&
+                  c->check_range (v, get_size ()));
+  }
+
+  operator uint32_t () const
+  {
+    unsigned b0 = v[0];
+    if (b0 < 0x80)
+      return b0;
+    else if (b0 < 0xC0)
+      return ((b0 & 0x3F) << 8) | v[1];
+    else if (b0 < 0xE0)
+      return ((b0 & 0x1F) << 16) | (v[1] << 8) | v[2];
+    else if (b0 < 0xF0)
+      return ((b0 & 0x0F) << 24) | (v[1] << 16) | (v[2] << 8) | v[3];
+    else
+      return (v[1] << 24) | (v[2] << 16) | (v[3] << 8) | v[4];
+  }
+
+  static bool serialize (hb_serialize_context_t *c, uint32_t v)
+  {
+    unsigned len = get_size (v);
+
+    unsigned char *buf = c->allocate_size<unsigned char> (len, false);
+    if (unlikely (!buf))
+      return false;
+
+    unsigned char *p = buf + len;
+    for (unsigned i = 0; i < len; i++)
+    {
+      *--p = v & 0xFF;
+      v >>= 8;
+    }
+
+    if (len > 1)
+      buf[0] |= ((1 << (len - 1)) - 1) << (9 - len);
+
+    return true;
+  }
+
+  protected:
+  unsigned char v[5];
+
+  public:
+  DEFINE_SIZE_MIN (1);
+};
+
 /* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
 typedef HBINT16 FWORD;
 
@@ -149,6 +223,7 @@ struct HBFixed : Type
 
   operator signed () const = delete;
   operator unsigned () const = delete;
+  explicit operator float () const { return to_float (); }
   typename Type::type to_int () const { return Type::v; }
   void set_int (typename Type::type i ) { Type::v = i; }
   float to_float (float offset = 0) const  { return ((int32_t) Type::v + offset) / shift; }
@@ -215,11 +290,6 @@ typedef Index NameID;
 struct VarIdx : HBUINT32 {
   static constexpr unsigned NO_VARIATION = 0xFFFFFFFFu;
   static_assert (NO_VARIATION == HB_OT_LAYOUT_NO_VARIATIONS_INDEX, "");
-  static uint32_t add (uint32_t i, unsigned short v)
-  {
-    if (i == NO_VARIATION) return i;
-    return i + v;
-  }
   VarIdx& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; }
 };
 DECLARE_NULL_NAMESPACE_BYTES (OT, VarIdx);
@@ -309,7 +379,7 @@ struct _hb_has_null<Type, true>
   static       Type *get_crap () { return &Crap (Type); }
 };
 
-template <typename Type, typename OffsetType, bool has_null=true>
+template <typename Type, typename OffsetType, typename BaseType=void, bool has_null=true>
 struct OffsetTo : Offset<OffsetType, has_null>
 {
   using target_t = Type;
@@ -335,22 +405,22 @@ struct OffsetTo : Offset<OffsetType, has
   }
 
   template <typename Base,
-            hb_enable_if (hb_is_convertible (const Base, const void *))>
+            hb_enable_if (hb_is_convertible (const Base, const BaseType *))>
   friend const Type& operator + (const Base &base, const OffsetTo &offset) { return offset ((const void *) base); }
   template <typename Base,
-            hb_enable_if (hb_is_convertible (const Base, const void *))>
+            hb_enable_if (hb_is_convertible (const Base, const BaseType *))>
   friend const Type& operator + (const OffsetTo &offset, const Base &base) { return offset ((const void *) base); }
   template <typename Base,
-            hb_enable_if (hb_is_convertible (Base, void *))>
+            hb_enable_if (hb_is_convertible (Base, BaseType *))>
   friend Type& operator + (Base &&base, OffsetTo &offset) { return offset ((void *) base); }
   template <typename Base,
-            hb_enable_if (hb_is_convertible (Base, void *))>
+            hb_enable_if (hb_is_convertible (Base, BaseType *))>
   friend Type& operator + (OffsetTo &offset, Base &&base) { return offset ((void *) base); }
 
 
-  template <typename ...Ts>
+  template <typename Base, typename ...Ts>
   bool serialize_subset (hb_subset_context_t *c, const OffsetTo& src,
-                         const void *src_base, Ts&&... ds)
+                         const Base *src_base, Ts&&... ds)
   {
     *this = 0;
     if (src.is_null ())
@@ -414,10 +484,11 @@ struct OffsetTo : Offset<OffsetType, has
                        const void *src_base, unsigned dst_bias = 0)
   { return serialize_copy (c, src, src_base, dst_bias, hb_serialize_context_t::Head); }
 
-  bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize_shallow (hb_sanitize_context_t *c, const BaseType *base) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this))) return_trace (false);
+    hb_barrier ();
     //if (unlikely (this->is_null ())) return_trace (true);
     if (unlikely ((const char *) base + (unsigned) *this < (const char *) base)) return_trace (false);
     return_trace (true);
@@ -427,10 +498,11 @@ struct OffsetTo : Offset<OffsetType, has
 #ifndef HB_OPTIMIZE_SIZE
   HB_ALWAYS_INLINE
 #endif
-  bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const
+  bool sanitize (hb_sanitize_context_t *c, const BaseType *base, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
     return_trace (sanitize_shallow (c, base) &&
+                  hb_barrier () &&
                   (this->is_null () ||
                    c->dispatch (StructAtOffset<Type> (base, *this), std::forward<Ts> (ds)...) ||
                    neuter (c)));
@@ -445,14 +517,14 @@ struct OffsetTo : Offset<OffsetType, has
   DEFINE_SIZE_STATIC (sizeof (OffsetType));
 };
 /* Partial specializations. */
-template <typename Type, bool has_null=true> using Offset16To = OffsetTo<Type, HBUINT16, has_null>;
-template <typename Type, bool has_null=true> using Offset24To = OffsetTo<Type, HBUINT24, has_null>;
-template <typename Type, bool has_null=true> using Offset32To = OffsetTo<Type, HBUINT32, has_null>;
-
-template <typename Type, typename OffsetType> using NNOffsetTo = OffsetTo<Type, OffsetType, false>;
-template <typename Type> using NNOffset16To = Offset16To<Type, false>;
-template <typename Type> using NNOffset24To = Offset24To<Type, false>;
-template <typename Type> using NNOffset32To = Offset32To<Type, false>;
+template <typename Type, typename BaseType=void, bool has_null=true> using Offset16To = OffsetTo<Type, HBUINT16, BaseType, has_null>;
+template <typename Type, typename BaseType=void, bool has_null=true> using Offset24To = OffsetTo<Type, HBUINT24, BaseType, has_null>;
+template <typename Type, typename BaseType=void, bool has_null=true> using Offset32To = OffsetTo<Type, HBUINT32, BaseType, has_null>;
+
+template <typename Type, typename OffsetType, typename BaseType=void> using NNOffsetTo = OffsetTo<Type, OffsetType, BaseType, false>;
+template <typename Type, typename BaseType=void> using NNOffset16To = Offset16To<Type, BaseType, false>;
+template <typename Type, typename BaseType=void> using NNOffset24To = Offset24To<Type, BaseType, false>;
+template <typename Type, typename BaseType=void> using NNOffset32To = Offset32To<Type, BaseType, false>;
 
 
 /*
@@ -536,6 +608,7 @@ struct UnsizedArrayOf
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
     if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
+    hb_barrier ();
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
         return_trace (false);
@@ -555,27 +628,27 @@ struct UnsizedArrayOf
 };
 
 /* Unsized array of offset's */
-template <typename Type, typename OffsetType, bool has_null=true>
-using UnsizedArray16OfOffsetTo = UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null>>;
+template <typename Type, typename OffsetType, typename BaseType=void, bool has_null=true>
+using UnsizedArray16OfOffsetTo = UnsizedArrayOf<OffsetTo<Type, OffsetType, BaseType, has_null>>;
 
 /* Unsized array of offsets relative to the beginning of the array itself. */
-template <typename Type, typename OffsetType, bool has_null=true>
-struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo<Type, OffsetType, has_null>
+template <typename Type, typename OffsetType, typename BaseType=void, bool has_null=true>
+struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo<Type, OffsetType, BaseType, has_null>
 {
   const Type& operator [] (int i_) const
   {
     unsigned int i = (unsigned int) i_;
-    const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
+    const OffsetTo<Type, OffsetType, BaseType, has_null> *p = &this->arrayZ[i];
     if (unlikely ((const void *) p < (const void *) this->arrayZ)) return Null (Type); /* Overflowed. */
-    _hb_compiler_memory_r_barrier ();
+    hb_barrier ();
     return this+*p;
   }
   Type& operator [] (int i_)
   {
     unsigned int i = (unsigned int) i_;
-    const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
+    const OffsetTo<Type, OffsetType, BaseType, has_null> *p = &this->arrayZ[i];
     if (unlikely ((const void *) p < (const void *) this->arrayZ)) return Crap (Type); /* Overflowed. */
-    _hb_compiler_memory_r_barrier ();
+    hb_barrier ();
     return this+*p;
   }
 
@@ -583,7 +656,7 @@ struct UnsizedListOfOffset16To : Unsized
   bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const
   {
     TRACE_SANITIZE (this);
-    return_trace ((UnsizedArray16OfOffsetTo<Type, OffsetType, has_null>
+    return_trace ((UnsizedArray16OfOffsetTo<Type, OffsetType, BaseType, has_null>
                    ::sanitize (c, count, this, std::forward<Ts> (ds)...)));
   }
 };
@@ -626,14 +699,14 @@ struct ArrayOf
   {
     unsigned int i = (unsigned int) i_;
     if (unlikely (i >= len)) return Null (Type);
-    _hb_compiler_memory_r_barrier ();
+    hb_barrier ();
     return arrayZ[i];
   }
   Type& operator [] (int i_)
   {
     unsigned int i = (unsigned int) i_;
     if (unlikely (i >= len)) return Crap (Type);
-    _hb_compiler_memory_r_barrier ();
+    hb_barrier ();
     return arrayZ[i];
   }
 
@@ -725,6 +798,7 @@ struct ArrayOf
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c))) return_trace (false);
     if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
+    hb_barrier ();
     unsigned int count = len;
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
@@ -735,7 +809,9 @@ struct ArrayOf
   bool sanitize_shallow (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (len.sanitize (c) && c->check_array_sized (arrayZ, len, sizeof (LenType)));
+    return_trace (len.sanitize (c) &&
+                  hb_barrier () &&
+                  c->check_array_sized (arrayZ, len, sizeof (LenType)));
   }
 
   public:
@@ -750,6 +826,7 @@ template <typename Type> using Array32Of
 using PString = ArrayOf<HBUINT8, HBUINT8>;
 
 /* Array of Offset's */
+template <typename Type> using Array8OfOffset24To = ArrayOf<OffsetTo<Type, HBUINT24>, HBUINT8>;
 template <typename Type> using Array16OfOffset16To = ArrayOf<OffsetTo<Type, HBUINT16>, HBUINT16>;
 template <typename Type> using Array16OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT16>;
 template <typename Type> using Array32OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>;
@@ -762,14 +839,14 @@ struct List16OfOffsetTo : ArrayOf<Offset
   {
     unsigned int i = (unsigned int) i_;
     if (unlikely (i >= this->len)) return Null (Type);
-    _hb_compiler_memory_r_barrier ();
+    hb_barrier ();
     return this+this->arrayZ[i];
   }
   const Type& operator [] (int i_)
   {
     unsigned int i = (unsigned int) i_;
     if (unlikely (i >= this->len)) return Crap (Type);
-    _hb_compiler_memory_r_barrier ();
+    hb_barrier ();
     return this+this->arrayZ[i];
   }
 
@@ -807,14 +884,14 @@ struct HeadlessArrayOf
   {
     unsigned int i = (unsigned int) i_;
     if (unlikely (i >= lenP1 || !i)) return Null (Type);
-    _hb_compiler_memory_r_barrier ();
+    hb_barrier ();
     return arrayZ[i-1];
   }
   Type& operator [] (int i_)
   {
     unsigned int i = (unsigned int) i_;
     if (unlikely (i >= lenP1 || !i)) return Crap (Type);
-    _hb_compiler_memory_r_barrier ();
+    hb_barrier ();
     return arrayZ[i-1];
   }
   unsigned int get_size () const
@@ -866,6 +943,7 @@ struct HeadlessArrayOf
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c))) return_trace (false);
     if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
+    hb_barrier ();
     unsigned int count = get_length ();
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
@@ -878,6 +956,7 @@ struct HeadlessArrayOf
   {
     TRACE_SANITIZE (this);
     return_trace (lenP1.sanitize (c) &&
+                  hb_barrier () &&
                   (!lenP1 || c->check_array_sized (arrayZ, lenP1 - 1, sizeof (LenType))));
   }
 
@@ -899,14 +978,14 @@ struct ArrayOfM1
   {
     unsigned int i = (unsigned int) i_;
     if (unlikely (i > lenM1)) return Null (Type);
-    _hb_compiler_memory_r_barrier ();
+    hb_barrier ();
     return arrayZ[i];
   }
   Type& operator [] (int i_)
   {
     unsigned int i = (unsigned int) i_;
     if (unlikely (i > lenM1)) return Crap (Type);
-    _hb_compiler_memory_r_barrier ();
+    hb_barrier ();
     return arrayZ[i];
   }
   unsigned int get_size () const
@@ -919,6 +998,7 @@ struct ArrayOfM1
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c))) return_trace (false);
     if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
+    hb_barrier ();
     unsigned int count = lenM1 + 1;
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
@@ -931,6 +1011,7 @@ struct ArrayOfM1
   {
     TRACE_SANITIZE (this);
     return_trace (lenM1.sanitize (c) &&
+                  hb_barrier () &&
                   (c->check_array_sized (arrayZ, lenM1 + 1, sizeof (LenType))));
   }
 
@@ -975,6 +1056,13 @@ struct SortedArrayOf : ArrayOf<Type, Len
     return_trace (ret);
   }
 
+  SortedArrayOf* copy (hb_serialize_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    SortedArrayOf* out = reinterpret_cast<SortedArrayOf *> (ArrayOf<Type, LenType>::copy (c));
+    return_trace (out);
+  }
+
   template <typename T>
   Type &bsearch (const T &x, Type &not_found = Crap (Type))
   { return *as_array ().bsearch (x, &not_found); }
@@ -1082,14 +1170,14 @@ struct VarSizedBinSearchArrayOf
   {
     unsigned int i = (unsigned int) i_;
     if (unlikely (i >= get_length ())) return Null (Type);
-    _hb_compiler_memory_r_barrier ();
+    hb_barrier ();
     return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
   }
   Type& operator [] (int i_)
   {
     unsigned int i = (unsigned int) i_;
     if (unlikely (i >= get_length ())) return Crap (Type);
-    _hb_compiler_memory_r_barrier ();
+    hb_barrier ();
     return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
   }
   unsigned int get_length () const
@@ -1104,6 +1192,7 @@ struct VarSizedBinSearchArrayOf
     TRACE_SANITIZE (this);
     if (unlikely (!sanitize_shallow (c))) return_trace (false);
     if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
+    hb_barrier ();
     unsigned int count = get_length ();
     for (unsigned int i = 0; i < count; i++)
       if (unlikely (!(*this)[i].sanitize (c, std::forward<Ts> (ds)...)))
@@ -1130,6 +1219,7 @@ struct VarSizedBinSearchArrayOf
   {
     TRACE_SANITIZE (this);
     return_trace (header.sanitize (c) &&
+                  hb_barrier () &&
                   Type::static_size <= header.unitSize &&
                   c->check_range (bytesZ.arrayZ,
                                   header.nUnits,
@@ -1144,6 +1234,800 @@ struct VarSizedBinSearchArrayOf
 };
 
 
+/* CFF INDEX */
+
+template <typename COUNT>
+struct CFFIndex
+{
+  unsigned int offset_array_size () const
+  { return offSize * (count + 1); }
+
+  template <typename Iterable,
+            hb_requires (hb_is_iterable (Iterable))>
+  bool serialize (hb_serialize_context_t *c,
+                  const Iterable &iterable,
+                  const unsigned *p_data_size = nullptr,
+                  unsigned min_off_size = 0)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned data_size;
+    if (p_data_size)
+      data_size = *p_data_size;
+    else
+      total_size (iterable, &data_size);
+
+    auto it = hb_iter (iterable);
+    if (unlikely (!serialize_header (c, +it, data_size, min_off_size))) return_trace (false);
+    unsigned char *ret = c->allocate_size<unsigned char> (data_size, false);
+    if (unlikely (!ret)) return_trace (false);
+    for (const auto &_ : +it)
+    {
+      unsigned len = _.length;
+      if (!len)
+        continue;
+      if (len <= 1)
+      {
+        *ret++ = *_.arrayZ;
+        continue;
+      }
+      hb_memcpy (ret, _.arrayZ, len);
+      ret += len;
+    }
+    return_trace (true);
+  }
+
+  template <typename Iterator,
+            hb_requires (hb_is_iterator (Iterator))>
+  bool serialize_header (hb_serialize_context_t *c,
+                         Iterator it,
+                         unsigned data_size,
+                         unsigned min_off_size = 0)
+  {
+    TRACE_SERIALIZE (this);
+
+    unsigned off_size = (hb_bit_storage (data_size + 1) + 7) / 8;
+    off_size = hb_max(min_off_size, off_size);
+
+    /* serialize CFFIndex header */
+    if (unlikely (!c->extend_min (this))) return_trace (false);
+    this->count = hb_len (it);
+    if (!this->count) return_trace (true);
+    if (unlikely (!c->extend (this->offSize))) return_trace (false);
+    this->offSize = off_size;
+    if (unlikely (!c->allocate_size<HBUINT8> (off_size * (this->count + 1), false)))
+      return_trace (false);
+
+    /* serialize indices */
+    unsigned int offset = 1;
+    if (HB_OPTIMIZE_SIZE_VAL)
+    {
+      unsigned int i = 0;
+      for (const auto &_ : +it)
+      {
+        set_offset_at (i++, offset);
+        offset += hb_len_of (_);
+      }
+      set_offset_at (i, offset);
+    }
+    else
+      switch (off_size)
+      {
+        case 1:
+        {
+          HBUINT8 *p = (HBUINT8 *) offsets;
+          for (const auto &_ : +it)
+          {
+            *p++ = offset;
+            offset += hb_len_of (_);
+          }
+          *p = offset;
+        }
+        break;
+        case 2:
+        {
+          HBUINT16 *p = (HBUINT16 *) offsets;
+          for (const auto &_ : +it)
+          {
+            *p++ = offset;
+            offset += hb_len_of (_);
+          }
+          *p = offset;
+        }
+        break;
+        case 3:
+        {
+          HBUINT24 *p = (HBUINT24 *) offsets;
+          for (const auto &_ : +it)
+          {
+            *p++ = offset;
+            offset += hb_len_of (_);
+          }
+          *p = offset;
+        }
+        break;
+        case 4:
+        {
+          HBUINT32 *p = (HBUINT32 *) offsets;
+          for (const auto &_ : +it)
+          {
+            *p++ = offset;
+            offset += hb_len_of (_);
+          }
+          *p = offset;
+        }
+        break;
+        default:
+        break;
+      }
+
+    assert (offset == data_size + 1);
+    return_trace (true);
+  }
+
+  template <typename Iterable,
+            hb_requires (hb_is_iterable (Iterable))>
+  static unsigned total_size (const Iterable &iterable, unsigned *data_size = nullptr, unsigned min_off_size = 0)
+  {
+    auto it = + hb_iter (iterable);
+    if (!it)
+    {
+      if (data_size) *data_size = 0;
+      return min_size;
+    }
+
+    unsigned total = 0;
+    for (const auto &_ : +it)
+      total += hb_len_of (_);
+
+    if (data_size) *data_size = total;
+
+    unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8;
+    off_size = hb_max(min_off_size, off_size);
+
+    return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total;
+  }
+
+  void set_offset_at (unsigned int index, unsigned int offset)
+  {
+    assert (index <= count);
+
+    unsigned int size = offSize;
+    const HBUINT8 *p = offsets;
+    switch (size)
+    {
+      case 1: ((HBUINT8  *) p)[index] = offset; break;
+      case 2: ((HBUINT16 *) p)[index] = offset; break;
+      case 3: ((HBUINT24 *) p)[index] = offset; break;
+      case 4: ((HBUINT32 *) p)[index] = offset; break;
+      default: return;
+    }
+  }
+
+  private:
+  unsigned int offset_at (unsigned int index) const
+  {
+    assert (index <= count);
+
+    unsigned int size = offSize;
+    const HBUINT8 *p = offsets;
+    switch (size)
+    {
+      case 1: return ((HBUINT8  *) p)[index];
+      case 2: return ((HBUINT16 *) p)[index];
+      case 3: return ((HBUINT24 *) p)[index];
+      case 4: return ((HBUINT32 *) p)[index];
+      default: return 0;
+    }
+  }
+
+  const unsigned char *data_base () const
+  { return (const unsigned char *) this + min_size + offSize.static_size - 1 + offset_array_size (); }
+  public:
+
+  hb_ubytes_t operator [] (unsigned int index) const
+  {
+    if (unlikely (index >= count)) return hb_ubytes_t ();
+    hb_barrier ();
+    unsigned offset0 = offset_at (index);
+    unsigned offset1 = offset_at (index + 1);
+    if (unlikely (offset1 < offset0 || offset1 > offset_at (count)))
+      return hb_ubytes_t ();
+    return hb_ubytes_t (data_base () + offset0, offset1 - offset0);
+  }
+
+  unsigned int get_size () const
+  {
+    if (count)
+      return min_size + offSize.static_size + offset_array_size () + (offset_at (count) - 1);
+    return min_size;  /* empty CFFIndex contains count only */
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
+                          (count == 0 || /* empty INDEX */
+                           (count < count + 1u &&
+                            c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 &&
+                            c->check_array (offsets, offSize, count + 1u) &&
+                            c->check_range (data_base (), offset_at (count))))));
+  }
+
+  public:
+  COUNT         count;          /* Number of object data. Note there are (count+1) offsets */
+  private:
+  HBUINT8       offSize;        /* The byte size of each offset in the offsets array. */
+  HBUINT8       offsets[HB_VAR_ARRAY];
+                                /* The array of (count + 1) offsets into objects array (1-base). */
+  /* HBUINT8 data[HB_VAR_ARRAY];        Object data */
+  public:
+  DEFINE_SIZE_MIN (COUNT::static_size);
+};
+typedef CFFIndex<HBUINT16> CFF1Index;
+typedef CFFIndex<HBUINT32> CFF2Index;
+
+
+/* TupleValues */
+struct TupleValues
+{
+  enum packed_value_flag_t
+  {
+    VALUES_ARE_ZEROS     = 0x80,
+    VALUES_ARE_BYTES     = 0x00,
+    VALUES_ARE_WORDS     = 0x40,
+    VALUES_ARE_LONGS     = 0xC0,
+    VALUES_SIZE_MASK     = 0xC0,
+    VALUE_RUN_COUNT_MASK = 0x3F
+  };
+
+  static unsigned compile (hb_array_t<const int> values, /* IN */
+                           hb_array_t<unsigned char> encoded_bytes /* OUT */)
+  {
+    unsigned num_values = values.length;
+    unsigned encoded_len = 0;
+    unsigned i = 0;
+    while (i < num_values)
+    {
+      int val = values.arrayZ[i];
+      if (val == 0)
+        encoded_len += encode_value_run_as_zeroes (i, encoded_bytes.sub_array (encoded_len), values);
+      else if (val >= -128 && val <= 127)
+        encoded_len += encode_value_run_as_bytes (i, encoded_bytes.sub_array (encoded_len), values);
+      else if (val >= -32768 && val <= 32767)
+        encoded_len += encode_value_run_as_words (i, encoded_bytes.sub_array (encoded_len), values);
+      else
+        encoded_len += encode_value_run_as_longs (i, encoded_bytes.sub_array (encoded_len), values);
+    }
+    return encoded_len;
+  }
+
+  static unsigned encode_value_run_as_zeroes (unsigned& i,
+                                              hb_array_t<unsigned char> encoded_bytes,
+                                              hb_array_t<const int> values)
+  {
+    unsigned num_values = values.length;
+    unsigned run_length = 0;
+    auto it = encoded_bytes.iter ();
+    unsigned encoded_len = 0;
+    while (i < num_values && values.arrayZ[i] == 0)
+    {
+      i++;
+      run_length++;
+    }
+
+    while (run_length >= 64)
+    {
+      *it++ = char (VALUES_ARE_ZEROS | 63);
+      run_length -= 64;
+      encoded_len++;
+    }
+
+    if (run_length)
+    {
+      *it++ = char (VALUES_ARE_ZEROS | (run_length - 1));
+      encoded_len++;
+    }
+    return encoded_len;
+  }
+
+  static unsigned encode_value_run_as_bytes (unsigned &i,
+                                             hb_array_t<unsigned char> encoded_bytes,
+                                             hb_array_t<const int> values)
+  {
+    unsigned start = i;
+    unsigned num_values = values.length;
+    while (i < num_values)
+    {
+      int val = values.arrayZ[i];
+      if (val > 127 || val < -128)
+        break;
+
+      /* from fonttools: if there're 2 or more zeros in a sequence,
+       * it is better to start a new run to save bytes. */
+      if (val == 0 && i + 1 < num_values && values.arrayZ[i+1] == 0)
+        break;
+
+      i++;
+    }
+    unsigned run_length = i - start;
+
+    unsigned encoded_len = 0;
+    auto it = encoded_bytes.iter ();
+
+    while (run_length >= 64)
+    {
+      *it++ = (VALUES_ARE_BYTES | 63);
+      encoded_len++;
+
+      for (unsigned j = 0; j < 64; j++)
+      {
+        *it++ = static_cast<char> (values.arrayZ[start + j]);
+        encoded_len++;
+      }
+
+      start += 64;
+      run_length -= 64;
+    }
+
+    if (run_length)
+    {
+      *it++ = (VALUES_ARE_BYTES | (run_length - 1));
+      encoded_len++;
+
+      while (start < i)
+      {
+        *it++ = static_cast<char> (values.arrayZ[start++]);
+        encoded_len++;
+      }
+    }
+
+    return encoded_len;
+  }
+
+  static unsigned encode_value_run_as_words (unsigned &i,
+                                             hb_array_t<unsigned char> encoded_bytes,
+                                             hb_array_t<const int> values)
+  {
+    unsigned start = i;
+    unsigned num_values = values.length;
+    while (i < num_values)
+    {
+      int val = values.arrayZ[i];
+
+      /* start a new run for a single zero value*/
+      if (val == 0) break;
+
+      /* from fonttools: continue word-encoded run if there's only one
+       * single value in the range [-128, 127] because it is more compact.
+       * Only start a new run when there're 2 continuous such values. */
+      if (val >= -128 && val <= 127 &&
+          i + 1 < num_values &&
+          values.arrayZ[i+1] >= -128 && values.arrayZ[i+1] <= 127)
+        break;
+
+      i++;
+    }
+
+    unsigned run_length = i - start;
+    auto it = encoded_bytes.iter ();
+    unsigned encoded_len = 0;
+    while (run_length >= 64)
+    {
+      *it++ = (VALUES_ARE_WORDS | 63);
+      encoded_len++;
+
+      for (unsigned j = 0; j < 64; j++)
+      {
+        int16_t value_val = values.arrayZ[start + j];
+        *it++ = static_cast<char> (value_val >> 8);
+        *it++ = static_cast<char> (value_val & 0xFF);
+
+        encoded_len += 2;
+      }
+
+      start += 64;
+      run_length -= 64;
+    }
+
+    if (run_length)
+    {
+      *it++ = (VALUES_ARE_WORDS | (run_length - 1));
+      encoded_len++;
+      while (start < i)
+      {
+        int16_t value_val = values.arrayZ[start++];
+        *it++ = static_cast<char> (value_val >> 8);
+        *it++ = static_cast<char> (value_val & 0xFF);
+
+        encoded_len += 2;
+      }
+    }
+    return encoded_len;
+  }
+
+  static unsigned encode_value_run_as_longs (unsigned &i,
+                                             hb_array_t<unsigned char> encoded_bytes,
+                                             hb_array_t<const int> values)
+  {
+    unsigned start = i;
+    unsigned num_values = values.length;
+    while (i < num_values)
+    {
+      int val = values.arrayZ[i];
+
+      if (val >= -32768 && val <= 32767)
+        break;
+
+      i++;
+    }
+
+    unsigned run_length = i - start;
+    auto it = encoded_bytes.iter ();
+    unsigned encoded_len = 0;
+    while (run_length >= 64)
+    {
+      *it++ = (VALUES_ARE_LONGS | 63);
+      encoded_len++;
+
+      for (unsigned j = 0; j < 64; j++)
+      {
+        int32_t value_val = values.arrayZ[start + j];
+        *it++ = static_cast<char> (value_val >> 24);
+        *it++ = static_cast<char> (value_val >> 16);
+        *it++ = static_cast<char> (value_val >> 8);
+        *it++ = static_cast<char> (value_val & 0xFF);
+
+        encoded_len += 4;
+      }
+
+      start += 64;
+      run_length -= 64;
+    }
+
+    if (run_length)
+    {
+      *it++ = (VALUES_ARE_LONGS | (run_length - 1));
+      encoded_len++;
+      while (start < i)
+      {
+        int32_t value_val = values.arrayZ[start++];
+        *it++ = static_cast<char> (value_val >> 24);
+        *it++ = static_cast<char> (value_val >> 16);
+        *it++ = static_cast<char> (value_val >> 8);
+        *it++ = static_cast<char> (value_val & 0xFF);
+
+        encoded_len += 4;
+      }
+    }
+    return encoded_len;
+  }
+
+  template <typename T>
+  static bool decompile (const HBUINT8 *&p /* IN/OUT */,
+                         hb_vector_t<T> &values /* IN/OUT */,
+                         const HBUINT8 *end,
+                         bool consume_all = false)
+  {
+    unsigned i = 0;
+    unsigned count = consume_all ? UINT_MAX : values.length;
+    if (consume_all)
+      values.alloc ((end - p) / 2);
+    while (i < count)
+    {
+      if (unlikely (p + 1 > end)) return consume_all;
+      unsigned control = *p++;
+      unsigned run_count = (control & VALUE_RUN_COUNT_MASK) + 1;
+      if (consume_all)
+      {
+        if (unlikely (!values.resize (values.length + run_count, false)))
+          return false;
+      }
+      unsigned stop = i + run_count;
+      if (unlikely (stop > count)) return false;
+      if ((control & VALUES_SIZE_MASK) == VALUES_ARE_ZEROS)
+      {
+        for (; i < stop; i++)
+          values.arrayZ[i] = 0;
+      }
+      else if ((control & VALUES_SIZE_MASK) ==  VALUES_ARE_WORDS)
+      {
+        if (unlikely (p + run_count * HBINT16::static_size > end)) return false;
+#ifndef HB_OPTIMIZE_SIZE
+        for (; i + 3 < stop; i += 4)
+        {
+          values.arrayZ[i] = * (const HBINT16 *) p;
+          p += HBINT16::static_size;
+          values.arrayZ[i + 1] = * (const HBINT16 *) p;
+          p += HBINT16::static_size;
+          values.arrayZ[i + 2] = * (const HBINT16 *) p;
+          p += HBINT16::static_size;
+          values.arrayZ[i + 3] = * (const HBINT16 *) p;
+          p += HBINT16::static_size;
+        }
+#endif
+        for (; i < stop; i++)
+        {
+          values.arrayZ[i] = * (const HBINT16 *) p;
+          p += HBINT16::static_size;
+        }
+      }
+      else if ((control & VALUES_SIZE_MASK) ==  VALUES_ARE_LONGS)
+      {
+        if (unlikely (p + run_count * HBINT32::static_size > end)) return false;
+        for (; i < stop; i++)
+        {
+          values.arrayZ[i] = * (const HBINT32 *) p;
+          p += HBINT32::static_size;
+        }
+      }
+      else if ((control & VALUES_SIZE_MASK) ==  VALUES_ARE_BYTES)
+      {
+        if (unlikely (p + run_count > end)) return false;
+#ifndef HB_OPTIMIZE_SIZE
+        for (; i + 3 < stop; i += 4)
+        {
+          values.arrayZ[i] = * (const HBINT8 *) p++;
+          values.arrayZ[i + 1] = * (const HBINT8 *) p++;
+          values.arrayZ[i + 2] = * (const HBINT8 *) p++;
+          values.arrayZ[i + 3] = * (const HBINT8 *) p++;
+        }
+#endif
+        for (; i < stop; i++)
+          values.arrayZ[i] = * (const HBINT8 *) p++;
+      }
+    }
+    return true;
+  }
+
+  struct iter_t : hb_iter_with_fallback_t<iter_t, int>
+  {
+    iter_t (const unsigned char *p_, unsigned len_)
+            : p (p_), endp (p_ + len_)
+    { if (ensure_run ()) read_value (); }
+
+    private:
+    const unsigned char *p;
+    const unsigned char * const endp;
+    int current_value = 0;
+    signed run_count = 0;
+    unsigned width = 0;
+
+    bool ensure_run ()
+    {
+      if (likely (run_count > 0)) return true;
+
+      if (unlikely (p >= endp))
+      {
+        run_count = 0;
+        current_value = 0;
+        return false;
+      }
+
+      unsigned control = *p++;
+      run_count = (control & VALUE_RUN_COUNT_MASK) + 1;
+      width = control & VALUES_SIZE_MASK;
+      switch (width)
+      {
+        case VALUES_ARE_ZEROS: width = 0; break;
+        case VALUES_ARE_BYTES: width = HBINT8::static_size;  break;
+        case VALUES_ARE_WORDS: width = HBINT16::static_size; break;
+        case VALUES_ARE_LONGS: width = HBINT32::static_size; break;
+        default: assert (false);
+      }
+
+      if (unlikely (p + run_count * width > endp))
+      {
+        run_count = 0;
+        current_value = 0;
+        return false;
+      }
+
+      return true;
+    }
+    void read_value ()
+    {
+      switch (width)
+      {
+        case 0: current_value = 0; break;
+        case 1: current_value = * (const HBINT8  *) p; break;
+        case 2: current_value = * (const HBINT16 *) p; break;
+        case 4: current_value = * (const HBINT32 *) p; break;
+      }
+      p += width;
+    }
+
+    public:
+
+    typedef int __item_t__;
+    __item_t__ __item__ () const
+    { return current_value; }
+
+    bool __more__ () const { return run_count || p < endp; }
+    void __next__ ()
+    {
+      run_count--;
+      if (unlikely (!ensure_run ()))
+        return;
+      read_value ();
+    }
+    void __forward__ (unsigned n)
+    {
+      if (unlikely (!ensure_run ()))
+        return;
+      while (n)
+      {
+        unsigned i = hb_min (n, (unsigned) run_count);
+        run_count -= i;
+        n -= i;
+        p += (i - 1) * width;
+        if (unlikely (!ensure_run ()))
+          return;
+        read_value ();
+      }
+    }
+    bool operator != (const iter_t& o) const
+    { return p != o.p || run_count != o.run_count; }
+    iter_t __end__ () const
+    {
+      iter_t it (endp, 0);
+      return it;
+    }
+  };
+
+  struct fetcher_t
+  {
+    fetcher_t (const unsigned char *p_, unsigned len_)
+              : p (p_), end (p_ + len_) {}
+
+    private:
+    const unsigned char *p;
+    const unsigned char * const end;
+    signed run_count = 0;
+    unsigned width = 0;
+
+    bool ensure_run ()
+    {
+      if (likely (run_count > 0)) return true;
+
+      if (unlikely (p >= end))
+      {
+        run_count = 0;
+        return false;
+      }
+
+      unsigned control = *p++;
+      run_count = (control & VALUE_RUN_COUNT_MASK) + 1;
+      width = control & VALUES_SIZE_MASK;
+      switch (width)
+      {
+        case VALUES_ARE_ZEROS: width = 0; break;
+        case VALUES_ARE_BYTES: width = HBINT8::static_size;  break;
+        case VALUES_ARE_WORDS: width = HBINT16::static_size; break;
+        case VALUES_ARE_LONGS: width = HBINT32::static_size; break;
+        default: assert (false);
+      }
+
+      if (unlikely (p + run_count * width > end))
+      {
+        run_count = 0;
+        return false;
+      }
+
+      return true;
+    }
+
+    void skip (unsigned n)
+    {
+      while (n)
+      {
+        if (unlikely (!ensure_run ()))
+          return;
+        unsigned i = hb_min (n, (unsigned) run_count);
+        run_count -= i;
+        n -= i;
+        p += i * width;
+      }
+    }
+
+    template <bool scaled>
+    void _add_to (hb_array_t<float> out, float scale = 1.0f)
+    {
+      unsigned n = out.length;
+      float *arrayZ = out.arrayZ;
+
+      for (unsigned i = 0; i < n;)
+      {
+        if (unlikely (!ensure_run ()))
+          break;
+        unsigned count = hb_min (n - i, (unsigned) run_count);
+        switch (width)
+        {
+          case 1:
+          {
+            const auto *pp = (const HBINT8 *) p;
+            unsigned j = 0;
+#ifndef HB_OPTIMIZE_SIZE
+            for (; j + 3 < count; j += 4)
+            {
+              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+            }
+#endif
+            for (; j < count; j++)
+              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+          }
+          break;
+          case 2:
+          {
+            const auto *pp = (const HBINT16 *) p;
+            unsigned j = 0;
+#ifndef HB_OPTIMIZE_SIZE
+            for (; j + 3 < count; j += 4)
+            {
+              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+            }
+#endif
+            for (; j < count; j++)
+              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+          }
+          break;
+          case 4:
+          {
+            const auto *pp = (const HBINT32 *) p;
+            for (unsigned j = 0; j < count; j++)
+              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
+          }
+          break;
+        }
+        p += count * width;
+        run_count -= count;
+        i += count;
+      }
+    }
+
+    public:
+    void add_to (hb_array_t<float> out, float scale = 1.0f)
+    {
+      unsigned n = out.length;
+
+      if (scale == 0.0f)
+      {
+        skip (n);
+        return;
+      }
+
+#ifndef HB_OPTIMIZE_SIZE
+      if (scale == 1.0f)
+        _add_to<false> (out);
+      else
+#endif
+        _add_to<true> (out, scale);
+    }
+  };
+};
+
+struct TupleList : CFF2Index
+{
+  TupleValues::iter_t operator [] (unsigned i) const
+  {
+    auto bytes = CFF2Index::operator [] (i);
+    return TupleValues::iter_t (bytes.arrayZ, bytes.length);
+  }
+
+  TupleValues::fetcher_t fetcher (unsigned i) const
+  {
+    auto bytes = CFF2Index::operator [] (i);
+    return TupleValues::fetcher_t (bytes.arrayZ, bytes.length);
+  }
+};
+
+
 } /* namespace OT */
 
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff-common.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff-common.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff-common.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff-common.hh	2025-06-27 08:03:14.000000000 +0000
@@ -41,10 +41,21 @@ using namespace OT;
 using objidx_t = hb_serialize_context_t::objidx_t;
 using whence_t = hb_serialize_context_t::whence_t;
 
-/* utility macro */
-template<typename Type>
-static inline const Type& StructAtOffsetOrNull (const void *P, unsigned int offset)
-{ return offset ? StructAtOffset<Type> (P, offset) : Null (Type); }
+/* CFF offsets can technically be negative */
+template<typename Type, typename ...Ts>
+static inline const Type& StructAtOffsetOrNull (const void *P, int offset, hb_sanitize_context_t &sc, Ts&&... ds)
+{
+  if (!offset) return Null (Type);
+
+  const char *p = (const char *) P + offset;
+  if (!sc.check_point (p)) return Null (Type);
+
+  const Type &obj = *reinterpret_cast<const Type *> (p);
+  if (!obj.sanitize (&sc, std::forward<Ts> (ds)...)) return Null (Type);
+
+  return obj;
+}
+
 
 struct code_pair_t
 {
@@ -57,241 +68,6 @@ using str_buff_t = hb_vector_t<unsigned
 using str_buff_vec_t = hb_vector_t<str_buff_t>;
 using glyph_to_sid_map_t = hb_vector_t<code_pair_t>;
 
-struct length_f_t
-{
-  template <typename Iterable,
-            hb_requires (hb_is_iterable (Iterable))>
-  unsigned operator () (const Iterable &_) const { return hb_len (hb_iter (_)); }
-
-  unsigned operator () (unsigned _) const { return _; }
-}
-HB_FUNCOBJ (length_f);
-
-/* CFF INDEX */
-template <typename COUNT>
-struct CFFIndex
-{
-  unsigned int offset_array_size () const
-  { return offSize * (count + 1); }
-
-  template <typename Iterable,
-            hb_requires (hb_is_iterable (Iterable))>
-  bool serialize (hb_serialize_context_t *c,
-                  const Iterable &iterable,
-                  const unsigned *p_data_size = nullptr)
-  {
-    TRACE_SERIALIZE (this);
-    unsigned data_size;
-    if (p_data_size)
-      data_size = *p_data_size;
-    else
-      total_size (iterable, &data_size);
-
-    auto it = hb_iter (iterable);
-    if (unlikely (!serialize_header (c, +it, data_size))) return_trace (false);
-    unsigned char *ret = c->allocate_size<unsigned char> (data_size, false);
-    if (unlikely (!ret)) return_trace (false);
-    for (const auto &_ : +it)
-    {
-      unsigned len = _.length;
-      if (!len)
-        continue;
-      if (len <= 1)
-      {
-        *ret++ = *_.arrayZ;
-        continue;
-      }
-      hb_memcpy (ret, _.arrayZ, len);
-      ret += len;
-    }
-    return_trace (true);
-  }
-
-  template <typename Iterator,
-            hb_requires (hb_is_iterator (Iterator))>
-  bool serialize_header (hb_serialize_context_t *c,
-                         Iterator it,
-                         unsigned data_size)
-  {
-    TRACE_SERIALIZE (this);
-
-    unsigned off_size = (hb_bit_storage (data_size + 1) + 7) / 8;
-
-    /* serialize CFFIndex header */
-    if (unlikely (!c->extend_min (this))) return_trace (false);
-    this->count = hb_len (it);
-    if (!this->count) return_trace (true);
-    if (unlikely (!c->extend (this->offSize))) return_trace (false);
-    this->offSize = off_size;
-    if (unlikely (!c->allocate_size<HBUINT8> (off_size * (this->count + 1), false)))
-      return_trace (false);
-
-    /* serialize indices */
-    unsigned int offset = 1;
-    if (HB_OPTIMIZE_SIZE_VAL)
-    {
-      unsigned int i = 0;
-      for (const auto &_ : +it)
-      {
-        set_offset_at (i++, offset);
-        offset += length_f (_);
-      }
-      set_offset_at (i, offset);
-    }
-    else
-      switch (off_size)
-      {
-        case 1:
-        {
-          HBUINT8 *p = (HBUINT8 *) offsets;
-          for (const auto &_ : +it)
-          {
-            *p++ = offset;
-            offset += length_f (_);
-          }
-          *p = offset;
-        }
-        break;
-        case 2:
-        {
-          HBUINT16 *p = (HBUINT16 *) offsets;
-          for (const auto &_ : +it)
-          {
-            *p++ = offset;
-            offset += length_f (_);
-          }
-          *p = offset;
-        }
-        break;
-        case 3:
-        {
-          HBUINT24 *p = (HBUINT24 *) offsets;
-          for (const auto &_ : +it)
-          {
-            *p++ = offset;
-            offset += length_f (_);
-          }
-          *p = offset;
-        }
-        break;
-        case 4:
-        {
-          HBUINT32 *p = (HBUINT32 *) offsets;
-          for (const auto &_ : +it)
-          {
-            *p++ = offset;
-            offset += length_f (_);
-          }
-          *p = offset;
-        }
-        break;
-        default:
-        break;
-      }
-
-    assert (offset == data_size + 1);
-    return_trace (true);
-  }
-
-  template <typename Iterable,
-            hb_requires (hb_is_iterable (Iterable))>
-  static unsigned total_size (const Iterable &iterable, unsigned *data_size = nullptr)
-  {
-    auto it = + hb_iter (iterable);
-    if (!it)
-    {
-      if (data_size) *data_size = 0;
-      return min_size;
-    }
-
-    unsigned total = 0;
-    for (const auto &_ : +it)
-      total += length_f (_);
-
-    if (data_size) *data_size = total;
-
-    unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8;
-
-    return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total;
-  }
-
-  void set_offset_at (unsigned int index, unsigned int offset)
-  {
-    assert (index <= count);
-
-    unsigned int size = offSize;
-    const HBUINT8 *p = offsets;
-    switch (size)
-    {
-      case 1: ((HBUINT8  *) p)[index] = offset; break;
-      case 2: ((HBUINT16 *) p)[index] = offset; break;
-      case 3: ((HBUINT24 *) p)[index] = offset; break;
-      case 4: ((HBUINT32 *) p)[index] = offset; break;
-      default: return;
-    }
-  }
-
-  private:
-  unsigned int offset_at (unsigned int index) const
-  {
-    assert (index <= count);
-
-    unsigned int size = offSize;
-    const HBUINT8 *p = offsets;
-    switch (size)
-    {
-      case 1: return ((HBUINT8  *) p)[index];
-      case 2: return ((HBUINT16 *) p)[index];
-      case 3: return ((HBUINT24 *) p)[index];
-      case 4: return ((HBUINT32 *) p)[index];
-      default: return 0;
-    }
-  }
-
-  const unsigned char *data_base () const
-  { return (const unsigned char *) this + min_size + offSize.static_size - 1 + offset_array_size (); }
-  public:
-
-  hb_ubytes_t operator [] (unsigned int index) const
-  {
-    if (unlikely (index >= count)) return hb_ubytes_t ();
-    _hb_compiler_memory_r_barrier ();
-    unsigned offset0 = offset_at (index);
-    unsigned offset1 = offset_at (index + 1);
-    if (unlikely (offset1 < offset0 || offset1 > offset_at (count)))
-      return hb_ubytes_t ();
-    return hb_ubytes_t (data_base () + offset0, offset1 - offset0);
-  }
-
-  unsigned int get_size () const
-  {
-    if (count)
-      return min_size + offSize.static_size + offset_array_size () + (offset_at (count) - 1);
-    return min_size;  /* empty CFFIndex contains count only */
-  }
-
-  bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-                          (count == 0 || /* empty INDEX */
-                           (count < count + 1u &&
-                            c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 &&
-                            c->check_array (offsets, offSize, count + 1u) &&
-                            c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count))))));
-  }
-
-  public:
-  COUNT         count;          /* Number of object data. Note there are (count+1) offsets */
-  private:
-  HBUINT8       offSize;        /* The byte size of each offset in the offsets array. */
-  HBUINT8       offsets[HB_VAR_ARRAY];
-                                /* The array of (count + 1) offsets into objects array (1-base). */
-  /* HBUINT8 data[HB_VAR_ARRAY];        Object data */
-  public:
-  DEFINE_SIZE_MIN (COUNT::static_size);
-};
-
 /* Top Dict, Font Dict, Private Dict */
 struct Dict : UnsizedByteStr
 {
@@ -412,6 +188,7 @@ struct FDSelect0 {
     TRACE_SANITIZE (this);
     if (unlikely (!(c->check_struct (this))))
       return_trace (false);
+    hb_barrier ();
     if (unlikely (!c->check_array (fds, c->get_num_glyphs ())))
       return_trace (false);
 
@@ -438,7 +215,9 @@ struct FDSelect3_4_Range
   bool sanitize (hb_sanitize_context_t *c, const void * /*nullptr*/, unsigned int fdcount) const
   {
     TRACE_SANITIZE (this);
-    return_trace (first < c->get_num_glyphs () && (fd < fdcount));
+    return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
+                  first < c->get_num_glyphs () && (fd < fdcount));
   }
 
   GID_TYPE    first;
@@ -456,15 +235,20 @@ struct FDSelect3_4
   bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this) || !ranges.sanitize (c, nullptr, fdcount) ||
-                  (nRanges () == 0) || ranges[0].first != 0))
+    if (unlikely (!(c->check_struct (this) &&
+                    ranges.sanitize (c, nullptr, fdcount) &&
+                    hb_barrier () &&
+                    (nRanges () != 0) &&
+                    ranges[0].first == 0)))
       return_trace (false);
 
     for (unsigned int i = 1; i < nRanges (); i++)
       if (unlikely (ranges[i - 1].first >= ranges[i].first))
         return_trace (false);
 
-    if (unlikely (!sentinel().sanitize (c) || (sentinel() != c->get_num_glyphs ())))
+    if (unlikely (!(sentinel().sanitize (c) &&
+                   hb_barrier () &&
+                   (sentinel() == c->get_num_glyphs ()))))
       return_trace (false);
 
     return_trace (true);
@@ -524,8 +308,8 @@ struct FDSelect
   {
     switch (format)
     {
-    case 0: return format.static_size + u.format0.get_size (num_glyphs);
-    case 3: return format.static_size + u.format3.get_size ();
+    case 0: hb_barrier (); return format.static_size + u.format0.get_size (num_glyphs);
+    case 3: hb_barrier (); return format.static_size + u.format3.get_size ();
     default:return 0;
     }
   }
@@ -536,8 +320,8 @@ struct FDSelect
 
     switch (format)
     {
-    case 0: return u.format0.get_fd (glyph);
-    case 3: return u.format3.get_fd (glyph);
+    case 0: hb_barrier (); return u.format0.get_fd (glyph);
+    case 3: hb_barrier (); return u.format3.get_fd (glyph);
     default:return 0;
     }
   }
@@ -548,8 +332,8 @@ struct FDSelect
 
     switch (format)
     {
-    case 0: return u.format0.get_fd_range (glyph);
-    case 3: return u.format3.get_fd_range (glyph);
+    case 0: hb_barrier (); return u.format0.get_fd_range (glyph);
+    case 3: hb_barrier (); return u.format3.get_fd_range (glyph);
     default:return {0, 1};
     }
   }
@@ -559,11 +343,12 @@ struct FDSelect
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
       return_trace (false);
+    hb_barrier ();
 
     switch (format)
     {
-    case 0: return_trace (u.format0.sanitize (c, fdcount));
-    case 3: return_trace (u.format3.sanitize (c, fdcount));
+    case 0: hb_barrier (); return_trace (u.format0.sanitize (c, fdcount));
+    case 3: hb_barrier (); return_trace (u.format3.sanitize (c, fdcount));
     default:return_trace (false);
     }
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.cc	2025-06-27 08:03:14.000000000 +0000
@@ -553,15 +553,6 @@ bool _get_path (const OT::cff1::accelera
   return true;
 }
 
-bool OT::cff1::accelerator_t::paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
-{
-  funcs->push_clip_glyph (data, glyph, font);
-  funcs->color (data, true, foreground);
-  funcs->pop_clip (data);
-
-  return true;
-}
-
 bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
 {
 #ifdef HB_NO_OT_FONT_CFF
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -51,9 +51,6 @@ namespace CFF {
 enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
 enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
 
-typedef CFFIndex<HBUINT16>  CFF1Index;
-
-typedef CFFIndex<HBUINT16> CFF1Index;
 typedef CFF1Index          CFF1CharStrings;
 typedef Subrs<HBUINT16>    CFF1Subrs;
 
@@ -242,8 +239,8 @@ struct Encoding
     unsigned int size = min_size;
     switch (table_format ())
     {
-    case 0: size += u.format0.get_size (); break;
-    case 1: size += u.format1.get_size (); break;
+    case 0: hb_barrier (); size += u.format0.get_size (); break;
+    case 1: hb_barrier (); size += u.format1.get_size (); break;
     }
     if (has_supplement ())
       size += suppEncData ().get_size ();
@@ -254,8 +251,8 @@ struct Encoding
   {
     switch (table_format ())
     {
-    case 0: return u.format0.get_code (glyph);
-    case 1: return u.format1.get_code (glyph);
+    case 0: hb_barrier (); return u.format0.get_code (glyph);
+    case 1: hb_barrier (); return u.format1.get_code (glyph);
     default:return 0;
     }
   }
@@ -275,11 +272,12 @@ struct Encoding
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
       return_trace (false);
+    hb_barrier ();
 
     switch (table_format ())
     {
-    case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
-    case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
+    case 0: hb_barrier (); if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
+    case 1: hb_barrier (); if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
     default:return_trace (false);
     }
     return_trace (likely (!has_supplement () || suppEncData ().sanitize (c)));
@@ -290,8 +288,8 @@ struct Encoding
   {
     switch (table_format ())
     {
-    case 0: return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
-    case 1: return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
+    case 0: hb_barrier (); return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
+    case 1: hb_barrier (); return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
     default:return Null (CFF1SuppEncData);
     }
   }
@@ -376,13 +374,13 @@ struct Charset1_2 {
   bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this)))
-      return_trace (false);
     num_glyphs--;
     unsigned i;
     for (i = 0; num_glyphs > 0; i++)
     {
-      if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
+      if (unlikely (!(ranges[i].sanitize (c) &&
+                      hb_barrier () &&
+                      (num_glyphs >= ranges[i].nLeft + 1))))
         return_trace (false);
       num_glyphs -= (ranges[i].nLeft + 1);
     }
@@ -569,9 +567,9 @@ struct Charset
   {
     switch (format)
     {
-    case 0: return min_size + u.format0.get_size (num_glyphs);
-    case 1: return min_size + u.format1.get_size (num_glyphs);
-    case 2: return min_size + u.format2.get_size (num_glyphs);
+    case 0: hb_barrier (); return min_size + u.format0.get_size (num_glyphs);
+    case 1: hb_barrier (); return min_size + u.format1.get_size (num_glyphs);
+    case 2: hb_barrier (); return min_size + u.format2.get_size (num_glyphs);
     default:return 0;
     }
   }
@@ -581,9 +579,9 @@ struct Charset
   {
     switch (format)
     {
-    case 0: return u.format0.get_sid (glyph, num_glyphs);
-    case 1: return u.format1.get_sid (glyph, num_glyphs, cache);
-    case 2: return u.format2.get_sid (glyph, num_glyphs, cache);
+    case 0: hb_barrier (); return u.format0.get_sid (glyph, num_glyphs);
+    case 1: hb_barrier (); return u.format1.get_sid (glyph, num_glyphs, cache);
+    case 2: hb_barrier (); return u.format2.get_sid (glyph, num_glyphs, cache);
     default:return 0;
     }
   }
@@ -592,9 +590,9 @@ struct Charset
   {
     switch (format)
     {
-    case 0: u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return;
-    case 1: u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return;
-    case 2: u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return;
+    case 0: hb_barrier (); u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return;
+    case 1: hb_barrier (); u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return;
+    case 2: hb_barrier (); u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return;
     default:return;
     }
   }
@@ -603,9 +601,9 @@ struct Charset
   {
     switch (format)
     {
-    case 0: return u.format0.get_glyph (sid, num_glyphs);
-    case 1: return u.format1.get_glyph (sid, num_glyphs);
-    case 2: return u.format2.get_glyph (sid, num_glyphs);
+    case 0: hb_barrier (); return u.format0.get_glyph (sid, num_glyphs);
+    case 1: hb_barrier (); return u.format1.get_glyph (sid, num_glyphs);
+    case 2: hb_barrier (); return u.format2.get_glyph (sid, num_glyphs);
     default:return 0;
     }
   }
@@ -615,12 +613,13 @@ struct Charset
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
       return_trace (false);
+    hb_barrier ();
 
     switch (format)
     {
-    case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries));
-    case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries));
-    case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries));
+    case 0: hb_barrier (); return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries));
+    case 1: hb_barrier (); return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries));
+    case 2: hb_barrier (); return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries));
     default:return_trace (false);
     }
   }
@@ -761,9 +760,9 @@ struct cff1_top_dict_values_t : top_dict
   unsigned int    ros_supplement;
   unsigned int    cidCount;
 
-  unsigned int    EncodingOffset;
-  unsigned int    CharsetOffset;
-  unsigned int    FDSelectOffset;
+  int             EncodingOffset;
+  int             CharsetOffset;
+  int             FDSelectOffset;
   table_info_t    privateDictInfo;
 };
 
@@ -819,24 +818,24 @@ struct cff1_top_dict_opset_t : top_dict_
         break;
 
       case OpCode_Encoding:
-        dictval.EncodingOffset = env.argStack.pop_uint ();
+        dictval.EncodingOffset = env.argStack.pop_int ();
         env.clear_args ();
         if (unlikely (dictval.EncodingOffset == 0)) return;
         break;
 
       case OpCode_charset:
-        dictval.CharsetOffset = env.argStack.pop_uint ();
+        dictval.CharsetOffset = env.argStack.pop_int ();
         env.clear_args ();
         if (unlikely (dictval.CharsetOffset == 0)) return;
         break;
 
       case OpCode_FDSelect:
-        dictval.FDSelectOffset = env.argStack.pop_uint ();
+        dictval.FDSelectOffset = env.argStack.pop_int ();
         env.clear_args ();
         break;
 
       case OpCode_Private:
-        dictval.privateDictInfo.offset = env.argStack.pop_uint ();
+        dictval.privateDictInfo.offset = env.argStack.pop_int ();
         dictval.privateDictInfo.size = env.argStack.pop_uint ();
         env.clear_args ();
         break;
@@ -911,7 +910,7 @@ struct cff1_private_dict_values_base_t :
   }
   void fini () { dict_values_t<VAL>::fini (); }
 
-  unsigned int      subrsOffset;
+  int                 subrsOffset;
   const CFF1Subrs    *localSubrs;
 };
 
@@ -946,7 +945,7 @@ struct cff1_private_dict_opset_t : dict_
         env.clear_args ();
         break;
       case OpCode_Subrs:
-        dictval.subrsOffset = env.argStack.pop_uint ();
+        dictval.subrsOffset = env.argStack.pop_int ();
         env.clear_args ();
         break;
 
@@ -988,7 +987,7 @@ struct cff1_private_dict_opset_subset_t
         break;
 
       case OpCode_Subrs:
-        dictval.subrsOffset = env.argStack.pop_uint ();
+        dictval.subrsOffset = env.argStack.pop_int ();
         env.clear_args ();
         break;
 
@@ -1055,6 +1054,7 @@ struct cff1
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   likely (version.major == 1));
   }
 
@@ -1085,14 +1085,17 @@ struct cff1
       nameIndex = &cff->nameIndex (cff);
       if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
         goto fail;
+      hb_barrier ();
 
-      topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
-      if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
+      topDictIndex = &StructAtOffsetOrNull<CFF1TopDictIndex> (nameIndex, nameIndex->get_size (), sc);
+      if (topDictIndex == &Null (CFF1TopDictIndex) || (topDictIndex->count == 0))
         goto fail;
+      hb_barrier ();
 
       { /* parse top dict */
         const hb_ubytes_t topDictStr = (*topDictIndex)[0];
         if (unlikely (!topDictStr.sanitize (&sc)))   goto fail;
+        hb_barrier ();
         cff1_top_dict_interp_env_t env (topDictStr);
         cff1_top_dict_interpreter_t top_interp (env);
         if (unlikely (!top_interp.interpret (topDict)))   goto fail;
@@ -1102,17 +1105,17 @@ struct cff1
         charset = &Null (Charset);
       else
       {
-        charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
-        if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc, &num_charset_entries)))   goto fail;
+        charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset, sc, &num_charset_entries);
+        if (unlikely (charset == &Null (Charset)))   goto fail;
       }
 
       fdCount = 1;
       if (is_CID ())
       {
-        fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
-        fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
-        if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) ||
-            (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
+        fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset, sc);
+        fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset, sc, fdArray->count);
+        if (unlikely (fdArray == &Null (CFF1FDArray) ||
+                      fdSelect == &Null (CFF1FDSelect)))
           goto fail;
 
         fdCount = fdArray->count;
@@ -1132,22 +1135,18 @@ struct cff1
       {
         if (!is_predef_encoding ())
         {
-          encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
-          if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc)))   goto fail;
+          encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset, sc);
+          if (unlikely (encoding == &Null (Encoding)))   goto fail;
         }
       }
 
-      stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
-      if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
+      stringIndex = &StructAtOffsetOrNull<CFF1StringIndex> (topDictIndex, topDictIndex->get_size (), sc);
+      if (stringIndex == &Null (CFF1StringIndex))
         goto fail;
 
-      globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
-      if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
-        goto fail;
-
-      charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
-
-      if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
+      globalSubrs = &StructAtOffsetOrNull<CFF1Subrs> (stringIndex, stringIndex->get_size (), sc);
+      charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset, sc);
+      if (charStrings == &Null (CFF1CharStrings))
         goto fail;
 
       num_glyphs = charStrings->count;
@@ -1166,6 +1165,7 @@ struct cff1
         {
           hb_ubytes_t fontDictStr = (*fdArray)[i];
           if (unlikely (!fontDictStr.sanitize (&sc)))   goto fail;
+          hb_barrier ();
           cff1_font_dict_values_t *font;
           cff1_top_dict_interp_env_t env (fontDictStr);
           cff1_font_dict_interpreter_t font_interp (env);
@@ -1175,17 +1175,14 @@ struct cff1
           font->init ();
           if (unlikely (!font_interp.interpret (*font)))   goto fail;
           PRIVDICTVAL *priv = &privateDicts[i];
-          const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
-          if (unlikely (!privDictStr.sanitize (&sc)))   goto fail;
+          const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
+          if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
           num_interp_env_t env2 (privDictStr);
           dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2);
           priv->init ();
           if (unlikely (!priv_interp.interpret (*priv)))   goto fail;
 
-          priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
-          if (priv->localSubrs != &Null (CFF1Subrs) &&
-              unlikely (!priv->localSubrs->sanitize (&sc)))
-            goto fail;
+          priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset, sc);
         }
       }
       else  /* non-CID */
@@ -1193,17 +1190,15 @@ struct cff1
         cff1_top_dict_values_t *font = &topDict;
         PRIVDICTVAL *priv = &privateDicts[0];
 
-        const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
-        if (unlikely (!privDictStr.sanitize (&sc)))   goto fail;
+        const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
+        if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
         num_interp_env_t env (privDictStr);
         dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env);
         priv->init ();
         if (unlikely (!priv_interp.interpret (*priv)))   goto fail;
 
-        priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
-        if (priv->localSubrs != &Null (CFF1Subrs) &&
-            unlikely (!priv->localSubrs->sanitize (&sc)))
-          goto fail;
+        priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset, sc);
+        hb_barrier ();
       }
 
       return;
@@ -1420,7 +1415,7 @@ struct cff1
       hb_sorted_vector_t<gname_t> *names = glyph_names.get_acquire ();
       if (unlikely (!names))
       {
-        names = (hb_sorted_vector_t<gname_t> *) hb_calloc (sizeof (hb_sorted_vector_t<gname_t>), 1);
+        names = (hb_sorted_vector_t<gname_t> *) hb_calloc (1, sizeof (hb_sorted_vector_t<gname_t>));
         if (likely (names))
         {
           names->init ();
@@ -1467,7 +1462,6 @@ struct cff1
     }
 
     HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
-    HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const;
     HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
 
     private:
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc	2025-06-27 08:03:14.000000000 +0000
@@ -143,15 +143,6 @@ bool OT::cff2::accelerator_t::get_extent
   return true;
 }
 
-bool OT::cff2::accelerator_t::paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
-{
-  funcs->push_clip_glyph (data, glyph, font);
-  funcs->color (data, true, foreground);
-  funcs->pop_clip (data);
-
-  return true;
-}
-
 struct cff2_path_param_t
 {
   cff2_path_param_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
@@ -203,6 +194,11 @@ struct cff2_cs_opset_path_t : cff2_cs_op
 
 bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
 {
+  return get_path_at (font, glyph, draw_session, hb_array (font->coords, font->num_coords));
+}
+
+bool OT::cff2::accelerator_t::get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t<const int> coords) const
+{
 #ifdef HB_NO_OT_FONT_CFF
   /* XXX Remove check when this code moves to .hh file. */
   return true;
@@ -212,7 +208,7 @@ bool OT::cff2::accelerator_t::get_path (
 
   unsigned int fd = fdSelect->get_fd (glyph);
   const hb_ubytes_t str = (*charStrings)[glyph];
-  cff2_cs_interp_env_t<number_t> env (str, *this, fd, font->coords, font->num_coords);
+  cff2_cs_interp_env_t<number_t> env (str, *this, fd, coords.arrayZ, coords.length);
   cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t, number_t> interp (env);
   cff2_path_param_t param (font, draw_session);
   if (unlikely (!interp.interpret (param))) return false;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -40,8 +40,6 @@ namespace CFF {
  */
 #define HB_OT_TAG_CFF2 HB_TAG('C','F','F','2')
 
-typedef CFFIndex<HBUINT32>  CFF2Index;
-
 typedef CFF2Index         CFF2CharStrings;
 typedef Subrs<HBUINT32>   CFF2Subrs;
 
@@ -64,9 +62,9 @@ struct CFF2FDSelect
   {
     switch (format)
     {
-    case 0: return format.static_size + u.format0.get_size (num_glyphs);
-    case 3: return format.static_size + u.format3.get_size ();
-    case 4: return format.static_size + u.format4.get_size ();
+    case 0: hb_barrier (); return format.static_size + u.format0.get_size (num_glyphs);
+    case 3: hb_barrier (); return format.static_size + u.format3.get_size ();
+    case 4: hb_barrier (); return format.static_size + u.format4.get_size ();
     default:return 0;
     }
   }
@@ -78,9 +76,9 @@ struct CFF2FDSelect
 
     switch (format)
     {
-    case 0: return u.format0.get_fd (glyph);
-    case 3: return u.format3.get_fd (glyph);
-    case 4: return u.format4.get_fd (glyph);
+    case 0: hb_barrier (); return u.format0.get_fd (glyph);
+    case 3: hb_barrier (); return u.format3.get_fd (glyph);
+    case 4: hb_barrier (); return u.format4.get_fd (glyph);
     default:return 0;
     }
   }
@@ -90,12 +88,13 @@ struct CFF2FDSelect
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
       return_trace (false);
+    hb_barrier ();
 
     switch (format)
     {
-    case 0: return_trace (u.format0.sanitize (c, fdcount));
-    case 3: return_trace (u.format3.sanitize (c, fdcount));
-    case 4: return_trace (u.format4.sanitize (c, fdcount));
+    case 0: hb_barrier (); return_trace (u.format0.sanitize (c, fdcount));
+    case 3: hb_barrier (); return_trace (u.format3.sanitize (c, fdcount));
+    case 4: hb_barrier (); return_trace (u.format4.sanitize (c, fdcount));
     default:return_trace (false);
     }
   }
@@ -110,19 +109,22 @@ struct CFF2FDSelect
   DEFINE_SIZE_MIN (2);
 };
 
-struct CFF2VariationStore
+struct CFF2ItemVariationStore
 {
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this)) && c->check_range (&varStore, size) && varStore.sanitize (c));
+    return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
+                  c->check_range (&varStore, size) &&
+                  varStore.sanitize (c));
   }
 
-  bool serialize (hb_serialize_context_t *c, const CFF2VariationStore *varStore)
+  bool serialize (hb_serialize_context_t *c, const CFF2ItemVariationStore *varStore)
   {
     TRACE_SERIALIZE (this);
     unsigned int size_ = varStore->get_size ();
-    CFF2VariationStore *dest = c->allocate_size<CFF2VariationStore> (size_);
+    CFF2ItemVariationStore *dest = c->allocate_size<CFF2ItemVariationStore> (size_);
     if (unlikely (!dest)) return_trace (false);
     hb_memcpy (dest, varStore, size_);
     return_trace (true);
@@ -131,9 +133,9 @@ struct CFF2VariationStore
   unsigned int get_size () const { return HBUINT16::static_size + size; }
 
   HBUINT16      size;
-  VariationStore  varStore;
+  ItemVariationStore  varStore;
 
-  DEFINE_SIZE_MIN (2 + VariationStore::min_size);
+  DEFINE_SIZE_MIN (2 + ItemVariationStore::min_size);
 };
 
 struct cff2_top_dict_values_t : top_dict_values_t<>
@@ -146,8 +148,8 @@ struct cff2_top_dict_values_t : top_dict
   }
   void fini () { top_dict_values_t<>::fini (); }
 
-  unsigned int  vstoreOffset;
-  unsigned int  FDSelectOffset;
+  int  vstoreOffset;
+  int  FDSelectOffset;
 };
 
 struct cff2_top_dict_opset_t : top_dict_opset_t<>
@@ -165,11 +167,11 @@ struct cff2_top_dict_opset_t : top_dict_
         break;
 
       case OpCode_vstore:
-        dictval.vstoreOffset = env.argStack.pop_uint ();
+        dictval.vstoreOffset = env.argStack.pop_int ();
         env.clear_args ();
         break;
       case OpCode_FDSelect:
-        dictval.FDSelectOffset = env.argStack.pop_uint ();
+        dictval.FDSelectOffset = env.argStack.pop_int ();
         env.clear_args ();
         break;
 
@@ -237,7 +239,7 @@ struct cff2_private_dict_values_base_t :
   }
   void fini () { dict_values_t<VAL>::fini (); }
 
-  unsigned int      subrsOffset;
+  int                subrsOffset;
   const CFF2Subrs   *localSubrs;
   unsigned int      ivs;
 };
@@ -291,7 +293,7 @@ struct cff2_private_dict_opset_t : dict_
         env.clear_args ();
         break;
       case OpCode_Subrs:
-        dictval.subrsOffset = env.argStack.pop_uint ();
+        dictval.subrsOffset = env.argStack.pop_int ();
         env.clear_args ();
         break;
       case OpCode_vsindexdict:
@@ -340,7 +342,7 @@ struct cff2_private_dict_opset_subset_t
         return;
 
       case OpCode_Subrs:
-        dictval.subrsOffset = env.argStack.pop_uint ();
+        dictval.subrsOffset = env.argStack.pop_int ();
         env.clear_args ();
         break;
 
@@ -384,6 +386,7 @@ struct cff2
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   likely (version.major == 2));
   }
 
@@ -414,23 +417,22 @@ struct cff2
       { /* parse top dict */
         hb_ubytes_t topDictStr = (cff2 + cff2->topDict).as_ubytes (cff2->topDictSize);
         if (unlikely (!topDictStr.sanitize (&sc))) goto fail;
+        hb_barrier ();
         num_interp_env_t env (topDictStr);
         cff2_top_dict_interpreter_t top_interp (env);
         topDict.init ();
         if (unlikely (!top_interp.interpret (topDict))) goto fail;
       }
 
-      globalSubrs = &StructAtOffset<CFF2Subrs> (cff2, cff2->topDict + cff2->topDictSize);
-      varStore = &StructAtOffsetOrNull<CFF2VariationStore> (cff2, topDict.vstoreOffset);
-      charStrings = &StructAtOffsetOrNull<CFF2CharStrings> (cff2, topDict.charStringsOffset);
-      fdArray = &StructAtOffsetOrNull<CFF2FDArray> (cff2, topDict.FDArrayOffset);
-      fdSelect = &StructAtOffsetOrNull<CFF2FDSelect> (cff2, topDict.FDSelectOffset);
-
-      if (((varStore != &Null (CFF2VariationStore)) && unlikely (!varStore->sanitize (&sc))) ||
-          (charStrings == &Null (CFF2CharStrings)) || unlikely (!charStrings->sanitize (&sc)) ||
-          (globalSubrs == &Null (CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) ||
-          (fdArray == &Null (CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) ||
-          (((fdSelect != &Null (CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count)))))
+      globalSubrs = &StructAtOffsetOrNull<CFF2Subrs> (cff2, cff2->topDict + cff2->topDictSize, sc);
+      varStore = &StructAtOffsetOrNull<CFF2ItemVariationStore> (cff2, topDict.vstoreOffset, sc);
+      charStrings = &StructAtOffsetOrNull<CFF2CharStrings> (cff2, topDict.charStringsOffset, sc);
+      fdArray = &StructAtOffsetOrNull<CFF2FDArray> (cff2, topDict.FDArrayOffset, sc);
+      fdSelect = &StructAtOffsetOrNull<CFF2FDSelect> (cff2, topDict.FDSelectOffset, sc, fdArray->count);
+
+      if (charStrings == &Null (CFF2CharStrings) ||
+          globalSubrs == &Null (CFF2Subrs) ||
+          fdArray == &Null (CFF2FDArray))
         goto fail;
 
       num_glyphs = charStrings->count;
@@ -446,6 +448,7 @@ struct cff2
       {
         const hb_ubytes_t fontDictStr = (*fdArray)[i];
         if (unlikely (!fontDictStr.sanitize (&sc))) goto fail;
+        hb_barrier ();
         cff2_font_dict_values_t  *font;
         num_interp_env_t env (fontDictStr);
         cff2_font_dict_interpreter_t font_interp (env);
@@ -454,17 +457,14 @@ struct cff2
         font->init ();
         if (unlikely (!font_interp.interpret (*font))) goto fail;
 
-        const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
-        if (unlikely (!privDictStr.sanitize (&sc))) goto fail;
+        const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
+        if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
         cff2_priv_dict_interp_env_t env2 (privDictStr);
         dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp (env2);
         privateDicts[i].init ();
         if (unlikely (!priv_interp.interpret (privateDicts[i]))) goto fail;
 
-        privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset);
-        if (privateDicts[i].localSubrs != &Null (CFF2Subrs) &&
-          unlikely (!privateDicts[i].localSubrs->sanitize (&sc)))
-          goto fail;
+        privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset, sc);
       }
 
       return;
@@ -499,7 +499,7 @@ struct cff2
     hb_blob_t                   *blob = nullptr;
     cff2_top_dict_values_t      topDict;
     const CFF2Subrs             *globalSubrs = nullptr;
-    const CFF2VariationStore    *varStore = nullptr;
+    const CFF2ItemVariationStore        *varStore = nullptr;
     const CFF2CharStrings       *charStrings = nullptr;
     const CFF2FDArray           *fdArray = nullptr;
     const CFF2FDSelect          *fdSelect = nullptr;
@@ -518,8 +518,8 @@ struct cff2
     HB_INTERNAL bool get_extents (hb_font_t *font,
                                   hb_codepoint_t glyph,
                                   hb_glyph_extents_t *extents) const;
-    HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) 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<const int> coords) const;
   };
 
   struct accelerator_subset_t : accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t>
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -41,6 +41,148 @@
 
 namespace OT {
 
+static inline uint8_t unicode_to_macroman (hb_codepoint_t u)
+{
+  static const struct unicode_to_macroman_t
+  {
+    uint16_t unicode;
+    uint8_t macroman;
+  }
+  mapping[] =
+  {
+    { 0x00A0, 0xCA },
+    { 0x00A1, 0xC1 },
+    { 0x00A2, 0xA2 },
+    { 0x00A3, 0xA3 },
+    { 0x00A5, 0xB4 },
+    { 0x00A7, 0xA4 },
+    { 0x00A8, 0xAC },
+    { 0x00A9, 0xA9 },
+    { 0x00AA, 0xBB },
+    { 0x00AB, 0xC7 },
+    { 0x00AC, 0xC2 },
+    { 0x00AE, 0xA8 },
+    { 0x00AF, 0xF8 },
+    { 0x00B0, 0xA1 },
+    { 0x00B1, 0xB1 },
+    { 0x00B4, 0xAB },
+    { 0x00B5, 0xB5 },
+    { 0x00B6, 0xA6 },
+    { 0x00B7, 0xE1 },
+    { 0x00B8, 0xFC },
+    { 0x00BA, 0xBC },
+    { 0x00BB, 0xC8 },
+    { 0x00BF, 0xC0 },
+    { 0x00C0, 0xCB },
+    { 0x00C1, 0xE7 },
+    { 0x00C2, 0xE5 },
+    { 0x00C3, 0xCC },
+    { 0x00C4, 0x80 },
+    { 0x00C5, 0x81 },
+    { 0x00C6, 0xAE },
+    { 0x00C7, 0x82 },
+    { 0x00C8, 0xE9 },
+    { 0x00C9, 0x83 },
+    { 0x00CA, 0xE6 },
+    { 0x00CB, 0xE8 },
+    { 0x00CC, 0xED },
+    { 0x00CD, 0xEA },
+    { 0x00CE, 0xEB },
+    { 0x00CF, 0xEC },
+    { 0x00D1, 0x84 },
+    { 0x00D2, 0xF1 },
+    { 0x00D3, 0xEE },
+    { 0x00D4, 0xEF },
+    { 0x00D5, 0xCD },
+    { 0x00D6, 0x85 },
+    { 0x00D8, 0xAF },
+    { 0x00D9, 0xF4 },
+    { 0x00DA, 0xF2 },
+    { 0x00DB, 0xF3 },
+    { 0x00DC, 0x86 },
+    { 0x00DF, 0xA7 },
+    { 0x00E0, 0x88 },
+    { 0x00E1, 0x87 },
+    { 0x00E2, 0x89 },
+    { 0x00E3, 0x8B },
+    { 0x00E4, 0x8A },
+    { 0x00E5, 0x8C },
+    { 0x00E6, 0xBE },
+    { 0x00E7, 0x8D },
+    { 0x00E8, 0x8F },
+    { 0x00E9, 0x8E },
+    { 0x00EA, 0x90 },
+    { 0x00EB, 0x91 },
+    { 0x00EC, 0x93 },
+    { 0x00ED, 0x92 },
+    { 0x00EE, 0x94 },
+    { 0x00EF, 0x95 },
+    { 0x00F1, 0x96 },
+    { 0x00F2, 0x98 },
+    { 0x00F3, 0x97 },
+    { 0x00F4, 0x99 },
+    { 0x00F5, 0x9B },
+    { 0x00F6, 0x9A },
+    { 0x00F7, 0xD6 },
+    { 0x00F8, 0xBF },
+    { 0x00F9, 0x9D },
+    { 0x00FA, 0x9C },
+    { 0x00FB, 0x9E },
+    { 0x00FC, 0x9F },
+    { 0x00FF, 0xD8 },
+    { 0x0131, 0xF5 },
+    { 0x0152, 0xCE },
+    { 0x0153, 0xCF },
+    { 0x0178, 0xD9 },
+    { 0x0192, 0xC4 },
+    { 0x02C6, 0xF6 },
+    { 0x02C7, 0xFF },
+    { 0x02D8, 0xF9 },
+    { 0x02D9, 0xFA },
+    { 0x02DA, 0xFB },
+    { 0x02DB, 0xFE },
+    { 0x02DC, 0xF7 },
+    { 0x02DD, 0xFD },
+    { 0x03A9, 0xBD },
+    { 0x03C0, 0xB9 },
+    { 0x2013, 0xD0 },
+    { 0x2014, 0xD1 },
+    { 0x2018, 0xD4 },
+    { 0x2019, 0xD5 },
+    { 0x201A, 0xE2 },
+    { 0x201C, 0xD2 },
+    { 0x201D, 0xD3 },
+    { 0x201E, 0xE3 },
+    { 0x2020, 0xA0 },
+    { 0x2021, 0xE0 },
+    { 0x2022, 0xA5 },
+    { 0x2026, 0xC9 },
+    { 0x2030, 0xE4 },
+    { 0x2039, 0xDC },
+    { 0x203A, 0xDD },
+    { 0x2044, 0xDA },
+    { 0x20AC, 0xDB },
+    { 0x2122, 0xAA },
+    { 0x2202, 0xB6 },
+    { 0x2206, 0xC6 },
+    { 0x220F, 0xB8 },
+    { 0x2211, 0xB7 },
+    { 0x221A, 0xC3 },
+    { 0x221E, 0xB0 },
+    { 0x222B, 0xBA },
+    { 0x2248, 0xC5 },
+    { 0x2260, 0xAD },
+    { 0x2264, 0xB2 },
+    { 0x2265, 0xB3 },
+    { 0x25CA, 0xD7 },
+    { 0xF8FF, 0xF0 },
+    { 0xFB01, 0xDE },
+    { 0xFB02, 0xDF },
+  };
+  auto *c = hb_bsearch (u, mapping, ARRAY_LENGTH (mapping), sizeof (mapping[0]),
+                        _hb_cmp_operator<uint16_t, uint16_t>);
+  return c ? c->macroman : 0;
+}
 
 struct CmapSubtableFormat0
 {
@@ -556,6 +698,7 @@ struct CmapSubtableFormat4
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
       return_trace (false);
+    hb_barrier ();
 
     if (unlikely (!c->check_range (this, length)))
     {
@@ -742,10 +885,11 @@ struct CmapSubtableLongSegmented
                         unsigned num_glyphs) const
   {
     hb_codepoint_t last_end = 0;
-    for (unsigned i = 0; i < this->groups.len; i++)
+    unsigned count = this->groups.len;
+    for (unsigned i = 0; i < count; i++)
     {
-      hb_codepoint_t start = this->groups[i].startCharCode;
-      hb_codepoint_t end = hb_min ((hb_codepoint_t) this->groups[i].endCharCode,
+      hb_codepoint_t start = this->groups.arrayZ[i].startCharCode;
+      hb_codepoint_t end = hb_min ((hb_codepoint_t) this->groups.arrayZ[i].endCharCode,
                                    (hb_codepoint_t) HB_UNICODE_MAX);
       if (unlikely (start > end || start < last_end)) {
         // Range is not in order and is invalid, skip it.
@@ -754,7 +898,7 @@ struct CmapSubtableLongSegmented
       last_end = end;
 
 
-      hb_codepoint_t gid = this->groups[i].glyphID;
+      hb_codepoint_t gid = this->groups.arrayZ[i].glyphID;
       if (!gid)
       {
         if (T::formatNumber == 13) continue;
@@ -767,9 +911,9 @@ struct CmapSubtableLongSegmented
 
       mapping->alloc (mapping->get_population () + end - start + 1);
 
+      unicodes->add_range (start, end);
       for (unsigned cp = start; cp <= end; cp++)
       {
-        unicodes->add (cp);
         mapping->set (cp, gid);
         gid += T::increment;
       }
@@ -1253,6 +1397,9 @@ struct CmapSubtableFormat14
     hb_vector_t<hb_pair_t<unsigned, unsigned>> obj_indices;
     for (int i = src_tbl->record.len - 1; i >= 0; i--)
     {
+      if (!unicodes->has(src_tbl->record[i].varSelector))
+        continue;
+
       hb_pair_t<unsigned, unsigned> result = src_tbl->record[i].copy (c, unicodes, glyphs_requested, glyph_map, base);
       if (result.first || result.second)
         obj_indices.push (result);
@@ -1309,6 +1456,7 @@ struct CmapSubtableFormat14
   {
     + hb_iter (record)
     | hb_filter (hb_bool, &VariationSelectorRecord::nonDefaultUVS)
+    | hb_filter (unicodes, &VariationSelectorRecord::varSelector)
     | hb_map (&VariationSelectorRecord::nonDefaultUVS)
     | hb_map (hb_add (this))
     | hb_apply ([=] (const NonDefaultUVS& _) { _.closure_glyphs (unicodes, glyphset); })
@@ -1353,12 +1501,12 @@ struct CmapSubtable
                   hb_codepoint_t *glyph) const
   {
     switch (u.format) {
-    case  0: return u.format0 .get_glyph (codepoint, glyph);
-    case  4: return u.format4 .get_glyph (codepoint, glyph);
-    case  6: return u.format6 .get_glyph (codepoint, glyph);
-    case 10: return u.format10.get_glyph (codepoint, glyph);
-    case 12: return u.format12.get_glyph (codepoint, glyph);
-    case 13: return u.format13.get_glyph (codepoint, glyph);
+    case  0: hb_barrier (); return u.format0 .get_glyph (codepoint, glyph);
+    case  4: hb_barrier (); return u.format4 .get_glyph (codepoint, glyph);
+    case  6: hb_barrier (); return u.format6 .get_glyph (codepoint, glyph);
+    case 10: hb_barrier (); return u.format10.get_glyph (codepoint, glyph);
+    case 12: hb_barrier (); return u.format12.get_glyph (codepoint, glyph);
+    case 13: hb_barrier (); return u.format13.get_glyph (codepoint, glyph);
     case 14:
     default: return false;
     }
@@ -1366,12 +1514,12 @@ struct CmapSubtable
   void collect_unicodes (hb_set_t *out, unsigned int num_glyphs = UINT_MAX) const
   {
     switch (u.format) {
-    case  0: u.format0 .collect_unicodes (out); return;
-    case  4: u.format4 .collect_unicodes (out); return;
-    case  6: u.format6 .collect_unicodes (out); return;
-    case 10: u.format10.collect_unicodes (out); return;
-    case 12: u.format12.collect_unicodes (out, num_glyphs); return;
-    case 13: u.format13.collect_unicodes (out, num_glyphs); return;
+    case  0: hb_barrier (); u.format0 .collect_unicodes (out); return;
+    case  4: hb_barrier (); u.format4 .collect_unicodes (out); return;
+    case  6: hb_barrier (); u.format6 .collect_unicodes (out); return;
+    case 10: hb_barrier (); u.format10.collect_unicodes (out); return;
+    case 12: hb_barrier (); u.format12.collect_unicodes (out, num_glyphs); return;
+    case 13: hb_barrier (); u.format13.collect_unicodes (out, num_glyphs); return;
     case 14:
     default: return;
     }
@@ -1382,12 +1530,12 @@ struct CmapSubtable
                         unsigned num_glyphs = UINT_MAX) const
   {
     switch (u.format) {
-    case  0: u.format0 .collect_mapping (unicodes, mapping); return;
-    case  4: u.format4 .collect_mapping (unicodes, mapping); return;
-    case  6: u.format6 .collect_mapping (unicodes, mapping); return;
-    case 10: u.format10.collect_mapping (unicodes, mapping); return;
-    case 12: u.format12.collect_mapping (unicodes, mapping, num_glyphs); return;
-    case 13: u.format13.collect_mapping (unicodes, mapping, num_glyphs); return;
+    case  0: hb_barrier (); u.format0 .collect_mapping (unicodes, mapping); return;
+    case  4: hb_barrier (); u.format4 .collect_mapping (unicodes, mapping); return;
+    case  6: hb_barrier (); u.format6 .collect_mapping (unicodes, mapping); return;
+    case 10: hb_barrier (); u.format10.collect_mapping (unicodes, mapping); return;
+    case 12: hb_barrier (); u.format12.collect_mapping (unicodes, mapping, num_glyphs); return;
+    case 13: hb_barrier (); u.format13.collect_mapping (unicodes, mapping, num_glyphs); return;
     case 14:
     default: return;
     }
@@ -1396,12 +1544,12 @@ struct CmapSubtable
   unsigned get_language () const
   {
     switch (u.format) {
-    case  0: return u.format0 .get_language ();
-    case  4: return u.format4 .get_language ();
-    case  6: return u.format6 .get_language ();
-    case 10: return u.format10.get_language ();
-    case 12: return u.format12.get_language ();
-    case 13: return u.format13.get_language ();
+    case  0: hb_barrier (); return u.format0 .get_language ();
+    case  4: hb_barrier (); return u.format4 .get_language ();
+    case  6: hb_barrier (); return u.format6 .get_language ();
+    case 10: hb_barrier (); return u.format10.get_language ();
+    case 12: hb_barrier (); return u.format12.get_language ();
+    case 13: hb_barrier (); return u.format13.get_language ();
     case 14:
     default: return 0;
     }
@@ -1416,9 +1564,9 @@ struct CmapSubtable
                   const void *base)
   {
     switch (format) {
-    case  4: return u.format4.serialize (c, it);
-    case 12: return u.format12.serialize (c, it);
-    case 14: return u.format14.serialize (c, &plan->unicodes, &plan->glyphs_requested, plan->glyph_map, base);
+    case  4: hb_barrier (); return u.format4.serialize (c, it);
+    case 12: hb_barrier (); return u.format12.serialize (c, it);
+    case 14: hb_barrier (); return u.format14.serialize (c, &plan->unicodes, &plan->glyphs_requested, plan->glyph_map, base);
     default: return;
     }
   }
@@ -1427,14 +1575,15 @@ struct CmapSubtable
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
+    hb_barrier ();
     switch (u.format) {
-    case  0: return_trace (u.format0 .sanitize (c));
-    case  4: return_trace (u.format4 .sanitize (c));
-    case  6: return_trace (u.format6 .sanitize (c));
-    case 10: return_trace (u.format10.sanitize (c));
-    case 12: return_trace (u.format12.sanitize (c));
-    case 13: return_trace (u.format13.sanitize (c));
-    case 14: return_trace (u.format14.sanitize (c));
+    case  0: hb_barrier (); return_trace (u.format0 .sanitize (c));
+    case  4: hb_barrier (); return_trace (u.format4 .sanitize (c));
+    case  6: hb_barrier (); return_trace (u.format6 .sanitize (c));
+    case 10: hb_barrier (); return_trace (u.format10.sanitize (c));
+    case 12: hb_barrier (); return_trace (u.format12.sanitize (c));
+    case 13: hb_barrier (); return_trace (u.format13.sanitize (c));
+    case 14: hb_barrier (); return_trace (u.format14.sanitize (c));
     default:return_trace (true);
     }
   }
@@ -1462,8 +1611,11 @@ struct EncodingRecord
     int ret;
     ret = platformID.cmp (other.platformID);
     if (ret) return ret;
-    ret = encodingID.cmp (other.encodingID);
-    if (ret) return ret;
+    if (other.encodingID != 0xFFFF)
+    {
+      ret = encodingID.cmp (other.encodingID);
+      if (ret) return ret;
+    }
     return 0;
   }
 
@@ -1811,9 +1963,13 @@ struct cmap
                                          c->plan));
   }
 
-  const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
+  const CmapSubtable *find_best_subtable (bool *symbol = nullptr,
+                                          bool *mac = nullptr,
+                                          bool *macroman = nullptr) const
   {
     if (symbol) *symbol = false;
+    if (mac) *mac = false;
+    if (macroman) *macroman = false;
 
     const CmapSubtable *subtable;
 
@@ -1838,6 +1994,20 @@ struct cmap
     if ((subtable = this->find_subtable (0, 1))) return subtable;
     if ((subtable = this->find_subtable (0, 0))) return subtable;
 
+    /* MacRoman subtable. */
+    if ((subtable = this->find_subtable (1, 0)))
+    {
+      if (mac) *mac = true;
+      if (macroman) *macroman = true;
+      return subtable;
+    }
+    /* Any other Mac subtable; we just map ASCII for these. */
+    if ((subtable = this->find_subtable (1, 0xFFFF)))
+    {
+      if (mac) *mac = true;
+      return subtable;
+    }
+
     /* Meh. */
     return &Null (CmapSubtable);
   }
@@ -1849,8 +2019,8 @@ struct cmap
     accelerator_t (hb_face_t *face)
     {
       this->table = hb_sanitize_context_t ().reference_table<cmap> (face);
-      bool symbol;
-      this->subtable = table->find_best_subtable (&symbol);
+      bool symbol, mac, macroman;
+      this->subtable = table->find_best_subtable (&symbol, &mac, &macroman);
       this->subtable_uvs = &Null (CmapSubtableFormat14);
       {
         const CmapSubtable *st = table->find_subtable (0, 5);
@@ -1859,6 +2029,7 @@ struct cmap
       }
 
       this->get_glyph_data = subtable;
+#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
       if (unlikely (symbol))
       {
         switch ((unsigned) face->table.OS2->get_font_page ()) {
@@ -1878,7 +2049,16 @@ struct cmap
           break;
         }
       }
+      else if (unlikely (macroman))
+      {
+        this->get_glyph_funcZ = get_glyph_from_macroman<CmapSubtable>;
+      }
+      else if (unlikely (mac))
+      {
+        this->get_glyph_funcZ = get_glyph_from_ascii<CmapSubtable>;
+      }
       else
+#endif
       {
         switch (subtable->u.format) {
         /* Accelerate format 4 and format 12. */
@@ -1921,7 +2101,7 @@ struct cmap
                             hb_codepoint_t *glyph,
                             cache_t *cache = nullptr) const
     {
-      if (unlikely (!this->get_glyph_funcZ)) return 0;
+      if (unlikely (!this->get_glyph_funcZ)) return false;
       return _cached_get (unicode, glyph, cache);
     }
 
@@ -2003,6 +2183,28 @@ struct cmap
       return false;
     }
 
+    template <typename Type>
+    HB_INTERNAL static bool get_glyph_from_ascii (const void *obj,
+                                                  hb_codepoint_t codepoint,
+                                                  hb_codepoint_t *glyph)
+    {
+      const Type *typed_obj = (const Type *) obj;
+      return codepoint < 0x80 && typed_obj->get_glyph (codepoint, glyph);
+    }
+
+    template <typename Type>
+    HB_INTERNAL static bool get_glyph_from_macroman (const void *obj,
+                                                     hb_codepoint_t codepoint,
+                                                     hb_codepoint_t *glyph)
+    {
+      if (get_glyph_from_ascii<Type> (obj, codepoint, glyph))
+        return true;
+
+      const Type *typed_obj = (const Type *) obj;
+      unsigned c = unicode_to_macroman (codepoint);
+      return c && typed_obj->get_glyph (c, glyph);
+    }
+
     private:
     hb_nonnull_ptr_t<const CmapSubtable> subtable;
     hb_nonnull_ptr_t<const CmapSubtableFormat14> subtable_uvs;
@@ -2032,34 +2234,13 @@ struct cmap
     return &(this+result.subtable);
   }
 
-  const EncodingRecord *find_encodingrec (unsigned int platform_id,
-                                          unsigned int encoding_id) const
-  {
-    EncodingRecord key;
-    key.platformID = platform_id;
-    key.encodingID = encoding_id;
-
-    return encodingRecord.as_array ().bsearch (key);
-  }
-
-  bool find_subtable (unsigned format) const
-  {
-    auto it =
-    + hb_iter (encodingRecord)
-    | hb_map (&EncodingRecord::subtable)
-    | hb_map (hb_add (this))
-    | hb_filter ([&] (const CmapSubtable& _) { return _.u.format == format; })
-    ;
-
-    return it.len ();
-  }
-
   public:
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   likely (version == 0) &&
                   encodingRecord.sanitize (c, this));
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh	2025-06-27 08:03:14.000000000 +0000
@@ -95,12 +95,18 @@ HB_OT_CORE_TABLE (OT, fvar)
 HB_OT_CORE_TABLE (OT, avar)
 HB_OT_CORE_TABLE (OT, cvar)
 HB_OT_ACCELERATOR (OT, gvar)
+#ifndef HB_NO_BEYOND_64K
+HB_OT_ACCELERATOR (OT, GVAR)
+#endif
 HB_OT_CORE_TABLE (OT, MVAR)
+#ifndef HB_NO_VAR_COMPOSITES
+HB_OT_ACCELERATOR (OT, VARC)
+#endif
 #endif
 
 /* Legacy kern. */
 #ifndef HB_NO_OT_KERN
-HB_OT_CORE_TABLE (OT, kern)
+HB_OT_ACCELERATOR (OT, kern)
 #endif
 
 /* OpenType shaping. */
@@ -118,9 +124,9 @@ HB_OT_CORE_TABLE (OT, BASE)
 
 /* AAT shaping. */
 #ifndef HB_NO_AAT
-HB_OT_TABLE (AAT, morx)
-HB_OT_TABLE (AAT, mort)
-HB_OT_TABLE (AAT, kerx)
+HB_OT_ACCELERATOR (AAT, morx)
+HB_OT_ACCELERATOR (AAT, mort)
+HB_OT_ACCELERATOR (AAT, kerx)
 HB_OT_TABLE (AAT, ankr)
 HB_OT_TABLE (AAT, trak)
 HB_OT_TABLE (AAT, ltag)
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc	2025-06-27 08:03:14.000000000 +0000
@@ -41,6 +41,9 @@
 #include "hb-ot-layout-gdef-table.hh"
 #include "hb-ot-layout-gsub-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
+#include "hb-ot-var-varc-table.hh"
+#include "hb-aat-layout-kerx-table.hh"
+#include "hb-aat-layout-morx-table.hh"
 
 
 void hb_ot_face_t::init0 (hb_face_t *face)
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc	2025-06-27 08:03:14.000000000 +0000
@@ -36,13 +36,17 @@
 #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"
 #include "hb-ot-cff1-table.hh"
 #include "hb-ot-hmtx-table.hh"
 #include "hb-ot-post-table.hh"
-#include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-ot-stat-table.hh"
+#include "hb-ot-var-varc-table.hh"
 #include "hb-ot-vorg-table.hh"
 #include "OT/Color/CBDT/CBDT.hh"
 #include "OT/Color/COLR/COLR.hh"
@@ -72,6 +76,10 @@ 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
@@ -90,6 +98,15 @@ _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,
@@ -199,7 +216,6 @@ hb_ot_get_glyph_h_advances (hb_font_t* f
                             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;
@@ -208,12 +224,12 @@ hb_ot_get_glyph_h_advances (hb_font_t* f
 
 #if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
   const OT::HVAR &HVAR = *hmtx.var_table;
-  const OT::VariationStore &varStore = &HVAR + HVAR.varStore;
-  OT::VariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr;
+  const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore;
+  OT::ItemVariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr;
 
   bool use_cache = font->num_coords;
 #else
-  OT::VariationStore::cache_t *varStore_cache = nullptr;
+  OT::ItemVariationStore::cache_t *varStore_cache = nullptr;
   bool use_cache = false;
 #endif
 
@@ -277,7 +293,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* f
   }
 
 #if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
-  OT::VariationStore::destroy_cache (varStore_cache);
+  OT::ItemVariationStore::destroy_cache (varStore_cache);
 #endif
 
   if (font->x_strength && !font->embolden_in_place)
@@ -291,6 +307,20 @@ hb_ot_get_glyph_h_advances (hb_font_t* f
       first_advance = &StructAtOffsetUnaligned<hb_position_t> (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<hb_codepoint_t> (first_glyph, glyph_stride);
+      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+    }
+  }
+#endif
 }
 
 #ifndef HB_NO_VERTICAL
@@ -313,10 +343,10 @@ hb_ot_get_glyph_v_advances (hb_font_t* f
   {
 #if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
     const OT::VVAR &VVAR = *vmtx.var_table;
-    const OT::VariationStore &varStore = &VVAR + VVAR.varStore;
-    OT::VariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr;
+    const OT::ItemVariationStore &varStore = &VVAR + VVAR.varStore;
+    OT::ItemVariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr;
 #else
-    OT::VariationStore::cache_t *varStore_cache = nullptr;
+    OT::ItemVariationStore::cache_t *varStore_cache = nullptr;
 #endif
 
     for (unsigned int i = 0; i < count; i++)
@@ -327,7 +357,7 @@ hb_ot_get_glyph_v_advances (hb_font_t* f
     }
 
 #if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
-    OT::VariationStore::destroy_cache (varStore_cache);
+    OT::ItemVariationStore::destroy_cache (varStore_cache);
 #endif
   }
   else
@@ -355,6 +385,20 @@ hb_ot_get_glyph_v_advances (hb_font_t* f
       first_advance = &StructAtOffsetUnaligned<hb_position_t> (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<hb_codepoint_t> (first_glyph, glyph_stride);
+      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+    }
+  }
+#endif
 }
 #endif
 
@@ -523,6 +567,10 @@ hb_ot_draw_glyph (hb_font_t *font,
   { // 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);
+#ifndef HB_NO_VAR_COMPOSITES
+    if (!font->face->table.VARC->get_path (font, glyph, draw_session))
+#endif
+    // Keep the following in synch with VARC::get_path_at()
     if (!font->face->table.glyf->get_path (font, glyph, draw_session))
 #ifndef HB_NO_CFF
     if (!font->face->table.cff2->get_path (font, glyph, draw_session))
@@ -563,11 +611,11 @@ hb_ot_paint_glyph (hb_font_t *font,
   if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return;
 #endif
 #endif
-  if (font->face->table.glyf->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
-#ifndef HB_NO_CFF
-  if (font->face->table.cff2->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
-  if (font->face->table.cff1->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
-#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);
 }
 #endif
 
@@ -634,7 +682,9 @@ _hb_ot_get_font_funcs ()
  * hb_ot_font_set_funcs:
  * @font: #hb_font_t to work upon
  *
- * Sets the font functions to use when working with @font.
+ * Sets the font functions to use when working with @font to
+ * the HarfBuzz's native implementation. This is the default
+ * for fonts newly created.
  *
  * Since: 0.9.28
  **/
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -71,6 +71,7 @@ struct DeviceRecord
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
                           c->check_range (this, sizeDeviceRecord)));
   }
 
@@ -94,7 +95,7 @@ struct hdmx
   bool serialize (hb_serialize_context_t *c,
                   unsigned version,
                   Iterator it,
-                  const hb_vector_t<hb_codepoint_pair_t> &new_to_old_gid_list,
+                  hb_array_t<const hb_codepoint_pair_t> new_to_old_gid_list,
                   unsigned num_glyphs)
   {
     TRACE_SERIALIZE (this);
@@ -152,6 +153,7 @@ struct hdmx
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   !hb_unsigned_mul_overflows (numRecords, sizeDeviceRecord) &&
                   min_size + numRecords * sizeDeviceRecord > numRecords * sizeDeviceRecord &&
                   sizeDeviceRecord >= DeviceRecord::min_size &&
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -103,6 +103,7 @@ struct head
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   version.major == 1 &&
                   magicNumber == 0x5F0F3CF5u);
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-hhea-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-hhea-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-hhea-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-hhea-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -50,7 +50,9 @@ struct _hea
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && likely (version.major == 1));
+    return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
+                  likely (version.major == 1));
   }
 
   public:
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -30,6 +30,7 @@
 #include "hb-open-type.hh"
 #include "hb-ot-maxp-table.hh"
 #include "hb-ot-hhea-table.hh"
+#include "hb-ot-os2-table.hh"
 #include "hb-ot-var-hvar-table.hh"
 #include "hb-ot-var-mvar-table.hh"
 #include "hb-ot-metrics.hh"
@@ -145,6 +146,29 @@ struct hmtxvmtx
         table->minTrailingBearing = min_rsb;
         table->maxExtent = max_extent;
       }
+
+      if (T::is_horizontal)
+      {
+        const auto &OS2 = *c->plan->source->table.OS2;
+        if (OS2.has_data () &&
+            table->ascender == OS2.sTypoAscender &&
+            table->descender == OS2.sTypoDescender &&
+            table->lineGap == OS2.sTypoLineGap)
+        {
+          table->ascender = static_cast<int> (roundf (OS2.sTypoAscender +
+                                                      MVAR.get_var (HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER,
+                                                                    c->plan->normalized_coords.arrayZ,
+                                                                    c->plan->normalized_coords.length)));
+          table->descender = static_cast<int> (roundf (OS2.sTypoDescender +
+                                                       MVAR.get_var (HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER,
+                                                                     c->plan->normalized_coords.arrayZ,
+                                                                     c->plan->normalized_coords.length)));
+          table->lineGap = static_cast<int> (roundf (OS2.sTypoLineGap +
+                                                     MVAR.get_var (HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP,
+                                                                   c->plan->normalized_coords.arrayZ,
+                                                                   c->plan->normalized_coords.length)));
+        }
+      }
     }
 #endif
 
@@ -158,7 +182,7 @@ struct hmtxvmtx
            hb_requires (hb_is_iterator (Iterator))>
   void serialize (hb_serialize_context_t *c,
                   Iterator it,
-                  const hb_vector_t<hb_codepoint_pair_t> new_to_old_gid_list,
+                  hb_array_t<const hb_codepoint_pair_t> new_to_old_gid_list,
                   unsigned num_long_metrics,
                   unsigned total_num_metrics)
   {
@@ -374,7 +398,7 @@ struct hmtxvmtx
 
     unsigned get_advance_with_var_unscaled (hb_codepoint_t  glyph,
                                             hb_font_t      *font,
-                                            VariationStore::cache_t *store_cache = nullptr) const
+                                            ItemVariationStore::cache_t *store_cache = nullptr) const
     {
       unsigned int advance = get_advance_without_var_unscaled (glyph);
 
@@ -387,7 +411,8 @@ struct hmtxvmtx
                                                                         font->coords, font->num_coords,
                                                                         store_cache));
 
-      return _glyf_get_advance_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
+      unsigned glyf_advance = _glyf_get_advance_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
+      return glyf_advance ? glyf_advance : advance;
 #else
       return advance;
 #endif
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -79,12 +79,23 @@ struct KernSubTableFormat3
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   c->check_range (kernValueZ,
                                   kernValueCount * sizeof (FWORD) +
                                   glyphCount * 2 +
                                   leftClassCount * rightClassCount));
   }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
+  {
+    set_t set;
+    if (likely (glyphCount))
+      set.add_range (0, glyphCount - 1);
+    left_set.union_ (set);
+    right_set.union_ (set);
+  }
+
   protected:
   KernSubTableHeader
                 header;
@@ -121,7 +132,7 @@ struct KernSubTable
   {
     switch (get_type ()) {
     /* This method hooks up to hb_font_t's get_h_kerning.  Only support Format0. */
-    case 0: return u.format0.get_kerning (left, right);
+    case 0: hb_barrier (); return u.format0.get_kerning (left, right);
     default:return 0;
     }
   }
@@ -134,22 +145,36 @@ struct KernSubTable
     switch (subtable_type) {
     case 0:     return_trace (c->dispatch (u.format0));
 #ifndef HB_NO_AAT_SHAPE
-    case 1:     return_trace (u.header.apple ? c->dispatch (u.format1, std::forward<Ts> (ds)...) : c->default_return_value ());
+    case 1:     return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
 #endif
     case 2:     return_trace (c->dispatch (u.format2));
 #ifndef HB_NO_AAT_SHAPE
-    case 3:     return_trace (u.header.apple ? c->dispatch (u.format3, std::forward<Ts> (ds)...) : c->default_return_value ());
+    case 3:     return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
 #endif
     default:    return_trace (c->default_return_value ());
     }
   }
 
+  template <typename set_t>
+  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
+  {
+    unsigned int subtable_type = get_type ();
+    switch (subtable_type) {
+    case 0:     u.format0.collect_glyphs (left_set, right_set, num_glyphs); return;
+    case 1:     u.format1.collect_glyphs (left_set, right_set, num_glyphs); return;
+    case 2:     u.format2.collect_glyphs (left_set, right_set, num_glyphs); return;
+    case 3:     u.format3.collect_glyphs (left_set, right_set, num_glyphs); return;
+    default:    return;
+    }
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!u.header.sanitize (c) ||
-                  u.header.length < u.header.min_size ||
-                  !c->check_range (this, u.header.length))) return_trace (false);
+    if (unlikely (!(u.header.sanitize (c) &&
+                    hb_barrier () &&
+                    u.header.length >= u.header.min_size &&
+                    c->check_range (this, u.header.length)))) return_trace (false);
 
     return_trace (dispatch (c));
   }
@@ -286,9 +311,9 @@ struct kern
   bool has_state_machine () const
   {
     switch (get_type ()) {
-    case 0: return u.ot.has_state_machine ();
+    case 0: hb_barrier (); return u.ot.has_state_machine ();
 #ifndef HB_NO_AAT_SHAPE
-    case 1: return u.aat.has_state_machine ();
+    case 1: hb_barrier (); return u.aat.has_state_machine ();
 #endif
     default:return false;
     }
@@ -297,9 +322,9 @@ struct kern
   bool has_cross_stream () const
   {
     switch (get_type ()) {
-    case 0: return u.ot.has_cross_stream ();
+    case 0: hb_barrier (); return u.ot.has_cross_stream ();
 #ifndef HB_NO_AAT_SHAPE
-    case 1: return u.aat.has_cross_stream ();
+    case 1: hb_barrier (); return u.aat.has_cross_stream ();
 #endif
     default:return false;
     }
@@ -308,16 +333,17 @@ struct kern
   int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
   {
     switch (get_type ()) {
-    case 0: return u.ot.get_h_kerning (left, right);
+    case 0: hb_barrier (); return u.ot.get_h_kerning (left, right);
 #ifndef HB_NO_AAT_SHAPE
-    case 1: return u.aat.get_h_kerning (left, right);
+    case 1: hb_barrier (); return u.aat.get_h_kerning (left, right);
 #endif
     default:return 0;
     }
   }
 
-  bool apply (AAT::hb_aat_apply_context_t *c) const
-  { return dispatch (c); }
+  bool apply (AAT::hb_aat_apply_context_t *c,
+              const AAT::kern_accelerator_data_t &accel_data) const
+  { return dispatch (c, accel_data); }
 
   template <typename context_t, typename ...Ts>
   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
@@ -337,9 +363,45 @@ struct kern
   {
     TRACE_SANITIZE (this);
     if (!u.version32.sanitize (c)) return_trace (false);
+    hb_barrier ();
     return_trace (dispatch (c));
   }
 
+  AAT::kern_accelerator_data_t create_accelerator_data (unsigned num_glyphs) const
+  {
+    switch (get_type ()) {
+    case 0: hb_barrier (); return u.ot.create_accelerator_data (num_glyphs);
+#ifndef HB_NO_AAT_SHAPE
+    case 1: hb_barrier (); return u.aat.create_accelerator_data (num_glyphs);
+#endif
+    default:return AAT::kern_accelerator_data_t ();
+    }
+  }
+
+  struct accelerator_t
+  {
+    accelerator_t (hb_face_t *face)
+    {
+      hb_sanitize_context_t sc;
+      this->table = sc.reference_table<kern> (face);
+      this->accel_data = this->table->create_accelerator_data (face->get_num_glyphs ());
+    }
+    ~accelerator_t ()
+    {
+      this->table.destroy ();
+    }
+
+    hb_blob_t *get_blob () const { return table.get_blob (); }
+
+    bool apply (AAT::hb_aat_apply_context_t *c) const
+    {
+      return table->apply (c, accel_data);
+    }
+
+    hb_blob_ptr_t<kern> table;
+    AAT::kern_accelerator_data_t accel_data;
+  };
+
   protected:
   union {
   HBUINT32              version32;
@@ -353,6 +415,10 @@ struct kern
   DEFINE_SIZE_UNION (4, version32);
 };
 
+struct kern_accelerator_t : kern::accelerator_t {
+  kern_accelerator_t (hb_face_t *face) : kern::accelerator_t (face) {}
+};
+
 } /* namespace OT */
 
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -46,6 +46,12 @@ struct BaseCoordFormat1
     return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate);
   }
 
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    return_trace ((bool) c->serializer->embed (*this));
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -67,6 +73,17 @@ struct BaseCoordFormat2
     return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate);
   }
 
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (c->serializer->check_assign (out->referenceGlyph,
+                                               c->plan->glyph_map->get (referenceGlyph),
+                                               HB_SERIALIZE_ERROR_INT_OVERFLOW));
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -86,7 +103,7 @@ struct BaseCoordFormat2
 struct BaseCoordFormat3
 {
   hb_position_t get_coord (hb_font_t *font,
-                           const VariationStore &var_store,
+                           const ItemVariationStore &var_store,
                            hb_direction_t direction) const
   {
     const Device &device = this+deviceTable;
@@ -96,6 +113,37 @@ struct BaseCoordFormat3
          : font->em_scale_x (coordinate) + device.get_x_delta (font, var_store);
   }
 
+  void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const
+  {
+    unsigned varidx = (this+deviceTable).get_variation_index ();
+    varidx_set.add (varidx);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+
+    if (!c->plan->pinned_at_default)
+    {
+      unsigned var_idx = (this+deviceTable).get_variation_index ();
+      if (var_idx != VarIdx::NO_VARIATION)
+      {
+        hb_pair_t<unsigned, int> *v;
+        if (!c->plan->base_variation_idx_map.has (var_idx, &v))
+          return_trace (false);
+
+        if (unlikely (!c->serializer->check_assign (out->coordinate, coordinate + hb_second (*v),
+                                                    HB_SERIALIZE_ERROR_INT_OVERFLOW)))
+          return_trace (false);
+      }
+    }
+    return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable,
+                                                   this, 0,
+                                                   hb_serialize_context_t::Head,
+                                                   &c->plan->base_variation_idx_map));
+  }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -120,25 +168,47 @@ struct BaseCoord
   bool has_data () const { return u.format; }
 
   hb_position_t get_coord (hb_font_t            *font,
-                           const VariationStore &var_store,
+                           const ItemVariationStore &var_store,
                            hb_direction_t        direction) const
   {
     switch (u.format) {
-    case 1: return u.format1.get_coord (font, direction);
-    case 2: return u.format2.get_coord (font, direction);
-    case 3: return u.format3.get_coord (font, var_store, direction);
+    case 1: hb_barrier (); return u.format1.get_coord (font, direction);
+    case 2: hb_barrier (); return u.format2.get_coord (font, direction);
+    case 3: hb_barrier (); return u.format3.get_coord (font, var_store, direction);
     default:return 0;
     }
   }
 
+  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);
+    default:return;
+    }
+  }
+
+  template <typename context_t, typename ...Ts>
+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+  {
+    if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
+    TRACE_DISPATCH (this, u.format);
+    switch (u.format) {
+    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+    default:return_trace (c->default_return_value ());
+    }
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!u.format.sanitize (c))) return_trace (false);
+    hb_barrier ();
     switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    case 3: return_trace (u.format3.sanitize (c));
+    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
+    case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
+    case 3: hb_barrier (); return_trace (u.format3.sanitize (c));
     default:return_trace (false);
     }
   }
@@ -160,12 +230,37 @@ struct FeatMinMaxRecord
 
   bool has_data () const { return tag; }
 
+  hb_tag_t get_feature_tag () const { return tag; }
+
   void get_min_max (const BaseCoord **min, const BaseCoord **max) const
   {
     if (likely (min)) *min = &(this+minCoord);
     if (likely (max)) *max = &(this+maxCoord);
   }
 
+  void collect_variation_indices (const hb_subset_plan_t* plan,
+                                  const void *base,
+                                  hb_set_t& varidx_set /* OUT */) const
+  {
+    if (!plan->layout_features.has (tag))
+      return;
+
+    (base+minCoord).collect_variation_indices (varidx_set);
+    (base+maxCoord).collect_variation_indices (varidx_set);
+  }
+
+  bool subset (hb_subset_context_t *c,
+               const void *base) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    if (!(out->minCoord.serialize_subset (c, minCoord, base)))
+      return_trace (false);
+
+    return_trace (out->maxCoord.serialize_subset (c, maxCoord, base));
+  }
+
   bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
@@ -205,6 +300,39 @@ struct MinMax
     }
   }
 
+  void collect_variation_indices (const hb_subset_plan_t* plan,
+                                  hb_set_t& varidx_set /* OUT */) const
+  {
+    (this+minCoord).collect_variation_indices (varidx_set);
+    (this+maxCoord).collect_variation_indices (varidx_set);
+    for (const FeatMinMaxRecord& record : featMinMaxRecords)
+      record.collect_variation_indices (plan, this, varidx_set);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+    if (!(out->minCoord.serialize_subset (c, minCoord, this)) ||
+        !(out->maxCoord.serialize_subset (c, maxCoord, this)))
+      return_trace (false);
+
+    unsigned len = 0;
+    for (const FeatMinMaxRecord& _ : featMinMaxRecords)
+    {
+      hb_tag_t feature_tag = _.get_feature_tag ();
+      if (!c->plan->layout_features.has (feature_tag))
+        continue;
+
+      if (!_.subset (c, this)) return false;
+      len++;
+    }
+    return_trace (c->serializer->check_assign (out->featMinMaxRecords.len, len,
+                                               HB_SERIALIZE_ERROR_INT_OVERFLOW));
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -239,6 +367,26 @@ struct BaseValues
     return this+baseCoords[baseline_tag_index];
   }
 
+  void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const
+  {
+    for (const auto& _ : baseCoords)
+      (this+_).collect_variation_indices (varidx_set);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+    out->defaultIndex = defaultIndex;
+
+    for (const auto& _ : baseCoords)
+      if (!subset_offset_array (c, out->baseCoords, this) (_))
+        return_trace (false);
+
+    return_trace (bool (out->baseCoords));
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -267,7 +415,22 @@ struct BaseLangSysRecord
 
   bool has_data () const { return baseLangSysTag; }
 
-  const MinMax &get_min_max () const { return this+minMax; }
+  const MinMax &get_min_max (const void* base) const { return base+minMax; }
+
+  void collect_variation_indices (const void* base,
+                                  const hb_subset_plan_t* plan,
+                                  hb_set_t& varidx_set /* OUT */) const
+  { (base+minMax).collect_variation_indices (plan, varidx_set); }
+
+  bool subset (hb_subset_context_t *c,
+               const void *base) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (out->minMax.serialize_subset (c, minMax, base));
+  }
 
   bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
@@ -290,14 +453,43 @@ struct BaseScript
   const MinMax &get_min_max (hb_tag_t language_tag) const
   {
     const BaseLangSysRecord& record = baseLangSysRecords.bsearch (language_tag);
-    return record.has_data () ? record.get_min_max () : this+defaultMinMax;
+    return record.has_data () ? record.get_min_max (this) : this+defaultMinMax;
   }
 
   const BaseCoord &get_base_coord (int baseline_tag_index) const
   { return (this+baseValues).get_base_coord (baseline_tag_index); }
 
   bool has_values () const { return baseValues; }
-  bool has_min_max () const { return defaultMinMax; /* TODO What if only per-language is present? */ }
+  bool has_min_max () const { return defaultMinMax || baseLangSysRecords; }
+
+  void collect_variation_indices (const hb_subset_plan_t* plan,
+                                  hb_set_t& varidx_set /* OUT */) const
+  {
+    (this+baseValues).collect_variation_indices (varidx_set);
+    (this+defaultMinMax).collect_variation_indices (plan, varidx_set);
+
+    for (const BaseLangSysRecord& _ : baseLangSysRecords)
+      _.collect_variation_indices (this, plan, varidx_set);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+    if (baseValues && !out->baseValues.serialize_subset (c, baseValues, this))
+      return_trace (false);
+
+    if (defaultMinMax && !out->defaultMinMax.serialize_subset (c, defaultMinMax, this))
+      return_trace (false);
+
+    for (const auto& _ : baseLangSysRecords)
+      if (!_.subset (c, this)) return_trace (false);
+
+    return_trace (c->serializer->check_assign (out->baseLangSysRecords.len, baseLangSysRecords.len,
+                                               HB_SERIALIZE_ERROR_INT_OVERFLOW));
+  }
 
   bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -331,9 +523,31 @@ struct BaseScriptRecord
 
   bool has_data () const { return baseScriptTag; }
 
+  hb_tag_t get_script_tag () const { return baseScriptTag; }
+
   const BaseScript &get_base_script (const BaseScriptList *list) const
   { return list+baseScript; }
 
+  void collect_variation_indices (const hb_subset_plan_t* plan,
+                                  const void* list,
+                                  hb_set_t& varidx_set /* OUT */) const
+  {
+    if (!plan->layout_scripts.has (baseScriptTag))
+      return;
+
+    (list+baseScript).collect_variation_indices (plan, varidx_set);
+  }
+
+  bool subset (hb_subset_context_t *c,
+               const void *base) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+
+    return_trace (out->baseScript.serialize_subset (c, baseScript, base));
+  }
+
   bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
@@ -360,6 +574,33 @@ struct BaseScriptList
     return record->has_data () ? record->get_base_script (this) : Null (BaseScript);
   }
 
+  void collect_variation_indices (const hb_subset_plan_t* plan,
+                                  hb_set_t& varidx_set /* OUT */) const
+  {
+    for (const BaseScriptRecord& _ : baseScriptRecords)
+      _.collect_variation_indices (plan, this, varidx_set);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+    unsigned len = 0;
+    for (const BaseScriptRecord& _ : baseScriptRecords)
+    {
+      hb_tag_t script_tag = _.get_script_tag ();
+      if (!c->plan->layout_scripts.has (script_tag))
+        continue;
+
+      if (!_.subset (c, this)) return false;
+      len++;
+    }
+    return_trace (c->serializer->check_assign (out->baseScriptRecords.len, len,
+                                               HB_SERIALIZE_ERROR_INT_OVERFLOW));
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -421,6 +662,20 @@ struct Axis
     return true;
   }
 
+  void collect_variation_indices (const hb_subset_plan_t* plan,
+                                  hb_set_t& varidx_set /* OUT */) const
+  { (this+baseScriptList).collect_variation_indices (plan, varidx_set); }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+
+    out->baseTagList.serialize_copy (c->serializer, baseTagList, this);
+    return_trace (out->baseScriptList.serialize_subset (c, baseScriptList, this));
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -452,8 +707,77 @@ struct BASE
   const Axis &get_axis (hb_direction_t direction) const
   { return HB_DIRECTION_IS_VERTICAL (direction) ? this+vAxis : this+hAxis; }
 
-  const VariationStore &get_var_store () const
-  { return version.to_int () < 0x00010001u ? Null (VariationStore) : this+varStore; }
+  bool has_var_store () const
+  { return version.to_int () >= 0x00010001u && varStore != 0; }
+
+  const ItemVariationStore &get_var_store () const
+  { return version.to_int () < 0x00010001u ? Null (ItemVariationStore) : this+varStore; }
+
+  void collect_variation_indices (const hb_subset_plan_t* plan,
+                                  hb_set_t& varidx_set /* OUT */) const
+  {
+    (this+hAxis).collect_variation_indices (plan, varidx_set);
+    (this+vAxis).collect_variation_indices (plan, varidx_set);
+  }
+
+  bool subset_varstore (hb_subset_context_t *c,
+                        BASE *out /* OUT */) const
+  {
+    TRACE_SUBSET (this);
+    if (!c->serializer->allocate_size<Offset32To<ItemVariationStore>> (Offset32To<ItemVariationStore>::static_size))
+        return_trace (false);
+    if (!c->plan->normalized_coords)
+      return_trace (out->varStore.serialize_subset (c, varStore, this, c->plan->base_varstore_inner_maps.as_array ()));
+
+    if (c->plan->all_axes_pinned)
+      return_trace (true);
+
+    item_variations_t item_vars;
+    if (!item_vars.instantiate (this+varStore, c->plan, true, true,
+                                c->plan->base_varstore_inner_maps.as_array ()))
+      return_trace (false);
+
+    if (!out->varStore.serialize_serialize (c->serializer,
+                                            item_vars.has_long_word (),
+                                            c->plan->axis_tags,
+                                            item_vars.get_region_list (),
+                                            item_vars.get_vardata_encodings ()))
+      return_trace (false);
+
+    const hb_map_t &varidx_map = item_vars.get_varidx_map ();
+    /* base_variation_idx_map in the plan is old_varidx->(varidx, delta)
+     * mapping, new varidx is generated for subsetting, we need to remap this
+     * after instancing */
+    for (auto _ : c->plan->base_variation_idx_map.iter_ref ())
+    {
+      uint32_t varidx = _.second.first;
+      uint32_t *new_varidx;
+      if (varidx_map.has (varidx, &new_varidx))
+        _.second.first = *new_varidx;
+      else
+        _.second.first = HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
+    }
+    return_trace (true);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+    out->version = version;
+    if (has_var_store () && !subset_varstore (c, out))
+        return_trace (false);
+
+    if (hAxis && !out->hAxis.serialize_subset (c, hAxis, this))
+      return_trace (false);
+
+    if (vAxis && !out->vAxis.serialize_subset (c, vAxis, this))
+      return_trace (false);
+
+    return_trace (true);
+  }
 
   bool get_baseline (hb_font_t      *font,
                      hb_tag_t        baseline_tag,
@@ -486,7 +810,7 @@ struct BASE
                                            &min_coord, &max_coord))
       return false;
 
-    const VariationStore &var_store = get_var_store ();
+    const ItemVariationStore &var_store = get_var_store ();
     if (likely (min && min_coord)) *min = min_coord->get_coord (font, var_store, direction);
     if (likely (max && max_coord)) *max = max_coord->get_coord (font, var_store, direction);
     return true;
@@ -496,6 +820,7 @@ struct BASE
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
                           likely (version.major == 1) &&
                           hAxis.sanitize (c, this) &&
                           vAxis.sanitize (c, this) &&
@@ -508,7 +833,7 @@ struct BASE
                                  * of BASE table (may be NULL) */
   Offset16To<Axis>vAxis;                /* Offset to vertical Axis table, from beginning
                                  * of BASE table (may be NULL) */
-  Offset32To<VariationStore>
+  Offset32To<ItemVariationStore>
                 varStore;       /* Offset to the table of Item Variation
                                  * Store--from beginning of BASE
                                  * header (may be NULL).  Introduced
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh	2025-06-27 08:03:14.000000000 +0000
@@ -34,6 +34,7 @@
 #include "hb-open-type.hh"
 #include "hb-set.hh"
 #include "hb-bimap.hh"
+#include "hb-cache.hh"
 
 #include "OT/Layout/Common/Coverage.hh"
 #include "OT/Layout/types.hh"
@@ -64,7 +65,7 @@ struct hb_collect_feature_substitutes_wi
   const hb_hashmap_t<hb_tag_t, Triple> *axes_location;
   hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *record_cond_idx_map;
   hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map;
-  bool& insert_catch_all_feature_variation_record;
+  hb_set_t& catch_all_record_feature_idxes;
 
   // not stored in subset_plan
   hb_set_t *feature_indices;
@@ -142,6 +143,8 @@ struct hb_subset_layout_context_t :
   const hb_map_t *feature_index_map;
   const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map;
   hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map;
+  const hb_set_t *catch_all_record_feature_idxes;
+  const hb_hashmap_t<unsigned, hb_pair_t<const void*, const void*>> *feature_idx_tag_map;
 
   unsigned cur_script_index;
   unsigned cur_feature_var_record_idx;
@@ -164,6 +167,8 @@ struct hb_subset_layout_context_t :
       feature_index_map = &c_->plan->gsub_features;
       feature_substitutes_map = &c_->plan->gsub_feature_substitutes_map;
       feature_record_cond_idx_map = c_->plan->user_axes_location.is_empty () ? nullptr : &c_->plan->gsub_feature_record_cond_idx_map;
+      catch_all_record_feature_idxes = &c_->plan->gsub_old_features;
+      feature_idx_tag_map = &c_->plan->gsub_old_feature_idx_tag_map;
     }
     else
     {
@@ -172,6 +177,8 @@ struct hb_subset_layout_context_t :
       feature_index_map = &c_->plan->gpos_features;
       feature_substitutes_map = &c_->plan->gpos_feature_substitutes_map;
       feature_record_cond_idx_map = c_->plan->user_axes_location.is_empty () ? nullptr : &c_->plan->gpos_feature_record_cond_idx_map;
+      catch_all_record_feature_idxes = &c_->plan->gpos_old_features;
+      feature_idx_tag_map = &c_->plan->gpos_old_feature_idx_tag_map;
     }
   }
 
@@ -182,7 +189,7 @@ struct hb_subset_layout_context_t :
   unsigned lookup_index_count;
 };
 
-struct VariationStore;
+struct ItemVariationStore;
 struct hb_collect_variation_indices_context_t :
        hb_dispatch_context_t<hb_collect_variation_indices_context_t>
 {
@@ -454,6 +461,7 @@ struct FeatureParamsSize
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this))) return_trace (false);
+    hb_barrier ();
 
     /* This subtable has some "history", if you will.  Some earlier versions of
      * Adobe tools calculated the offset of the FeatureParams subtable from the
@@ -639,8 +647,7 @@ struct FeatureParamsCharacterVariants
       return;
 
     unsigned last_name_id = (unsigned) firstParamUILabelNameID + (unsigned) numNamedParameters - 1;
-    if (last_name_id >= 256 && last_name_id <= 32767)
-      nameids_to_retain->add_range (firstParamUILabelNameID, last_name_id);
+    nameids_to_retain->add_range (firstParamUILabelNameID, last_name_id);
   }
 
   bool subset (hb_subset_context_t *c) const
@@ -820,6 +827,7 @@ struct Feature
     TRACE_SANITIZE (this);
     if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
       return_trace (false);
+    hb_barrier ();
 
     /* Some earlier versions of Adobe tools calculated the offset of the
      * FeatureParams subtable from the beginning of the FeatureList table!
@@ -838,6 +846,7 @@ struct Feature
     unsigned int orig_offset = featureParams;
     if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
       return_trace (false);
+    hb_barrier ();
 
     if (featureParams == 0 && closure &&
         closure->tag == HB_TAG ('s','i','z','e') &&
@@ -900,7 +909,8 @@ struct Record
   {
     TRACE_SANITIZE (this);
     const Record_sanitize_closure_t closure = {tag, base};
-    return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
+    return_trace (c->check_struct (this) &&
+                  offset.sanitize (c, base, &closure));
   }
 
   Tag           tag;            /* 4-byte Tag identifier */
@@ -1371,10 +1381,20 @@ struct Lookup
 
     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
     {
-      if (unlikely (!c->serializer->extend (out))) return_trace (false);
       const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
-      HBUINT16 &outMarkFilteringSet = StructAfter<HBUINT16> (out->subTable);
-      outMarkFilteringSet = markFilteringSet;
+      hb_codepoint_t *idx;
+      if (!c->plan->used_mark_sets_map.has (markFilteringSet, &idx))
+      {
+        unsigned new_flag = lookupFlag;
+        new_flag &= ~LookupFlag::UseMarkFilteringSet;
+        out->lookupFlag = new_flag;
+      }
+      else
+      {
+        if (unlikely (!c->serializer->extend (out))) return_trace (false);
+        HBUINT16 &outMarkFilteringSet = StructAfter<HBUINT16> (out->subTable);
+        outMarkFilteringSet = *idx;
+      }
     }
 
     // Always keep the lookup even if it's empty. The rest of layout subsetting depends on lookup
@@ -1391,6 +1411,7 @@ struct Lookup
   {
     TRACE_SANITIZE (this);
     if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
+    hb_barrier ();
 
     unsigned subtables = get_subtable_count ();
     if (unlikely (!c->visit_subtables (subtables))) return_trace (false);
@@ -1406,6 +1427,8 @@ struct Lookup
 
     if (unlikely (get_type () == TSubTable::Extension && !c->get_edit_count ()))
     {
+      hb_barrier ();
+
       /* The spec says all subtables of an Extension lookup should
        * have the same type, which shall not be the Extension type
        * itself (but we already checked for that).
@@ -2045,24 +2068,33 @@ struct ClassDef
   unsigned int get_class (hb_codepoint_t glyph_id) const
   {
     switch (u.format) {
-    case 1: return u.format1.get_class (glyph_id);
-    case 2: return u.format2.get_class (glyph_id);
+    case 1: hb_barrier (); return u.format1.get_class (glyph_id);
+    case 2: hb_barrier (); return u.format2.get_class (glyph_id);
 #ifndef HB_NO_BEYOND_64K
-    case 3: return u.format3.get_class (glyph_id);
-    case 4: return u.format4.get_class (glyph_id);
+    case 3: hb_barrier (); return u.format3.get_class (glyph_id);
+    case 4: hb_barrier (); return u.format4.get_class (glyph_id);
 #endif
     default:return 0;
     }
   }
+  unsigned int get_class (hb_codepoint_t glyph_id,
+                          hb_ot_lookup_cache_t *cache) const
+  {
+    unsigned klass;
+    if (cache && cache->get (glyph_id, &klass)) return klass;
+    klass = get_class (glyph_id);
+    if (cache) cache->set (glyph_id, klass);
+    return klass;
+  }
 
   unsigned get_population () const
   {
     switch (u.format) {
-    case 1: return u.format1.get_population ();
-    case 2: return u.format2.get_population ();
+    case 1: hb_barrier (); return u.format1.get_population ();
+    case 2: hb_barrier (); return u.format2.get_population ();
 #ifndef HB_NO_BEYOND_64K
-    case 3: return u.format3.get_population ();
-    case 4: return u.format4.get_population ();
+    case 3: hb_barrier (); return u.format3.get_population ();
+    case 4: hb_barrier (); return u.format4.get_population ();
 #endif
     default:return NOT_COVERED;
     }
@@ -2124,11 +2156,11 @@ struct ClassDef
 
     switch (u.format)
     {
-    case 1: return_trace (u.format1.serialize (c, it));
-    case 2: return_trace (u.format2.serialize (c, it));
+    case 1: hb_barrier (); return_trace (u.format1.serialize (c, it));
+    case 2: hb_barrier (); return_trace (u.format2.serialize (c, it));
 #ifndef HB_NO_BEYOND_64K
-    case 3: return_trace (u.format3.serialize (c, it));
-    case 4: return_trace (u.format4.serialize (c, it));
+    case 3: hb_barrier (); return_trace (u.format3.serialize (c, it));
+    case 4: hb_barrier (); return_trace (u.format4.serialize (c, it));
 #endif
     default:return_trace (false);
     }
@@ -2142,11 +2174,11 @@ struct ClassDef
   {
     TRACE_SUBSET (this);
     switch (u.format) {
-    case 1: return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
-    case 2: return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+    case 1: hb_barrier (); return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+    case 2: hb_barrier (); return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
 #ifndef HB_NO_BEYOND_64K
-    case 3: return_trace (u.format3.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
-    case 4: return_trace (u.format4.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+    case 3: hb_barrier (); return_trace (u.format3.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+    case 4: hb_barrier (); return_trace (u.format4.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
 #endif
     default:return_trace (false);
     }
@@ -2156,12 +2188,13 @@ struct ClassDef
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
+    hb_barrier ();
     switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
+    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
+    case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
 #ifndef HB_NO_BEYOND_64K
-    case 3: return_trace (u.format3.sanitize (c));
-    case 4: return_trace (u.format4.sanitize (c));
+    case 3: hb_barrier (); return_trace (u.format3.sanitize (c));
+    case 4: hb_barrier (); return_trace (u.format4.sanitize (c));
 #endif
     default:return_trace (true);
     }
@@ -2170,11 +2203,11 @@ struct ClassDef
   unsigned cost () const
   {
     switch (u.format) {
-    case 1: return u.format1.cost ();
-    case 2: return u.format2.cost ();
+    case 1: hb_barrier (); return u.format1.cost ();
+    case 2: hb_barrier (); return u.format2.cost ();
 #ifndef HB_NO_BEYOND_64K
-    case 3: return u.format3.cost ();
-    case 4: return u.format4.cost ();
+    case 3: hb_barrier (); return u.format3.cost ();
+    case 4: hb_barrier (); return u.format4.cost ();
 #endif
     default:return 0u;
     }
@@ -2186,11 +2219,11 @@ struct ClassDef
   bool collect_coverage (set_t *glyphs) const
   {
     switch (u.format) {
-    case 1: return u.format1.collect_coverage (glyphs);
-    case 2: return u.format2.collect_coverage (glyphs);
+    case 1: hb_barrier (); return u.format1.collect_coverage (glyphs);
+    case 2: hb_barrier (); return u.format2.collect_coverage (glyphs);
 #ifndef HB_NO_BEYOND_64K
-    case 3: return u.format3.collect_coverage (glyphs);
-    case 4: return u.format4.collect_coverage (glyphs);
+    case 3: hb_barrier (); return u.format3.collect_coverage (glyphs);
+    case 4: hb_barrier (); return u.format4.collect_coverage (glyphs);
 #endif
     default:return false;
     }
@@ -2202,11 +2235,11 @@ struct ClassDef
   bool collect_class (set_t *glyphs, unsigned int klass) const
   {
     switch (u.format) {
-    case 1: return u.format1.collect_class (glyphs, klass);
-    case 2: return u.format2.collect_class (glyphs, klass);
+    case 1: hb_barrier (); return u.format1.collect_class (glyphs, klass);
+    case 2: hb_barrier (); return u.format2.collect_class (glyphs, klass);
 #ifndef HB_NO_BEYOND_64K
-    case 3: return u.format3.collect_class (glyphs, klass);
-    case 4: return u.format4.collect_class (glyphs, klass);
+    case 3: hb_barrier (); return u.format3.collect_class (glyphs, klass);
+    case 4: hb_barrier (); return u.format4.collect_class (glyphs, klass);
 #endif
     default:return false;
     }
@@ -2215,11 +2248,11 @@ struct ClassDef
   bool intersects (const hb_set_t *glyphs) const
   {
     switch (u.format) {
-    case 1: return u.format1.intersects (glyphs);
-    case 2: return u.format2.intersects (glyphs);
+    case 1: hb_barrier (); return u.format1.intersects (glyphs);
+    case 2: hb_barrier (); return u.format2.intersects (glyphs);
 #ifndef HB_NO_BEYOND_64K
-    case 3: return u.format3.intersects (glyphs);
-    case 4: return u.format4.intersects (glyphs);
+    case 3: hb_barrier (); return u.format3.intersects (glyphs);
+    case 4: hb_barrier (); return u.format4.intersects (glyphs);
 #endif
     default:return false;
     }
@@ -2227,11 +2260,11 @@ struct ClassDef
   bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
   {
     switch (u.format) {
-    case 1: return u.format1.intersects_class (glyphs, klass);
-    case 2: return u.format2.intersects_class (glyphs, klass);
+    case 1: hb_barrier (); return u.format1.intersects_class (glyphs, klass);
+    case 2: hb_barrier (); return u.format2.intersects_class (glyphs, klass);
 #ifndef HB_NO_BEYOND_64K
-    case 3: return u.format3.intersects_class (glyphs, klass);
-    case 4: return u.format4.intersects_class (glyphs, klass);
+    case 3: hb_barrier (); return u.format3.intersects_class (glyphs, klass);
+    case 4: hb_barrier (); return u.format4.intersects_class (glyphs, klass);
 #endif
     default:return false;
     }
@@ -2240,11 +2273,11 @@ struct ClassDef
   void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const
   {
     switch (u.format) {
-    case 1: return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
-    case 2: return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+    case 1: hb_barrier (); return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+    case 2: hb_barrier (); return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
 #ifndef HB_NO_BEYOND_64K
-    case 3: return u.format3.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
-    case 4: return u.format4.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+    case 3: hb_barrier (); return u.format3.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+    case 4: hb_barrier (); return u.format4.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
 #endif
     default:return;
     }
@@ -2253,11 +2286,11 @@ struct ClassDef
   void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
   {
     switch (u.format) {
-    case 1: return u.format1.intersected_classes (glyphs, intersect_classes);
-    case 2: return u.format2.intersected_classes (glyphs, intersect_classes);
+    case 1: hb_barrier (); return u.format1.intersected_classes (glyphs, intersect_classes);
+    case 2: hb_barrier (); return u.format2.intersected_classes (glyphs, intersect_classes);
 #ifndef HB_NO_BEYOND_64K
-    case 3: return u.format3.intersected_classes (glyphs, intersect_classes);
-    case 4: return u.format4.intersected_classes (glyphs, intersect_classes);
+    case 3: hb_barrier (); return u.format3.intersected_classes (glyphs, intersect_classes);
+    case 4: hb_barrier (); return u.format4.intersected_classes (glyphs, intersect_classes);
 #endif
     default:return;
     }
@@ -2447,6 +2480,8 @@ struct VarRegionAxis
     int peak = peakCoord.to_int ();
     if (peak == 0 || coord == peak)
       return 1.f;
+    else if (coord == 0) // Faster
+      return 0.f;
 
     int start = startCoord.to_int (), end = endCoord.to_int ();
 
@@ -2470,8 +2505,6 @@ struct VarRegionAxis
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
-    /* TODO Handle invalid start/peak/end configs, so we don't
-     * have to do that at runtime. */
   }
 
   bool serialize (hb_serialize_context_t *c) const
@@ -2487,6 +2520,33 @@ struct VarRegionAxis
   public:
   DEFINE_SIZE_STATIC (6);
 };
+struct SparseVarRegionAxis
+{
+  float evaluate (const int *coords, unsigned int coord_len) const
+  {
+    unsigned i = axisIndex;
+    int coord = i < coord_len ? coords[i] : 0;
+    return axis.evaluate (coord);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  bool serialize (hb_serialize_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    return_trace (c->embed (this));
+  }
+
+  public:
+  HBUINT16 axisIndex;
+  VarRegionAxis axis;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
 
 #define REGION_CACHE_ITEM_CACHE_INVALID 2.f
 
@@ -2534,7 +2594,9 @@ struct VarRegionList
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && axesZ.sanitize (c, axisCount * regionCount));
+    return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
+                  axesZ.sanitize (c, axisCount * regionCount));
   }
 
   bool serialize (hb_serialize_context_t *c,
@@ -2615,7 +2677,7 @@ struct VarRegionList
       float max_val = axis_region->endCoord.to_float ();
 
       if (def_val != 0.f)
-        axis_tuples.set (*axis_tag, Triple (min_val, def_val, max_val));
+        axis_tuples.set (*axis_tag, Triple ((double) min_val, (double) def_val, (double) max_val));
       axis_region++;
     }
     return !axis_tuples.in_error ();
@@ -2649,6 +2711,65 @@ struct VarRegionList
   DEFINE_SIZE_ARRAY (4, axesZ);
 };
 
+struct SparseVariationRegion : Array16Of<SparseVarRegionAxis>
+{
+  float evaluate (const int *coords, unsigned int coord_len) const
+  {
+    float v = 1.f;
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      float factor = arrayZ[i].evaluate (coords, coord_len);
+      if (factor == 0.f)
+        return 0.;
+      v *= factor;
+    }
+    return v;
+  }
+};
+
+struct SparseVarRegionList
+{
+  using cache_t = float;
+
+  float evaluate (unsigned int region_index,
+                  const int *coords, unsigned int coord_len,
+                  cache_t *cache = nullptr) const
+  {
+    if (unlikely (region_index >= regions.len))
+      return 0.;
+
+    float *cached_value = nullptr;
+    if (cache)
+    {
+      cached_value = &(cache[region_index]);
+      if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID))
+        return *cached_value;
+    }
+
+    const SparseVariationRegion &region = this+regions[region_index];
+
+    float v = region.evaluate (coords, coord_len);
+
+    if (cache)
+      *cached_value = v;
+    return v;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (regions.sanitize (c, this));
+  }
+
+  public:
+  Array16Of<Offset32To<SparseVariationRegion>>
+                regions;
+  public:
+  DEFINE_SIZE_ARRAY (2, regions);
+};
+
+
 struct VarData
 {
   unsigned int get_item_count () const
@@ -2728,6 +2849,7 @@ struct VarData
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
                   regionIndices.sanitize (c) &&
+                  hb_barrier () &&
                   wordCount () <= regionIndices.len &&
                   c->check_range (get_delta_bytes (),
                                   itemCount,
@@ -3009,7 +3131,53 @@ struct VarData
   DEFINE_SIZE_ARRAY (6, regionIndices);
 };
 
-struct VariationStore
+struct MultiVarData
+{
+  unsigned int get_size () const
+  { return min_size
+         - regionIndices.min_size + regionIndices.get_size ()
+         + StructAfter<CFF2Index> (regionIndices).get_size ();
+  }
+
+  void get_delta (unsigned int inner,
+                  const int *coords, unsigned int coord_count,
+                  const SparseVarRegionList &regions,
+                  hb_array_t<float> out,
+                  SparseVarRegionList::cache_t *cache = nullptr) const
+  {
+    auto &deltaSets = StructAfter<decltype (deltaSetsX)> (regionIndices);
+
+    auto values_iter = deltaSets.fetcher (inner);
+    unsigned regionCount = regionIndices.len;
+    for (unsigned regionIndex = 0; regionIndex < regionCount; regionIndex++)
+    {
+      float scalar = regions.evaluate (regionIndices.arrayZ[regionIndex],
+                                       coords, coord_count,
+                                       cache);
+      values_iter.add_to (out, scalar);
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (format.sanitize (c) &&
+                  hb_barrier () &&
+                  format == 1 &&
+                  regionIndices.sanitize (c) &&
+                  hb_barrier () &&
+                  StructAfter<decltype (deltaSetsX)> (regionIndices).sanitize (c));
+  }
+
+  protected:
+  HBUINT8             format; // 1
+  Array16Of<HBUINT16> regionIndices;
+  TupleList           deltaSetsX;
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+struct ItemVariationStore
 {
   friend struct item_variations_t;
   using cache_t = VarRegionList::cache_t;
@@ -3061,7 +3229,7 @@ struct VariationStore
     return get_delta (outer, inner, coords, coord_count, cache);
   }
   float get_delta (unsigned int index,
-                   hb_array_t<int> coords,
+                   hb_array_t<const int> coords,
                    VarRegionList::cache_t *cache = nullptr) const
   {
     return get_delta (index,
@@ -3077,6 +3245,7 @@ struct VariationStore
 
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   format == 1 &&
                   regions.sanitize (c, this) &&
                   dataSets.sanitize (c, this));
@@ -3113,7 +3282,7 @@ struct VariationStore
   }
 
   bool serialize (hb_serialize_context_t *c,
-                  const VariationStore *src,
+                  const ItemVariationStore *src,
                   const hb_array_t <const hb_inc_bimap_t> &inner_maps)
   {
     TRACE_SERIALIZE (this);
@@ -3169,7 +3338,7 @@ struct VariationStore
     return_trace (true);
   }
 
-  VariationStore *copy (hb_serialize_context_t *c) const
+  ItemVariationStore *copy (hb_serialize_context_t *c) const
   {
     TRACE_SERIALIZE (this);
     auto *out = c->start_embed (this);
@@ -3180,6 +3349,8 @@ struct VariationStore
     for (unsigned i = 0; i < count; i++)
     {
       hb_inc_bimap_t *map = inner_maps.push ();
+      if (!c->propagate_error(inner_maps))
+        return_trace(nullptr);
       auto &data = this+dataSets[i];
 
       unsigned itemCount = data.get_item_count ();
@@ -3199,7 +3370,7 @@ struct VariationStore
     return_trace (false);
 #endif
 
-    VariationStore *varstore_prime = c->serializer->start_embed<VariationStore> ();
+    ItemVariationStore *varstore_prime = c->serializer->start_embed<ItemVariationStore> ();
     if (unlikely (!varstore_prime)) return_trace (false);
 
     varstore_prime->serialize (c->serializer, this, inner_maps);
@@ -3265,8 +3436,370 @@ struct VariationStore
   DEFINE_SIZE_ARRAY_SIZED (8, dataSets);
 };
 
+struct MultiItemVariationStore
+{
+  using cache_t = SparseVarRegionList::cache_t;
+
+  cache_t *create_cache (hb_array_t<float> static_cache = hb_array_t<float> ()) const
+  {
+#ifdef HB_NO_VAR
+    return nullptr;
+#endif
+    auto &r = this+regions;
+    unsigned count = r.regions.len;
+
+    float *cache;
+    if (count <= static_cache.length)
+      cache = static_cache.arrayZ;
+    else
+    {
+      cache = (float *) hb_malloc (sizeof (float) * count);
+      if (unlikely (!cache)) return nullptr;
+    }
+
+    for (unsigned i = 0; i < count; i++)
+      cache[i] = REGION_CACHE_ITEM_CACHE_INVALID;
+
+    return cache;
+  }
+
+  static void destroy_cache (cache_t *cache,
+                             hb_array_t<float> static_cache = hb_array_t<float> ())
+  {
+    if (cache != static_cache.arrayZ)
+      hb_free (cache);
+  }
+
+  private:
+  void get_delta (unsigned int outer, unsigned int inner,
+                  const int *coords, unsigned int coord_count,
+                  hb_array_t<float> out,
+                  VarRegionList::cache_t *cache = nullptr) const
+  {
+#ifdef HB_NO_VAR
+    return;
+#endif
+
+    if (unlikely (outer >= dataSets.len))
+      return;
+
+    return (this+dataSets[outer]).get_delta (inner,
+                                             coords, coord_count,
+                                             this+regions,
+                                             out,
+                                             cache);
+  }
+
+  public:
+  void get_delta (unsigned int index,
+                  const int *coords, unsigned int coord_count,
+                  hb_array_t<float> out,
+                  VarRegionList::cache_t *cache = nullptr) const
+  {
+    unsigned int outer = index >> 16;
+    unsigned int inner = index & 0xFFFF;
+    get_delta (outer, inner, coords, coord_count, out, cache);
+  }
+  void get_delta (unsigned int index,
+                  hb_array_t<const int> coords,
+                  hb_array_t<float> out,
+                  VarRegionList::cache_t *cache = nullptr) const
+  {
+    return get_delta (index,
+                      coords.arrayZ, coords.length,
+                      out,
+                      cache);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+#ifdef HB_NO_VAR
+    return true;
+#endif
+
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
+                  format == 1 &&
+                  regions.sanitize (c, this) &&
+                  dataSets.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16                              format; // 1
+  Offset32To<SparseVarRegionList>       regions;
+  Array16OfOffset32To<MultiVarData>     dataSets;
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (8, dataSets);
+};
+
 #undef REGION_CACHE_ITEM_CACHE_INVALID
 
+template <typename MapCountT>
+struct DeltaSetIndexMapFormat01
+{
+  friend struct DeltaSetIndexMap;
+
+  unsigned get_size () const
+  { return min_size + mapCount * get_width (); }
+
+  private:
+  DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    return_trace (c->embed (this));
+  }
+
+  template <typename T>
+  bool serialize (hb_serialize_context_t *c, const T &plan)
+  {
+    unsigned int width = plan.get_width ();
+    unsigned int inner_bit_count = plan.get_inner_bit_count ();
+    const hb_array_t<const uint32_t> output_map = plan.get_output_map ();
+
+    TRACE_SERIALIZE (this);
+    if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0))))
+      return_trace (false);
+    if (unlikely (!c->extend_min (this))) return_trace (false);
+
+    entryFormat = ((width-1)<<4)|(inner_bit_count-1);
+    mapCount = output_map.length;
+    HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length);
+    if (unlikely (!p)) return_trace (false);
+    for (unsigned int i = 0; i < output_map.length; i++)
+    {
+      unsigned int v = output_map.arrayZ[i];
+      if (v)
+      {
+        unsigned int outer = v >> 16;
+        unsigned int inner = v & 0xFFFF;
+        unsigned int u = (outer << inner_bit_count) | inner;
+        for (unsigned int w = width; w > 0;)
+        {
+          p[--w] = u;
+          u >>= 8;
+        }
+      }
+      p += width;
+    }
+    return_trace (true);
+  }
+
+  uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */
+  {
+    /* If count is zero, pass value unchanged.  This takes
+     * care of direct mapping for advance map. */
+    if (!mapCount)
+      return v;
+
+    if (v >= mapCount)
+      v = mapCount - 1;
+
+    unsigned int u = 0;
+    { /* Fetch it. */
+      unsigned int w = get_width ();
+      const HBUINT8 *p = mapDataZ.arrayZ + w * v;
+      for (; w; w--)
+        u = (u << 8) + *p++;
+    }
+
+    { /* Repack it. */
+      unsigned int n = get_inner_bit_count ();
+      unsigned int outer = u >> n;
+      unsigned int inner = u & ((1 << n) - 1);
+      u = (outer<<16) | inner;
+    }
+
+    return u;
+  }
+
+  unsigned get_map_count () const       { return mapCount; }
+  unsigned get_width () const           { return ((entryFormat >> 4) & 3) + 1; }
+  unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; }
+
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
+                  c->check_range (mapDataZ.arrayZ,
+                                  mapCount,
+                                  get_width ()));
+  }
+
+  protected:
+  HBUINT8       format;         /* Format identifier--format = 0 */
+  HBUINT8       entryFormat;    /* A packed field that describes the compressed
+                                 * representation of delta-set indices. */
+  MapCountT     mapCount;       /* The number of mapping entries. */
+  UnsizedArrayOf<HBUINT8>
+                mapDataZ;       /* The delta-set index mapping data. */
+
+  public:
+  DEFINE_SIZE_ARRAY (2+MapCountT::static_size, mapDataZ);
+};
+
+struct DeltaSetIndexMap
+{
+  template <typename T>
+  bool serialize (hb_serialize_context_t *c, const T &plan)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned length = plan.get_output_map ().length;
+    u.format = length <= 0xFFFF ? 0 : 1;
+    switch (u.format) {
+    case 0: hb_barrier (); return_trace (u.format0.serialize (c, plan));
+    case 1: hb_barrier (); return_trace (u.format1.serialize (c, plan));
+    default:return_trace (false);
+    }
+  }
+
+  uint32_t map (unsigned v) const
+  {
+    switch (u.format) {
+    case 0: hb_barrier (); return (u.format0.map (v));
+    case 1: hb_barrier (); return (u.format1.map (v));
+    default:return v;
+    }
+  }
+
+  unsigned get_map_count () const
+  {
+    switch (u.format) {
+    case 0: hb_barrier (); return u.format0.get_map_count ();
+    case 1: hb_barrier (); return u.format1.get_map_count ();
+    default:return 0;
+    }
+  }
+
+  unsigned get_width () const
+  {
+    switch (u.format) {
+    case 0: hb_barrier (); return u.format0.get_width ();
+    case 1: hb_barrier (); return u.format1.get_width ();
+    default:return 0;
+    }
+  }
+
+  unsigned get_inner_bit_count () const
+  {
+    switch (u.format) {
+    case 0: hb_barrier (); return u.format0.get_inner_bit_count ();
+    case 1: hb_barrier (); return u.format1.get_inner_bit_count ();
+    default:return 0;
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    hb_barrier ();
+    switch (u.format) {
+    case 0: hb_barrier (); return_trace (u.format0.sanitize (c));
+    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+
+  DeltaSetIndexMap* copy (hb_serialize_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    switch (u.format) {
+    case 0: hb_barrier (); return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format0.copy (c)));
+    case 1: hb_barrier (); return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format1.copy (c)));
+    default:return_trace (nullptr);
+    }
+  }
+
+  protected:
+  union {
+  HBUINT8                            format;         /* Format identifier */
+  DeltaSetIndexMapFormat01<HBUINT16> format0;
+  DeltaSetIndexMapFormat01<HBUINT32> format1;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (1, format);
+};
+
+
+struct ItemVarStoreInstancer
+{
+  ItemVarStoreInstancer (const ItemVariationStore *varStore_,
+                         const DeltaSetIndexMap *varIdxMap,
+                         hb_array_t<const int> coords,
+                         VarRegionList::cache_t *cache = nullptr) :
+    varStore (varStore_), varIdxMap (varIdxMap), coords (coords), cache (cache)
+  {
+    if (!varStore)
+      varStore = &Null(ItemVariationStore);
+  }
+
+  operator bool () const { return varStore && bool (coords); }
+
+  float operator[] (uint32_t varIdx) const
+  { return (*this) (varIdx); }
+
+  float operator() (uint32_t varIdx, unsigned short offset = 0) const
+  {
+   if (!coords || varIdx == VarIdx::NO_VARIATION)
+     return 0.f;
+
+    varIdx += offset;
+    if (varIdxMap)
+      varIdx = varIdxMap->map (varIdx);
+    return varStore->get_delta (varIdx, coords, cache);
+  }
+
+  const ItemVariationStore *varStore;
+  const DeltaSetIndexMap *varIdxMap;
+  hb_array_t<const int> coords;
+  VarRegionList::cache_t *cache;
+};
+
+struct MultiItemVarStoreInstancer
+{
+  MultiItemVarStoreInstancer (const MultiItemVariationStore *varStore,
+                              const DeltaSetIndexMap *varIdxMap,
+                              hb_array_t<const int> coords,
+                              SparseVarRegionList::cache_t *cache = nullptr) :
+    varStore (varStore), varIdxMap (varIdxMap), coords (coords), cache (cache)
+  {
+    if (!varStore)
+      varStore = &Null(MultiItemVariationStore);
+  }
+
+  operator bool () const { return varStore && bool (coords); }
+
+  float operator[] (uint32_t varIdx) const
+  {
+    float v = 0;
+    (*this) (hb_array (&v, 1), varIdx);
+    return v;
+  }
+
+  void operator() (hb_array_t<float> out, uint32_t varIdx, unsigned short offset = 0) const
+  {
+    if (coords && varIdx != VarIdx::NO_VARIATION)
+    {
+      varIdx += offset;
+      if (varIdxMap)
+        varIdx = varIdxMap->map (varIdx);
+      varStore->get_delta (varIdx, coords, out, cache);
+    }
+    else
+      for (unsigned i = 0; i < out.length; i++)
+        out.arrayZ[i] = 0.f;
+  }
+
+  const MultiItemVariationStore *varStore;
+  const DeltaSetIndexMap *varIdxMap;
+  hb_array_t<const int> coords;
+  SparseVarRegionList::cache_t *cache;
+};
+
+
 /*
  * Feature Variations
  */
@@ -3278,7 +3811,16 @@ enum Cond_with_Var_flag_t
   DROP_RECORD_WITH_VAR = 3,
 };
 
-struct ConditionFormat1
+struct Condition;
+
+template <typename Instancer>
+static bool
+_hb_recurse_condition_evaluate (const struct Condition &condition,
+                                const int *coords,
+                                unsigned int coord_len,
+                                Instancer *instancer);
+
+struct ConditionAxisRange
 {
   friend struct Condition;
 
@@ -3298,19 +3840,19 @@ struct ConditionFormat1
       return_trace (false);
 
     const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location = c->plan->axes_location;
-    Triple axis_limit{-1.f, 0.f, 1.f};
+    Triple axis_limit{-1.0, 0.0, 1.0};
     Triple *normalized_limit;
     if (normalized_axes_location.has (*axis_tag, &normalized_limit))
       axis_limit = *normalized_limit;
 
     const hb_hashmap_t<hb_tag_t, TripleDistances>& axes_triple_distances = c->plan->axes_triple_distances;
-    TripleDistances axis_triple_distances{1.f, 1.f};
+    TripleDistances axis_triple_distances{1.0, 1.0};
     TripleDistances *triple_dists;
     if (axes_triple_distances.has (*axis_tag, &triple_dists))
       axis_triple_distances = *triple_dists;
 
-    float normalized_min = renormalizeValue (filterRangeMinValue.to_float (), axis_limit, axis_triple_distances, false);
-    float normalized_max = renormalizeValue (filterRangeMaxValue.to_float (), axis_limit, axis_triple_distances, false);
+    float normalized_min = renormalizeValue ((double) filterRangeMinValue.to_float (), axis_limit, axis_triple_distances, false);
+    float normalized_max = renormalizeValue ((double) filterRangeMaxValue.to_float (), axis_limit, axis_triple_distances, false);
     out->filterRangeMinValue.set_float (normalized_min);
     out->filterRangeMaxValue.set_float (normalized_max);
 
@@ -3328,10 +3870,14 @@ struct ConditionFormat1
 
     hb_tag_t axis_tag = c->axes_index_tag_map->get (axisIndex);
 
-    Triple axis_range (-1.f, 0.f, 1.f);
+    Triple axis_range (-1.0, 0.0, 1.0);
     Triple *axis_limit;
+    bool axis_set_by_user = false;
     if (c->axes_location->has (axis_tag, &axis_limit))
+    {
       axis_range = *axis_limit;
+      axis_set_by_user = true;
+    }
 
     float axis_min_val = axis_range.minimum;
     float axis_default_val = axis_range.middle;
@@ -3350,26 +3896,26 @@ struct ConditionFormat1
       return DROP_RECORD_WITH_VAR;
 
     //condition met and axis pinned, drop the condition
-    if (c->axes_location->has (axis_tag) &&
-        c->axes_location->get (axis_tag).is_point ())
+    if (axis_set_by_user && axis_range.is_point ())
       return DROP_COND_WITH_VAR;
 
     if (filter_max_val != axis_max_val || filter_min_val != axis_min_val)
     {
       // add axisIndex->value into the hashmap so we can check if the record is
       // unique with variations
-      int16_t int_filter_max_val = filterRangeMaxValue.to_int ();
-      int16_t int_filter_min_val = filterRangeMinValue.to_int ();
+      uint16_t int_filter_max_val = (uint16_t) filterRangeMaxValue.to_int ();
+      uint16_t int_filter_min_val = (uint16_t) filterRangeMinValue.to_int ();
       hb_codepoint_t val = (int_filter_max_val << 16) + int_filter_min_val;
 
       condition_map->set (axisIndex, val);
       return KEEP_COND_WITH_VAR;
     }
-
     return KEEP_RECORD_WITH_VAR;
   }
 
-  bool evaluate (const int *coords, unsigned int coord_len) const
+  template <typename Instancer>
+  bool evaluate (const int *coords, unsigned int coord_len,
+                 Instancer *instancer HB_UNUSED) const
   {
     int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
     return filterRangeMinValue.to_int () <= coord && coord <= filterRangeMaxValue.to_int ();
@@ -3390,12 +3936,199 @@ struct ConditionFormat1
   DEFINE_SIZE_STATIC (8);
 };
 
+struct ConditionValue
+{
+  friend struct Condition;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  private:
+  template <typename Instancer>
+  bool evaluate (const int *coords, unsigned int coord_len,
+                 Instancer *instancer) const
+  {
+    signed value = defaultValue;
+    value += (*instancer)[varIdx];
+    return value > 0;
+  }
+
+  bool subset (hb_subset_context_t *c,
+               hb_subset_layout_context_t *l,
+               bool insert_catch_all) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 2 */
+  HBINT16       defaultValue;   /* Value at default instance. */
+  VarIdx        varIdx;         /* Variation index */
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct ConditionAnd
+{
+  friend struct Condition;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  private:
+  template <typename Instancer>
+  bool evaluate (const int *coords, unsigned int coord_len,
+                 Instancer *instancer) const
+  {
+    unsigned int count = conditions.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!_hb_recurse_condition_evaluate (this+conditions.arrayZ[i],
+                                           coords, coord_len,
+                                           instancer))
+        return false;
+    return true;
+  }
+
+  bool subset (hb_subset_context_t *c,
+               hb_subset_layout_context_t *l,
+               bool insert_catch_all) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (conditions.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 3 */
+  Array8OfOffset24To<struct Condition>  conditions;
+  public:
+  DEFINE_SIZE_ARRAY (3, conditions);
+};
+
+struct ConditionOr
+{
+  friend struct Condition;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  private:
+  template <typename Instancer>
+  bool evaluate (const int *coords, unsigned int coord_len,
+                 Instancer *instancer) const
+  {
+    unsigned int count = conditions.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (_hb_recurse_condition_evaluate (this+conditions.arrayZ[i],
+                                          coords, coord_len,
+                                          instancer))
+        return true;
+    return false;
+  }
+
+  bool subset (hb_subset_context_t *c,
+               hb_subset_layout_context_t *l,
+               bool insert_catch_all) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (conditions.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 4 */
+  Array8OfOffset24To<struct Condition>  conditions;
+  public:
+  DEFINE_SIZE_ARRAY (3, conditions);
+};
+
+struct ConditionNegate
+{
+  friend struct Condition;
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  private:
+  template <typename Instancer>
+  bool evaluate (const int *coords, unsigned int coord_len,
+                 Instancer *instancer) const
+  {
+    return !_hb_recurse_condition_evaluate (this+condition,
+                                            coords, coord_len,
+                                            instancer);
+  }
+
+  bool subset (hb_subset_context_t *c,
+               hb_subset_layout_context_t *l,
+               bool insert_catch_all) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (condition.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 5 */
+  Offset24To<struct Condition>  condition;
+  public:
+  DEFINE_SIZE_STATIC (5);
+};
+
 struct Condition
 {
-  bool evaluate (const int *coords, unsigned int coord_len) const
+  template <typename Instancer>
+  bool evaluate (const int *coords, unsigned int coord_len,
+                 Instancer *instancer) const
   {
     switch (u.format) {
-    case 1: return u.format1.evaluate (coords, coord_len);
+    case 1: hb_barrier (); return u.format1.evaluate (coords, coord_len, instancer);
+    case 2: hb_barrier (); return u.format2.evaluate (coords, coord_len, instancer);
+    case 3: hb_barrier (); return u.format3.evaluate (coords, coord_len, instancer);
+    case 4: hb_barrier (); return u.format4.evaluate (coords, coord_len, instancer);
+    case 5: hb_barrier (); return u.format5.evaluate (coords, coord_len, instancer);
     default:return false;
     }
   }
@@ -3404,7 +4137,8 @@ struct Condition
                                              hb_map_t *condition_map /* OUT */) const
   {
     switch (u.format) {
-    case 1: return u.format1.keep_with_variations (c, condition_map);
+    case 1: hb_barrier (); return u.format1.keep_with_variations (c, condition_map);
+    // TODO(subset)
     default: c->apply = false; return KEEP_COND_WITH_VAR;
     }
   }
@@ -3415,7 +4149,11 @@ struct Condition
     if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
     TRACE_DISPATCH (this, u.format);
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -3424,8 +4162,13 @@ struct Condition
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
+    hb_barrier ();
     switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
+    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
+    case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
+    case 3: hb_barrier (); return_trace (u.format3.sanitize (c));
+    case 4: hb_barrier (); return_trace (u.format4.sanitize (c));
+    case 5: hb_barrier (); return_trace (u.format5.sanitize (c));
     default:return_trace (true);
     }
   }
@@ -3433,19 +4176,51 @@ struct Condition
   protected:
   union {
   HBUINT16              format;         /* Format identifier */
-  ConditionFormat1      format1;
+  ConditionAxisRange    format1;
+  ConditionValue        format2;
+  ConditionAnd          format3;
+  ConditionOr           format4;
+  ConditionNegate       format5;
   } u;
   public:
   DEFINE_SIZE_UNION (2, format);
 };
 
+template <typename Instancer>
+bool
+_hb_recurse_condition_evaluate (const struct Condition &condition,
+                                const int *coords,
+                                unsigned int coord_len,
+                                Instancer *instancer)
+{
+  return condition.evaluate (coords, coord_len, instancer);
+}
+
+struct ConditionList
+{
+  const Condition& operator[] (unsigned i) const
+  { return this+conditions[i]; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (conditions.sanitize (c, this));
+  }
+
+  protected:
+  Array32OfOffset32To<Condition> conditions;
+  public:
+  DEFINE_SIZE_ARRAY (4, conditions);
+};
+
 struct ConditionSet
 {
-  bool evaluate (const int *coords, unsigned int coord_len) const
+  bool evaluate (const int *coords, unsigned int coord_len,
+                 ItemVarStoreInstancer *instancer) const
   {
     unsigned int count = conditions.len;
     for (unsigned int i = 0; i < count; i++)
-      if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len))
+      if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len, instancer))
         return false;
     return true;
   }
@@ -3497,12 +4272,15 @@ struct ConditionSet
   }
 
   bool subset (hb_subset_context_t *c,
-               hb_subset_layout_context_t *l) const
+               hb_subset_layout_context_t *l,
+               bool insert_catch_all) const
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (this);
     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
 
+    if (insert_catch_all) return_trace (true);
+
     hb_set_t *retained_cond_set = nullptr;
     if (l->feature_record_cond_idx_map != nullptr)
       retained_cond_set = l->feature_record_cond_idx_map->get (l->cur_feature_var_record_idx);
@@ -3548,27 +4326,51 @@ struct FeatureTableSubstitutionRecord
   }
 
   void collect_feature_substitutes_with_variations (hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
+                                                    hb_set_t& catch_all_record_feature_idxes,
                                                     const hb_set_t *feature_indices,
                                                     const void *base) const
   {
     if (feature_indices->has (featureIndex))
+    {
       feature_substitutes_map->set (featureIndex, &(base+feature));
+      catch_all_record_feature_idxes.add (featureIndex);
+    }
+  }
+
+  bool serialize (hb_subset_layout_context_t *c,
+                  unsigned feature_index,
+                  const Feature *f, const Tag *tag)
+  {
+    TRACE_SERIALIZE (this);
+    hb_serialize_context_t *s = c->subset_context->serializer;
+    if (unlikely (!s->extend_min (this))) return_trace (false);
+
+    uint32_t *new_feature_idx;
+    if (!c->feature_index_map->has (feature_index, &new_feature_idx))
+      return_trace (false);
+
+    if (!s->check_assign (featureIndex, *new_feature_idx, HB_SERIALIZE_ERROR_INT_OVERFLOW))
+      return_trace (false);
+
+    s->push ();
+    bool ret = f->subset (c->subset_context, c, tag);
+    if (ret) s->add_link (feature, s->pop_pack ());
+    else s->pop_discard ();
+
+    return_trace (ret);
   }
 
   bool subset (hb_subset_layout_context_t *c, const void *base) const
   {
     TRACE_SUBSET (this);
-    if (!c->feature_index_map->has (featureIndex) ||
-        c->feature_substitutes_map->has (featureIndex)) {
-      // Feature that is being substituted is not being retained, so we don't
-      // need this.
+    uint32_t *new_feature_index;
+    if (!c->feature_index_map->has (featureIndex, &new_feature_index))
       return_trace (false);
-    }
 
     auto *out = c->subset_context->serializer->embed (this);
     if (unlikely (!out)) return_trace (false);
 
-    out->featureIndex = c->feature_index_map->get (featureIndex);
+    out->featureIndex = *new_feature_index;
     return_trace (out->feature.serialize_subset (c->subset_context, feature, base, c));
   }
 
@@ -3600,16 +4402,10 @@ struct FeatureTableSubstitution
   }
 
   void collect_lookups (const hb_set_t *feature_indexes,
-                        const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
                         hb_set_t       *lookup_indexes /* OUT */) const
   {
     + hb_iter (substitutions)
     | hb_filter (feature_indexes, &FeatureTableSubstitutionRecord::featureIndex)
-    | hb_filter ([feature_substitutes_map] (const FeatureTableSubstitutionRecord& record)
-                 {
-                   if (feature_substitutes_map == nullptr) return true;
-                   return !feature_substitutes_map->has (record.featureIndex);
-                 })
     | hb_apply ([this, lookup_indexes] (const FeatureTableSubstitutionRecord& r)
                 { r.collect_lookups (this, lookup_indexes); })
     ;
@@ -3634,11 +4430,14 @@ struct FeatureTableSubstitution
   void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
   {
     for (const FeatureTableSubstitutionRecord& record : substitutions)
-      record.collect_feature_substitutes_with_variations (c->feature_substitutes_map, c->feature_indices, this);
+      record.collect_feature_substitutes_with_variations (c->feature_substitutes_map,
+                                                          c->catch_all_record_feature_idxes,
+                                                          c->feature_indices, this);
   }
 
   bool subset (hb_subset_context_t        *c,
-               hb_subset_layout_context_t *l) const
+               hb_subset_layout_context_t *l,
+               bool insert_catch_all) const
   {
     TRACE_SUBSET (this);
     auto *out = c->serializer->start_embed (*this);
@@ -3647,6 +4446,22 @@ struct FeatureTableSubstitution
     out->version.major = version.major;
     out->version.minor = version.minor;
 
+    if (insert_catch_all)
+    {
+      for (unsigned feature_index : *(l->catch_all_record_feature_idxes))
+      {
+        hb_pair_t<const void*, const void*> *p;
+        if (!l->feature_idx_tag_map->has (feature_index, &p))
+          return_trace (false);
+        auto *o = out->substitutions.serialize_append (c->serializer);
+        if (!o->serialize (l, feature_index,
+                           reinterpret_cast<const Feature*> (p->first),
+                           reinterpret_cast<const Tag*> (p->second)))
+          return_trace (false);
+      }
+      return_trace (true);
+    }
+
     + substitutions.iter ()
     | hb_apply (subset_record_array (l, &(out->substitutions), this))
     ;
@@ -3658,6 +4473,7 @@ struct FeatureTableSubstitution
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
+                  hb_barrier () &&
                   likely (version.major == 1) &&
                   substitutions.sanitize (c, this));
   }
@@ -3676,10 +4492,9 @@ struct FeatureVariationRecord
 
   void collect_lookups (const void     *base,
                         const hb_set_t *feature_indexes,
-                        const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
                         hb_set_t       *lookup_indexes /* OUT */) const
   {
-    return (base+substitutions).collect_lookups (feature_indexes, feature_substitutes_map, lookup_indexes);
+    return (base+substitutions).collect_lookups (feature_indexes, lookup_indexes);
   }
 
   void closure_features (const void     *base,
@@ -3705,14 +4520,15 @@ struct FeatureVariationRecord
     }
   }
 
-  bool subset (hb_subset_layout_context_t *c, const void *base) const
+  bool subset (hb_subset_layout_context_t *c, const void *base,
+               bool insert_catch_all = false) const
   {
     TRACE_SUBSET (this);
     auto *out = c->subset_context->serializer->embed (this);
     if (unlikely (!out)) return_trace (false);
 
-    out->conditions.serialize_subset (c->subset_context, conditions, base, c);
-    out->substitutions.serialize_subset (c->subset_context, substitutions, base, c);
+    out->conditions.serialize_subset (c->subset_context, conditions, base, c, insert_catch_all);
+    out->substitutions.serialize_subset (c->subset_context, substitutions, base, c, insert_catch_all);
 
     return_trace (true);
   }
@@ -3738,13 +4554,14 @@ struct FeatureVariations
   static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFFFFFu;
 
   bool find_index (const int *coords, unsigned int coord_len,
-                   unsigned int *index) const
+                   unsigned int *index,
+                   ItemVarStoreInstancer *instancer) const
   {
     unsigned int count = varRecords.len;
     for (unsigned int i = 0; i < count; i++)
     {
       const FeatureVariationRecord &record = varRecords.arrayZ[i];
-      if ((this+record.conditions).evaluate (coords, coord_len))
+      if ((this+record.conditions).evaluate (coords, coord_len, instancer))
       {
         *index = i;
         return true;
@@ -3771,9 +4588,8 @@ struct FeatureVariations
       if (c->universal)
         break;
     }
-    if (c->variation_applied && !c->universal &&
-        !c->record_cond_idx_map->is_empty ())
-      c->insert_catch_all_feature_variation_record = true;
+    if (c->universal || c->record_cond_idx_map->is_empty ())
+      c->catch_all_record_feature_idxes.reset ();
   }
 
   FeatureVariations* copy (hb_serialize_context_t *c) const
@@ -3783,11 +4599,17 @@ struct FeatureVariations
   }
 
   void collect_lookups (const hb_set_t *feature_indexes,
-                        const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
+                        const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
                         hb_set_t       *lookup_indexes /* OUT */) const
   {
-    for (const FeatureVariationRecord& r : varRecords)
-      r.collect_lookups (this, feature_indexes, feature_substitutes_map, lookup_indexes);
+    unsigned count = varRecords.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (feature_record_cond_idx_map &&
+          !feature_record_cond_idx_map->has (i))
+        continue;
+      varRecords[i].collect_lookups (this, feature_indexes, lookup_indexes);
+    }
   }
 
   void closure_features (const hb_map_t *lookup_indexes,
@@ -3832,6 +4654,13 @@ struct FeatureVariations
       l->cur_feature_var_record_idx = i;
       subset_record_array (l, &(out->varRecords), this) (varRecords[i]);
     }
+
+    if (out->varRecords.len && !l->catch_all_record_feature_idxes->is_empty ())
+    {
+      bool insert_catch_all_record = true;
+      subset_record_array (l, &(out->varRecords), this, insert_catch_all_record) (varRecords[0]);
+    }
+
     return_trace (bool (out->varRecords));
   }
 
@@ -3839,6 +4668,7 @@ struct FeatureVariations
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
+                  hb_barrier () &&
                   likely (version.major == 1) &&
                   varRecords.sanitize (c, this));
   }
@@ -3945,13 +4775,13 @@ struct VariationDevice
   private:
 
   hb_position_t get_x_delta (hb_font_t *font,
-                             const VariationStore &store,
-                             VariationStore::cache_t *store_cache = nullptr) const
+                             const ItemVariationStore &store,
+                             ItemVariationStore::cache_t *store_cache = nullptr) const
   { return font->em_scalef_x (get_delta (font, store, store_cache)); }
 
   hb_position_t get_y_delta (hb_font_t *font,
-                             const VariationStore &store,
-                             VariationStore::cache_t *store_cache = nullptr) const
+                             const ItemVariationStore &store,
+                             ItemVariationStore::cache_t *store_cache = nullptr) const
   { return font->em_scalef_y (get_delta (font, store, store_cache)); }
 
   VariationDevice* copy (hb_serialize_context_t *c,
@@ -3985,14 +4815,14 @@ struct VariationDevice
   private:
 
   float get_delta (hb_font_t *font,
-                   const VariationStore &store,
-                   VariationStore::cache_t *store_cache = nullptr) const
+                   const ItemVariationStore &store,
+                   ItemVariationStore::cache_t *store_cache = nullptr) const
   {
-    return store.get_delta (varIdx, font->coords, font->num_coords, (VariationStore::cache_t *) store_cache);
+    return store.get_delta (varIdx, font->coords, font->num_coords, (ItemVariationStore::cache_t *) store_cache);
   }
 
   protected:
-  VarIdx        varIdx;
+  VarIdx        varIdx;         /* Variation index */
   HBUINT16      deltaFormat;    /* Format identifier for this table: 0x0x8000 */
   public:
   DEFINE_SIZE_STATIC (6);
@@ -4012,8 +4842,8 @@ struct DeviceHeader
 struct Device
 {
   hb_position_t get_x_delta (hb_font_t *font,
-                             const VariationStore &store=Null (VariationStore),
-                             VariationStore::cache_t *store_cache = nullptr) const
+                             const ItemVariationStore &store=Null (ItemVariationStore),
+                             ItemVariationStore::cache_t *store_cache = nullptr) const
   {
     switch (u.b.format)
     {
@@ -4030,8 +4860,8 @@ struct Device
     }
   }
   hb_position_t get_y_delta (hb_font_t *font,
-                             const VariationStore &store=Null (VariationStore),
-                             VariationStore::cache_t *store_cache = nullptr) const
+                             const ItemVariationStore &store=Null (ItemVariationStore),
+                             ItemVariationStore::cache_t *store_cache = nullptr) const
   {
     switch (u.b.format)
     {
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh	2025-06-27 08:03:14.000000000 +0000
@@ -406,6 +406,7 @@ struct hb_ot_apply_context_t :
 
     void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
     void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
+    void set_ignore_hidden (bool ignore_hidden_) { ignore_hidden = ignore_hidden_; }
     void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
     void set_mask (hb_mask_t mask_) { mask = mask_; }
     void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; }
@@ -451,9 +452,10 @@ struct hb_ot_apply_context_t :
       if (!c->check_glyph_property (&info, lookup_props))
         return SKIP_YES;
 
-      if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) &&
+      if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
                     (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
-                    (ignore_zwj || !_hb_glyph_info_is_zwj (&info))))
+                    (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) &&
+                    (ignore_hidden || !_hb_glyph_info_is_hidden (&info))))
         return SKIP_MAYBE;
 
       return SKIP_NO;
@@ -464,6 +466,7 @@ struct hb_ot_apply_context_t :
     hb_mask_t mask = -1;
     bool ignore_zwnj = false;
     bool ignore_zwj = false;
+    bool ignore_hidden = false;
     bool per_syllable = false;
     uint8_t syllable = 0;
     match_func_t match_func = nullptr;
@@ -486,6 +489,8 @@ struct hb_ot_apply_context_t :
       matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj));
       /* Ignore ZWJ if we are matching context, or asked to. */
       matcher.set_ignore_zwj  (context_match || c->auto_zwj);
+      /* Ignore hidden glyphs (like CGJ) during GPOS. */
+      matcher.set_ignore_hidden (c->table_index == 1);
       matcher.set_mask (context_match ? -1 : c->lookup_mask);
       /* Per syllable matching is only for GSUB. */
       matcher.set_per_syllable (c->table_index == 0 && c->per_syllable);
@@ -708,8 +713,9 @@ struct hb_ot_apply_context_t :
   recurse_func_t recurse_func = nullptr;
   const GDEF &gdef;
   const GDEF::accelerator_t &gdef_accel;
-  const VariationStore &var_store;
-  VariationStore::cache_t *var_store_cache;
+  const hb_ot_layout_lookup_accelerator_t *lookup_accel = nullptr;
+  const ItemVariationStore &var_store;
+  ItemVariationStore::cache_t *var_store_cache;
   hb_set_digest_t digest;
 
   hb_direction_t direction;
@@ -723,7 +729,6 @@ struct hb_ot_apply_context_t :
   bool auto_zwj = true;
   bool per_syllable = false;
   bool random = false;
-  uint32_t random_state = 1;
   unsigned new_syllables = (unsigned) -1;
 
   signed last_base = -1; // GPOS uses
@@ -758,15 +763,17 @@ struct hb_ot_apply_context_t :
                                          nullptr
 #endif
                                         ),
-                        digest (buffer_->digest ()),
                         direction (buffer_->props.direction),
                         has_glyph_classes (gdef.has_glyph_classes ())
-  { init_iters (); }
+  {
+    init_iters ();
+    buffer->collect_codepoints (digest);
+  }
 
   ~hb_ot_apply_context_t ()
   {
 #ifndef HB_NO_VAR
-    VariationStore::destroy_cache (var_store_cache);
+    ItemVariationStore::destroy_cache (var_store_cache);
 #endif
   }
 
@@ -788,8 +795,8 @@ struct hb_ot_apply_context_t :
   uint32_t random_number ()
   {
     /* http://www.cplusplus.com/reference/random/minstd_rand/ */
-    random_state = random_state * 48271 % 2147483647;
-    return random_state;
+    buffer->random_state = buffer->random_state * 48271 % 2147483647;
+    return buffer->random_state;
   }
 
   bool match_properties_mark (hb_codepoint_t  glyph,
@@ -895,6 +902,13 @@ struct hb_ot_apply_context_t :
   }
 };
 
+enum class hb_ot_lookup_cache_op_t
+{
+  CREATE,
+  ENTER,
+  LEAVE,
+  DESTROY,
+};
 
 struct hb_accelerate_subtables_context_t :
        hb_dispatch_context_t<hb_accelerate_subtables_context_t>
@@ -919,19 +933,23 @@ struct hb_accelerate_subtables_context_t
   }
 
   template <typename T>
-  static inline auto cache_func_ (const T *obj, hb_ot_apply_context_t *c, bool enter, hb_priority<1>) HB_RETURN (bool, obj->cache_func (c, enter) )
-  template <typename T>
-  static inline bool cache_func_ (const T *obj, hb_ot_apply_context_t *c, bool enter, hb_priority<0>) { return false; }
+  static inline auto cache_func_ (void *p,
+                                  hb_ot_lookup_cache_op_t op,
+                                  hb_priority<1>) HB_RETURN (void *, T::cache_func (p, op) )
+  template <typename T=void>
+  static inline void * cache_func_ (void *p,
+                                    hb_ot_lookup_cache_op_t op HB_UNUSED,
+                                    hb_priority<0>) { return (void *) false; }
   template <typename Type>
-  static inline bool cache_func_to (const void *obj, hb_ot_apply_context_t *c, bool enter)
+  static inline void * cache_func_to (void *p,
+                                      hb_ot_lookup_cache_op_t op)
   {
-    const Type *typed_obj = (const Type *) obj;
-    return cache_func_ (typed_obj, c, enter, hb_prioritize);
+    return cache_func_<Type> (p, op, hb_prioritize);
   }
 #endif
 
   typedef bool (*hb_apply_func_t) (const void *obj, hb_ot_apply_context_t *c);
-  typedef bool (*hb_cache_func_t) (const void *obj, hb_ot_apply_context_t *c, bool enter);
+  typedef void * (*hb_cache_func_t) (void *p, hb_ot_lookup_cache_op_t op);
 
   struct hb_applicable_t
   {
@@ -968,11 +986,11 @@ struct hb_accelerate_subtables_context_t
     }
     bool cache_enter (hb_ot_apply_context_t *c) const
     {
-      return cache_func (obj, c, true);
+      return (bool) cache_func (c, hb_ot_lookup_cache_op_t::ENTER);
     }
     void cache_leave (hb_ot_apply_context_t *c) const
     {
-      cache_func (obj, c, false);
+      cache_func (c, hb_ot_lookup_cache_op_t::LEAVE);
     }
 #endif
 
@@ -1255,7 +1273,7 @@ static bool match_input (hb_ot_apply_con
                          match_func_t match_func,
                          const void *match_data,
                          unsigned int *end_position,
-                         unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
+                         unsigned int *match_positions,
                          unsigned int *p_total_component_count = nullptr)
 {
   TRACE_APPLY (nullptr);
@@ -1379,7 +1397,7 @@ static bool match_input (hb_ot_apply_con
 }
 static inline bool ligate_input (hb_ot_apply_context_t *c,
                                  unsigned int count, /* Including the first glyph */
-                                 const unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
+                                 const unsigned int *match_positions, /* Including the first glyph */
                                  unsigned int match_end,
                                  hb_codepoint_t lig_glyph,
                                  unsigned int total_component_count)
@@ -1458,6 +1476,7 @@ static inline bool ligate_input (hb_ot_a
         unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
         if (this_comp == 0)
           this_comp = last_num_components;
+        assert (components_so_far >= last_num_components);
         unsigned int new_lig_comp = components_so_far - last_num_components +
                                     hb_min (this_comp, last_num_components);
           _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
@@ -1483,6 +1502,7 @@ static inline bool ligate_input (hb_ot_a
       unsigned this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
       if (!this_comp) break;
 
+      assert (components_so_far >= last_num_components);
       unsigned new_lig_comp = components_so_far - last_num_components +
                               hb_min (this_comp, last_num_components);
       _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
@@ -1538,6 +1558,7 @@ static bool match_lookahead (hb_ot_apply
   TRACE_APPLY (nullptr);
 
   hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
+  assert (start_index >= 1);
   skippy_iter.reset (start_index - 1);
   skippy_iter.set_match_func (match_func, match_data);
   skippy_iter.set_glyph_data (lookahead);
@@ -1687,7 +1708,7 @@ static inline void recurse_lookups (cont
 
 static inline void apply_lookup (hb_ot_apply_context_t *c,
                                  unsigned int count, /* Including the first glyph */
-                                 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
+                                 unsigned int *match_positions, /* Including the first glyph */
                                  unsigned int lookupCount,
                                  const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
                                  unsigned int match_end)
@@ -1695,6 +1716,9 @@ static inline void apply_lookup (hb_ot_a
   hb_buffer_t *buffer = c->buffer;
   int end;
 
+  unsigned int *match_positions_input = match_positions;
+  unsigned int match_positions_count = count;
+
   /* All positions are distance from beginning of *output* buffer.
    * Adjust. */
   {
@@ -1798,6 +1822,27 @@ static inline void apply_lookup (hb_ot_a
     {
       if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
         break;
+      if (unlikely (delta + count > match_positions_count))
+      {
+        unsigned new_match_positions_count = hb_max (delta + count, hb_max(match_positions_count, 4u) * 1.5);
+        if (match_positions == match_positions_input)
+        {
+          match_positions = (unsigned int *) hb_malloc (new_match_positions_count * sizeof (match_positions[0]));
+          if (unlikely (!match_positions))
+            break;
+          memcpy (match_positions, match_positions_input, count * sizeof (match_positions[0]));
+          match_positions_count = new_match_positions_count;
+        }
+        else
+        {
+          unsigned int *new_match_positions = (unsigned int *) hb_realloc (match_positions, new_match_positions_count * sizeof (match_positions[0]));
+          if (unlikely (!new_match_positions))
+            break;
+          match_positions = new_match_positions;
+          match_positions_count = new_match_positions_count;
+        }
+      }
+
     }
     else
     {
@@ -1821,6 +1866,10 @@ static inline void apply_lookup (hb_ot_a
       match_positions[next] += delta;
   }
 
+  if (match_positions != match_positions_input)
+    hb_free (match_positions);
+
+  assert (end >= 0);
   (void) buffer->move_to (end);
 }
 
@@ -1921,8 +1970,18 @@ static bool context_apply_lookup (hb_ot_
                                   const LookupRecord lookupRecord[],
                                   const ContextApplyLookupContext &lookup_context)
 {
+  if (unlikely (inputCount > HB_MAX_CONTEXT_LENGTH)) return false;
+  unsigned match_positions_stack[4];
+  unsigned *match_positions = match_positions_stack;
+  if (unlikely (inputCount > ARRAY_LENGTH (match_positions_stack)))
+  {
+    match_positions = (unsigned *) hb_malloc (hb_max (inputCount, 1u) * sizeof (match_positions[0]));
+    if (unlikely (!match_positions))
+      return false;
+  }
+
   unsigned match_end = 0;
-  unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
+  bool ret = false;
   if (match_input (c,
                    inputCount, input,
                    lookup_context.funcs.match, lookup_context.match_data,
@@ -1933,13 +1992,18 @@ static bool context_apply_lookup (hb_ot_
                   inputCount, match_positions,
                   lookupCount, lookupRecord,
                   match_end);
-    return true;
+    ret = true;
   }
   else
   {
     c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
-    return false;
+    ret = false;
   }
+
+  if (unlikely (match_positions != match_positions_stack))
+    hb_free (match_positions);
+
+  return ret;
 }
 
 template <typename Types>
@@ -2051,6 +2115,7 @@ struct Rule
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   c->check_range (inputZ.arrayZ,
                                   inputZ.item_size * (inputCount ? inputCount - 1 : 0) +
                                   LookupRecord::static_size * lookupCount));
@@ -2572,25 +2637,35 @@ struct ContextFormat2_5
     unsigned c = (this+classDef).cost () * ruleSet.len;
     return c >= 4 ? c : 0;
   }
-  bool cache_func (hb_ot_apply_context_t *c, bool enter) const
+  static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
   {
-    if (enter)
+    switch (op)
     {
-      if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
-        return false;
-      auto &info = c->buffer->info;
-      unsigned count = c->buffer->len;
-      for (unsigned i = 0; i < count; i++)
-        info[i].syllable() = 255;
-      c->new_syllables = 255;
-      return true;
-    }
-    else
-    {
-      c->new_syllables = (unsigned) -1;
-      HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
-      return true;
+      case hb_ot_lookup_cache_op_t::CREATE:
+        return (void *) true;
+      case hb_ot_lookup_cache_op_t::ENTER:
+      {
+        hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p;
+        if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
+          return (void *) false;
+        auto &info = c->buffer->info;
+        unsigned count = c->buffer->len;
+        for (unsigned i = 0; i < count; i++)
+          info[i].syllable() = 255;
+        c->new_syllables = 255;
+        return (void *) true;
+      }
+      case hb_ot_lookup_cache_op_t::LEAVE:
+      {
+        hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p;
+        c->new_syllables = (unsigned) -1;
+        HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
+        return nullptr;
+      }
+      case hb_ot_lookup_cache_op_t::DESTROY:
+        return nullptr;
     }
+    return nullptr;
   }
 
   bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
@@ -2599,7 +2674,7 @@ struct ContextFormat2_5
   {
     TRACE_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
+    if (index == NOT_COVERED) return_trace (false);
 
     const ClassDef &class_def = this+classDef;
 
@@ -2785,7 +2860,7 @@ struct ContextFormat3
   {
     TRACE_APPLY (this);
     unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
+    if (index == NOT_COVERED) return_trace (false);
 
     const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
     struct ContextApplyLookupContext lookup_context = {
@@ -2826,6 +2901,7 @@ struct ContextFormat3
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this))) return_trace (false);
+    hb_barrier ();
     unsigned int count = glyphCount;
     if (unlikely (!count)) return_trace (false); /* We want to access coverageZ[0] freely. */
     if (unlikely (!c->check_array (coverageZ.arrayZ, count))) return_trace (false);
@@ -2858,12 +2934,12 @@ struct Context
     if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
     TRACE_DISPATCH (this, u.format);
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
-    case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
-    case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
 #ifndef HB_NO_BEYOND_64K
-    case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
-    case 5: return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
+    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
 #endif
     default:return_trace (c->default_return_value ());
     }
@@ -3017,9 +3093,20 @@ static bool chain_context_apply_lookup (
                                         const LookupRecord lookupRecord[],
                                         const ChainContextApplyLookupContext &lookup_context)
 {
+  if (unlikely (inputCount > HB_MAX_CONTEXT_LENGTH)) return false;
+  unsigned match_positions_stack[4];
+  unsigned *match_positions = match_positions_stack;
+  if (unlikely (inputCount > ARRAY_LENGTH (match_positions_stack)))
+  {
+    match_positions = (unsigned *) hb_malloc (hb_max (inputCount, 1u) * sizeof (match_positions[0]));
+    if (unlikely (!match_positions))
+      return false;
+  }
+
+  unsigned start_index = c->buffer->out_len;
   unsigned end_index = c->buffer->idx;
   unsigned match_end = 0;
-  unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
+  bool ret = true;
   if (!(match_input (c,
                      inputCount, input,
                      lookup_context.funcs.match[1], lookup_context.match_data[1],
@@ -3030,17 +3117,18 @@ static bool chain_context_apply_lookup (
                            match_end, &end_index)))
   {
     c->buffer->unsafe_to_concat (c->buffer->idx, end_index);
-    return false;
+    ret = false;
+    goto done;
   }
 
-  unsigned start_index = c->buffer->out_len;
   if (!match_backtrack (c,
                         backtrackCount, backtrack,
                         lookup_context.funcs.match[0], lookup_context.match_data[0],
                         &start_index))
   {
     c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
-    return false;
+    ret = false;
+    goto done;
   }
 
   c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
@@ -3048,7 +3136,12 @@ static bool chain_context_apply_lookup (
                 inputCount, match_positions,
                 lookupCount, lookupRecord,
                 match_end);
-  return true;
+  done:
+
+  if (unlikely (match_positions != match_positions_stack))
+    hb_free (match_positions);
+
+  return ret;
 }
 
 template <typename Types>
@@ -3219,10 +3312,13 @@ struct ChainRule
     TRACE_SANITIZE (this);
     /* Hyper-optimized sanitized because this is really hot. */
     if (unlikely (!backtrack.len.sanitize (c))) return_trace (false);
+    hb_barrier ();
     const auto &input = StructAfter<decltype (inputX)> (backtrack);
     if (unlikely (!input.lenP1.sanitize (c))) return_trace (false);
+    hb_barrier ();
     const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
     if (unlikely (!lookahead.len.sanitize (c))) return_trace (false);
+    hb_barrier ();
     const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
     return_trace (likely (lookup.sanitize (c)));
   }
@@ -3327,6 +3423,15 @@ struct ChainRuleSet
      *
      * Replicated from LigatureSet::apply(). */
 
+    /* If the input skippy has non-auto joiners behavior (as in Indic shapers),
+     * skip this fast path, as we don't distinguish between input & lookahead
+     * matching in the fast path.
+     *
+     * https://github.com/harfbuzz/harfbuzz/issues/4813
+     */
+    if (!c->auto_zwnj || !c->auto_zwj)
+      goto slow;
+
     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (c->buffer->idx);
     skippy_iter.set_match_func (match_always, nullptr);
@@ -3366,10 +3471,10 @@ struct ChainRuleSet
     }
     matched = skippy_iter.next ();
     if (likely (matched && !skippy_iter.may_skip (c->buffer->info[skippy_iter.idx])))
-     {
+    {
       second = &c->buffer->info[skippy_iter.idx];
       unsafe_to2 = skippy_iter.idx + 1;
-     }
+    }
 
     auto match_input = lookup_context.funcs.match[1];
     auto match_lookahead = lookup_context.funcs.match[2];
@@ -3569,7 +3674,7 @@ struct ChainContextFormat1_4
   {
     TRACE_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
+    if (index == NOT_COVERED) return_trace (false);
 
     const ChainRuleSet &rule_set = this+ruleSet[index];
     struct ChainContextApplyLookupContext lookup_context = {
@@ -3780,28 +3885,37 @@ struct ChainContextFormat2_5
 
   unsigned cache_cost () const
   {
-    unsigned c = (this+lookaheadClassDef).cost () * ruleSet.len;
-    return c >= 4 ? c : 0;
+    return (this+lookaheadClassDef).cost () * ruleSet.len;
   }
-  bool cache_func (hb_ot_apply_context_t *c, bool enter) const
+  static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
   {
-    if (enter)
+    switch (op)
     {
-      if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
-        return false;
-      auto &info = c->buffer->info;
-      unsigned count = c->buffer->len;
-      for (unsigned i = 0; i < count; i++)
-        info[i].syllable() = 255;
-      c->new_syllables = 255;
-      return true;
-    }
-    else
-    {
-      c->new_syllables = (unsigned) -1;
-      HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
-      return true;
+      case hb_ot_lookup_cache_op_t::CREATE:
+        return (void *) true;
+      case hb_ot_lookup_cache_op_t::ENTER:
+      {
+        hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p;
+        if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
+          return (void *) false;
+        auto &info = c->buffer->info;
+        unsigned count = c->buffer->len;
+        for (unsigned i = 0; i < count; i++)
+          info[i].syllable() = 255;
+        c->new_syllables = 255;
+        return (void *) true;
+      }
+      case hb_ot_lookup_cache_op_t::LEAVE:
+      {
+        hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p;
+        c->new_syllables = (unsigned) -1;
+        HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
+        return nullptr;
+      }
+      case hb_ot_lookup_cache_op_t::DESTROY:
+        return nullptr;
     }
+    return nullptr;
   }
 
   bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
@@ -3810,7 +3924,7 @@ struct ChainContextFormat2_5
   {
     TRACE_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
+    if (index == NOT_COVERED) return_trace (false);
 
     const ClassDef &backtrack_class_def = this+backtrackClassDef;
     const ClassDef &input_class_def = this+inputClassDef;
@@ -4056,7 +4170,7 @@ struct ChainContextFormat3
     const auto &input = StructAfter<decltype (inputX)> (backtrack);
 
     unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
+    if (index == NOT_COVERED) return_trace (false);
 
     const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
     const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
@@ -4121,11 +4235,14 @@ struct ChainContextFormat3
   {
     TRACE_SANITIZE (this);
     if (unlikely (!backtrack.sanitize (c, this))) return_trace (false);
+    hb_barrier ();
     const auto &input = StructAfter<decltype (inputX)> (backtrack);
     if (unlikely (!input.sanitize (c, this))) return_trace (false);
+    hb_barrier ();
     if (unlikely (!input.len)) return_trace (false); /* To be consistent with Context. */
     const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
     if (unlikely (!lookahead.sanitize (c, this))) return_trace (false);
+    hb_barrier ();
     const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
     return_trace (likely (lookup.sanitize (c)));
   }
@@ -4159,12 +4276,12 @@ struct ChainContext
     if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
     TRACE_DISPATCH (this, u.format);
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
-    case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
-    case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
 #ifndef HB_NO_BEYOND_64K
-    case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
-    case 5: return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
+    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
 #endif
     default:return_trace (c->default_return_value ());
     }
@@ -4209,6 +4326,7 @@ struct ExtensionFormat1
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   extensionLookupType != T::SubTable::Extension);
   }
 
@@ -4247,7 +4365,7 @@ struct Extension
   unsigned int get_type () const
   {
     switch (u.format) {
-    case 1: return u.format1.get_type ();
+    case 1: hb_barrier (); return u.format1.get_type ();
     default:return 0;
     }
   }
@@ -4255,7 +4373,7 @@ struct Extension
   const X& get_subtable () const
   {
     switch (u.format) {
-    case 1: return u.format1.template get_subtable<typename T::SubTable> ();
+    case 1: hb_barrier (); return u.format1.template get_subtable<typename T::SubTable> ();
     default:return Null (typename T::SubTable);
     }
   }
@@ -4267,7 +4385,7 @@ struct Extension
   typename hb_subset_context_t::return_t dispatch (hb_subset_context_t *c, Ts&&... ds) const
   {
     switch (u.format) {
-    case 1: return u.format1.subset (c);
+    case 1: hb_barrier (); return u.format1.subset (c);
     default: return c->default_return_value ();
     }
   }
@@ -4278,7 +4396,7 @@ struct Extension
     if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
     TRACE_DISPATCH (this, u.format);
     switch (u.format) {
-    case 1: return_trace (u.format1.dispatch (c, std::forward<Ts> (ds)...));
+    case 1: hb_barrier (); return_trace (u.format1.dispatch (c, std::forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -4320,10 +4438,21 @@ struct hb_ot_layout_lookup_accelerator_t
 
     thiz->digest.init ();
     for (auto& subtable : hb_iter (thiz->subtables, count))
-      thiz->digest.add (subtable.digest);
+      thiz->digest.union_ (subtable.digest);
 
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+    if (c_accelerate_subtables.cache_user_cost < 4)
+      c_accelerate_subtables.cache_user_idx = (unsigned) -1;
+
     thiz->cache_user_idx = c_accelerate_subtables.cache_user_idx;
+
+    if (thiz->cache_user_idx != (unsigned) -1)
+    {
+      thiz->cache = thiz->subtables[thiz->cache_user_idx].cache_func (nullptr, hb_ot_lookup_cache_op_t::CREATE);
+      if (!thiz->cache)
+        thiz->cache_user_idx = (unsigned) -1;
+    }
+
     for (unsigned i = 0; i < count; i++)
       if (i != thiz->cache_user_idx)
         thiz->subtables[i].apply_cached_func = thiz->subtables[i].apply_func;
@@ -4332,6 +4461,17 @@ struct hb_ot_layout_lookup_accelerator_t
     return thiz;
   }
 
+  void fini ()
+  {
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+    if (cache)
+    {
+      assert (cache_user_idx != (unsigned) -1);
+      subtables[cache_user_idx].cache_func (cache, hb_ot_lookup_cache_op_t::DESTROY);
+    }
+#endif
+  }
+
   bool may_have (hb_codepoint_t g) const
   { return digest.may_have (g); }
 
@@ -4340,6 +4480,7 @@ struct hb_ot_layout_lookup_accelerator_t
 #endif
   bool apply (hb_ot_apply_context_t *c, unsigned subtables_count, bool use_cache) const
   {
+    c->lookup_accel = this;
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
     if (use_cache)
     {
@@ -4379,10 +4520,13 @@ struct hb_ot_layout_lookup_accelerator_t
 
 
   hb_set_digest_t digest;
-  private:
 #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+  public:
+  void *cache = nullptr;
+  private:
   unsigned cache_user_idx = (unsigned) -1;
 #endif
+  private:
   hb_accelerate_subtables_context_t::hb_applicable_t subtables[HB_VAR_ARRAY];
 };
 
@@ -4472,13 +4616,6 @@ struct GSUBGPOSVersion1_2
       if (!c->subset_context->serializer->extend_min (&out->featureVars))
         return_trace (false);
 
-      // TODO(qxliu76): the current implementation doesn't correctly handle feature variations
-      //                that are dropped by instancing when the associated conditions don't trigger.
-      //                Since partial instancing isn't yet supported this isn't an issue yet but will
-      //                need to be fixed for partial instancing.
-
-
-
       // if all axes are pinned all feature vars are dropped.
       bool ret = !c->subset_context->plan->all_axes_pinned
                  && out->featureVars.serialize_subset (c->subset_context, featureVars, this, c);
@@ -4500,9 +4637,9 @@ struct GSUBGPOS
   unsigned int get_size () const
   {
     switch (u.version.major) {
-    case 1: return u.version1.get_size ();
+    case 1: hb_barrier (); return u.version1.get_size ();
 #ifndef HB_NO_BEYOND_64K
-    case 2: return u.version2.get_size ();
+    case 2: hb_barrier (); return u.version2.get_size ();
 #endif
     default: return u.version.static_size;
     }
@@ -4513,10 +4650,11 @@ struct GSUBGPOS
   {
     TRACE_SANITIZE (this);
     if (unlikely (!u.version.sanitize (c))) return_trace (false);
+    hb_barrier ();
     switch (u.version.major) {
-    case 1: return_trace (u.version1.sanitize<TLookup> (c));
+    case 1: hb_barrier (); return_trace (u.version1.sanitize<TLookup> (c));
 #ifndef HB_NO_BEYOND_64K
-    case 2: return_trace (u.version2.sanitize<TLookup> (c));
+    case 2: hb_barrier (); return_trace (u.version2.sanitize<TLookup> (c));
 #endif
     default: return_trace (true);
     }
@@ -4526,9 +4664,9 @@ struct GSUBGPOS
   bool subset (hb_subset_layout_context_t *c) const
   {
     switch (u.version.major) {
-    case 1: return u.version1.subset<TLookup> (c);
+    case 1: hb_barrier (); return u.version1.subset<TLookup> (c);
 #ifndef HB_NO_BEYOND_64K
-    case 2: return u.version2.subset<TLookup> (c);
+    case 2: hb_barrier (); return u.version2.subset<TLookup> (c);
 #endif
     default: return false;
     }
@@ -4537,9 +4675,9 @@ struct GSUBGPOS
   const ScriptList &get_script_list () const
   {
     switch (u.version.major) {
-    case 1: return this+u.version1.scriptList;
+    case 1: hb_barrier (); return this+u.version1.scriptList;
 #ifndef HB_NO_BEYOND_64K
-    case 2: return this+u.version2.scriptList;
+    case 2: hb_barrier (); return this+u.version2.scriptList;
 #endif
     default: return Null (ScriptList);
     }
@@ -4547,9 +4685,9 @@ struct GSUBGPOS
   const FeatureList &get_feature_list () const
   {
     switch (u.version.major) {
-    case 1: return this+u.version1.featureList;
+    case 1: hb_barrier (); return this+u.version1.featureList;
 #ifndef HB_NO_BEYOND_64K
-    case 2: return this+u.version2.featureList;
+    case 2: hb_barrier (); return this+u.version2.featureList;
 #endif
     default: return Null (FeatureList);
     }
@@ -4557,9 +4695,9 @@ struct GSUBGPOS
   unsigned int get_lookup_count () const
   {
     switch (u.version.major) {
-    case 1: return (this+u.version1.lookupList).len;
+    case 1: hb_barrier (); return (this+u.version1.lookupList).len;
 #ifndef HB_NO_BEYOND_64K
-    case 2: return (this+u.version2.lookupList).len;
+    case 2: hb_barrier (); return (this+u.version2.lookupList).len;
 #endif
     default: return 0;
     }
@@ -4567,9 +4705,9 @@ struct GSUBGPOS
   const Lookup& get_lookup (unsigned int i) const
   {
     switch (u.version.major) {
-    case 1: return (this+u.version1.lookupList)[i];
+    case 1: hb_barrier (); return (this+u.version1.lookupList)[i];
 #ifndef HB_NO_BEYOND_64K
-    case 2: return (this+u.version2.lookupList)[i];
+    case 2: hb_barrier (); return (this+u.version2.lookupList)[i];
 #endif
     default: return Null (Lookup);
     }
@@ -4577,9 +4715,9 @@ struct GSUBGPOS
   const FeatureVariations &get_feature_variations () const
   {
     switch (u.version.major) {
-    case 1: return (u.version.to_int () >= 0x00010001u ? this+u.version1.featureVars : Null (FeatureVariations));
+    case 1: hb_barrier (); return (u.version.to_int () >= 0x00010001u && hb_barrier () ? this+u.version1.featureVars : Null (FeatureVariations));
 #ifndef HB_NO_BEYOND_64K
-    case 2: return this+u.version2.featureVars;
+    case 2: hb_barrier (); return this+u.version2.featureVars;
 #endif
     default: return Null (FeatureVariations);
     }
@@ -4613,13 +4751,14 @@ struct GSUBGPOS
   { return get_feature_list ().find_index (tag, index); }
 
   bool find_variations_index (const int *coords, unsigned int num_coords,
-                              unsigned int *index) const
+                              unsigned int *index,
+                              ItemVarStoreInstancer *instancer) const
   {
 #ifdef HB_NO_VAR
     *index = FeatureVariations::NOT_FOUND_INDEX;
     return false;
 #endif
-    return get_feature_variations ().find_index (coords, num_coords, index);
+    return get_feature_variations ().find_index (coords, num_coords, index, instancer);
   }
   const Feature& get_feature_variation (unsigned int feature_index,
                                         unsigned int variations_index) const
@@ -4638,11 +4777,11 @@ struct GSUBGPOS
   }
 
   void feature_variation_collect_lookups (const hb_set_t *feature_indexes,
-                                          const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
+                                          const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
                                           hb_set_t       *lookup_indexes /* OUT */) const
   {
 #ifndef HB_NO_VAR
-    get_feature_variations ().collect_lookups (feature_indexes, feature_substitutes_map, lookup_indexes);
+    get_feature_variations ().collect_lookups (feature_indexes, feature_record_cond_idx_map, lookup_indexes);
 #endif
   }
 
@@ -4772,7 +4911,12 @@ struct GSUBGPOS
     ~accelerator_t ()
     {
       for (unsigned int i = 0; i < this->lookup_count; i++)
-        hb_free (this->accels[i]);
+      {
+        auto *accel = this->accels[i].get_relaxed ();
+        if (accel)
+          accel->fini ();
+        hb_free (accel);
+      }
       hb_free (this->accels);
       this->table.destroy ();
     }
@@ -4793,6 +4937,7 @@ struct GSUBGPOS
 
         if (unlikely (!accels[lookup_index].cmpexch (nullptr, accel)))
         {
+          accel->fini ();
           hb_free (accel);
           goto retry;
         }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-jstf-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-jstf-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-jstf-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-jstf-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -214,6 +214,7 @@ struct JSTF
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
+                  hb_barrier () &&
                   likely (version.major == 1) &&
                   scriptList.sanitize (c, this));
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc	2025-06-27 08:03:14.000000000 +0000
@@ -87,7 +87,7 @@ using OT::Layout::GPOS;
 bool
 hb_ot_layout_has_kerning (hb_face_t *face)
 {
-  return face->table.kern->has_data ();
+  return face->table.kern->table->has_data ();
 }
 
 /**
@@ -103,7 +103,7 @@ hb_ot_layout_has_kerning (hb_face_t *fac
 bool
 hb_ot_layout_has_machine_kerning (hb_face_t *face)
 {
-  return face->table.kern->has_state_machine ();
+  return face->table.kern->table->has_state_machine ();
 }
 
 /**
@@ -123,7 +123,7 @@ hb_ot_layout_has_machine_kerning (hb_fac
 bool
 hb_ot_layout_has_cross_kerning (hb_face_t *face)
 {
-  return face->table.kern->has_cross_stream ();
+  return face->table.kern->table->has_cross_stream ();
 }
 
 void
@@ -132,7 +132,7 @@ hb_ot_layout_kern (const hb_ot_shape_pla
                    hb_buffer_t  *buffer)
 {
   hb_blob_t *blob = font->face->table.kern.get_blob ();
-  const AAT::kern& kern = *blob->as<AAT::kern> ();
+  const auto& kern = *font->face->table.kern;
 
   AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
 
@@ -246,6 +246,18 @@ OT::GDEF::is_blocklisted (hb_blob_t *blo
     /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85  Padauk.ttf
      *  "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
     case HB_CODEPOINT_ENCODE3 (1004, 59092, 14836):
+    /* 88d2006ca084f04af2df1954ed714a8c71e8400f  Courier New.ttf from macOS 15 */
+    case HB_CODEPOINT_ENCODE3 (588, 5078, 14418):
+    /* 608e3ebb6dd1aee521cff08eb07d500a2c59df68  Courier New Bold.ttf from macOS 15 */
+    case HB_CODEPOINT_ENCODE3 (588, 5078, 14238):
+    /* d13221044ff054efd78f1cd8631b853c3ce85676  cour.ttf from Windows 10 */
+    case HB_CODEPOINT_ENCODE3 (894, 17162, 33960):
+    /* 68ed4a22d8067fcf1622ac6f6e2f4d3a2e3ec394  courbd.ttf from Windows 10 */
+    case HB_CODEPOINT_ENCODE3 (894, 17154, 34472):
+    /* 4cdb0259c96b7fd7c103821bb8f08f7cc6b211d7  cour.ttf from Windows 8.1 */
+    case HB_CODEPOINT_ENCODE3 (816, 7868, 17052):
+    /* 920483d8a8ed37f7f0afdabbe7f679aece7c75d8  courbd.ttf from Windows 8.1 */
+    case HB_CODEPOINT_ENCODE3 (816, 7868, 17138):
       return true;
   }
   return false;
@@ -1443,8 +1455,12 @@ hb_ot_layout_table_find_feature_variatio
                                             unsigned int *variations_index /* out */)
 {
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+  const OT::GDEF &gdef = *face->table.GDEF->table;
 
-  return g.find_variations_index (coords, num_coords, variations_index);
+  auto instancer = OT::ItemVarStoreInstancer(&gdef.get_var_store(), nullptr,
+                                             hb_array (coords, num_coords));
+
+  return g.find_variations_index (coords, num_coords, variations_index, &instancer);
 }
 
 
@@ -1907,9 +1923,10 @@ apply_forward (OT::hb_ot_apply_context_t
   while (buffer->idx < buffer->len && buffer->successful)
   {
     bool applied = false;
-    if (accel.digest.may_have (buffer->cur().codepoint) &&
-        (buffer->cur().mask & c->lookup_mask) &&
-        c->check_glyph_property (&buffer->cur(), c->lookup_props))
+    auto &cur = buffer->cur();
+    if (accel.digest.may_have (cur.codepoint) &&
+        (cur.mask & c->lookup_mask) &&
+        c->check_glyph_property (&cur, c->lookup_props))
      {
        applied = accel.apply (c, subtable_count, use_cache);
      }
@@ -1935,9 +1952,10 @@ apply_backward (OT::hb_ot_apply_context_
   hb_buffer_t *buffer = c->buffer;
   do
   {
-    if (accel.digest.may_have (buffer->cur().codepoint) &&
-        (buffer->cur().mask & c->lookup_mask) &&
-        c->check_glyph_property (&buffer->cur(), c->lookup_props))
+    auto &cur = buffer->cur();
+    if (accel.digest.may_have (cur.codepoint) &&
+        (cur.mask & c->lookup_mask) &&
+        c->check_glyph_property (&cur, c->lookup_props))
       ret |= accel.apply (c, subtable_count, false);
 
     /* The reverse lookup doesn't "advance" cursor (for good reason). */
@@ -2017,7 +2035,7 @@ inline void hb_ot_map_t::apply (const Pr
        * (plus some past glyphs).
        *
        * Only try applying the lookup if there is any overlap. */
-      if (accel->digest.may_have (c.digest))
+      if (accel->digest.may_intersect (c.digest))
       {
         c.set_lookup_index (lookup_index);
         c.set_lookup_mask (lookup.mask, false);
@@ -2043,7 +2061,7 @@ inline void hb_ot_map_t::apply (const Pr
       if (stage->pause_func (plan, font, buffer))
       {
         /* Refresh working buffer digest since buffer changed. */
-        c.digest = buffer->digest ();
+        buffer->collect_codepoints (c.digest);
       }
     }
   }
@@ -2127,7 +2145,7 @@ hb_ot_layout_get_font_extents (hb_font_t
                                hb_tag_t           language_tag,
                                hb_font_extents_t *extents)
 {
-  hb_position_t min, max;
+  hb_position_t min = 0, max = 0;
   if (font->face->table.BASE->get_min_max (font, direction, script_tag, language_tag, HB_TAG_NONE,
                                            &min, &max))
   {
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh	2025-06-27 08:03:14.000000000 +0000
@@ -173,12 +173,12 @@ _hb_next_syllable (hb_buffer_t *buffer,
 
 /* Design:
  * unicode_props() is a two-byte number.  The low byte includes:
- * - General_Category: 5 bits.
+ * - Modified General_Category: 5 bits.
  * - A bit each for:
  *   * Is it Default_Ignorable(); we have a modified Default_Ignorable().
  *   * Whether it's one of the four Mongolian Free Variation Selectors,
  *     CGJ, or other characters that are hidden but should not be ignored
- *     like most other Default_Ignorable()s do during matching.
+ *     like most other Default_Ignorable()s do during GSUB matching.
  *   * Whether it's a grapheme continuation.
  *
  * The high-byte has different meanings, switched by the Gen-Cat:
@@ -186,17 +186,23 @@ _hb_next_syllable (hb_buffer_t *buffer,
  * - For Cf: whether it's ZWJ, ZWNJ, or something else.
  * - For Ws: index of which space character this is, if space fallback
  *   is needed, ie. we don't set this by default, only if asked to.
+ *
+ * Above I said "modified" General_Category. This is because we need to
+ * remember Variation Selectors, and we don't have bits left. So we
+ * change their Gen_Cat from Mn to Cf, and use a bit of the high byte to
+ * remember them.
  */
 
 enum hb_unicode_props_flags_t {
   UPROPS_MASK_GEN_CAT   = 0x001Fu,
   UPROPS_MASK_IGNORABLE = 0x0020u,
-  UPROPS_MASK_HIDDEN    = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..4, or TAG characters */
+  UPROPS_MASK_HIDDEN    = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..4, or TAG characters, or CGJ sometimes */
   UPROPS_MASK_CONTINUATION=0x0080u,
 
   /* If GEN_CAT=FORMAT, top byte masks: */
   UPROPS_MASK_Cf_ZWJ    = 0x0100u,
-  UPROPS_MASK_Cf_ZWNJ   = 0x0200u
+  UPROPS_MASK_Cf_ZWNJ   = 0x0200u,
+  UPROPS_MASK_Cf_VS     = 0x0400u
 };
 HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
 
@@ -229,7 +235,7 @@ _hb_glyph_info_set_unicode_props (hb_gly
       /* TAG characters need similar treatment. Fixes:
        * https://github.com/harfbuzz/harfbuzz/issues/463 */
       else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
-      /* COMBINING GRAPHEME JOINER should not be skipped; at least some times.
+      /* COMBINING GRAPHEME JOINER should not be skipped during GSUB either.
        * https://github.com/harfbuzz/harfbuzz/issues/554 */
       else if (unlikely (u == 0x034Fu))
       {
@@ -302,6 +308,27 @@ _hb_glyph_info_get_unicode_space_fallbac
          (hb_unicode_funcs_t::space_t) (info->unicode_props()>>8) :
          hb_unicode_funcs_t::NOT_SPACE;
 }
+static inline bool
+_hb_glyph_info_is_variation_selector (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_get_general_category (info) ==
+         HB_UNICODE_GENERAL_CATEGORY_FORMAT &&
+         (info->unicode_props() & UPROPS_MASK_Cf_VS);
+}
+static inline void
+_hb_glyph_info_set_variation_selector (hb_glyph_info_t *info, bool customize)
+{
+  if (customize)
+  {
+    _hb_glyph_info_set_general_category (info, HB_UNICODE_GENERAL_CATEGORY_FORMAT);
+    info->unicode_props() |= UPROPS_MASK_Cf_VS;
+  }
+  else
+  {
+    // Reset to their original condition
+    _hb_glyph_info_set_general_category (info, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK);
+  }
+}
 
 static inline bool _hb_glyph_info_substituted (const hb_glyph_info_t *info);
 
@@ -311,12 +338,20 @@ _hb_glyph_info_is_default_ignorable (con
   return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
          !_hb_glyph_info_substituted (info);
 }
+static inline void
+_hb_glyph_info_set_default_ignorable (hb_glyph_info_t *info)
+{
+  info->unicode_props() |= UPROPS_MASK_IGNORABLE;
+}
+static inline void
+_hb_glyph_info_clear_default_ignorable (hb_glyph_info_t *info)
+{
+  info->unicode_props() &= ~ UPROPS_MASK_IGNORABLE;
+}
 static inline bool
-_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)
+_hb_glyph_info_is_hidden (const hb_glyph_info_t *info)
 {
-  return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
-          == UPROPS_MASK_IGNORABLE) &&
-         !_hb_glyph_info_substituted (info);
+  return info->unicode_props() & UPROPS_MASK_HIDDEN;
 }
 static inline void
 _hb_glyph_info_unhide (hb_glyph_info_t *info)
@@ -330,7 +365,7 @@ _hb_glyph_info_set_continuation (hb_glyp
   info->unicode_props() |= UPROPS_MASK_CONTINUATION;
 }
 static inline void
-_hb_glyph_info_reset_continuation (hb_glyph_info_t *info)
+_hb_glyph_info_clear_continuation (hb_glyph_info_t *info)
 {
   info->unicode_props() &= ~ UPROPS_MASK_CONTINUATION;
 }
@@ -603,8 +638,7 @@ _hb_buffer_assert_gsubgpos_vars (hb_buff
 }
 
 /* Make sure no one directly touches our props... */
-#undef unicode_props0
-#undef unicode_props1
+#undef unicode_props
 #undef lig_props
 #undef glyph_props
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-map.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-map.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-map.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-map.cc	2025-06-27 08:03:14.000000000 +0000
@@ -390,5 +390,19 @@ hb_ot_map_builder_t::compile (hb_ot_map_
   }
 }
 
+unsigned int hb_ot_map_t::get_feature_tags (unsigned int start_offset, unsigned int *tag_count, hb_tag_t *tags) const
+{
+  if (tag_count)
+  {
+    auto sub_features = features.as_array ().sub_array (start_offset, tag_count);
+    if (tags)
+    {
+      for (unsigned int i = 0; i < sub_features.length; i++)
+        tags[i] = sub_features[i].tag;
+    }
+  }
+
+  return features.length;
+}
 
 #endif
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-map.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-map.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-map.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-map.hh	2025-06-27 08:03:14.000000000 +0000
@@ -166,6 +166,9 @@ struct hb_ot_map_t
                           const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
   HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
   HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
+  HB_INTERNAL unsigned int get_feature_tags (unsigned int  start_offset,
+                                             unsigned int *tag_count, /* IN/OUT */
+                                             hb_tag_t     *tags /* OUT */) const;
 
   public:
   hb_tag_t chosen_script[2];
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -333,6 +333,7 @@ struct MathKern
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   c->check_array (mathValueRecordsZ.arrayZ, 2 * heightCount + 1) &&
                   sanitize_math_value_records (c));
   }
@@ -343,27 +344,20 @@ struct MathKern
     const MathValueRecord* kernValue = mathValueRecordsZ.arrayZ + heightCount;
     int sign = font->y_scale < 0 ? -1 : +1;
 
-    /* The description of the MathKern table is a ambiguous, but interpreting
-     * "between the two heights found at those indexes" for 0 < i < len as
-     *
-     *   correctionHeight[i-1] < correction_height <= correctionHeight[i]
-     *
-     * makes the result consistent with the limit cases and we can just use the
-     * binary search algorithm of std::upper_bound:
+    /* According to OpenType spec (v1.9), except for the boundary cases, the index
+     * chosen for kern value should be i such that
+     *    correctionHeight[i-1] <= correction_height < correctionHeight[i]
+     * We can use the binary search algorithm of std::upper_bound(). Or, we can
+     * use the internal hb_bsearch_impl.
      */
-    unsigned int i = 0;
-    unsigned int count = heightCount;
-    while (count > 0)
-    {
-      unsigned int half = count / 2;
-      hb_position_t height = correctionHeight[i + half].get_y_value (font, this);
-      if (sign * height < sign * correction_height)
-      {
-        i += half + 1;
-        count -= half + 1;
-      } else
-        count = half;
-    }
+    unsigned int pos;
+    auto cmp = +[](const void* key, const void* p,
+                   int sign, hb_font_t* font, const MathKern* mathKern) -> int {
+      return sign * *(hb_position_t*)key - sign * ((MathValueRecord*)p)->get_y_value(font, mathKern);
+    };
+    unsigned int i = hb_bsearch_impl(&pos, correction_height, correctionHeight,
+                                     heightCount, MathValueRecord::static_size,
+                                     cmp, sign, font, this) ? pos + 1 : pos;
     return kernValue[i].get_x_value (font, this);
   }
 
@@ -984,6 +978,7 @@ struct MathVariants
     return_trace (c->check_struct (this) &&
                   vertGlyphCoverage.sanitize (c, this) &&
                   horizGlyphCoverage.sanitize (c, this) &&
+                  hb_barrier () &&
                   c->check_array (glyphConstruction.arrayZ, vertGlyphCount + horizGlyphCount) &&
                   sanitize_offsets (c));
   }
@@ -1103,6 +1098,7 @@ struct MATH
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
                   likely (version.major == 1) &&
+                  hb_barrier () &&
                   mathConstants.sanitize (c, this) &&
                   mathGlyphInfo.sanitize (c, this) &&
                   mathVariants.sanitize (c, this));
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-maxp-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-maxp-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-maxp-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-maxp-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -85,7 +85,7 @@ struct maxp
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
       return_trace (false);
-
+    hb_barrier ();
     if (version.major == 1)
     {
       const maxpV1Tail &v1 = StructAfter<maxpV1Tail> (*this);
@@ -103,6 +103,7 @@ struct maxp
     maxp_prime->numGlyphs = hb_min (c->plan->num_output_glyphs (), 0xFFFFu);
     if (maxp_prime->version.major == 1)
     {
+      hb_barrier ();
       const maxpV1Tail *src_v1 = &StructAfter<maxpV1Tail> (*this);
       maxpV1Tail *dest_v1 = c->serializer->embed<maxpV1Tail> (src_v1);
       if (unlikely (!dest_v1)) return_trace (false);
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-meta-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-meta-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-meta-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-meta-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -51,6 +51,7 @@ struct DataMap
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
                           dataZ.sanitize (c, base, dataLength)));
   }
 
@@ -101,6 +102,7 @@ struct meta
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
                           version == 1 &&
                           dataMaps.sanitize (c, this)));
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-os2-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-os2-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-os2-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-os2-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -209,6 +209,23 @@ struct OS2
     return ret;
   }
 
+  static unsigned calc_avg_char_width (const hb_hashmap_t<hb_codepoint_t, hb_pair_t<unsigned, int>>& hmtx_map)
+  {
+    unsigned num = 0;
+    unsigned total_width = 0;
+    for (const auto& _ : hmtx_map.values_ref ())
+    {
+      unsigned width = _.first;
+      if (width)
+      {
+        total_width += width;
+        num++;
+      }
+    }
+
+    return num ? (unsigned) roundf ((double) total_width / (double) num) : 0;
+  }
+
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
@@ -239,17 +256,23 @@ struct OS2
 
       if (os2_prime->version >= 2)
       {
+        hb_barrier ();
         auto *table = & const_cast<OS2V2Tail &> (os2_prime->v2 ());
         HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_X_HEIGHT,                   sxHeight);
         HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_CAP_HEIGHT,                 sCapHeight);
       }
+
+      unsigned avg_char_width = calc_avg_char_width (c->plan->hmtx_map);
+      if (!c->serializer->check_assign (os2_prime->xAvgCharWidth, avg_char_width,
+                                        HB_SERIALIZE_ERROR_INT_OVERFLOW))
+        return_trace (false);
     }
 #endif
 
     Triple *axis_range;
     if (c->plan->user_axes_location.has (HB_TAG ('w','g','h','t'), &axis_range))
     {
-      unsigned weight_class = static_cast<unsigned> (roundf (hb_clamp (axis_range->middle, 1.0f, 1000.0f)));
+      unsigned weight_class = static_cast<unsigned> (roundf (hb_clamp (axis_range->middle, 1.0, 1000.0)));
       if (os2_prime->usWeightClass != weight_class)
         os2_prime->usWeightClass = weight_class;
     }
@@ -261,12 +284,12 @@ struct OS2
         os2_prime->usWidthClass = width_class;
     }
 
+    os2_prime->usFirstCharIndex = hb_min (0xFFFFu, c->plan->os2_info.min_cmap_codepoint);
+    os2_prime->usLastCharIndex  = hb_min (0xFFFFu, c->plan->os2_info.max_cmap_codepoint);
+
     if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES)
       return_trace (true);
 
-    os2_prime->usFirstCharIndex = hb_min (0xFFFFu, c->plan->unicodes.get_min ());
-    os2_prime->usLastCharIndex  = hb_min (0xFFFFu, c->plan->unicodes.get_max ());
-
     _update_unicode_ranges (&c->plan->unicodes, os2_prime->ulUnicodeRange);
 
     return_trace (true);
@@ -334,6 +357,7 @@ struct OS2
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this))) return_trace (false);
+    hb_barrier ();
     if (unlikely (version >= 1 && !v1X.sanitize (c))) return_trace (false);
     if (unlikely (version >= 2 && !v2X.sanitize (c))) return_trace (false);
     if (unlikely (version >= 5 && !v5X.sanitize (c))) return_trace (false);
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table-v2subset.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table-v2subset.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table-v2subset.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table-v2subset.hh	2025-06-27 08:03:14.000000000 +0000
@@ -84,9 +84,9 @@ HB_INTERNAL bool postV2Tail::subset (hb_
   old_gid_new_index_map.alloc (num_glyphs);
   glyph_name_to_new_index.alloc (num_glyphs);
 
-  for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
+  for (auto _ : c->plan->new_to_old_gid_list)
   {
-    hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
+    hb_codepoint_t old_gid = _.second;
     unsigned old_index = glyphNameIndex[old_gid];
 
     unsigned new_index;
@@ -125,13 +125,22 @@ HB_INTERNAL bool postV2Tail::subset (hb_
     old_gid_new_index_map.set (old_gid, new_index);
   }
 
+  if (old_gid_new_index_map.in_error())
+    return_trace (false);
+
   auto index_iter =
   + hb_range (num_glyphs)
-  | hb_map (reverse_glyph_map)
-  | hb_map_retains_sorting ([&](hb_codepoint_t old_gid)
+  | hb_map_retains_sorting ([&](hb_codepoint_t new_gid)
                             {
-                              unsigned new_index = old_gid_new_index_map.get (old_gid);
-                              return hb_pair_t<unsigned, unsigned> (old_gid, new_index);
+                              hb_codepoint_t *old_gid;
+                              /* use 0 for retain-gid holes, which refers to the name .notdef,
+                               * as the glyphNameIndex entry for that glyph ID."*/
+                              unsigned new_index = 0;
+                              if (reverse_glyph_map.has (new_gid, &old_gid)) {
+                                new_index = old_gid_new_index_map.get (*old_gid);
+                                return hb_pair_t<unsigned, unsigned> (*old_gid, new_index);
+                              }
+                              return hb_pair_t<unsigned, unsigned> (new_gid, new_index);
                             })
   ;
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -116,13 +116,16 @@ struct post
     Triple *axis_range;
     if (c->plan->user_axes_location.has (HB_TAG ('s','l','n','t'), &axis_range))
     {
-      float italic_angle = hb_max (-90.f, hb_min (axis_range->middle, 90.f));
+      float italic_angle = hb_max (-90.0, hb_min (axis_range->middle, 90.0));
       if (post_prime->italicAngle.to_float () != italic_angle)
         post_prime->italicAngle.set_float (italic_angle);
     }
 
     if (glyph_names && version.major == 2)
+    {
+      hb_barrier ();
       return_trace (v2X.subset (c));
+    }
 
     return_trace (true);
   }
@@ -138,6 +141,7 @@ struct post
 
       version = table->version.to_int ();
       if (version != 0x00020000) return;
+      hb_barrier ();
 
       const postV2Tail &v2 = table->v2X;
 
@@ -217,10 +221,16 @@ struct post
     unsigned int get_glyph_count () const
     {
       if (version == 0x00010000)
+      {
+        hb_barrier ();
         return format1_names_length;
+      }
 
       if (version == 0x00020000)
+      {
+        hb_barrier ();
         return glyphNameIndex->len;
+      }
 
       return 0;
     }
@@ -245,13 +255,18 @@ struct post
     {
       if (version == 0x00010000)
       {
+        hb_barrier ();
         if (glyph >= format1_names_length)
           return hb_bytes_t ();
 
         return format1_names (glyph);
       }
 
-      if (version != 0x00020000 || glyph >= glyphNameIndex->len)
+      if (version != 0x00020000)
+        return hb_bytes_t ();
+      hb_barrier ();
+
+      if (glyph >= glyphNameIndex->len)
         return hb_bytes_t ();
 
       unsigned int index = glyphNameIndex->arrayZ[glyph];
@@ -284,8 +299,9 @@ struct post
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   (version.to_int () == 0x00010000 ||
-                   (version.to_int () == 0x00020000 && v2X.sanitize (c)) ||
+                   (version.to_int () == 0x00020000 && hb_barrier () && v2X.sanitize (c)) ||
                    version.to_int () == 0x00030000));
   }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.cc	2025-06-27 08:03:14.000000000 +0000
@@ -74,23 +74,6 @@
  *     Indic shaper may want to disallow recomposing of two matras.
  */
 
-static bool
-decompose_unicode (const hb_ot_shape_normalize_context_t *c,
-                   hb_codepoint_t  ab,
-                   hb_codepoint_t *a,
-                   hb_codepoint_t *b)
-{
-  return (bool) c->unicode->decompose (ab, a, b);
-}
-
-static bool
-compose_unicode (const hb_ot_shape_normalize_context_t *c,
-                 hb_codepoint_t  a,
-                 hb_codepoint_t  b,
-                 hb_codepoint_t *ab)
-{
-  return (bool) c->unicode->compose (a, b, ab);
-}
 
 static inline void
 set_glyph (hb_glyph_info_t &info, hb_font_t *font)
@@ -170,7 +153,7 @@ decompose_current_character (const hb_ot
   hb_codepoint_t u = buffer->cur().codepoint;
   hb_codepoint_t glyph = 0;
 
-  if (shortest && c->font->get_nominal_glyph (u, &glyph, c->not_found))
+  if (shortest && c->font->get_nominal_glyph (u, &glyph, buffer->not_found))
   {
     next_char (buffer, glyph);
     return;
@@ -182,7 +165,7 @@ decompose_current_character (const hb_ot
     return;
   }
 
-  if (!shortest && c->font->get_nominal_glyph (u, &glyph, c->not_found))
+  if (!shortest && c->font->get_nominal_glyph (u, &glyph, buffer->not_found))
   {
     next_char (buffer, glyph);
     return;
@@ -237,6 +220,12 @@ handle_variation_selector_cluster (const
         /* Just pass on the two characters separately, let GSUB do its magic. */
         set_glyph (buffer->cur(), font);
         (void) buffer->next_glyph ();
+
+        buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK;
+        _hb_glyph_info_set_variation_selector (&buffer->cur(), true);
+        if (buffer->not_found_variation_selector != HB_CODEPOINT_INVALID)
+          _hb_glyph_info_clear_default_ignorable (&buffer->cur());
+
         set_glyph (buffer->cur(), font);
         (void) buffer->next_glyph ();
       }
@@ -307,15 +296,15 @@ _hb_ot_shape_normalize (const hb_ot_shap
       mode = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS;
   }
 
-  const hb_ot_shape_normalize_context_t c = {
+  hb_ot_shape_normalize_context_t c = {
     plan,
     buffer,
     font,
     buffer->unicode,
-    buffer->not_found,
-    plan->shaper->decompose ? plan->shaper->decompose : decompose_unicode,
-    plan->shaper->compose   ? plan->shaper->compose   : compose_unicode
+    plan->shaper->decompose ? plan->shaper->decompose : hb_ot_shape_normalize_context_t::decompose_unicode,
+    plan->shaper->compose   ? plan->shaper->compose   : hb_ot_shape_normalize_context_t::compose_unicode
   };
+  c.override_decompose_and_compose (plan->shaper->decompose, plan->shaper->compose);
 
   bool always_short_circuit = mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE;
   bool might_short_circuit = always_short_circuit ||
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.hh	2025-06-27 08:03:14.000000000 +0000
@@ -28,6 +28,7 @@
 #define HB_OT_SHAPE_NORMALIZE_HH
 
 #include "hb.hh"
+#include "hb-unicode.hh"
 
 
 /* buffer var allocations, used during the normalization process */
@@ -52,11 +53,42 @@ HB_INTERNAL void _hb_ot_shape_normalize
 
 struct hb_ot_shape_normalize_context_t
 {
+  static bool
+  decompose_unicode (const hb_ot_shape_normalize_context_t *c,
+                     hb_codepoint_t  ab,
+                     hb_codepoint_t *a,
+                     hb_codepoint_t *b)
+  {
+    return (bool) c->unicode->decompose (ab, a, b);
+  }
+
+  static bool
+  compose_unicode (const hb_ot_shape_normalize_context_t *c,
+                   hb_codepoint_t  a,
+                   hb_codepoint_t  b,
+                   hb_codepoint_t *ab)
+  {
+    return (bool) c->unicode->compose (a, b, ab);
+  }
+
+  void
+  override_decompose_and_compose (bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
+                                                      hb_codepoint_t  ab,
+                                                      hb_codepoint_t *a,
+                                                      hb_codepoint_t *b),
+                                  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
+                                                   hb_codepoint_t  a,
+                                                   hb_codepoint_t  b,
+                                                   hb_codepoint_t *ab))
+  {
+    this->decompose = decompose ? decompose : decompose_unicode;
+    this->compose = compose ? compose : compose_unicode;
+  }
+
   const hb_ot_shape_plan_t *plan;
   hb_buffer_t *buffer;
   hb_font_t *font;
   hb_unicode_funcs_t *unicode;
-  const hb_codepoint_t not_found;
   bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
                      hb_codepoint_t  ab,
                      hb_codepoint_t *a,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc	2025-06-27 08:03:14.000000000 +0000
@@ -46,6 +46,8 @@
 #include "hb-set.hh"
 
 #include "hb-aat-layout.hh"
+#include "hb-ot-stat-table.hh"
+
 
 static inline bool
 _hb_codepoint_is_regional_indicator (hb_codepoint_t u)
@@ -85,7 +87,7 @@ hb_ot_shape_planner_t::hb_ot_shape_plann
                                                 , apply_morx (_hb_apply_morx (face, props))
 #endif
 {
-  shaper = hb_ot_shaper_categorize (this);
+  shaper = hb_ot_shaper_categorize (props.script, props.direction, map.chosen_script[0]);
 
   script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
   script_fallback_mark_positioning = shaper->fallback_position;
@@ -121,10 +123,6 @@ hb_ot_shape_planner_t::compile (hb_ot_sh
   plan.kern_mask = plan.map.get_mask (kern_tag);
   plan.requested_kerning = !!plan.kern_mask;
 #endif
-#ifndef HB_NO_AAT_SHAPE
-  plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k'));
-  plan.requested_tracking = !!plan.trak_mask;
-#endif
 
   bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX;
   bool disable_gpos = plan.shaper->gpos_tag &&
@@ -155,7 +153,7 @@ hb_ot_shape_planner_t::compile (hb_ot_sh
 #endif
   bool has_gpos = !disable_gpos && hb_ot_layout_has_positioning (face);
   if (false)
-    ;
+    {}
 #ifndef HB_NO_AAT_SHAPE
   /* Prefer GPOS over kerx if GSUB is present;
    * https://github.com/harfbuzz/harfbuzz/issues/3008 */
@@ -167,15 +165,16 @@ hb_ot_shape_planner_t::compile (hb_ot_sh
 
   if (!plan.apply_kerx && (!has_gpos_kern || !plan.apply_gpos))
   {
+    if (false) {}
 #ifndef HB_NO_AAT_SHAPE
-    if (has_kerx)
+    else if (has_kerx)
       plan.apply_kerx = true;
-    else
 #endif
 #ifndef HB_NO_OT_KERN
-    if (hb_ot_layout_has_kerning (face))
+    else if (hb_ot_layout_has_kerning (face))
       plan.apply_kern = true;
 #endif
+    else {}
   }
 
   plan.apply_fallback_kern = !(plan.apply_gpos || plan.apply_kerx || plan.apply_kern);
@@ -206,9 +205,6 @@ hb_ot_shape_planner_t::compile (hb_ot_sh
      https://github.com/harfbuzz/harfbuzz/issues/2967. */
   if (plan.apply_morx)
     plan.adjust_mark_positioning_when_zeroing = false;
-
-  /* Currently we always apply trak. */
-  plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face);
 #endif
 }
 
@@ -273,11 +269,6 @@ hb_ot_shape_plan_t::position (hb_font_t
 #endif
   else if (this->apply_fallback_kern)
     _hb_ot_shape_fallback_kern (this, font, buffer);
-
-#ifndef HB_NO_AAT_SHAPE
-  if (this->apply_trak)
-    hb_aat_layout_track (this, font, buffer);
-#endif
 }
 
 
@@ -345,13 +336,6 @@ hb_ot_shape_collect_features (hb_ot_shap
   /* Random! */
   map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE);
 
-#ifndef HB_NO_AAT_SHAPE
-  /* Tracking.  We enable dummy feature here just to allow disabling
-   * AAT 'trak' table using features.
-   * https://github.com/harfbuzz/harfbuzz/issues/1303 */
-  map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK);
-#endif
-
   map->enable_feature (HB_TAG ('H','a','r','f')); /* Considered required. */
   map->enable_feature (HB_TAG ('H','A','R','F')); /* Considered discretionary. */
 
@@ -837,6 +821,28 @@ hb_ot_zero_width_default_ignorables (con
 }
 
 static void
+hb_ot_deal_with_variation_selectors (hb_buffer_t *buffer)
+{
+  if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK) ||
+        buffer->not_found_variation_selector == HB_CODEPOINT_INVALID)
+    return;
+
+  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 (_hb_glyph_info_is_variation_selector (&info[i]))
+    {
+      info[i].codepoint = buffer->not_found_variation_selector;
+      pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
+      _hb_glyph_info_set_variation_selector (&info[i], false);
+    }
+  }
+}
+
+static void
 hb_ot_hide_default_ignorables (hb_buffer_t *buffer,
                                hb_font_t   *font)
 {
@@ -965,6 +971,7 @@ hb_ot_substitute_post (const hb_ot_shape
     hb_aat_layout_remove_deleted_glyphs (c->buffer);
 #endif
 
+  hb_ot_deal_with_variation_selectors (c->buffer);
   hb_ot_hide_default_ignorables (c->buffer, c->font);
 
   if (c->plan->shaper->postprocess_glyphs &&
@@ -1253,6 +1260,36 @@ hb_ot_shape_plan_collect_lookups (hb_sha
 }
 
 
+/**
+ * hb_ot_shape_plan_get_feature_tags:
+ * @shape_plan: A shaping plan
+ * @start_offset: The index of first feature to retrieve
+ * @tag_count: (inout): Input = the maximum number of features to return;
+ *                      Output = the actual number of features returned (may be zero)
+ * @tags: (out) (array length=tag_count): The array of enabled feature
+ *
+ * Fetches the list of OpenType feature tags enabled for a shaping plan, if possible.
+ *
+ * Return value: Total number of feature tagss.
+ *
+ * Since: 10.3.0
+ */
+unsigned int
+hb_ot_shape_plan_get_feature_tags (hb_shape_plan_t *shape_plan,
+                                   unsigned int     start_offset,
+                                   unsigned int    *tag_count, /* IN/OUT */
+                                   hb_tag_t        *tags /* OUT */)
+{
+#ifndef HB_NO_OT_SHAPE
+  return shape_plan->ot.map.get_feature_tags (start_offset, tag_count, tags);
+#else
+  if (tag_count)
+        *tag_count = 0;
+  return 0;
+#endif
+}
+
+
 /* TODO Move this to hb-ot-shape-normalize, make it do decompose, and make it public. */
 static void
 add_char (hb_font_t          *font,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.h 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.h
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.h	2025-06-27 08:03:14.000000000 +0000
@@ -48,6 +48,12 @@ hb_ot_shape_plan_collect_lookups (hb_sha
                                   hb_tag_t         table_tag,
                                   hb_set_t        *lookup_indexes /* OUT */);
 
+HB_EXTERN unsigned int
+hb_ot_shape_plan_get_feature_tags (hb_shape_plan_t *shape_plan,
+                                   unsigned int     start_offset,
+                                   unsigned int    *tag_count, /* IN/OUT */
+                                   hb_tag_t        *tags /* OUT */);
+
 HB_END_DECLS
 
 #endif /* HB_OT_SHAPE_H */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh	2025-06-27 08:03:14.000000000 +0000
@@ -51,7 +51,8 @@ struct hb_ot_shape_plan_key_t
 
   bool equal (const hb_ot_shape_plan_key_t *other)
   {
-    return 0 == hb_memcmp (this, other, sizeof (*this));
+    return variations_index[0] == other->variations_index[0] &&
+           variations_index[1] == other->variations_index[1];
   }
 };
 
@@ -79,22 +80,12 @@ struct hb_ot_shape_plan_t
 #else
   static constexpr hb_mask_t kern_mask = 0;
 #endif
-#ifndef HB_NO_AAT_SHAPE
-  hb_mask_t trak_mask;
-#else
-  static constexpr hb_mask_t trak_mask = 0;
-#endif
 
 #ifndef HB_NO_OT_KERN
   bool requested_kerning : 1;
 #else
   static constexpr bool requested_kerning = false;
 #endif
-#ifndef HB_NO_AAT_SHAPE
-  bool requested_tracking : 1;
-#else
-  static constexpr bool requested_tracking = false;
-#endif
 #ifndef HB_NO_OT_SHAPE_FRACTIONS
   bool has_frac : 1;
 #else
@@ -117,11 +108,9 @@ struct hb_ot_shape_plan_t
 #ifndef HB_NO_AAT_SHAPE
   bool apply_kerx : 1;
   bool apply_morx : 1;
-  bool apply_trak : 1;
 #else
   static constexpr bool apply_kerx = false;
   static constexpr bool apply_morx = false;
-  static constexpr bool apply_trak = false;
 #endif
 
   void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-fallback.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-fallback.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-fallback.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-fallback.hh	2025-06-27 08:03:14.000000000 +0000
@@ -355,6 +355,8 @@ arabic_fallback_plan_destroy (arabic_fal
   for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
     if (fallback_plan->lookup_array[i])
     {
+      if (fallback_plan->accel_array[i])
+        fallback_plan->accel_array[i]->fini ();
       hb_free (fallback_plan->accel_array[i]);
       if (fallback_plan->free_lookups)
         hb_free (fallback_plan->lookup_array[i]);
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-joining-list.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-joining-list.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-joining-list.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-joining-list.hh	2025-06-27 08:03:14.000000000 +0000
@@ -6,10 +6,10 @@
  *
  * on files with these headers:
  *
- * # ArabicShaping-15.1.0.txt
- * # Date: 2023-01-05
- * # Scripts-15.1.0.txt
- * # Date: 2023-07-28, 16:01:07 GMT
+ * # ArabicShaping-16.0.0.txt
+ * # Date: 2024-07-30
+ * # Scripts-16.0.0.txt
+ * # Date: 2024-04-30, 21:48:40 GMT
  */
 
 #ifndef HB_OT_SHAPER_ARABIC_JOINING_LIST_HH
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -6,10 +6,10 @@
  *
  * on files with these headers:
  *
- * # ArabicShaping-15.1.0.txt
- * # Date: 2023-01-05
- * # Blocks-15.1.0.txt
- * # Date: 2023-07-28, 15:47:20 GMT
+ * # ArabicShaping-16.0.0.txt
+ * # Date: 2024-07-30
+ * # Blocks-16.0.0.txt
+ * # Date: 2024-02-02
  * UnicodeData.txt does not have a header.
  */
 
@@ -136,7 +136,13 @@ static const uint8_t joining_table[] =
   /* 10D00 */ L,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
   /* 10D20 */ D,D,R,D,
 
-#define joining_offset_0x10f30u 1182
+#define joining_offset_0x10ec2u 1182
+
+  /* Arabic Extended-C */
+
+  /* 10EC0 */     R,D,D,
+
+#define joining_offset_0x10f30u 1185
 
   /* Sogdian */
 
@@ -155,14 +161,14 @@ static const uint8_t joining_table[] =
   /* 10FA0 */                                 D,U,D,D,R,R,R,U,D,R,R,D,D,R,D,D,
   /* 10FC0 */ U,D,R,R,D,U,U,U,U,R,D,L,
 
-#define joining_offset_0x110bdu 1338
+#define joining_offset_0x110bdu 1341
 
   /* Kaithi */
 
   /* 110A0 */                                                           U,X,X,
   /* 110C0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,U,
 
-#define joining_offset_0x1e900u 1355
+#define joining_offset_0x1e900u 1358
 
   /* Adlam */
 
@@ -170,7 +176,7 @@ static const uint8_t joining_table[] =
   /* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
   /* 1E940 */ D,D,D,D,X,X,X,X,X,X,X,T,
 
-}; /* Table items: 1431; occupancy: 57% */
+}; /* Table items: 1434; occupancy: 57% */
 
 
 static unsigned int
@@ -198,6 +204,7 @@ joining_type (hb_codepoint_t u)
       if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u];
       if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u];
       if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D23u)) return joining_table[u - 0x10D00u + joining_offset_0x10d00u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x10EC2u, 0x10EC4u)) return joining_table[u - 0x10EC2u + joining_offset_0x10ec2u];
       if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x10FCBu)) return joining_table[u - 0x10F30u + joining_offset_0x10f30u];
       break;
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc	2025-06-27 08:03:14.000000000 +0000
@@ -233,10 +233,7 @@ collect_features_arabic (hb_ot_shape_pla
    map->enable_feature (HB_TAG('c','a','l','t'), F_MANUAL_ZWJ);
    /* https://github.com/harfbuzz/harfbuzz/issues/1573 */
    if (!map->has_feature (HB_TAG('r','c','l','t')))
-   {
      map->add_gsub_pause (nullptr);
-     map->enable_feature (HB_TAG('r','c','l','t'), F_MANUAL_ZWJ);
-   }
 
    map->enable_feature (HB_TAG('l','i','g','a'), F_MANUAL_ZWJ);
    map->enable_feature (HB_TAG('c','l','i','g'), F_MANUAL_ZWJ);
@@ -560,9 +557,9 @@ apply_stch (const hb_ot_shape_plan_t *pl
 
       DEBUG_MSG (ARABIC, nullptr, "%s stretch at (%u,%u,%u)",
                  step == MEASURE ? "measuring" : "cutting", context, start, end);
-      DEBUG_MSG (ARABIC, nullptr, "rest of word:    count=%u width %d", start - context, w_total);
-      DEBUG_MSG (ARABIC, nullptr, "fixed tiles:     count=%d width=%d", n_fixed, w_fixed);
-      DEBUG_MSG (ARABIC, nullptr, "repeating tiles: count=%d width=%d", n_repeating, w_repeating);
+      DEBUG_MSG (ARABIC, nullptr, "rest of word:    count=%u width %" PRId32, start - context, w_total);
+      DEBUG_MSG (ARABIC, nullptr, "fixed tiles:     count=%d width=%" PRId32, n_fixed, w_fixed);
+      DEBUG_MSG (ARABIC, nullptr, "repeating tiles: count=%d width=%" PRId32, n_repeating, w_repeating);
 
       /* Number of additional times to repeat each repeating tile. */
       int n_copies = 0;
@@ -602,7 +599,7 @@ apply_stch (const hb_ot_shape_plan_t *pl
           if (info[k - 1].arabic_shaping_action() == STCH_REPEATING)
             repeat += n_copies;
 
-          DEBUG_MSG (ARABIC, nullptr, "appending %u copies of glyph %u; j=%u",
+          DEBUG_MSG (ARABIC, nullptr, "appending %u copies of glyph %" PRIu32 "; j=%u",
                      repeat, info[k - 1].codepoint, j);
           pos[k - 1].x_advance = 0;
           for (unsigned int n = 0; n < repeat; n++)
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hebrew.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hebrew.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hebrew.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hebrew.cc	2025-06-27 08:03:14.000000000 +0000
@@ -78,7 +78,7 @@ compose_hebrew (const hb_ot_shape_normal
   return found;
 #endif
 
-  if (!found && !c->plan->has_gpos_mark)
+  if (!found && (c->plan && !c->plan->has_gpos_mark))
   {
       /* Special-case Hebrew presentation forms that are excluded from
        * standard normalization, but wanted for old fonts. */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-machine.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-machine.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-machine.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-machine.hh	2025-06-27 08:03:14.000000000 +0000
@@ -68,6 +68,7 @@ enum indic_syllable_type_t {
 #define indic_syllable_machine_ex_Ra 15u
 #define indic_syllable_machine_ex_Repha 14u
 #define indic_syllable_machine_ex_SM 8u
+#define indic_syllable_machine_ex_SMPst 57u
 #define indic_syllable_machine_ex_Symbol 17u
 #define indic_syllable_machine_ex_V 2u
 #define indic_syllable_machine_ex_VD 9u
@@ -76,251 +77,916 @@ enum indic_syllable_type_t {
 #define indic_syllable_machine_ex_ZWNJ 5u
 
 
-#line 80 "hb-ot-shaper-indic-machine.hh"
+#line 81 "hb-ot-shaper-indic-machine.hh"
 static const unsigned char _indic_syllable_machine_trans_keys[] = {
-        8u, 8u, 4u, 13u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u,
-        8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 4u, 13u,
-        8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 8u, 8u,
-        5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 5u, 13u, 8u, 8u, 1u, 18u,
-        3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 5u, 9u, 5u, 9u, 9u, 9u, 5u, 9u,
-        1u, 15u, 1u, 15u, 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 4u, 13u,
-        5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 3u, 16u, 3u, 16u, 4u, 16u,
-        1u, 15u, 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u,
-        1u, 15u, 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 4u, 13u, 5u, 9u,
-        5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 4u, 13u, 3u, 16u, 3u, 16u,
-        4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u,
-        1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 3u, 16u, 4u, 13u, 5u, 9u,
-        5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 4u, 13u, 4u, 13u, 3u, 16u, 3u, 16u,
-        4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u,
-        1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 3u, 16u, 4u, 13u, 5u, 9u,
-        5u, 9u, 3u, 9u, 5u, 9u, 1u, 16u, 3u, 16u, 1u, 16u, 4u, 13u, 5u, 13u,
-        5u, 13u, 9u, 9u, 5u, 9u, 1u, 15u, 3u, 9u, 5u, 9u, 5u, 9u, 9u, 9u,
+        8u, 57u, 4u, 57u, 5u, 57u, 5u, 57u, 13u, 13u, 4u, 57u, 4u, 57u, 4u, 57u,
+        8u, 57u, 5u, 57u, 5u, 57u, 13u, 13u, 4u, 57u, 4u, 57u, 4u, 57u, 4u, 57u,
+        8u, 57u, 5u, 57u, 5u, 57u, 13u, 13u, 4u, 57u, 4u, 57u, 4u, 57u, 8u, 57u,
+        5u, 57u, 5u, 57u, 13u, 13u, 4u, 57u, 4u, 57u, 5u, 57u, 8u, 57u, 1u, 57u,
+        3u, 57u, 3u, 57u, 4u, 57u, 1u, 57u, 5u, 57u, 5u, 57u, 9u, 9u, 5u, 9u,
+        1u, 57u, 1u, 57u, 1u, 57u, 3u, 57u, 4u, 57u, 5u, 57u, 5u, 57u, 4u, 57u,
+        5u, 57u, 3u, 57u, 5u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 4u, 57u,
+        1u, 57u, 3u, 57u, 3u, 57u, 4u, 57u, 1u, 57u, 5u, 57u, 9u, 9u, 5u, 9u,
+        1u, 57u, 1u, 57u, 3u, 57u, 4u, 57u, 5u, 57u, 5u, 57u, 4u, 57u, 5u, 57u,
+        5u, 57u, 3u, 57u, 5u, 57u, 3u, 57u, 3u, 57u, 4u, 57u, 3u, 57u, 3u, 57u,
+        4u, 57u, 1u, 57u, 3u, 57u, 1u, 57u, 5u, 57u, 9u, 9u, 5u, 9u, 1u, 57u,
+        1u, 57u, 3u, 57u, 4u, 57u, 5u, 57u, 5u, 57u, 3u, 57u, 4u, 57u, 5u, 57u,
+        5u, 57u, 3u, 57u, 5u, 57u, 3u, 57u, 4u, 57u, 4u, 57u, 3u, 57u, 3u, 57u,
+        4u, 57u, 1u, 57u, 3u, 57u, 1u, 57u, 5u, 57u, 9u, 9u, 5u, 9u, 1u, 57u,
+        1u, 57u, 3u, 57u, 4u, 57u, 5u, 57u, 5u, 57u, 3u, 57u, 4u, 57u, 5u, 57u,
+        5u, 57u, 3u, 57u, 5u, 57u, 1u, 57u, 3u, 57u, 1u, 57u, 4u, 57u, 5u, 57u,
+        5u, 57u, 9u, 9u, 5u, 9u, 1u, 57u, 3u, 57u, 5u, 57u, 5u, 57u, 9u, 9u,
         5u, 9u, 1u, 15u, 0
 };
 
 static const char _indic_syllable_machine_key_spans[] = {
-        1, 10, 9, 9, 1, 10, 10, 10,
-        1, 9, 9, 1, 10, 10, 10, 10,
-        1, 9, 9, 1, 10, 10, 10, 1,
-        9, 9, 1, 10, 10, 9, 1, 18,
-        14, 14, 13, 15, 5, 5, 1, 5,
-        15, 15, 15, 11, 10, 9, 9, 10,
-        5, 7, 5, 14, 14, 14, 14, 13,
-        15, 14, 14, 13, 15, 5, 1, 5,
-        15, 15, 11, 10, 9, 9, 10, 5,
-        5, 7, 5, 14, 14, 10, 14, 14,
-        13, 15, 14, 15, 5, 1, 5, 15,
-        15, 11, 10, 9, 9, 14, 10, 5,
-        5, 7, 5, 14, 10, 10, 14, 14,
-        13, 15, 14, 15, 5, 1, 5, 15,
-        15, 11, 10, 9, 9, 14, 10, 5,
-        5, 7, 5, 16, 14, 16, 10, 9,
-        9, 1, 5, 15, 7, 5, 5, 1,
+        50, 54, 53, 53, 1, 54, 54, 54,
+        50, 53, 53, 1, 54, 54, 54, 54,
+        50, 53, 53, 1, 54, 54, 54, 50,
+        53, 53, 1, 54, 54, 53, 50, 57,
+        55, 55, 54, 57, 53, 53, 1, 5,
+        57, 57, 57, 55, 54, 53, 53, 54,
+        53, 55, 53, 55, 55, 55, 55, 54,
+        57, 55, 55, 54, 57, 53, 1, 5,
+        57, 57, 55, 54, 53, 53, 54, 53,
+        53, 55, 53, 55, 55, 54, 55, 55,
+        54, 57, 55, 57, 53, 1, 5, 57,
+        57, 55, 54, 53, 53, 55, 54, 53,
+        53, 55, 53, 55, 54, 54, 55, 55,
+        54, 57, 55, 57, 53, 1, 5, 57,
+        57, 55, 54, 53, 53, 55, 54, 53,
+        53, 55, 53, 57, 55, 57, 54, 53,
+        53, 1, 5, 57, 55, 53, 53, 1,
         5, 15
 };
 
 static const short _indic_syllable_machine_index_offsets[] = {
-        0, 2, 13, 23, 33, 35, 46, 57,
-        68, 70, 80, 90, 92, 103, 114, 125,
-        136, 138, 148, 158, 160, 171, 182, 193,
-        195, 205, 215, 217, 228, 239, 249, 251,
-        270, 285, 300, 314, 330, 336, 342, 344,
-        350, 366, 382, 398, 410, 421, 431, 441,
-        452, 458, 466, 472, 487, 502, 517, 532,
-        546, 562, 577, 592, 606, 622, 628, 630,
-        636, 652, 668, 680, 691, 701, 711, 722,
-        728, 734, 742, 748, 763, 778, 789, 804,
-        819, 833, 849, 864, 880, 886, 888, 894,
-        910, 926, 938, 949, 959, 969, 984, 995,
-        1001, 1007, 1015, 1021, 1036, 1047, 1058, 1073,
-        1088, 1102, 1118, 1133, 1149, 1155, 1157, 1163,
-        1179, 1195, 1207, 1218, 1228, 1238, 1253, 1264,
-        1270, 1276, 1284, 1290, 1307, 1322, 1339, 1350,
-        1360, 1370, 1372, 1378, 1394, 1402, 1408, 1414,
-        1416, 1422
+        0, 51, 106, 160, 214, 216, 271, 326,
+        381, 432, 486, 540, 542, 597, 652, 707,
+        762, 813, 867, 921, 923, 978, 1033, 1088,
+        1139, 1193, 1247, 1249, 1304, 1359, 1413, 1464,
+        1522, 1578, 1634, 1689, 1747, 1801, 1855, 1857,
+        1863, 1921, 1979, 2037, 2093, 2148, 2202, 2256,
+        2311, 2365, 2421, 2475, 2531, 2587, 2643, 2699,
+        2754, 2812, 2868, 2924, 2979, 3037, 3091, 3093,
+        3099, 3157, 3215, 3271, 3326, 3380, 3434, 3489,
+        3543, 3597, 3653, 3707, 3763, 3819, 3874, 3930,
+        3986, 4041, 4099, 4155, 4213, 4267, 4269, 4275,
+        4333, 4391, 4447, 4502, 4556, 4610, 4666, 4721,
+        4775, 4829, 4885, 4939, 4995, 5050, 5105, 5161,
+        5217, 5272, 5330, 5386, 5444, 5498, 5500, 5506,
+        5564, 5622, 5678, 5733, 5787, 5841, 5897, 5952,
+        6006, 6060, 6116, 6170, 6228, 6284, 6342, 6397,
+        6451, 6505, 6507, 6513, 6571, 6627, 6681, 6735,
+        6737, 6743
 };
 
 static const unsigned char _indic_syllable_machine_indicies[] = {
-        1, 0, 2, 3, 3, 4, 5, 0,
-        0, 0, 0, 4, 0, 3, 3, 4,
-        6, 0, 0, 0, 0, 4, 0, 3,
-        3, 4, 5, 0, 0, 0, 0, 4,
-        0, 4, 0, 7, 3, 3, 4, 5,
-        0, 0, 0, 0, 4, 0, 2, 3,
-        3, 4, 5, 0, 0, 0, 8, 4,
-        0, 10, 11, 11, 12, 13, 9, 9,
-        9, 9, 12, 9, 14, 9, 11, 11,
-        12, 15, 9, 9, 9, 9, 12, 9,
-        11, 11, 12, 13, 9, 9, 9, 9,
-        12, 9, 12, 9, 16, 11, 11, 12,
-        13, 9, 9, 9, 9, 12, 9, 10,
-        11, 11, 12, 13, 9, 9, 9, 17,
-        12, 9, 10, 11, 11, 12, 13, 9,
-        9, 9, 18, 12, 9, 20, 21, 21,
-        22, 23, 19, 19, 19, 24, 22, 19,
-        25, 19, 21, 21, 22, 27, 26, 26,
-        26, 26, 22, 26, 21, 21, 22, 23,
-        19, 19, 19, 19, 22, 19, 22, 26,
-        20, 21, 21, 22, 23, 19, 19, 19,
-        19, 22, 19, 28, 21, 21, 22, 23,
-        19, 19, 19, 19, 22, 19, 30, 31,
-        31, 32, 33, 29, 29, 29, 34, 32,
+        1, 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,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 1, 0, 2, 3, 3, 4, 5,
+        0, 0, 0, 0, 4, 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, 0, 0, 0, 0,
+        5, 0, 3, 3, 4, 6, 0, 0,
+        0, 0, 4, 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, 0, 0, 0, 0, 6, 0,
+        3, 3, 4, 5, 0, 0, 0, 0,
+        4, 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,
+        0, 0, 0, 0, 5, 0, 4, 0,
+        7, 3, 3, 4, 5, 0, 0, 0,
+        0, 4, 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, 0, 0, 0, 0, 5, 0, 2,
+        3, 3, 4, 5, 0, 0, 0, 8,
+        4, 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,
+        0, 0, 0, 0, 5, 0, 10, 11,
+        11, 12, 13, 9, 9, 9, 9, 12,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 13, 9, 14, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 14, 9,
+        11, 11, 12, 15, 9, 9, 9, 9,
+        12, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 15, 9, 11, 11,
+        12, 13, 9, 9, 9, 9, 12, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 13, 9, 12, 9, 16, 11,
+        11, 12, 13, 9, 9, 9, 9, 12,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 13, 9, 10, 11, 11,
+        12, 13, 9, 9, 9, 17, 12, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 13, 9, 10, 11, 11, 12,
+        13, 9, 9, 9, 18, 12, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9,
+        9, 13, 9, 20, 21, 21, 22, 23,
+        19, 19, 19, 24, 22, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        23, 19, 25, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 25, 19, 21, 21, 22,
+        27, 26, 26, 26, 26, 22, 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, 26, 26, 26, 26,
+        26, 26, 26, 26, 26, 26, 26, 26,
+        26, 27, 26, 21, 21, 22, 23, 19,
+        19, 19, 19, 22, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 23,
+        19, 22, 26, 20, 21, 21, 22, 23,
+        19, 19, 19, 19, 22, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        23, 19, 28, 21, 21, 22, 23, 19,
+        19, 19, 19, 22, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 19,
+        19, 19, 19, 19, 19, 19, 19, 23,
+        19, 30, 31, 31, 32, 33, 29, 29,
+        29, 34, 32, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 33, 29,
+        35, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
         29, 35, 29, 31, 31, 32, 36, 29,
-        29, 29, 29, 32, 29, 31, 31, 32,
-        33, 29, 29, 29, 29, 32, 29, 32,
+        29, 29, 29, 32, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 36,
+        29, 31, 31, 32, 33, 29, 29, 29,
+        29, 32, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 33, 29, 32,
         29, 30, 31, 31, 32, 33, 29, 29,
-        29, 29, 32, 29, 37, 31, 31, 32,
-        33, 29, 29, 29, 29, 32, 29, 21,
+        29, 29, 32, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 33, 29,
+        37, 31, 31, 32, 33, 29, 29, 29,
+        29, 32, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 29, 29, 29,
+        29, 29, 29, 29, 29, 33, 29, 21,
         21, 22, 38, 0, 0, 0, 0, 22,
-        0, 40, 39, 42, 43, 44, 45, 46,
-        47, 22, 23, 48, 49, 49, 24, 22,
-        50, 51, 52, 53, 54, 41, 56, 57,
-        58, 59, 4, 5, 60, 55, 55, 8,
-        4, 55, 55, 61, 55, 62, 57, 63,
-        63, 4, 5, 60, 55, 55, 55, 4,
-        55, 55, 61, 55, 57, 63, 63, 4,
-        5, 60, 55, 55, 55, 4, 55, 55,
-        61, 55, 42, 55, 55, 55, 64, 65,
-        55, 1, 60, 55, 55, 55, 55, 55,
-        42, 55, 66, 66, 55, 1, 60, 55,
-        60, 55, 55, 67, 60, 55, 60, 55,
-        60, 55, 55, 55, 60, 55, 42, 55,
-        68, 55, 66, 66, 55, 1, 60, 55,
-        55, 55, 55, 55, 42, 55, 42, 55,
-        55, 55, 66, 66, 55, 1, 60, 55,
-        55, 55, 55, 55, 42, 55, 42, 55,
-        55, 55, 66, 65, 55, 1, 60, 55,
-        55, 55, 55, 55, 42, 55, 69, 70,
-        71, 71, 4, 5, 60, 55, 55, 55,
-        4, 55, 70, 71, 71, 4, 5, 60,
-        55, 55, 55, 4, 55, 71, 71, 4,
-        5, 60, 55, 55, 55, 4, 55, 60,
-        55, 55, 67, 60, 55, 55, 55, 4,
-        55, 72, 73, 73, 4, 5, 60, 55,
-        55, 55, 4, 55, 64, 74, 55, 1,
-        60, 55, 64, 55, 66, 66, 55, 1,
-        60, 55, 66, 74, 55, 1, 60, 55,
-        56, 57, 63, 63, 4, 5, 60, 55,
-        55, 55, 4, 55, 55, 61, 55, 56,
-        57, 58, 63, 4, 5, 60, 55, 55,
-        8, 4, 55, 55, 61, 55, 76, 77,
-        78, 79, 12, 13, 80, 75, 75, 18,
-        12, 75, 75, 81, 75, 82, 77, 83,
-        79, 12, 13, 80, 75, 75, 75, 12,
-        75, 75, 81, 75, 77, 83, 79, 12,
-        13, 80, 75, 75, 75, 12, 75, 75,
-        81, 75, 84, 75, 75, 75, 85, 86,
-        75, 14, 80, 75, 75, 75, 75, 75,
-        84, 75, 87, 77, 88, 89, 12, 13,
-        80, 75, 75, 17, 12, 75, 75, 81,
-        75, 90, 77, 83, 83, 12, 13, 80,
-        75, 75, 75, 12, 75, 75, 81, 75,
-        77, 83, 83, 12, 13, 80, 75, 75,
-        75, 12, 75, 75, 81, 75, 84, 75,
-        75, 75, 91, 86, 75, 14, 80, 75,
-        75, 75, 75, 75, 84, 75, 80, 75,
-        75, 92, 80, 75, 80, 75, 80, 75,
-        75, 75, 80, 75, 84, 75, 93, 75,
-        91, 91, 75, 14, 80, 75, 75, 75,
-        75, 75, 84, 75, 84, 75, 75, 75,
-        91, 91, 75, 14, 80, 75, 75, 75,
-        75, 75, 84, 75, 94, 95, 96, 96,
-        12, 13, 80, 75, 75, 75, 12, 75,
-        95, 96, 96, 12, 13, 80, 75, 75,
-        75, 12, 75, 96, 96, 12, 13, 80,
-        75, 75, 75, 12, 75, 80, 75, 75,
-        92, 80, 75, 75, 75, 12, 75, 97,
-        98, 98, 12, 13, 80, 75, 75, 75,
-        12, 75, 85, 99, 75, 14, 80, 75,
-        91, 91, 75, 14, 80, 75, 85, 75,
-        91, 91, 75, 14, 80, 75, 91, 99,
-        75, 14, 80, 75, 87, 77, 83, 83,
-        12, 13, 80, 75, 75, 75, 12, 75,
-        75, 81, 75, 87, 77, 88, 83, 12,
-        13, 80, 75, 75, 17, 12, 75, 75,
-        81, 75, 10, 11, 11, 12, 13, 75,
-        75, 75, 75, 12, 75, 76, 77, 83,
-        79, 12, 13, 80, 75, 75, 75, 12,
-        75, 75, 81, 75, 101, 45, 102, 102,
-        22, 23, 48, 100, 100, 100, 22, 100,
-        100, 52, 100, 45, 102, 102, 22, 23,
-        48, 100, 100, 100, 22, 100, 100, 52,
-        100, 103, 100, 100, 100, 104, 105, 100,
-        25, 48, 100, 100, 100, 100, 100, 103,
-        100, 44, 45, 106, 107, 22, 23, 48,
-        100, 100, 24, 22, 100, 100, 52, 100,
-        103, 100, 100, 100, 108, 105, 100, 25,
-        48, 100, 100, 100, 100, 100, 103, 100,
-        48, 100, 100, 109, 48, 100, 48, 100,
-        48, 100, 100, 100, 48, 100, 103, 100,
-        110, 100, 108, 108, 100, 25, 48, 100,
-        100, 100, 100, 100, 103, 100, 103, 100,
-        100, 100, 108, 108, 100, 25, 48, 100,
-        100, 100, 100, 100, 103, 100, 111, 112,
-        113, 113, 22, 23, 48, 100, 100, 100,
-        22, 100, 112, 113, 113, 22, 23, 48,
-        100, 100, 100, 22, 100, 113, 113, 22,
-        23, 48, 100, 100, 100, 22, 100, 48,
-        100, 100, 109, 48, 100, 100, 100, 22,
-        100, 44, 45, 102, 102, 22, 23, 48,
-        100, 100, 100, 22, 100, 100, 52, 100,
-        114, 115, 115, 22, 23, 48, 100, 100,
-        100, 22, 100, 104, 116, 100, 25, 48,
-        100, 108, 108, 100, 25, 48, 100, 104,
-        100, 108, 108, 100, 25, 48, 100, 108,
-        116, 100, 25, 48, 100, 44, 45, 106,
-        102, 22, 23, 48, 100, 100, 24, 22,
-        100, 100, 52, 100, 20, 21, 21, 22,
-        23, 117, 117, 117, 24, 22, 117, 20,
-        21, 21, 22, 23, 117, 117, 117, 117,
-        22, 117, 119, 120, 121, 122, 32, 33,
-        123, 118, 118, 34, 32, 118, 118, 124,
-        118, 125, 120, 122, 122, 32, 33, 123,
-        118, 118, 118, 32, 118, 118, 124, 118,
-        120, 122, 122, 32, 33, 123, 118, 118,
-        118, 32, 118, 118, 124, 118, 126, 118,
-        118, 118, 127, 128, 118, 35, 123, 118,
-        118, 118, 118, 118, 126, 118, 119, 120,
-        121, 49, 32, 33, 123, 118, 118, 34,
-        32, 118, 118, 124, 118, 126, 118, 118,
-        118, 129, 128, 118, 35, 123, 118, 118,
-        118, 118, 118, 126, 118, 123, 118, 118,
-        130, 123, 118, 123, 118, 123, 118, 118,
-        118, 123, 118, 126, 118, 131, 118, 129,
-        129, 118, 35, 123, 118, 118, 118, 118,
-        118, 126, 118, 126, 118, 118, 118, 129,
-        129, 118, 35, 123, 118, 118, 118, 118,
-        118, 126, 118, 132, 133, 134, 134, 32,
-        33, 123, 118, 118, 118, 32, 118, 133,
-        134, 134, 32, 33, 123, 118, 118, 118,
-        32, 118, 134, 134, 32, 33, 123, 118,
-        118, 118, 32, 118, 123, 118, 118, 130,
-        123, 118, 118, 118, 32, 118, 119, 120,
-        122, 122, 32, 33, 123, 118, 118, 118,
-        32, 118, 118, 124, 118, 135, 136, 136,
-        32, 33, 123, 118, 118, 118, 32, 118,
-        127, 137, 118, 35, 123, 118, 129, 129,
-        118, 35, 123, 118, 127, 118, 129, 129,
-        118, 35, 123, 118, 129, 137, 118, 35,
-        123, 118, 42, 43, 44, 45, 106, 102,
-        22, 23, 48, 49, 49, 24, 22, 100,
-        42, 52, 100, 56, 138, 58, 59, 4,
-        5, 60, 55, 55, 8, 4, 55, 55,
-        61, 55, 42, 43, 44, 45, 139, 140,
-        22, 141, 142, 55, 49, 24, 22, 55,
-        42, 52, 55, 20, 143, 143, 22, 141,
-        60, 55, 55, 24, 22, 55, 60, 55,
-        55, 67, 60, 55, 55, 55, 22, 55,
-        142, 55, 55, 144, 142, 55, 55, 55,
-        22, 55, 142, 55, 142, 55, 55, 55,
-        142, 55, 42, 55, 68, 20, 143, 143,
-        22, 141, 60, 55, 55, 55, 22, 55,
-        42, 55, 146, 145, 147, 147, 145, 40,
-        148, 145, 147, 147, 145, 40, 148, 145,
-        148, 145, 145, 149, 148, 145, 148, 145,
-        148, 145, 145, 145, 148, 145, 42, 117,
-        117, 117, 117, 117, 117, 117, 117, 49,
-        117, 117, 117, 117, 42, 117, 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, 0, 0,
+        0, 0, 0, 38, 0, 40, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 40, 39,
+        42, 43, 44, 45, 46, 47, 22, 23,
+        48, 49, 49, 24, 22, 50, 51, 52,
+        53, 54, 41, 41, 41, 41, 41, 41,
+        41, 41, 41, 41, 41, 41, 41, 41,
+        41, 41, 41, 41, 41, 41, 41, 41,
+        41, 41, 41, 41, 41, 41, 41, 41,
+        41, 41, 41, 41, 41, 41, 41, 41,
+        55, 41, 57, 58, 59, 60, 4, 5,
+        61, 56, 56, 8, 4, 56, 56, 62,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        5, 56, 63, 58, 64, 64, 4, 5,
+        61, 56, 56, 56, 4, 56, 56, 62,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        5, 56, 58, 64, 64, 4, 5, 61,
+        56, 56, 56, 4, 56, 56, 62, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 5,
+        56, 42, 56, 56, 56, 65, 66, 56,
+        1, 61, 56, 56, 56, 56, 56, 42,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 1, 56, 67, 67, 56, 1, 61,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 1,
+        56, 61, 56, 56, 68, 61, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 68, 56, 61,
+        56, 61, 56, 56, 56, 61, 56, 42,
+        56, 69, 56, 67, 67, 56, 1, 61,
+        56, 56, 56, 56, 56, 42, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 1,
+        56, 42, 56, 56, 56, 67, 67, 56,
+        1, 61, 56, 56, 56, 56, 56, 42,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 1, 56, 42, 56, 56, 56, 67,
+        66, 56, 1, 61, 56, 56, 56, 56,
+        56, 42, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 1, 56, 70, 71, 72,
+        72, 4, 5, 61, 56, 56, 56, 4,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 5, 56, 71, 72, 72,
+        4, 5, 61, 56, 56, 56, 4, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 5, 56, 72, 72, 4, 5,
+        61, 56, 56, 56, 4, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        5, 56, 61, 56, 56, 68, 61, 56,
+        56, 56, 4, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 68, 56,
+        73, 74, 74, 4, 5, 61, 56, 56,
+        56, 4, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 5, 56, 65,
+        75, 56, 1, 61, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 1, 56, 65, 56, 67,
+        67, 56, 1, 61, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 1, 56, 67, 75, 56,
+        1, 61, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 1, 56, 57, 58, 64, 64, 4,
+        5, 61, 56, 56, 56, 4, 56, 56,
+        62, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 5, 56, 57, 58, 59, 64, 4,
+        5, 61, 56, 56, 8, 4, 56, 56,
+        62, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 5, 56, 77, 78, 79, 80, 12,
+        13, 81, 76, 76, 18, 12, 76, 76,
+        82, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 13, 76, 83, 78, 84, 80, 12,
+        13, 81, 76, 76, 76, 12, 76, 76,
+        82, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 13, 76, 78, 84, 80, 12, 13,
+        81, 76, 76, 76, 12, 76, 76, 82,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        13, 76, 85, 76, 76, 76, 86, 87,
+        76, 14, 81, 76, 76, 76, 76, 76,
+        85, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 14, 76, 88, 78, 89, 90,
+        12, 13, 81, 76, 76, 17, 12, 76,
+        76, 82, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 13, 76, 91, 78, 84, 84,
+        12, 13, 81, 76, 76, 76, 12, 76,
+        76, 82, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 13, 76, 78, 84, 84, 12,
+        13, 81, 76, 76, 76, 12, 76, 76,
+        82, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 13, 76, 85, 76, 76, 76, 92,
+        87, 76, 14, 81, 76, 76, 76, 76,
+        76, 85, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 14, 76, 81, 76, 76,
+        93, 81, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 93, 76, 81, 76, 81, 76, 76,
+        76, 81, 76, 85, 76, 94, 76, 92,
+        92, 76, 14, 81, 76, 76, 76, 76,
+        76, 85, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 14, 76, 85, 76, 76,
+        76, 92, 92, 76, 14, 81, 76, 76,
+        76, 76, 76, 85, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 14, 76, 95,
+        96, 97, 97, 12, 13, 81, 76, 76,
+        76, 12, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 13, 76, 96,
+        97, 97, 12, 13, 81, 76, 76, 76,
+        12, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 13, 76, 97, 97,
+        12, 13, 81, 76, 76, 76, 12, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 13, 76, 81, 76, 76, 93,
+        81, 76, 76, 76, 12, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        93, 76, 98, 99, 99, 12, 13, 81,
+        76, 76, 76, 12, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 13,
+        76, 86, 100, 76, 14, 81, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 14, 76, 92,
+        92, 76, 14, 81, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 14, 76, 86, 76, 92,
+        92, 76, 14, 81, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 14, 76, 92, 100, 76,
+        14, 81, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 14, 76, 88, 78, 84, 84, 12,
+        13, 81, 76, 76, 76, 12, 76, 76,
+        82, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 13, 76, 88, 78, 89, 84, 12,
+        13, 81, 76, 76, 17, 12, 76, 76,
+        82, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 13, 76, 10, 11, 11, 12, 13,
+        76, 76, 76, 76, 12, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        13, 76, 77, 78, 84, 80, 12, 13,
+        81, 76, 76, 76, 12, 76, 76, 82,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        76, 76, 76, 76, 76, 76, 76, 76,
+        13, 76, 102, 45, 103, 103, 22, 23,
+        48, 101, 101, 101, 22, 101, 101, 52,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        23, 101, 45, 103, 103, 22, 23, 48,
+        101, 101, 101, 22, 101, 101, 52, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 23,
+        101, 104, 101, 101, 101, 105, 106, 101,
+        25, 48, 101, 101, 101, 101, 101, 104,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 25, 101, 44, 45, 107, 108, 22,
+        23, 48, 101, 101, 24, 22, 101, 101,
+        52, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 23, 101, 104, 101, 101, 101, 109,
+        106, 101, 25, 48, 101, 101, 101, 101,
+        101, 104, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 25, 101, 48, 101, 101,
+        110, 48, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 110, 101, 48, 101, 48, 101, 101,
+        101, 48, 101, 104, 101, 111, 101, 109,
+        109, 101, 25, 48, 101, 101, 101, 101,
+        101, 104, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 25, 101, 104, 101, 101,
+        101, 109, 109, 101, 25, 48, 101, 101,
+        101, 101, 101, 104, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 25, 101, 112,
+        113, 114, 114, 22, 23, 48, 101, 101,
+        101, 22, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 23, 101, 113,
+        114, 114, 22, 23, 48, 101, 101, 101,
+        22, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 23, 101, 114, 114,
+        22, 23, 48, 101, 101, 101, 22, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 23, 101, 48, 26, 26, 110,
+        48, 26, 26, 26, 22, 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, 26, 26, 26, 26, 26,
+        26, 26, 26, 26, 26, 26, 26, 26,
+        110, 26, 44, 45, 103, 103, 22, 23,
+        48, 101, 101, 101, 22, 101, 101, 52,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        23, 101, 115, 116, 116, 22, 23, 48,
+        101, 101, 101, 22, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 23,
+        101, 105, 117, 101, 25, 48, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 25, 101, 109,
+        109, 101, 25, 48, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 25, 101, 105, 101, 109,
+        109, 101, 25, 48, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 25, 101, 109, 117, 101,
+        25, 48, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 25, 101, 44, 45, 107, 103, 22,
+        23, 48, 101, 101, 24, 22, 101, 101,
+        52, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 23, 101, 20, 21, 21, 22, 23,
+        118, 118, 118, 24, 22, 118, 118, 118,
+        118, 118, 118, 118, 118, 118, 118, 118,
+        118, 118, 118, 118, 118, 118, 118, 118,
+        118, 118, 118, 118, 118, 118, 118, 118,
+        118, 118, 118, 118, 118, 118, 118, 118,
+        118, 118, 118, 118, 118, 118, 118, 118,
+        23, 118, 20, 21, 21, 22, 23, 118,
+        118, 118, 118, 22, 118, 118, 118, 118,
+        118, 118, 118, 118, 118, 118, 118, 118,
+        118, 118, 118, 118, 118, 118, 118, 118,
+        118, 118, 118, 118, 118, 118, 118, 118,
+        118, 118, 118, 118, 118, 118, 118, 118,
+        118, 118, 118, 118, 118, 118, 118, 23,
+        118, 120, 121, 122, 123, 32, 33, 124,
+        119, 119, 34, 32, 119, 119, 125, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 33,
+        119, 126, 121, 123, 123, 32, 33, 124,
+        119, 119, 119, 32, 119, 119, 125, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 33,
+        119, 121, 123, 123, 32, 33, 124, 119,
+        119, 119, 32, 119, 119, 125, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 33, 119,
+        127, 119, 119, 119, 128, 129, 119, 35,
+        124, 119, 119, 119, 119, 119, 127, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        35, 119, 120, 121, 122, 49, 32, 33,
+        124, 119, 119, 34, 32, 119, 119, 125,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        33, 119, 127, 119, 119, 119, 130, 129,
+        119, 35, 124, 119, 119, 119, 119, 119,
+        127, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 35, 119, 124, 119, 119, 131,
+        124, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        131, 119, 124, 119, 124, 119, 119, 119,
+        124, 119, 127, 119, 132, 119, 130, 130,
+        119, 35, 124, 119, 119, 119, 119, 119,
+        127, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 35, 119, 127, 119, 119, 119,
+        130, 130, 119, 35, 124, 119, 119, 119,
+        119, 119, 127, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 35, 119, 133, 134,
+        135, 135, 32, 33, 124, 119, 119, 119,
+        32, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 33, 119, 134, 135,
+        135, 32, 33, 124, 119, 119, 119, 32,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 33, 119, 135, 135, 32,
+        33, 124, 119, 119, 119, 32, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 33, 119, 124, 119, 119, 131, 124,
+        119, 119, 119, 32, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 131,
+        119, 120, 121, 123, 123, 32, 33, 124,
+        119, 119, 119, 32, 119, 119, 125, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 33,
+        119, 136, 137, 137, 32, 33, 124, 119,
+        119, 119, 32, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 33, 119,
+        128, 138, 119, 35, 124, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 35, 119, 130, 130,
+        119, 35, 124, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 35, 119, 128, 119, 130, 130,
+        119, 35, 124, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 35, 119, 130, 138, 119, 35,
+        124, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        119, 119, 119, 119, 119, 119, 119, 119,
+        35, 119, 42, 43, 44, 45, 107, 103,
+        22, 23, 48, 49, 49, 24, 22, 101,
+        42, 52, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 101, 101, 101, 101, 101, 101,
+        101, 101, 23, 101, 57, 139, 59, 60,
+        4, 5, 61, 56, 56, 8, 4, 56,
+        56, 62, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 5, 56, 42, 43, 44, 45,
+        140, 141, 22, 142, 143, 56, 49, 24,
+        22, 56, 42, 52, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 142, 56, 20, 144,
+        144, 22, 142, 61, 56, 56, 24, 22,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 142, 56, 61, 56, 56,
+        68, 61, 56, 56, 56, 22, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 68, 56, 143, 56, 56, 145, 143,
+        56, 56, 56, 22, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 145,
+        56, 143, 56, 143, 56, 56, 56, 143,
+        56, 42, 56, 69, 20, 144, 144, 22,
+        142, 61, 56, 56, 56, 22, 56, 42,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 56, 56, 56, 56, 56, 56, 56,
+        56, 142, 56, 147, 146, 148, 148, 146,
+        40, 149, 146, 146, 146, 146, 146, 146,
+        146, 146, 146, 146, 146, 146, 146, 146,
+        146, 146, 146, 146, 146, 146, 146, 146,
+        146, 146, 146, 146, 146, 146, 146, 146,
+        146, 146, 146, 146, 146, 146, 146, 146,
+        146, 146, 146, 146, 146, 146, 146, 146,
+        146, 40, 146, 148, 148, 146, 40, 149,
+        146, 146, 146, 146, 146, 146, 146, 146,
+        146, 146, 146, 146, 146, 146, 146, 146,
+        146, 146, 146, 146, 146, 146, 146, 146,
+        146, 146, 146, 146, 146, 146, 146, 146,
+        146, 146, 146, 146, 146, 146, 146, 146,
+        146, 146, 146, 146, 146, 146, 146, 40,
+        146, 149, 146, 146, 150, 149, 146, 146,
+        146, 146, 146, 146, 146, 146, 146, 146,
+        146, 146, 146, 146, 146, 146, 146, 146,
+        146, 146, 146, 146, 146, 146, 146, 146,
+        146, 146, 146, 146, 146, 146, 146, 146,
+        146, 146, 146, 146, 146, 146, 146, 146,
+        146, 146, 146, 146, 146, 150, 146, 149,
+        146, 149, 146, 146, 146, 149, 146, 42,
+        118, 118, 118, 118, 118, 118, 118, 118,
+        49, 118, 118, 118, 118, 42, 118, 0
 };
 
 static const unsigned char _indic_syllable_machine_trans_targs[] = {
@@ -330,41 +996,41 @@ static const unsigned char _indic_syllab
         93, 84, 31, 19, 98, 31, 107, 24,
         113, 116, 117, 108, 26, 122, 127, 31,
         134, 31, 32, 53, 79, 81, 100, 101,
-        85, 102, 123, 124, 94, 132, 137, 31,
-        33, 35, 6, 52, 38, 47, 34, 1,
-        36, 40, 0, 39, 41, 44, 45, 3,
-        48, 5, 49, 31, 54, 56, 14, 77,
-        62, 70, 55, 7, 57, 72, 64, 58,
-        13, 76, 59, 8, 63, 65, 67, 68,
-        10, 71, 12, 73, 31, 80, 20, 82,
-        96, 87, 15, 99, 16, 86, 88, 90,
-        91, 18, 95, 21, 97, 31, 31, 103,
-        105, 22, 27, 109, 118, 104, 106, 120,
-        111, 23, 110, 112, 114, 115, 25, 119,
-        28, 121, 125, 126, 131, 128, 129, 29,
-        130, 31, 133, 30, 135, 136
+        85, 102, 123, 124, 94, 132, 137, 92,
+        31, 33, 35, 6, 52, 38, 47, 34,
+        1, 36, 40, 0, 39, 41, 44, 45,
+        3, 48, 5, 49, 31, 54, 56, 14,
+        77, 62, 70, 55, 7, 57, 72, 64,
+        58, 13, 76, 59, 8, 63, 65, 67,
+        68, 10, 71, 12, 73, 31, 80, 20,
+        82, 96, 87, 15, 99, 16, 86, 88,
+        90, 91, 18, 95, 21, 97, 31, 31,
+        103, 105, 22, 27, 109, 118, 104, 106,
+        120, 111, 23, 110, 112, 114, 115, 25,
+        119, 28, 121, 125, 126, 131, 128, 129,
+        29, 130, 31, 133, 30, 135, 136
 };
 
 static const char _indic_syllable_machine_trans_actions[] = {
         1, 0, 2, 0, 2, 0, 0, 2,
         2, 3, 2, 0, 2, 0, 0, 0,
-        2, 2, 2, 4, 2, 0, 5, 0,
+        2, 2, 2, 4, 2, 0, 5, 5,
         5, 0, 6, 0, 2, 7, 2, 0,
         2, 0, 2, 0, 0, 2, 0, 8,
         0, 11, 2, 2, 5, 0, 12, 12,
         0, 2, 5, 2, 5, 2, 0, 13,
-        2, 0, 0, 2, 0, 2, 2, 0,
-        2, 2, 0, 0, 2, 2, 2, 0,
-        0, 0, 2, 14, 2, 0, 0, 2,
-        0, 2, 2, 0, 2, 2, 2, 2,
+        14, 2, 0, 0, 2, 0, 2, 2,
         0, 2, 2, 0, 0, 2, 2, 2,
-        0, 0, 0, 2, 15, 5, 0, 5,
-        2, 2, 0, 5, 0, 0, 2, 5,
-        5, 0, 0, 0, 2, 16, 17, 2,
-        0, 0, 0, 0, 2, 2, 2, 2,
-        2, 0, 0, 2, 2, 2, 0, 0,
-        0, 2, 0, 18, 18, 0, 0, 0,
-        0, 19, 2, 0, 0, 0
+        0, 0, 0, 2, 15, 2, 0, 0,
+        2, 0, 2, 2, 0, 2, 2, 2,
+        2, 0, 2, 2, 0, 0, 2, 2,
+        2, 0, 0, 0, 2, 16, 5, 0,
+        5, 2, 2, 0, 5, 0, 0, 2,
+        5, 5, 0, 0, 0, 2, 17, 18,
+        2, 0, 0, 0, 0, 2, 2, 2,
+        2, 2, 0, 0, 2, 2, 2, 0,
+        0, 0, 2, 0, 19, 19, 0, 0,
+        0, 0, 20, 2, 0, 0, 0
 };
 
 static const char _indic_syllable_machine_to_state_actions[] = {
@@ -414,20 +1080,20 @@ static const short _indic_syllable_machi
         10, 10, 10, 10, 10, 10, 10, 20,
         20, 27, 20, 27, 20, 20, 30, 30,
         30, 30, 30, 30, 30, 1, 40, 0,
-        56, 56, 56, 56, 56, 56, 56, 56,
-        56, 56, 56, 56, 56, 56, 56, 56,
-        56, 56, 56, 56, 56, 76, 76, 76,
-        76, 76, 76, 76, 76, 76, 76, 76,
-        76, 76, 76, 76, 76, 76, 76, 76,
-        76, 76, 76, 76, 76, 76, 76, 101,
-        101, 101, 101, 101, 101, 101, 101, 101,
-        101, 101, 101, 101, 101, 101, 101, 101,
-        101, 101, 101, 101, 118, 118, 119, 119,
-        119, 119, 119, 119, 119, 119, 119, 119,
-        119, 119, 119, 119, 119, 119, 119, 119,
-        119, 119, 119, 101, 56, 56, 56, 56,
-        56, 56, 56, 56, 146, 146, 146, 146,
-        146, 118
+        57, 57, 57, 57, 57, 57, 57, 57,
+        57, 57, 57, 57, 57, 57, 57, 57,
+        57, 57, 57, 57, 57, 77, 77, 77,
+        77, 77, 77, 77, 77, 77, 77, 77,
+        77, 77, 77, 77, 77, 77, 77, 77,
+        77, 77, 77, 77, 77, 77, 77, 102,
+        102, 102, 102, 102, 102, 102, 102, 102,
+        102, 102, 102, 102, 27, 102, 102, 102,
+        102, 102, 102, 102, 119, 119, 120, 120,
+        120, 120, 120, 120, 120, 120, 120, 120,
+        120, 120, 120, 120, 120, 120, 120, 120,
+        120, 120, 120, 102, 57, 57, 57, 57,
+        57, 57, 57, 57, 147, 147, 147, 147,
+        147, 119
 };
 
 static const int indic_syllable_machine_start = 31;
@@ -441,7 +1107,7 @@ static const int indic_syllable_machine_
 
 
 
-#line 118 "hb-ot-shaper-indic-machine.rl"
+#line 121 "hb-ot-shaper-indic-machine.rl"
 
 
 #define found_syllable(syllable_type) \
@@ -460,7 +1126,7 @@ find_syllables_indic (hb_buffer_t *buffe
   int cs;
   hb_glyph_info_t *info = buffer->info;
 
-#line 464 "hb-ot-shaper-indic-machine.hh"
+#line 1130 "hb-ot-shaper-indic-machine.hh"
         {
         cs = indic_syllable_machine_start;
         ts = 0;
@@ -468,7 +1134,7 @@ find_syllables_indic (hb_buffer_t *buffe
         act = 0;
         }
 
-#line 138 "hb-ot-shaper-indic-machine.rl"
+#line 141 "hb-ot-shaper-indic-machine.rl"
 
 
   p = 0;
@@ -476,7 +1142,7 @@ find_syllables_indic (hb_buffer_t *buffe
 
   unsigned int syllable_serial = 1;
 
-#line 480 "hb-ot-shaper-indic-machine.hh"
+#line 1146 "hb-ot-shaper-indic-machine.hh"
         {
         int _slen;
         int _trans;
@@ -490,7 +1156,7 @@ _resume:
 #line 1 "NONE"
         {ts = p;}
         break;
-#line 494 "hb-ot-shaper-indic-machine.hh"
+#line 1160 "hb-ot-shaper-indic-machine.hh"
         }
 
         _keys = _indic_syllable_machine_trans_keys + (cs<<1);
@@ -513,51 +1179,51 @@ _eof_trans:
         {te = p+1;}
         break;
         case 11:
-#line 114 "hb-ot-shaper-indic-machine.rl"
+#line 117 "hb-ot-shaper-indic-machine.rl"
         {te = p+1;{ found_syllable (indic_non_indic_cluster); }}
         break;
-        case 13:
-#line 109 "hb-ot-shaper-indic-machine.rl"
+        case 14:
+#line 111 "hb-ot-shaper-indic-machine.rl"
         {te = p;p--;{ found_syllable (indic_consonant_syllable); }}
         break;
-        case 14:
-#line 110 "hb-ot-shaper-indic-machine.rl"
+        case 15:
+#line 112 "hb-ot-shaper-indic-machine.rl"
         {te = p;p--;{ found_syllable (indic_vowel_syllable); }}
         break;
-        case 17:
-#line 111 "hb-ot-shaper-indic-machine.rl"
+        case 18:
+#line 113 "hb-ot-shaper-indic-machine.rl"
         {te = p;p--;{ found_syllable (indic_standalone_cluster); }}
         break;
-        case 19:
-#line 112 "hb-ot-shaper-indic-machine.rl"
+        case 20:
+#line 114 "hb-ot-shaper-indic-machine.rl"
         {te = p;p--;{ found_syllable (indic_symbol_cluster); }}
         break;
-        case 15:
-#line 113 "hb-ot-shaper-indic-machine.rl"
+        case 16:
+#line 116 "hb-ot-shaper-indic-machine.rl"
         {te = p;p--;{ found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
         break;
-        case 16:
-#line 114 "hb-ot-shaper-indic-machine.rl"
+        case 17:
+#line 117 "hb-ot-shaper-indic-machine.rl"
         {te = p;p--;{ found_syllable (indic_non_indic_cluster); }}
         break;
         case 1:
-#line 109 "hb-ot-shaper-indic-machine.rl"
+#line 111 "hb-ot-shaper-indic-machine.rl"
         {{p = ((te))-1;}{ found_syllable (indic_consonant_syllable); }}
         break;
         case 3:
-#line 110 "hb-ot-shaper-indic-machine.rl"
+#line 112 "hb-ot-shaper-indic-machine.rl"
         {{p = ((te))-1;}{ found_syllable (indic_vowel_syllable); }}
         break;
         case 7:
-#line 111 "hb-ot-shaper-indic-machine.rl"
+#line 113 "hb-ot-shaper-indic-machine.rl"
         {{p = ((te))-1;}{ found_syllable (indic_standalone_cluster); }}
         break;
         case 8:
-#line 112 "hb-ot-shaper-indic-machine.rl"
+#line 114 "hb-ot-shaper-indic-machine.rl"
         {{p = ((te))-1;}{ found_syllable (indic_symbol_cluster); }}
         break;
         case 4:
-#line 113 "hb-ot-shaper-indic-machine.rl"
+#line 116 "hb-ot-shaper-indic-machine.rl"
         {{p = ((te))-1;}{ found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
         break;
         case 6:
@@ -567,33 +1233,42 @@ _eof_trans:
         {{p = ((te))-1;} found_syllable (indic_consonant_syllable); }
         break;
         case 5:
-        {{p = ((te))-1;} found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
+        {{p = ((te))-1;} found_syllable (indic_non_indic_cluster); }
         break;
         case 6:
+        {{p = ((te))-1;} found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
+        break;
+        case 7:
         {{p = ((te))-1;} found_syllable (indic_non_indic_cluster); }
         break;
         }
         }
         break;
-        case 18:
+        case 19:
 #line 1 "NONE"
         {te = p+1;}
-#line 109 "hb-ot-shaper-indic-machine.rl"
+#line 111 "hb-ot-shaper-indic-machine.rl"
         {act = 1;}
         break;
-        case 5:
+        case 13:
 #line 1 "NONE"
         {te = p+1;}
-#line 113 "hb-ot-shaper-indic-machine.rl"
+#line 115 "hb-ot-shaper-indic-machine.rl"
         {act = 5;}
         break;
-        case 12:
+        case 5:
 #line 1 "NONE"
         {te = p+1;}
-#line 114 "hb-ot-shaper-indic-machine.rl"
+#line 116 "hb-ot-shaper-indic-machine.rl"
         {act = 6;}
         break;
-#line 597 "hb-ot-shaper-indic-machine.hh"
+        case 12:
+#line 1 "NONE"
+        {te = p+1;}
+#line 117 "hb-ot-shaper-indic-machine.rl"
+        {act = 7;}
+        break;
+#line 1272 "hb-ot-shaper-indic-machine.hh"
         }
 
 _again:
@@ -602,7 +1277,7 @@ _again:
 #line 1 "NONE"
         {ts = 0;}
         break;
-#line 606 "hb-ot-shaper-indic-machine.hh"
+#line 1281 "hb-ot-shaper-indic-machine.hh"
         }
 
         if ( ++p != pe )
@@ -618,7 +1293,7 @@ _again:
 
         }
 
-#line 146 "hb-ot-shaper-indic-machine.rl"
+#line 149 "hb-ot-shaper-indic-machine.rl"
 
 }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-table.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-table.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-table.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-table.cc	2025-06-27 08:03:14.000000000 +0000
@@ -6,12 +6,12 @@
  *
  * on files with these headers:
  *
- * # IndicSyllabicCategory-15.1.0.txt
- * # Date: 2023-01-05
- * # IndicPositionalCategory-15.1.0.txt
- * # Date: 2023-01-05
- * # Blocks-15.1.0.txt
- * # Date: 2023-07-28, 15:47:20 GMT
+ * # IndicSyllabicCategory-16.0.0.txt
+ * # Date: 2024-04-30, 21:48:21 GMT
+ * # IndicPositionalCategory-16.0.0.txt
+ * # Date: 2024-04-30, 21:48:21 GMT
+ * # Blocks-16.0.0.txt
+ * # Date: 2024-02-02
  */
 
 #include "hb.hh"
@@ -48,6 +48,7 @@
 #define OT_CM I_Cat(CM)
 #define OT_Symbol I_Cat(Symbol)
 #define OT_CS I_Cat(CS)
+#define OT_SMPst I_Cat(SMPst)
 /* khmer */
 #define OT_VAbv K_Cat(VAbv)
 #define OT_VBlw K_Cat(VBlw)
@@ -89,12 +90,13 @@ static_assert (OT_VPst == M_Cat(VPst), "
 #define _OT_MW   OT_MW           /*   2 chars; MW */
 #define _OT_MY   OT_MY           /*   3 chars; MY */
 #define _OT_N    OT_N            /*  17 chars; N */
-#define _OT_GB   OT_PLACEHOLDER  /* 165 chars; PLACEHOLDER */
+#define _OT_GB   OT_PLACEHOLDER  /* 185 chars; PLACEHOLDER */
 #define _OT_PT   OT_PT           /*   8 chars; PT */
 #define _OT_R    OT_Ra           /*  14 chars; Ra */
 #define _OT_Rf   OT_Repha        /*   1 chars; Repha */
 #define _OT_Rt   OT_Robatic      /*   3 chars; Robatic */
-#define _OT_SM   OT_SM           /*  56 chars; SM */
+#define _OT_SM   OT_SM           /*  50 chars; SM */
+#define _OT_SP   OT_SMPst        /*   6 chars; SMPst */
 #define _OT_S    OT_Symbol       /*  22 chars; Symbol */
 #define _OT_V    OT_V            /* 172 chars; V */
 #define _OT_VA   OT_VAbv         /*  18 chars; VAbv */
@@ -112,7 +114,7 @@ static_assert (OT_VPst == M_Cat(VPst), "
 #define _POS_A   POS_AFTER_MAIN  /*   3 chars; AFTER_MAIN */
 #define _POS_AP  POS_AFTER_POST  /*  50 chars; AFTER_POST */
 #define _POS_AS  POS_AFTER_SUB   /*  51 chars; AFTER_SUB */
-#define _POS_C   POS_BASE_C      /* 833 chars; BASE_C */
+#define _POS_C   POS_BASE_C      /* 853 chars; BASE_C */
 #define _POS_BS  POS_BEFORE_SUB  /*  25 chars; BEFORE_SUB */
 #define _POS_B   POS_BELOW_C     /*  13 chars; BELOW_C */
 #define _POS_X   POS_END         /*  71 chars; END */
@@ -145,7 +147,7 @@ static const uint16_t indic_table[] = {
 
   /* Latin-1 Supplement */
 
-  /* 00B0 */  _(X,X),  _(X,X),_(SM,SM),_(SM,SM),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
+  /* 00B0 */  _(X,X),  _(X,X),_(SP,SM),_(SP,SM),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
   /* 00B8 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
   /* 00C0 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
   /* 00C8 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
@@ -398,9 +400,9 @@ static const uint16_t indic_table[] = {
 
   /* Superscripts and Subscripts */
 
-  /* 2070 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),_(SM,SM),  _(X,X),  _(X,X),  _(X,X),
+  /* 2070 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),_(SP,SM),  _(X,X),  _(X,X),  _(X,X),
   /* 2078 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
-  /* 2080 */  _(X,X),  _(X,X),_(SM,SM),_(SM,SM),_(SM,SM),  _(X,X),  _(X,X),  _(X,X),
+  /* 2080 */  _(X,X),  _(X,X),_(SP,SM),_(SP,SM),_(SP,SM),  _(X,X),  _(X,X),  _(X,X),
 
 #define indic_offset_0x25f8u 1592
 
@@ -458,7 +460,16 @@ static const uint16_t indic_table[] = {
 
   /* 11338 */  _(X,X),  _(X,X),  _(X,X),  _(N,X),  _(N,X),  _(X,X),  _(X,X),  _(X,X),
 
-}; /* Table items: 1728; occupancy: 71% */
+#define indic_offset_0x116d0u 1728
+
+
+  /* Myanmar Extended-C */
+
+  /* 116D0 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+  /* 116D8 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+  /* 116E0 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
+
+}; /* Table items: 1752; occupancy: 71% */
 
 uint16_t
 hb_indic_get_categories (hb_codepoint_t u)
@@ -498,6 +509,7 @@ hb_indic_get_categories (hb_codepoint_t
     case 0x11u:
       if (hb_in_range<hb_codepoint_t> (u, 0x11300u, 0x11307u)) return indic_table[u - 0x11300u + indic_offset_0x11300u];
       if (hb_in_range<hb_codepoint_t> (u, 0x11338u, 0x1133Fu)) return indic_table[u - 0x11338u + indic_offset_0x11338u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x116D0u, 0x116E7u)) return indic_table[u - 0x116D0u + indic_offset_0x116d0u];
       break;
 
     default:
@@ -530,6 +542,7 @@ hb_indic_get_categories (hb_codepoint_t
 #undef _OT_Rf
 #undef _OT_Rt
 #undef _OT_SM
+#undef _OT_SP
 #undef _OT_S
 #undef _OT_V
 #undef _OT_VA
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-myanmar-machine.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-myanmar-machine.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-myanmar-machine.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-myanmar-machine.hh	2025-06-27 08:03:14.000000000 +0000
@@ -68,6 +68,7 @@ enum myanmar_syllable_type_t {
 #define myanmar_syllable_machine_ex_PT 39u
 #define myanmar_syllable_machine_ex_Ra 15u
 #define myanmar_syllable_machine_ex_SM 8u
+#define myanmar_syllable_machine_ex_SMPst 57u
 #define myanmar_syllable_machine_ex_VAbv 20u
 #define myanmar_syllable_machine_ex_VBlw 21u
 #define myanmar_syllable_machine_ex_VPre 22u
@@ -77,35 +78,35 @@ enum myanmar_syllable_type_t {
 #define myanmar_syllable_machine_ex_ZWNJ 5u
 
 
-#line 81 "hb-ot-shaper-myanmar-machine.hh"
+#line 82 "hb-ot-shaper-myanmar-machine.hh"
 static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
-        1u, 41u, 3u, 41u, 5u, 39u, 5u, 8u, 3u, 41u, 3u, 39u, 3u, 39u, 5u, 39u,
-        5u, 39u, 3u, 39u, 3u, 39u, 3u, 41u, 5u, 39u, 1u, 15u, 3u, 39u, 3u, 39u,
-        3u, 40u, 3u, 39u, 3u, 41u, 3u, 41u, 3u, 39u, 3u, 41u, 3u, 41u, 3u, 41u,
-        3u, 41u, 3u, 41u, 5u, 39u, 5u, 8u, 3u, 41u, 3u, 39u, 3u, 39u, 5u, 39u,
-        5u, 39u, 3u, 39u, 3u, 39u, 3u, 41u, 5u, 39u, 1u, 15u, 3u, 41u, 3u, 39u,
-        3u, 39u, 3u, 40u, 3u, 39u, 3u, 41u, 3u, 41u, 3u, 39u, 3u, 41u, 3u, 41u,
-        3u, 41u, 3u, 41u, 3u, 41u, 3u, 41u, 3u, 41u, 1u, 41u, 1u, 15u, 0
+        1u, 57u, 3u, 57u, 5u, 57u, 5u, 57u, 3u, 57u, 5u, 57u, 3u, 57u, 3u, 57u,
+        3u, 57u, 3u, 57u, 3u, 57u, 5u, 57u, 1u, 15u, 3u, 57u, 3u, 57u, 3u, 57u,
+        3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u,
+        3u, 57u, 5u, 57u, 5u, 57u, 3u, 57u, 5u, 57u, 3u, 57u, 3u, 57u, 3u, 57u,
+        3u, 57u, 3u, 57u, 5u, 57u, 1u, 15u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u,
+        3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u,
+        3u, 57u, 3u, 57u, 3u, 57u, 1u, 57u, 1u, 15u, 0
 };
 
 static const char _myanmar_syllable_machine_key_spans[] = {
-        41, 39, 35, 4, 39, 37, 37, 35,
-        35, 37, 37, 39, 35, 15, 37, 37,
-        38, 37, 39, 39, 37, 39, 39, 39,
-        39, 39, 35, 4, 39, 37, 37, 35,
-        35, 37, 37, 39, 35, 15, 39, 37,
-        37, 38, 37, 39, 39, 37, 39, 39,
-        39, 39, 39, 39, 39, 41, 15
+        57, 55, 53, 53, 55, 53, 55, 55,
+        55, 55, 55, 53, 15, 55, 55, 55,
+        55, 55, 55, 55, 55, 55, 55, 55,
+        55, 53, 53, 55, 53, 55, 55, 55,
+        55, 55, 53, 15, 55, 55, 55, 55,
+        55, 55, 55, 55, 55, 55, 55, 55,
+        55, 55, 55, 57, 15
 };
 
 static const short _myanmar_syllable_machine_index_offsets[] = {
-        0, 42, 82, 118, 123, 163, 201, 239,
-        275, 311, 349, 387, 427, 463, 479, 517,
-        555, 594, 632, 672, 712, 750, 790, 830,
-        870, 910, 950, 986, 991, 1031, 1069, 1107,
-        1143, 1179, 1217, 1255, 1295, 1331, 1347, 1387,
-        1425, 1463, 1502, 1540, 1580, 1620, 1658, 1698,
-        1738, 1778, 1818, 1858, 1898, 1938, 1980
+        0, 58, 114, 168, 222, 278, 332, 388,
+        444, 500, 556, 612, 666, 682, 738, 794,
+        850, 906, 962, 1018, 1074, 1130, 1186, 1242,
+        1298, 1354, 1408, 1462, 1518, 1572, 1628, 1684,
+        1740, 1796, 1852, 1906, 1922, 1978, 2034, 2090,
+        2146, 2202, 2258, 2314, 2370, 2426, 2482, 2538,
+        2594, 2650, 2706, 2762, 2820
 };
 
 static const char _myanmar_syllable_machine_indicies[] = {
@@ -114,273 +115,378 @@ static const char _myanmar_syllable_mach
         0, 8, 0, 9, 10, 11, 12, 0,
         0, 0, 0, 0, 0, 0, 0, 13,
         0, 0, 14, 15, 16, 17, 18, 19,
-        20, 0, 22, 23, 24, 24, 21, 25,
-        26, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 27, 28, 29, 30, 21,
-        21, 21, 21, 21, 21, 21, 21, 31,
-        21, 21, 32, 33, 34, 35, 36, 37,
-        38, 21, 24, 24, 21, 25, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 30, 21, 21, 21,
-        21, 21, 21, 21, 21, 39, 21, 21,
-        21, 21, 21, 21, 36, 21, 24, 24,
-        21, 25, 21, 22, 21, 24, 24, 21,
-        25, 26, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 40, 21, 21, 30,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        41, 21, 21, 42, 21, 21, 21, 36,
-        21, 41, 21, 22, 21, 24, 24, 21,
-        25, 26, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 30,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 36,
-        21, 43, 21, 24, 24, 21, 25, 36,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 44, 21,
-        21, 21, 21, 21, 21, 36, 21, 24,
-        24, 21, 25, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 44, 21, 21, 21, 21, 21,
-        21, 36, 21, 24, 24, 21, 25, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 36, 21, 22,
-        21, 24, 24, 21, 25, 26, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        40, 21, 21, 30, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 36, 21, 22, 21, 24,
-        24, 21, 25, 26, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 40, 21,
-        21, 30, 21, 21, 21, 21, 21, 21,
-        21, 21, 41, 21, 21, 21, 21, 21,
-        21, 36, 21, 22, 21, 24, 24, 21,
-        25, 26, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 40, 21, 21, 30,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        41, 21, 21, 21, 21, 21, 21, 36,
-        21, 41, 21, 24, 24, 21, 25, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 30, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 36, 21, 1,
-        1, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 1, 21, 22,
-        21, 24, 24, 21, 25, 26, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        27, 28, 21, 30, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 36, 21, 22, 21, 24,
-        24, 21, 25, 26, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 28,
-        21, 30, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 36, 21, 22, 21, 24, 24, 21,
-        25, 26, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 27, 28, 29, 30,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 36,
-        45, 21, 22, 21, 24, 24, 21, 25,
-        26, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 27, 28, 29, 30, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 36, 21,
-        22, 21, 24, 24, 21, 25, 26, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 27, 28, 29, 30, 21, 21, 21,
-        21, 21, 21, 21, 21, 31, 21, 21,
-        32, 33, 34, 35, 36, 21, 38, 21,
-        22, 21, 24, 24, 21, 25, 26, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 27, 28, 29, 30, 21, 21, 21,
-        21, 21, 21, 21, 21, 45, 21, 21,
-        21, 21, 21, 21, 36, 21, 38, 21,
-        22, 21, 24, 24, 21, 25, 26, 21,
-        21, 21, 21, 21, 21, 21, 21, 21,
-        21, 27, 28, 29, 30, 21, 21, 21,
-        21, 21, 21, 21, 21, 45, 21, 21,
-        21, 21, 21, 21, 36, 21, 22, 21,
-        24, 24, 21, 25, 26, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 27,
-        28, 29, 30, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 32, 21,
-        34, 21, 36, 21, 38, 21, 22, 21,
-        24, 24, 21, 25, 26, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 27,
-        28, 29, 30, 21, 21, 21, 21, 21,
-        21, 21, 21, 45, 21, 21, 32, 21,
-        21, 21, 36, 21, 38, 21, 22, 21,
-        24, 24, 21, 25, 26, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 27,
-        28, 29, 30, 21, 21, 21, 21, 21,
-        21, 21, 21, 46, 21, 21, 32, 33,
-        34, 21, 36, 21, 38, 21, 22, 21,
-        24, 24, 21, 25, 26, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 27,
-        28, 29, 30, 21, 21, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 32, 33,
-        34, 21, 36, 21, 38, 21, 22, 23,
-        24, 24, 21, 25, 26, 21, 21, 21,
-        21, 21, 21, 21, 21, 21, 21, 27,
-        28, 29, 30, 21, 21, 21, 21, 21,
-        21, 21, 21, 31, 21, 21, 32, 33,
-        34, 35, 36, 21, 38, 21, 48, 48,
+        20, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        21, 0, 23, 24, 25, 25, 22, 26,
+        27, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 28, 29, 30, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 32,
+        22, 22, 33, 34, 35, 36, 37, 38,
+        39, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 25, 25, 22, 26, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 31, 22, 22, 22,
+        22, 22, 22, 22, 22, 40, 22, 22,
+        22, 22, 22, 22, 37, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 26, 22,
+        25, 25, 22, 26, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 37, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 26, 22, 41, 22,
+        25, 25, 22, 26, 37, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 26, 22, 22, 22, 22,
+        22, 22, 37, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 26, 22, 25, 25,
+        22, 26, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 26, 22, 22, 22, 22, 22, 22,
+        37, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 26, 22, 23, 22, 25, 25,
+        22, 26, 27, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 42, 22, 22,
+        31, 22, 22, 22, 22, 22, 22, 22,
+        22, 43, 22, 22, 44, 22, 22, 22,
+        37, 22, 43, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 26, 22, 23, 22, 25, 25,
+        22, 26, 27, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        31, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        37, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 26, 22, 23, 22, 25, 25,
+        22, 26, 27, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 42, 22, 22,
+        31, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        37, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 26, 22, 23, 22, 25, 25,
+        22, 26, 27, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 42, 22, 22,
+        31, 22, 22, 22, 22, 22, 22, 22,
+        22, 43, 22, 22, 22, 22, 22, 22,
+        37, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 26, 22, 23, 22, 25, 25,
+        22, 26, 27, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 42, 22, 22,
+        31, 22, 22, 22, 22, 22, 22, 22,
+        22, 43, 22, 22, 22, 22, 22, 22,
+        37, 22, 43, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 26, 22, 25, 25, 22, 26,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 37, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 1, 1, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        1, 22, 23, 22, 25, 25, 22, 26,
+        27, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 28, 29, 22, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 37, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 23, 22, 25, 25, 22, 26,
+        27, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 29, 22, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 37, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 23, 22, 25, 25, 22, 26,
+        27, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 28, 29, 30, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 37, 45,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 23, 22, 25, 25, 22, 26,
+        27, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 28, 29, 30, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 37, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 23, 22, 25, 25, 22, 26,
+        27, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 28, 29, 30, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 32,
+        22, 22, 33, 34, 35, 36, 37, 22,
+        39, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 23, 22, 25, 25, 22, 26,
+        27, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 28, 29, 30, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 45,
+        22, 22, 22, 22, 22, 22, 37, 22,
+        39, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 23, 22, 25, 25, 22, 26,
+        27, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 28, 29, 30, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 45,
+        22, 22, 22, 22, 22, 22, 37, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 23, 22, 25, 25, 22, 26,
+        27, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 28, 29, 30, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 33, 22, 35, 22, 37, 22,
+        39, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 23, 22, 25, 25, 22, 26,
+        27, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 28, 29, 30, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 45,
+        22, 22, 33, 22, 22, 22, 37, 22,
+        39, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 23, 22, 25, 25, 22, 26,
+        27, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 28, 29, 30, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 46,
+        22, 22, 33, 34, 35, 22, 37, 22,
+        39, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 23, 22, 25, 25, 22, 26,
+        27, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 28, 29, 30, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 33, 34, 35, 22, 37, 22,
+        39, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 23, 24, 25, 25, 22, 26,
+        27, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 28, 29, 30, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 32,
+        22, 22, 33, 34, 35, 36, 37, 22,
+        39, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 48, 48, 47, 5, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 12, 47, 47, 47,
+        47, 47, 47, 47, 47, 49, 47, 47,
+        47, 47, 47, 47, 18, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 5, 47,
+        48, 48, 50, 5, 50, 50, 50, 50,
+        50, 50, 50, 50, 50, 50, 50, 50,
+        50, 50, 50, 50, 50, 50, 50, 50,
+        50, 50, 50, 50, 50, 50, 50, 50,
+        50, 50, 18, 50, 50, 50, 50, 50,
+        50, 50, 50, 50, 50, 50, 50, 50,
+        50, 50, 50, 50, 5, 50, 51, 47,
+        48, 48, 47, 5, 18, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 5, 47, 47, 47, 47,
+        47, 47, 18, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 5, 47, 48, 48,
         47, 5, 47, 47, 47, 47, 47, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        47, 5, 47, 47, 47, 47, 47, 47,
+        18, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 5, 47, 2, 47, 48, 48,
+        47, 5, 6, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 52, 47, 47,
         12, 47, 47, 47, 47, 47, 47, 47,
-        47, 49, 47, 47, 47, 47, 47, 47,
-        18, 47, 48, 48, 47, 5, 47, 2,
-        47, 48, 48, 47, 5, 6, 47, 47,
+        47, 53, 47, 47, 54, 47, 47, 47,
+        18, 47, 53, 47, 47, 47, 47, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        50, 47, 47, 12, 47, 47, 47, 47,
-        47, 47, 47, 47, 51, 47, 47, 52,
-        47, 47, 47, 18, 47, 51, 47, 2,
-        47, 48, 48, 47, 5, 6, 47, 47,
+        47, 47, 5, 47, 2, 47, 48, 48,
+        47, 5, 6, 47, 47, 47, 47, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        47, 47, 47, 12, 47, 47, 47, 47,
+        12, 47, 47, 47, 47, 47, 47, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        47, 47, 47, 18, 47, 53, 47, 48,
-        48, 47, 5, 18, 47, 47, 47, 47,
+        18, 47, 47, 47, 47, 47, 47, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 5, 47, 2, 47, 48, 48,
+        47, 5, 6, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 52, 47, 47,
+        12, 47, 47, 47, 47, 47, 47, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        47, 47, 54, 47, 47, 47, 47, 47,
-        47, 18, 47, 48, 48, 47, 5, 47,
+        18, 47, 47, 47, 47, 47, 47, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 5, 47, 2, 47, 48, 48,
+        47, 5, 6, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 52, 47, 47,
+        12, 47, 47, 47, 47, 47, 47, 47,
+        47, 53, 47, 47, 47, 47, 47, 47,
+        18, 47, 47, 47, 47, 47, 47, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        47, 47, 47, 47, 47, 47, 54, 47,
-        47, 47, 47, 47, 47, 18, 47, 48,
-        48, 47, 5, 47, 47, 47, 47, 47,
+        47, 47, 5, 47, 2, 47, 48, 48,
+        47, 5, 6, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 52, 47, 47,
+        12, 47, 47, 47, 47, 47, 47, 47,
+        47, 53, 47, 47, 47, 47, 47, 47,
+        18, 47, 53, 47, 47, 47, 47, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 5, 47, 48, 48, 47, 5,
         47, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 12, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        47, 18, 47, 2, 47, 48, 48, 47,
-        5, 6, 47, 47, 47, 47, 47, 47,
-        47, 47, 47, 47, 50, 47, 47, 12,
+        47, 47, 47, 47, 47, 47, 18, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        47, 47, 47, 47, 47, 47, 47, 18,
-        47, 2, 47, 48, 48, 47, 5, 6,
         47, 47, 47, 47, 47, 47, 47, 47,
-        47, 47, 50, 47, 47, 12, 47, 47,
-        47, 47, 47, 47, 47, 47, 51, 47,
-        47, 47, 47, 47, 47, 18, 47, 2,
-        47, 48, 48, 47, 5, 6, 47, 47,
+        5, 47, 55, 55, 47, 47, 47, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        50, 47, 47, 12, 47, 47, 47, 47,
-        47, 47, 47, 47, 51, 47, 47, 47,
-        47, 47, 47, 18, 47, 51, 47, 48,
-        48, 47, 5, 47, 47, 47, 47, 47,
+        55, 47, 2, 3, 48, 48, 47, 5,
+        6, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 9, 10, 11, 12, 47,
+        47, 47, 47, 47, 47, 47, 47, 13,
+        47, 47, 14, 15, 16, 17, 18, 19,
+        20, 47, 47, 47, 47, 47, 47, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        47, 12, 47, 47, 47, 47, 47, 47,
+        5, 47, 2, 47, 48, 48, 47, 5,
+        6, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 9, 10, 47, 12, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        47, 18, 47, 55, 55, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 18, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        47, 55, 47, 2, 3, 48, 48, 47,
-        5, 6, 47, 47, 47, 47, 47, 47,
-        47, 47, 47, 47, 9, 10, 11, 12,
         47, 47, 47, 47, 47, 47, 47, 47,
-        13, 47, 47, 14, 15, 16, 17, 18,
-        19, 20, 47, 2, 47, 48, 48, 47,
-        5, 6, 47, 47, 47, 47, 47, 47,
-        47, 47, 47, 47, 9, 10, 47, 12,
+        5, 47, 2, 47, 48, 48, 47, 5,
+        6, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 10, 47, 12, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        47, 47, 47, 47, 47, 47, 47, 18,
-        47, 2, 47, 48, 48, 47, 5, 6,
+        47, 47, 47, 47, 47, 47, 18, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        47, 47, 47, 10, 47, 12, 47, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        47, 47, 47, 47, 47, 18, 47, 2,
-        47, 48, 48, 47, 5, 6, 47, 47,
+        5, 47, 2, 47, 48, 48, 47, 5,
+        6, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 9, 10, 11, 12, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        9, 10, 11, 12, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 18, 56,
         47, 47, 47, 47, 47, 47, 47, 47,
-        47, 47, 47, 18, 56, 47, 2, 47,
-        48, 48, 47, 5, 6, 47, 47, 47,
-        47, 47, 47, 47, 47, 47, 47, 9,
-        10, 11, 12, 47, 47, 47, 47, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
-        47, 47, 18, 47, 2, 47, 48, 48,
-        47, 5, 6, 47, 47, 47, 47, 47,
-        47, 47, 47, 47, 47, 9, 10, 11,
-        12, 47, 47, 47, 47, 47, 47, 47,
-        47, 13, 47, 47, 14, 15, 16, 17,
-        18, 47, 20, 47, 2, 47, 48, 48,
-        47, 5, 6, 47, 47, 47, 47, 47,
-        47, 47, 47, 47, 47, 9, 10, 11,
-        12, 47, 47, 47, 47, 47, 47, 47,
-        47, 56, 47, 47, 47, 47, 47, 47,
-        18, 47, 20, 47, 2, 47, 48, 48,
-        47, 5, 6, 47, 47, 47, 47, 47,
-        47, 47, 47, 47, 47, 9, 10, 11,
-        12, 47, 47, 47, 47, 47, 47, 47,
-        47, 56, 47, 47, 47, 47, 47, 47,
-        18, 47, 2, 47, 48, 48, 47, 5,
+        5, 47, 2, 47, 48, 48, 47, 5,
+        6, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 9, 10, 11, 12, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 18, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        5, 47, 2, 47, 48, 48, 47, 5,
+        6, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 9, 10, 11, 12, 47,
+        47, 47, 47, 47, 47, 47, 47, 13,
+        47, 47, 14, 15, 16, 17, 18, 47,
+        20, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        5, 47, 2, 47, 48, 48, 47, 5,
+        6, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 9, 10, 11, 12, 47,
+        47, 47, 47, 47, 47, 47, 47, 56,
+        47, 47, 47, 47, 47, 47, 18, 47,
+        20, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        5, 47, 2, 47, 48, 48, 47, 5,
+        6, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 9, 10, 11, 12, 47,
+        47, 47, 47, 47, 47, 47, 47, 56,
+        47, 47, 47, 47, 47, 47, 18, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        5, 47, 2, 47, 48, 48, 47, 5,
         6, 47, 47, 47, 47, 47, 47, 47,
         47, 47, 47, 9, 10, 11, 12, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
         47, 47, 14, 47, 16, 47, 18, 47,
-        20, 47, 2, 47, 48, 48, 47, 5,
+        20, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        5, 47, 2, 47, 48, 48, 47, 5,
         6, 47, 47, 47, 47, 47, 47, 47,
         47, 47, 47, 9, 10, 11, 12, 47,
         47, 47, 47, 47, 47, 47, 47, 56,
         47, 47, 14, 47, 47, 47, 18, 47,
-        20, 47, 2, 47, 48, 48, 47, 5,
+        20, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        5, 47, 2, 47, 48, 48, 47, 5,
         6, 47, 47, 47, 47, 47, 47, 47,
         47, 47, 47, 9, 10, 11, 12, 47,
         47, 47, 47, 47, 47, 47, 47, 57,
         47, 47, 14, 15, 16, 47, 18, 47,
-        20, 47, 2, 47, 48, 48, 47, 5,
+        20, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        5, 47, 2, 47, 48, 48, 47, 5,
         6, 47, 47, 47, 47, 47, 47, 47,
         47, 47, 47, 9, 10, 11, 12, 47,
         47, 47, 47, 47, 47, 47, 47, 47,
         47, 47, 14, 15, 16, 47, 18, 47,
-        20, 47, 2, 3, 48, 48, 47, 5,
+        20, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        5, 47, 2, 3, 48, 48, 47, 5,
         6, 47, 47, 47, 47, 47, 47, 47,
         47, 47, 47, 9, 10, 11, 12, 47,
         47, 47, 47, 47, 47, 47, 47, 13,
         47, 47, 14, 15, 16, 17, 18, 47,
-        20, 47, 22, 23, 24, 24, 21, 25,
-        26, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 27, 28, 29, 30, 21,
-        21, 21, 21, 21, 21, 21, 21, 58,
-        21, 21, 32, 33, 34, 35, 36, 37,
-        38, 21, 22, 59, 24, 24, 21, 25,
-        26, 21, 21, 21, 21, 21, 21, 21,
-        21, 21, 21, 27, 28, 29, 30, 21,
-        21, 21, 21, 21, 21, 21, 21, 31,
-        21, 21, 32, 33, 34, 35, 36, 21,
-        38, 21, 1, 1, 2, 3, 48, 48,
+        20, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        5, 47, 23, 24, 25, 25, 22, 26,
+        27, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 28, 29, 30, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 58,
+        22, 22, 33, 34, 35, 36, 37, 38,
+        39, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 23, 59, 25, 25, 22, 26,
+        27, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 28, 29, 30, 31, 22,
+        22, 22, 22, 22, 22, 22, 22, 32,
+        22, 22, 33, 34, 35, 36, 37, 22,
+        39, 22, 22, 22, 22, 22, 22, 22,
+        22, 22, 22, 22, 22, 22, 22, 22,
+        26, 22, 1, 1, 2, 3, 48, 48,
         47, 5, 6, 1, 1, 47, 47, 47,
         1, 47, 47, 47, 47, 9, 10, 11,
         12, 47, 47, 47, 47, 47, 47, 47,
         47, 13, 47, 47, 14, 15, 16, 17,
-        18, 19, 20, 47, 1, 1, 60, 60,
+        18, 19, 20, 47, 47, 47, 47, 47,
+        47, 47, 47, 47, 47, 47, 47, 47,
+        47, 47, 5, 47, 1, 1, 60, 60,
         60, 60, 60, 60, 60, 1, 1, 60,
         60, 60, 1, 60, 0
 };
 
 static const char _myanmar_syllable_machine_trans_targs[] = {
-        0, 1, 26, 37, 0, 27, 29, 51,
-        54, 39, 40, 41, 28, 43, 44, 46,
-        47, 48, 30, 50, 45, 0, 2, 13,
-        0, 3, 5, 14, 15, 16, 4, 18,
-        19, 21, 22, 23, 6, 25, 20, 12,
-        9, 10, 11, 7, 8, 17, 24, 0,
-        0, 36, 33, 34, 35, 31, 32, 38,
-        42, 49, 52, 53, 0
+        0, 1, 25, 35, 0, 26, 30, 49,
+        52, 37, 38, 39, 29, 41, 42, 44,
+        45, 46, 27, 48, 43, 26, 0, 2,
+        12, 0, 3, 7, 13, 14, 15, 6,
+        17, 18, 20, 21, 22, 4, 24, 19,
+        11, 5, 8, 9, 10, 16, 23, 0,
+        0, 34, 0, 28, 31, 32, 33, 36,
+        40, 47, 50, 51, 0
 };
 
 static const char _myanmar_syllable_machine_trans_actions[] = {
-        3, 0, 0, 0, 4, 0, 0, 0,
+        3, 0, 0, 0, 4, 5, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 5, 0, 0,
-        6, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 6, 7, 0,
+        0, 8, 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, 9
+        0, 0, 0, 0, 0, 0, 0, 9,
+        10, 0, 11, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 12
 };
 
 static const char _myanmar_syllable_machine_to_state_actions[] = {
@@ -390,7 +496,7 @@ static const char _myanmar_syllable_mach
         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
 };
 
 static const char _myanmar_syllable_machine_from_state_actions[] = {
@@ -400,17 +506,17 @@ static const char _myanmar_syllable_mach
         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
 };
 
 static const short _myanmar_syllable_machine_eof_trans[] = {
-        0, 22, 22, 22, 22, 22, 22, 22,
-        22, 22, 22, 22, 22, 22, 22, 22,
-        22, 22, 22, 22, 22, 22, 22, 22,
-        22, 22, 48, 48, 48, 48, 48, 48,
+        0, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23,
+        23, 23, 23, 23, 23, 23, 23, 23,
+        23, 48, 51, 48, 48, 48, 48, 48,
         48, 48, 48, 48, 48, 48, 48, 48,
         48, 48, 48, 48, 48, 48, 48, 48,
-        48, 48, 48, 22, 22, 48, 61
+        48, 23, 23, 48, 61
 };
 
 static const int myanmar_syllable_machine_start = 0;
@@ -424,7 +530,7 @@ static const int myanmar_syllable_machin
 
 
 
-#line 117 "hb-ot-shaper-myanmar-machine.rl"
+#line 118 "hb-ot-shaper-myanmar-machine.rl"
 
 
 #define found_syllable(syllable_type) \
@@ -443,7 +549,7 @@ find_syllables_myanmar (hb_buffer_t *buf
   int cs;
   hb_glyph_info_t *info = buffer->info;
 
-#line 447 "hb-ot-shaper-myanmar-machine.hh"
+#line 553 "hb-ot-shaper-myanmar-machine.hh"
         {
         cs = myanmar_syllable_machine_start;
         ts = 0;
@@ -451,7 +557,7 @@ find_syllables_myanmar (hb_buffer_t *buf
         act = 0;
         }
 
-#line 137 "hb-ot-shaper-myanmar-machine.rl"
+#line 138 "hb-ot-shaper-myanmar-machine.rl"
 
 
   p = 0;
@@ -459,7 +565,7 @@ find_syllables_myanmar (hb_buffer_t *buf
 
   unsigned int syllable_serial = 1;
 
-#line 463 "hb-ot-shaper-myanmar-machine.hh"
+#line 569 "hb-ot-shaper-myanmar-machine.hh"
         {
         int _slen;
         int _trans;
@@ -473,7 +579,7 @@ _resume:
 #line 1 "NONE"
         {ts = p;}
         break;
-#line 477 "hb-ot-shaper-myanmar-machine.hh"
+#line 583 "hb-ot-shaper-myanmar-machine.hh"
         }
 
         _keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
@@ -491,35 +597,59 @@ _eof_trans:
                 goto _again;
 
         switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
-        case 6:
-#line 110 "hb-ot-shaper-myanmar-machine.rl"
+        case 8:
+#line 111 "hb-ot-shaper-myanmar-machine.rl"
         {te = p+1;{ found_syllable (myanmar_consonant_syllable); }}
         break;
         case 4:
-#line 111 "hb-ot-shaper-myanmar-machine.rl"
+#line 112 "hb-ot-shaper-myanmar-machine.rl"
         {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
         break;
-        case 8:
-#line 112 "hb-ot-shaper-myanmar-machine.rl"
+        case 10:
+#line 113 "hb-ot-shaper-myanmar-machine.rl"
         {te = p+1;{ found_syllable (myanmar_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
         break;
         case 3:
-#line 113 "hb-ot-shaper-myanmar-machine.rl"
+#line 114 "hb-ot-shaper-myanmar-machine.rl"
         {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
         break;
-        case 5:
-#line 110 "hb-ot-shaper-myanmar-machine.rl"
-        {te = p;p--;{ found_syllable (myanmar_consonant_syllable); }}
-        break;
         case 7:
-#line 112 "hb-ot-shaper-myanmar-machine.rl"
-        {te = p;p--;{ found_syllable (myanmar_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+#line 111 "hb-ot-shaper-myanmar-machine.rl"
+        {te = p;p--;{ found_syllable (myanmar_consonant_syllable); }}
         break;
         case 9:
 #line 113 "hb-ot-shaper-myanmar-machine.rl"
+        {te = p;p--;{ found_syllable (myanmar_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+        break;
+        case 12:
+#line 114 "hb-ot-shaper-myanmar-machine.rl"
         {te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }}
         break;
-#line 523 "hb-ot-shaper-myanmar-machine.hh"
+        case 11:
+#line 1 "NONE"
+        {       switch( act ) {
+        case 2:
+        {{p = ((te))-1;} found_syllable (myanmar_non_myanmar_cluster); }
+        break;
+        case 3:
+        {{p = ((te))-1;} found_syllable (myanmar_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
+        break;
+        }
+        }
+        break;
+        case 6:
+#line 1 "NONE"
+        {te = p+1;}
+#line 112 "hb-ot-shaper-myanmar-machine.rl"
+        {act = 2;}
+        break;
+        case 5:
+#line 1 "NONE"
+        {te = p+1;}
+#line 113 "hb-ot-shaper-myanmar-machine.rl"
+        {act = 3;}
+        break;
+#line 653 "hb-ot-shaper-myanmar-machine.hh"
         }
 
 _again:
@@ -528,7 +658,7 @@ _again:
 #line 1 "NONE"
         {ts = 0;}
         break;
-#line 532 "hb-ot-shaper-myanmar-machine.hh"
+#line 662 "hb-ot-shaper-myanmar-machine.hh"
         }
 
         if ( ++p != pe )
@@ -544,7 +674,7 @@ _again:
 
         }
 
-#line 145 "hb-ot-shaper-myanmar-machine.rl"
+#line 146 "hb-ot-shaper-myanmar-machine.rl"
 
 }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-machine.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-machine.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-machine.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-machine.hh	2025-06-27 08:03:14.000000000 +0000
@@ -81,6 +81,7 @@ enum use_syllable_type_t {
 #define use_syllable_machine_ex_N 4u
 #define use_syllable_machine_ex_O 0u
 #define use_syllable_machine_ex_R 18u
+#define use_syllable_machine_ex_RK 56u
 #define use_syllable_machine_ex_SB 51u
 #define use_syllable_machine_ex_SE 52u
 #define use_syllable_machine_ex_SMAbv 41u
@@ -99,62 +100,62 @@ enum use_syllable_type_t {
 #define use_syllable_machine_ex_ZWNJ 14u
 
 
-#line 103 "hb-ot-shaper-use-machine.hh"
+#line 104 "hb-ot-shaper-use-machine.hh"
 static const unsigned char _use_syllable_machine_trans_keys[] = {
-        49u, 51u, 0u, 53u, 11u, 53u, 11u, 53u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u,
+        49u, 51u, 0u, 56u, 11u, 56u, 11u, 56u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u,
         14u, 47u, 14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u,
         14u, 48u, 14u, 53u, 14u, 53u, 14u, 53u, 14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u,
-        12u, 53u, 12u, 53u, 11u, 53u, 1u, 14u, 1u, 48u, 14u, 42u, 14u, 42u, 11u, 53u,
+        12u, 53u, 12u, 53u, 11u, 56u, 1u, 14u, 1u, 48u, 14u, 42u, 14u, 42u, 11u, 56u,
         1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u, 14u, 46u, 14u, 46u, 14u, 14u,
         14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u, 14u, 53u, 14u, 53u, 14u, 53u,
-        14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 53u, 1u, 14u,
-        1u, 14u, 1u, 48u, 13u, 14u, 4u, 14u, 11u, 53u, 11u, 53u, 1u, 53u, 14u, 48u,
-        14u, 47u, 14u, 47u, 14u, 47u, 14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u, 14u, 48u,
-        14u, 48u, 1u, 14u, 14u, 48u, 14u, 53u, 14u, 53u, 14u, 53u, 14u, 53u, 12u, 53u,
-        14u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 53u, 1u, 14u, 1u, 14u, 1u, 48u,
-        11u, 53u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u, 14u, 46u, 14u, 46u,
-        14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u, 14u, 53u, 14u, 53u,
-        14u, 53u, 14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 53u,
-        1u, 14u, 1u, 48u, 4u, 14u, 13u, 14u, 1u, 53u, 14u, 42u, 14u, 42u, 1u, 5u,
-        14u, 55u, 14u, 51u, 14u, 52u, 14u, 54u, 11u, 53u, 0
+        14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 56u, 1u, 14u,
+        1u, 14u, 1u, 48u, 14u, 14u, 13u, 14u, 4u, 14u, 11u, 56u, 11u, 56u, 1u, 53u,
+        14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u, 14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u,
+        14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u, 14u, 53u, 14u, 53u, 14u, 53u, 14u, 53u,
+        12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 56u, 1u, 14u, 1u, 14u,
+        1u, 48u, 14u, 14u, 11u, 56u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u,
+        14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u,
+        14u, 53u, 14u, 53u, 14u, 53u, 14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u,
+        12u, 53u, 11u, 56u, 1u, 14u, 1u, 48u, 4u, 14u, 13u, 14u, 1u, 56u, 14u, 42u,
+        14u, 42u, 1u, 5u, 14u, 55u, 14u, 51u, 14u, 52u, 14u, 54u, 11u, 56u, 0
 };
 
 static const char _use_syllable_machine_key_spans[] = {
-        3, 54, 43, 43, 53, 35, 34, 34,
+        3, 57, 46, 46, 53, 35, 34, 34,
         34, 33, 33, 1, 35, 35, 35, 14,
         35, 40, 40, 40, 40, 42, 40, 42,
-        42, 42, 43, 14, 48, 29, 29, 43,
+        42, 42, 46, 14, 48, 29, 29, 46,
         53, 35, 34, 34, 34, 33, 33, 1,
         35, 35, 35, 14, 35, 40, 40, 40,
-        40, 42, 40, 42, 42, 42, 43, 14,
-        14, 48, 2, 11, 43, 43, 53, 35,
-        34, 34, 34, 33, 33, 1, 35, 35,
-        35, 14, 35, 40, 40, 40, 40, 42,
-        40, 42, 42, 42, 43, 14, 14, 48,
-        43, 53, 35, 34, 34, 34, 33, 33,
-        1, 35, 35, 35, 14, 35, 40, 40,
-        40, 40, 42, 40, 42, 42, 42, 43,
-        14, 48, 11, 2, 53, 29, 29, 5,
-        42, 38, 39, 41, 43
+        40, 42, 40, 42, 42, 42, 46, 14,
+        14, 48, 1, 2, 11, 46, 46, 53,
+        35, 34, 34, 34, 33, 33, 1, 35,
+        35, 35, 14, 35, 40, 40, 40, 40,
+        42, 40, 42, 42, 42, 46, 14, 14,
+        48, 1, 46, 53, 35, 34, 34, 34,
+        33, 33, 1, 35, 35, 35, 14, 35,
+        40, 40, 40, 40, 42, 40, 42, 42,
+        42, 46, 14, 48, 11, 2, 56, 29,
+        29, 5, 42, 38, 39, 41, 46
 };
 
 static const short _use_syllable_machine_index_offsets[] = {
-        0, 4, 59, 103, 147, 201, 237, 272,
-        307, 342, 376, 410, 412, 448, 484, 520,
-        535, 571, 612, 653, 694, 735, 778, 819,
-        862, 905, 948, 992, 1007, 1056, 1086, 1116,
-        1160, 1214, 1250, 1285, 1320, 1355, 1389, 1423,
-        1425, 1461, 1497, 1533, 1548, 1584, 1625, 1666,
-        1707, 1748, 1791, 1832, 1875, 1918, 1961, 2005,
-        2020, 2035, 2084, 2087, 2099, 2143, 2187, 2241,
-        2277, 2312, 2347, 2382, 2416, 2450, 2452, 2488,
-        2524, 2560, 2575, 2611, 2652, 2693, 2734, 2775,
-        2818, 2859, 2902, 2945, 2988, 3032, 3047, 3062,
-        3111, 3155, 3209, 3245, 3280, 3315, 3350, 3384,
-        3418, 3420, 3456, 3492, 3528, 3543, 3579, 3620,
-        3661, 3702, 3743, 3786, 3827, 3870, 3913, 3956,
-        4000, 4015, 4064, 4076, 4079, 4133, 4163, 4193,
-        4199, 4242, 4281, 4321, 4363
+        0, 4, 62, 109, 156, 210, 246, 281,
+        316, 351, 385, 419, 421, 457, 493, 529,
+        544, 580, 621, 662, 703, 744, 787, 828,
+        871, 914, 957, 1004, 1019, 1068, 1098, 1128,
+        1175, 1229, 1265, 1300, 1335, 1370, 1404, 1438,
+        1440, 1476, 1512, 1548, 1563, 1599, 1640, 1681,
+        1722, 1763, 1806, 1847, 1890, 1933, 1976, 2023,
+        2038, 2053, 2102, 2104, 2107, 2119, 2166, 2213,
+        2267, 2303, 2338, 2373, 2408, 2442, 2476, 2478,
+        2514, 2550, 2586, 2601, 2637, 2678, 2719, 2760,
+        2801, 2844, 2885, 2928, 2971, 3014, 3061, 3076,
+        3091, 3140, 3142, 3189, 3243, 3279, 3314, 3349,
+        3384, 3418, 3452, 3454, 3490, 3526, 3562, 3577,
+        3613, 3654, 3695, 3736, 3777, 3820, 3861, 3904,
+        3947, 3990, 4037, 4052, 4101, 4113, 4116, 4173,
+        4203, 4233, 4239, 4282, 4321, 4361, 4403
 };
 
 static const unsigned char _use_syllable_machine_indicies[] = {
@@ -165,571 +166,578 @@ static const unsigned char _use_syllable
         19, 20, 21, 8, 22, 23, 24, 25,
         5, 26, 27, 28, 5, 29, 30, 31,
         32, 33, 34, 35, 32, 1, 5, 36,
-        5, 37, 5, 39, 40, 38, 41, 38,
-        38, 38, 38, 38, 38, 38, 42, 43,
-        44, 45, 46, 47, 48, 49, 50, 39,
-        51, 52, 53, 54, 38, 55, 56, 57,
-        38, 58, 59, 38, 60, 61, 62, 63,
-        60, 38, 38, 38, 38, 64, 38, 39,
-        40, 38, 41, 38, 38, 38, 38, 38,
-        38, 38, 42, 43, 44, 45, 46, 47,
-        48, 49, 50, 39, 51, 52, 53, 54,
-        38, 55, 56, 57, 38, 38, 38, 38,
-        60, 61, 62, 63, 60, 38, 38, 38,
-        38, 64, 38, 39, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        41, 38, 38, 38, 38, 38, 38, 38,
-        38, 43, 44, 45, 46, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 55,
-        56, 57, 38, 38, 38, 38, 38, 61,
-        62, 63, 65, 38, 38, 38, 38, 43,
-        38, 41, 38, 38, 38, 38, 38, 38,
-        38, 38, 43, 44, 45, 46, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        55, 56, 57, 38, 38, 38, 38, 38,
-        61, 62, 63, 65, 38, 41, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 44,
-        45, 46, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 61, 62, 63, 38,
-        41, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 45, 46, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 61,
-        62, 63, 38, 41, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 46,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 61, 62, 63, 38, 41, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 61, 62, 38,
-        41, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        62, 38, 41, 38, 41, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 44, 45,
-        46, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 55, 56, 57, 38, 38,
-        38, 38, 38, 61, 62, 63, 65, 38,
-        41, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 44, 45, 46, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        56, 57, 38, 38, 38, 38, 38, 61,
-        62, 63, 65, 38, 41, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 44, 45,
-        46, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 57, 38, 38,
-        38, 38, 38, 61, 62, 63, 65, 38,
-        66, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 41, 38, 41,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 44, 45, 46, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 61, 62,
-        63, 65, 38, 41, 38, 38, 38, 38,
-        38, 38, 38, 42, 43, 44, 45, 46,
-        38, 38, 38, 38, 38, 38, 52, 53,
-        54, 38, 55, 56, 57, 38, 38, 38,
-        38, 38, 61, 62, 63, 65, 38, 38,
-        38, 38, 43, 38, 41, 38, 38, 38,
-        38, 38, 38, 38, 38, 43, 44, 45,
-        46, 38, 38, 38, 38, 38, 38, 52,
-        53, 54, 38, 55, 56, 57, 38, 38,
-        38, 38, 38, 61, 62, 63, 65, 38,
-        38, 38, 38, 43, 38, 41, 38, 38,
-        38, 38, 38, 38, 38, 38, 43, 44,
-        45, 46, 38, 38, 38, 38, 38, 38,
-        38, 53, 54, 38, 55, 56, 57, 38,
-        38, 38, 38, 38, 61, 62, 63, 65,
-        38, 38, 38, 38, 43, 38, 41, 38,
-        38, 38, 38, 38, 38, 38, 38, 43,
-        44, 45, 46, 38, 38, 38, 38, 38,
-        38, 38, 38, 54, 38, 55, 56, 57,
-        38, 38, 38, 38, 38, 61, 62, 63,
-        65, 38, 38, 38, 38, 43, 38, 67,
-        38, 41, 38, 38, 38, 38, 38, 38,
-        38, 42, 43, 44, 45, 46, 38, 48,
-        49, 38, 38, 38, 52, 53, 54, 38,
-        55, 56, 57, 38, 38, 38, 38, 38,
-        61, 62, 63, 65, 38, 38, 38, 38,
-        43, 38, 41, 38, 38, 38, 38, 38,
-        38, 38, 38, 43, 44, 45, 46, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 55, 56, 57, 38, 38, 38, 38,
-        38, 61, 62, 63, 65, 38, 38, 38,
-        38, 43, 38, 67, 38, 41, 38, 38,
-        38, 38, 38, 38, 38, 42, 43, 44,
-        45, 46, 38, 38, 49, 38, 38, 38,
-        52, 53, 54, 38, 55, 56, 57, 38,
-        38, 38, 38, 38, 61, 62, 63, 65,
-        38, 38, 38, 38, 43, 38, 67, 38,
-        41, 38, 38, 38, 38, 38, 38, 38,
-        42, 43, 44, 45, 46, 38, 38, 38,
-        38, 38, 38, 52, 53, 54, 38, 55,
-        56, 57, 38, 38, 38, 38, 38, 61,
-        62, 63, 65, 38, 38, 38, 38, 43,
-        38, 67, 38, 41, 38, 38, 38, 38,
-        38, 38, 38, 42, 43, 44, 45, 46,
-        47, 48, 49, 38, 38, 38, 52, 53,
-        54, 38, 55, 56, 57, 38, 38, 38,
-        38, 38, 61, 62, 63, 65, 38, 38,
-        38, 38, 43, 38, 39, 40, 38, 41,
-        38, 38, 38, 38, 38, 38, 38, 42,
+        5, 37, 5, 5, 38, 5, 40, 41,
+        39, 42, 39, 39, 39, 39, 39, 39,
+        39, 43, 44, 45, 46, 47, 48, 49,
+        50, 51, 40, 52, 53, 54, 55, 39,
+        56, 57, 58, 39, 59, 60, 39, 61,
+        62, 63, 64, 61, 39, 39, 39, 39,
+        65, 39, 39, 64, 39, 40, 41, 39,
+        42, 39, 39, 39, 39, 39, 39, 39,
         43, 44, 45, 46, 47, 48, 49, 50,
-        38, 51, 52, 53, 54, 38, 55, 56,
-        57, 38, 38, 38, 38, 60, 61, 62,
-        63, 60, 38, 38, 38, 38, 64, 38,
-        39, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 41, 38, 39,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 41, 38, 38, 38,
-        38, 38, 38, 38, 38, 43, 44, 45,
-        46, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 55, 56, 57, 38, 38,
-        38, 38, 38, 61, 62, 63, 65, 38,
-        41, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 58, 59, 38, 41, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 38, 38, 38, 38, 38, 38,
-        38, 38, 59, 38, 4, 69, 68, 70,
-        68, 68, 68, 68, 68, 68, 68, 71,
-        72, 73, 74, 75, 76, 77, 78, 79,
-        4, 80, 81, 82, 83, 68, 84, 85,
-        86, 68, 68, 68, 68, 87, 88, 89,
-        90, 91, 68, 68, 68, 68, 92, 68,
-        4, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 70, 68, 68,
-        68, 68, 68, 68, 68, 68, 72, 73,
-        74, 75, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 84, 85, 86, 68,
-        68, 68, 68, 68, 88, 89, 90, 93,
-        68, 68, 68, 68, 72, 68, 70, 68,
-        68, 68, 68, 68, 68, 68, 68, 72,
-        73, 74, 75, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 84, 85, 86,
-        68, 68, 68, 68, 68, 88, 89, 90,
-        93, 68, 70, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 73, 74, 75, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 88, 89, 90, 68, 70, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        74, 75, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 88, 89, 90, 68,
-        70, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 75, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 88,
-        89, 90, 68, 70, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 88, 89, 68, 70, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 89, 68, 70,
-        68, 70, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 73, 74, 75, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        84, 85, 86, 68, 68, 68, 68, 68,
-        88, 89, 90, 93, 68, 70, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 73,
-        74, 75, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 85, 86, 68,
-        68, 68, 68, 68, 88, 89, 90, 93,
-        68, 70, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 73, 74, 75, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 86, 68, 68, 68, 68, 68,
-        88, 89, 90, 93, 68, 95, 94, 94,
-        94, 94, 94, 94, 94, 94, 94, 94,
-        94, 94, 96, 94, 70, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 73, 74,
-        75, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 88, 89, 90, 93, 68,
-        70, 68, 68, 68, 68, 68, 68, 68,
-        71, 72, 73, 74, 75, 68, 68, 68,
-        68, 68, 68, 81, 82, 83, 68, 84,
-        85, 86, 68, 68, 68, 68, 68, 88,
-        89, 90, 93, 68, 68, 68, 68, 72,
-        68, 70, 68, 68, 68, 68, 68, 68,
-        68, 68, 72, 73, 74, 75, 68, 68,
-        68, 68, 68, 68, 81, 82, 83, 68,
-        84, 85, 86, 68, 68, 68, 68, 68,
-        88, 89, 90, 93, 68, 68, 68, 68,
-        72, 68, 70, 68, 68, 68, 68, 68,
-        68, 68, 68, 72, 73, 74, 75, 68,
-        68, 68, 68, 68, 68, 68, 82, 83,
-        68, 84, 85, 86, 68, 68, 68, 68,
-        68, 88, 89, 90, 93, 68, 68, 68,
-        68, 72, 68, 70, 68, 68, 68, 68,
-        68, 68, 68, 68, 72, 73, 74, 75,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        83, 68, 84, 85, 86, 68, 68, 68,
-        68, 68, 88, 89, 90, 93, 68, 68,
-        68, 68, 72, 68, 97, 68, 70, 68,
-        68, 68, 68, 68, 68, 68, 71, 72,
-        73, 74, 75, 68, 77, 78, 68, 68,
-        68, 81, 82, 83, 68, 84, 85, 86,
-        68, 68, 68, 68, 68, 88, 89, 90,
-        93, 68, 68, 68, 68, 72, 68, 70,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        72, 73, 74, 75, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 84, 85,
-        86, 68, 68, 68, 68, 68, 88, 89,
-        90, 93, 68, 68, 68, 68, 72, 68,
-        97, 68, 70, 68, 68, 68, 68, 68,
-        68, 68, 71, 72, 73, 74, 75, 68,
-        68, 78, 68, 68, 68, 81, 82, 83,
-        68, 84, 85, 86, 68, 68, 68, 68,
-        68, 88, 89, 90, 93, 68, 68, 68,
-        68, 72, 68, 97, 68, 70, 68, 68,
-        68, 68, 68, 68, 68, 71, 72, 73,
-        74, 75, 68, 68, 68, 68, 68, 68,
-        81, 82, 83, 68, 84, 85, 86, 68,
-        68, 68, 68, 68, 88, 89, 90, 93,
-        68, 68, 68, 68, 72, 68, 97, 68,
-        70, 68, 68, 68, 68, 68, 68, 68,
-        71, 72, 73, 74, 75, 76, 77, 78,
-        68, 68, 68, 81, 82, 83, 68, 84,
-        85, 86, 68, 68, 68, 68, 68, 88,
-        89, 90, 93, 68, 68, 68, 68, 72,
-        68, 4, 69, 68, 70, 68, 68, 68,
-        68, 68, 68, 68, 71, 72, 73, 74,
-        75, 76, 77, 78, 79, 68, 80, 81,
-        82, 83, 68, 84, 85, 86, 68, 68,
-        68, 68, 87, 88, 89, 90, 91, 68,
-        68, 68, 68, 92, 68, 4, 98, 98,
-        98, 98, 98, 98, 98, 98, 98, 98,
-        98, 98, 99, 98, 4, 94, 94, 94,
-        94, 94, 94, 94, 94, 94, 94, 94,
-        94, 96, 94, 4, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        70, 68, 68, 68, 68, 68, 68, 68,
-        68, 72, 73, 74, 75, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 84,
-        85, 86, 68, 68, 68, 68, 68, 88,
-        89, 90, 93, 68, 101, 102, 100, 6,
-        103, 103, 103, 103, 103, 103, 103, 103,
-        103, 104, 103, 105, 106, 68, 70, 68,
-        68, 68, 68, 68, 68, 68, 107, 108,
-        109, 110, 111, 112, 113, 114, 115, 105,
-        116, 117, 118, 119, 68, 120, 121, 122,
-        68, 58, 59, 68, 123, 124, 125, 126,
-        127, 68, 68, 68, 68, 128, 68, 105,
-        106, 68, 70, 68, 68, 68, 68, 68,
-        68, 68, 107, 108, 109, 110, 111, 112,
-        113, 114, 115, 105, 116, 117, 118, 119,
-        68, 120, 121, 122, 68, 68, 68, 68,
-        123, 124, 125, 126, 127, 68, 68, 68,
-        68, 128, 68, 105, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        70, 68, 68, 68, 68, 68, 68, 68,
-        68, 108, 109, 110, 111, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 120,
-        121, 122, 68, 68, 68, 68, 68, 124,
-        125, 126, 129, 68, 68, 68, 68, 108,
-        68, 70, 68, 68, 68, 68, 68, 68,
-        68, 68, 108, 109, 110, 111, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        120, 121, 122, 68, 68, 68, 68, 68,
-        124, 125, 126, 129, 68, 70, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 109,
-        110, 111, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 124, 125, 126, 68,
-        70, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 110, 111, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 124,
-        125, 126, 68, 70, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 111,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 124, 125, 126, 68, 70, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 124, 125, 68,
-        70, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        125, 68, 70, 68, 70, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 109, 110,
-        111, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 120, 121, 122, 68, 68,
-        68, 68, 68, 124, 125, 126, 129, 68,
-        70, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 109, 110, 111, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        121, 122, 68, 68, 68, 68, 68, 124,
-        125, 126, 129, 68, 70, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 109, 110,
-        111, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 122, 68, 68,
-        68, 68, 68, 124, 125, 126, 129, 68,
-        130, 94, 94, 94, 94, 94, 94, 94,
-        94, 94, 94, 94, 94, 96, 94, 70,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 109, 110, 111, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 124, 125,
-        126, 129, 68, 70, 68, 68, 68, 68,
-        68, 68, 68, 107, 108, 109, 110, 111,
-        68, 68, 68, 68, 68, 68, 117, 118,
-        119, 68, 120, 121, 122, 68, 68, 68,
-        68, 68, 124, 125, 126, 129, 68, 68,
-        68, 68, 108, 68, 70, 68, 68, 68,
-        68, 68, 68, 68, 68, 108, 109, 110,
-        111, 68, 68, 68, 68, 68, 68, 117,
-        118, 119, 68, 120, 121, 122, 68, 68,
-        68, 68, 68, 124, 125, 126, 129, 68,
-        68, 68, 68, 108, 68, 70, 68, 68,
-        68, 68, 68, 68, 68, 68, 108, 109,
-        110, 111, 68, 68, 68, 68, 68, 68,
-        68, 118, 119, 68, 120, 121, 122, 68,
-        68, 68, 68, 68, 124, 125, 126, 129,
-        68, 68, 68, 68, 108, 68, 70, 68,
-        68, 68, 68, 68, 68, 68, 68, 108,
-        109, 110, 111, 68, 68, 68, 68, 68,
-        68, 68, 68, 119, 68, 120, 121, 122,
-        68, 68, 68, 68, 68, 124, 125, 126,
-        129, 68, 68, 68, 68, 108, 68, 131,
-        68, 70, 68, 68, 68, 68, 68, 68,
-        68, 107, 108, 109, 110, 111, 68, 113,
-        114, 68, 68, 68, 117, 118, 119, 68,
-        120, 121, 122, 68, 68, 68, 68, 68,
-        124, 125, 126, 129, 68, 68, 68, 68,
-        108, 68, 70, 68, 68, 68, 68, 68,
-        68, 68, 68, 108, 109, 110, 111, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 120, 121, 122, 68, 68, 68, 68,
-        68, 124, 125, 126, 129, 68, 68, 68,
-        68, 108, 68, 131, 68, 70, 68, 68,
-        68, 68, 68, 68, 68, 107, 108, 109,
-        110, 111, 68, 68, 114, 68, 68, 68,
-        117, 118, 119, 68, 120, 121, 122, 68,
-        68, 68, 68, 68, 124, 125, 126, 129,
-        68, 68, 68, 68, 108, 68, 131, 68,
-        70, 68, 68, 68, 68, 68, 68, 68,
-        107, 108, 109, 110, 111, 68, 68, 68,
-        68, 68, 68, 117, 118, 119, 68, 120,
-        121, 122, 68, 68, 68, 68, 68, 124,
-        125, 126, 129, 68, 68, 68, 68, 108,
-        68, 131, 68, 70, 68, 68, 68, 68,
-        68, 68, 68, 107, 108, 109, 110, 111,
-        112, 113, 114, 68, 68, 68, 117, 118,
-        119, 68, 120, 121, 122, 68, 68, 68,
-        68, 68, 124, 125, 126, 129, 68, 68,
-        68, 68, 108, 68, 105, 106, 68, 70,
-        68, 68, 68, 68, 68, 68, 68, 107,
-        108, 109, 110, 111, 112, 113, 114, 115,
-        68, 116, 117, 118, 119, 68, 120, 121,
-        122, 68, 68, 68, 68, 123, 124, 125,
-        126, 127, 68, 68, 68, 68, 128, 68,
-        105, 98, 98, 98, 98, 98, 98, 98,
-        98, 98, 98, 98, 98, 99, 98, 105,
-        94, 94, 94, 94, 94, 94, 94, 94,
-        94, 94, 94, 94, 96, 94, 105, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 70, 68, 68, 68, 68,
-        68, 68, 68, 68, 108, 109, 110, 111,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 120, 121, 122, 68, 68, 68,
-        68, 68, 124, 125, 126, 129, 68, 8,
-        9, 132, 11, 132, 132, 132, 132, 132,
-        132, 132, 13, 14, 15, 16, 17, 18,
-        19, 20, 21, 8, 22, 23, 24, 25,
-        132, 26, 27, 28, 132, 132, 132, 132,
-        32, 33, 34, 35, 32, 132, 132, 132,
-        132, 37, 132, 8, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        11, 132, 132, 132, 132, 132, 132, 132,
-        132, 14, 15, 16, 17, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 26,
-        27, 28, 132, 132, 132, 132, 132, 33,
-        34, 35, 133, 132, 132, 132, 132, 14,
-        132, 11, 132, 132, 132, 132, 132, 132,
-        132, 132, 14, 15, 16, 17, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        26, 27, 28, 132, 132, 132, 132, 132,
-        33, 34, 35, 133, 132, 11, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 15,
-        16, 17, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 33, 34, 35, 132,
-        11, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 16, 17, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 33,
-        34, 35, 132, 11, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 17,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 33, 34, 35, 132, 11, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 33, 34, 132,
-        11, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        34, 132, 11, 132, 11, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 15, 16,
-        17, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 26, 27, 28, 132, 132,
-        132, 132, 132, 33, 34, 35, 133, 132,
-        11, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 15, 16, 17, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        27, 28, 132, 132, 132, 132, 132, 33,
-        34, 35, 133, 132, 11, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 15, 16,
-        17, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 28, 132, 132,
-        132, 132, 132, 33, 34, 35, 133, 132,
-        134, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 11, 132, 11,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 15, 16, 17, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 33, 34,
-        35, 133, 132, 11, 132, 132, 132, 132,
-        132, 132, 132, 13, 14, 15, 16, 17,
-        132, 132, 132, 132, 132, 132, 23, 24,
-        25, 132, 26, 27, 28, 132, 132, 132,
-        132, 132, 33, 34, 35, 133, 132, 132,
-        132, 132, 14, 132, 11, 132, 132, 132,
-        132, 132, 132, 132, 132, 14, 15, 16,
-        17, 132, 132, 132, 132, 132, 132, 23,
-        24, 25, 132, 26, 27, 28, 132, 132,
-        132, 132, 132, 33, 34, 35, 133, 132,
-        132, 132, 132, 14, 132, 11, 132, 132,
-        132, 132, 132, 132, 132, 132, 14, 15,
-        16, 17, 132, 132, 132, 132, 132, 132,
-        132, 24, 25, 132, 26, 27, 28, 132,
-        132, 132, 132, 132, 33, 34, 35, 133,
-        132, 132, 132, 132, 14, 132, 11, 132,
-        132, 132, 132, 132, 132, 132, 132, 14,
-        15, 16, 17, 132, 132, 132, 132, 132,
-        132, 132, 132, 25, 132, 26, 27, 28,
-        132, 132, 132, 132, 132, 33, 34, 35,
-        133, 132, 132, 132, 132, 14, 132, 135,
-        132, 11, 132, 132, 132, 132, 132, 132,
-        132, 13, 14, 15, 16, 17, 132, 19,
-        20, 132, 132, 132, 23, 24, 25, 132,
-        26, 27, 28, 132, 132, 132, 132, 132,
-        33, 34, 35, 133, 132, 132, 132, 132,
-        14, 132, 11, 132, 132, 132, 132, 132,
-        132, 132, 132, 14, 15, 16, 17, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 26, 27, 28, 132, 132, 132, 132,
-        132, 33, 34, 35, 133, 132, 132, 132,
-        132, 14, 132, 135, 132, 11, 132, 132,
-        132, 132, 132, 132, 132, 13, 14, 15,
-        16, 17, 132, 132, 20, 132, 132, 132,
-        23, 24, 25, 132, 26, 27, 28, 132,
-        132, 132, 132, 132, 33, 34, 35, 133,
-        132, 132, 132, 132, 14, 132, 135, 132,
-        11, 132, 132, 132, 132, 132, 132, 132,
-        13, 14, 15, 16, 17, 132, 132, 132,
-        132, 132, 132, 23, 24, 25, 132, 26,
-        27, 28, 132, 132, 132, 132, 132, 33,
-        34, 35, 133, 132, 132, 132, 132, 14,
-        132, 135, 132, 11, 132, 132, 132, 132,
-        132, 132, 132, 13, 14, 15, 16, 17,
-        18, 19, 20, 132, 132, 132, 23, 24,
-        25, 132, 26, 27, 28, 132, 132, 132,
-        132, 132, 33, 34, 35, 133, 132, 132,
-        132, 132, 14, 132, 8, 9, 132, 11,
-        132, 132, 132, 132, 132, 132, 132, 13,
-        14, 15, 16, 17, 18, 19, 20, 21,
-        132, 22, 23, 24, 25, 132, 26, 27,
-        28, 132, 132, 132, 132, 32, 33, 34,
-        35, 32, 132, 132, 132, 132, 37, 132,
-        8, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 11, 132, 8,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 11, 132, 132, 132,
-        132, 132, 132, 132, 132, 14, 15, 16,
-        17, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 26, 27, 28, 132, 132,
-        132, 132, 132, 33, 34, 35, 133, 132,
-        136, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 11, 132, 10, 11, 132, 4,
-        132, 132, 132, 4, 132, 132, 132, 132,
-        132, 8, 9, 10, 11, 132, 132, 132,
-        132, 132, 132, 132, 13, 14, 15, 16,
-        17, 18, 19, 20, 21, 8, 22, 23,
-        24, 25, 132, 26, 27, 28, 132, 29,
-        30, 132, 32, 33, 34, 35, 32, 132,
-        132, 132, 132, 37, 132, 11, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        29, 30, 132, 11, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 132,
-        132, 132, 132, 132, 132, 132, 132, 30,
-        132, 4, 137, 137, 137, 4, 137, 139,
-        138, 138, 138, 138, 138, 138, 138, 138,
-        138, 138, 138, 138, 138, 138, 138, 138,
-        138, 138, 138, 138, 138, 138, 138, 138,
-        138, 138, 138, 138, 138, 138, 138, 138,
-        138, 138, 138, 140, 138, 141, 138, 141,
-        142, 138, 139, 138, 138, 138, 138, 138,
-        138, 138, 138, 138, 138, 138, 138, 138,
-        138, 138, 138, 138, 138, 138, 138, 138,
-        138, 138, 138, 138, 138, 138, 138, 138,
-        138, 138, 138, 138, 138, 1, 140, 140,
-        138, 139, 138, 138, 138, 138, 138, 138,
-        138, 138, 138, 138, 138, 138, 138, 138,
-        138, 138, 138, 138, 138, 138, 138, 138,
-        138, 138, 138, 138, 138, 138, 138, 138,
-        138, 138, 138, 138, 138, 140, 138, 141,
-        138, 139, 138, 138, 138, 138, 138, 138,
-        138, 138, 138, 138, 138, 138, 138, 138,
-        138, 138, 138, 138, 138, 138, 138, 138,
-        138, 138, 138, 138, 138, 138, 138, 138,
-        138, 138, 138, 138, 138, 140, 138, 141,
-        138, 141, 138, 39, 40, 38, 41, 38,
-        38, 38, 38, 38, 38, 38, 42, 43,
-        44, 45, 46, 47, 48, 49, 50, 39,
-        51, 52, 53, 54, 38, 55, 56, 57,
-        38, 58, 59, 38, 60, 61, 62, 63,
-        60, 1, 38, 2, 38, 64, 38, 0
+        51, 40, 52, 53, 54, 55, 39, 56,
+        57, 58, 39, 39, 39, 39, 61, 62,
+        63, 64, 61, 39, 39, 39, 39, 65,
+        39, 39, 64, 39, 40, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 42, 39, 39, 39, 39, 39, 39,
+        39, 39, 44, 45, 46, 47, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        56, 57, 58, 39, 39, 39, 39, 39,
+        62, 63, 64, 66, 39, 39, 39, 39,
+        44, 39, 42, 39, 39, 39, 39, 39,
+        39, 39, 39, 44, 45, 46, 47, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 56, 57, 58, 39, 39, 39, 39,
+        39, 62, 63, 64, 66, 39, 42, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        45, 46, 47, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 62, 63, 64,
+        39, 42, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 46, 47, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        62, 63, 64, 39, 42, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        47, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 62, 63, 64, 39, 42,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 62, 63,
+        39, 42, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 63, 39, 42, 39, 42, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 45,
+        46, 47, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 56, 57, 58, 39,
+        39, 39, 39, 39, 62, 63, 64, 66,
+        39, 42, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 45, 46, 47, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 57, 58, 39, 39, 39, 39, 39,
+        62, 63, 64, 66, 39, 42, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 45,
+        46, 47, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 58, 39,
+        39, 39, 39, 39, 62, 63, 64, 66,
+        39, 67, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 42, 39,
+        42, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 45, 46, 47, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 62,
+        63, 64, 66, 39, 42, 39, 39, 39,
+        39, 39, 39, 39, 43, 44, 45, 46,
+        47, 39, 39, 39, 39, 39, 39, 53,
+        54, 55, 39, 56, 57, 58, 39, 39,
+        39, 39, 39, 62, 63, 64, 66, 39,
+        39, 39, 39, 44, 39, 42, 39, 39,
+        39, 39, 39, 39, 39, 39, 44, 45,
+        46, 47, 39, 39, 39, 39, 39, 39,
+        53, 54, 55, 39, 56, 57, 58, 39,
+        39, 39, 39, 39, 62, 63, 64, 66,
+        39, 39, 39, 39, 44, 39, 42, 39,
+        39, 39, 39, 39, 39, 39, 39, 44,
+        45, 46, 47, 39, 39, 39, 39, 39,
+        39, 39, 54, 55, 39, 56, 57, 58,
+        39, 39, 39, 39, 39, 62, 63, 64,
+        66, 39, 39, 39, 39, 44, 39, 42,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        44, 45, 46, 47, 39, 39, 39, 39,
+        39, 39, 39, 39, 55, 39, 56, 57,
+        58, 39, 39, 39, 39, 39, 62, 63,
+        64, 66, 39, 39, 39, 39, 44, 39,
+        68, 39, 42, 39, 39, 39, 39, 39,
+        39, 39, 43, 44, 45, 46, 47, 39,
+        49, 50, 39, 39, 39, 53, 54, 55,
+        39, 56, 57, 58, 39, 39, 39, 39,
+        39, 62, 63, 64, 66, 39, 39, 39,
+        39, 44, 39, 42, 39, 39, 39, 39,
+        39, 39, 39, 39, 44, 45, 46, 47,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 56, 57, 58, 39, 39, 39,
+        39, 39, 62, 63, 64, 66, 39, 39,
+        39, 39, 44, 39, 68, 39, 42, 39,
+        39, 39, 39, 39, 39, 39, 43, 44,
+        45, 46, 47, 39, 39, 50, 39, 39,
+        39, 53, 54, 55, 39, 56, 57, 58,
+        39, 39, 39, 39, 39, 62, 63, 64,
+        66, 39, 39, 39, 39, 44, 39, 68,
+        39, 42, 39, 39, 39, 39, 39, 39,
+        39, 43, 44, 45, 46, 47, 39, 39,
+        39, 39, 39, 39, 53, 54, 55, 39,
+        56, 57, 58, 39, 39, 39, 39, 39,
+        62, 63, 64, 66, 39, 39, 39, 39,
+        44, 39, 68, 39, 42, 39, 39, 39,
+        39, 39, 39, 39, 43, 44, 45, 46,
+        47, 48, 49, 50, 39, 39, 39, 53,
+        54, 55, 39, 56, 57, 58, 39, 39,
+        39, 39, 39, 62, 63, 64, 66, 39,
+        39, 39, 39, 44, 39, 40, 41, 39,
+        42, 39, 39, 39, 39, 39, 39, 39,
+        43, 44, 45, 46, 47, 48, 49, 50,
+        51, 39, 52, 53, 54, 55, 39, 56,
+        57, 58, 39, 39, 39, 39, 61, 62,
+        63, 64, 61, 39, 39, 39, 39, 65,
+        39, 39, 64, 39, 40, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 42, 39, 40, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        42, 39, 39, 39, 39, 39, 39, 39,
+        39, 44, 45, 46, 47, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 56,
+        57, 58, 39, 39, 39, 39, 39, 62,
+        63, 64, 66, 39, 42, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 59,
+        60, 39, 42, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 60, 39,
+        4, 70, 69, 71, 69, 69, 69, 69,
+        69, 69, 69, 72, 73, 74, 75, 76,
+        77, 78, 79, 80, 4, 81, 82, 83,
+        84, 69, 85, 86, 87, 69, 69, 69,
+        69, 88, 89, 90, 91, 92, 69, 69,
+        69, 69, 93, 69, 69, 94, 69, 4,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 71, 69, 69, 69,
+        69, 69, 69, 69, 69, 73, 74, 75,
+        76, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 85, 86, 87, 69, 69,
+        69, 69, 69, 89, 90, 91, 95, 69,
+        69, 69, 69, 73, 69, 71, 69, 69,
+        69, 69, 69, 69, 69, 69, 73, 74,
+        75, 76, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 85, 86, 87, 69,
+        69, 69, 69, 69, 89, 90, 91, 95,
+        69, 71, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 74, 75, 76, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        89, 90, 91, 69, 71, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 75,
+        76, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 89, 90, 91, 69, 71,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 76, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 89, 90,
+        91, 69, 71, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 89, 90, 69, 71, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 90, 69, 71, 69,
+        71, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 74, 75, 76, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 85,
+        86, 87, 69, 69, 69, 69, 69, 89,
+        90, 91, 95, 69, 71, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 74, 75,
+        76, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 86, 87, 69, 69,
+        69, 69, 69, 89, 90, 91, 95, 69,
+        71, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 74, 75, 76, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 87, 69, 69, 69, 69, 69, 89,
+        90, 91, 95, 69, 97, 96, 96, 96,
+        96, 96, 96, 96, 96, 96, 96, 96,
+        96, 98, 96, 71, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 74, 75, 76,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 89, 90, 91, 95, 69, 71,
+        69, 69, 69, 69, 69, 69, 69, 72,
+        73, 74, 75, 76, 69, 69, 69, 69,
+        69, 69, 82, 83, 84, 69, 85, 86,
+        87, 69, 69, 69, 69, 69, 89, 90,
+        91, 95, 69, 69, 69, 69, 73, 69,
+        71, 69, 69, 69, 69, 69, 69, 69,
+        69, 73, 74, 75, 76, 69, 69, 69,
+        69, 69, 69, 82, 83, 84, 69, 85,
+        86, 87, 69, 69, 69, 69, 69, 89,
+        90, 91, 95, 69, 69, 69, 69, 73,
+        69, 71, 69, 69, 69, 69, 69, 69,
+        69, 69, 73, 74, 75, 76, 69, 69,
+        69, 69, 69, 69, 69, 83, 84, 69,
+        85, 86, 87, 69, 69, 69, 69, 69,
+        89, 90, 91, 95, 69, 69, 69, 69,
+        73, 69, 71, 69, 69, 69, 69, 69,
+        69, 69, 69, 73, 74, 75, 76, 69,
+        69, 69, 69, 69, 69, 69, 69, 84,
+        69, 85, 86, 87, 69, 69, 69, 69,
+        69, 89, 90, 91, 95, 69, 69, 69,
+        69, 73, 69, 99, 69, 71, 69, 69,
+        69, 69, 69, 69, 69, 72, 73, 74,
+        75, 76, 69, 78, 79, 69, 69, 69,
+        82, 83, 84, 69, 85, 86, 87, 69,
+        69, 69, 69, 69, 89, 90, 91, 95,
+        69, 69, 69, 69, 73, 69, 71, 69,
+        69, 69, 69, 69, 69, 69, 69, 73,
+        74, 75, 76, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 85, 86, 87,
+        69, 69, 69, 69, 69, 89, 90, 91,
+        95, 69, 69, 69, 69, 73, 69, 99,
+        69, 71, 69, 69, 69, 69, 69, 69,
+        69, 72, 73, 74, 75, 76, 69, 69,
+        79, 69, 69, 69, 82, 83, 84, 69,
+        85, 86, 87, 69, 69, 69, 69, 69,
+        89, 90, 91, 95, 69, 69, 69, 69,
+        73, 69, 99, 69, 71, 69, 69, 69,
+        69, 69, 69, 69, 72, 73, 74, 75,
+        76, 69, 69, 69, 69, 69, 69, 82,
+        83, 84, 69, 85, 86, 87, 69, 69,
+        69, 69, 69, 89, 90, 91, 95, 69,
+        69, 69, 69, 73, 69, 99, 69, 71,
+        69, 69, 69, 69, 69, 69, 69, 72,
+        73, 74, 75, 76, 77, 78, 79, 69,
+        69, 69, 82, 83, 84, 69, 85, 86,
+        87, 69, 69, 69, 69, 69, 89, 90,
+        91, 95, 69, 69, 69, 69, 73, 69,
+        4, 70, 69, 71, 69, 69, 69, 69,
+        69, 69, 69, 72, 73, 74, 75, 76,
+        77, 78, 79, 80, 69, 81, 82, 83,
+        84, 69, 85, 86, 87, 69, 69, 69,
+        69, 88, 89, 90, 91, 92, 69, 69,
+        69, 69, 93, 69, 69, 94, 69, 4,
+        100, 100, 100, 100, 100, 100, 100, 100,
+        100, 100, 100, 100, 101, 100, 4, 96,
+        96, 96, 96, 96, 96, 96, 96, 96,
+        96, 96, 96, 98, 96, 4, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 71, 69, 69, 69, 69, 69,
+        69, 69, 69, 73, 74, 75, 76, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 85, 86, 87, 69, 69, 69, 69,
+        69, 89, 90, 91, 95, 69, 101, 100,
+        103, 104, 102, 6, 105, 105, 105, 105,
+        105, 105, 105, 105, 105, 106, 105, 107,
+        108, 69, 71, 69, 69, 69, 69, 69,
+        69, 69, 109, 110, 111, 112, 113, 114,
+        115, 116, 117, 107, 118, 119, 120, 121,
+        69, 122, 123, 124, 69, 59, 60, 69,
+        125, 126, 127, 128, 129, 69, 69, 69,
+        69, 130, 69, 69, 131, 69, 107, 108,
+        69, 71, 69, 69, 69, 69, 69, 69,
+        69, 109, 110, 111, 112, 113, 114, 115,
+        116, 117, 107, 118, 119, 120, 121, 69,
+        122, 123, 124, 69, 69, 69, 69, 125,
+        126, 127, 128, 129, 69, 69, 69, 69,
+        130, 69, 69, 131, 69, 107, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 71, 69, 69, 69, 69, 69,
+        69, 69, 69, 110, 111, 112, 113, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 122, 123, 124, 69, 69, 69, 69,
+        69, 126, 127, 128, 132, 69, 69, 69,
+        69, 110, 69, 71, 69, 69, 69, 69,
+        69, 69, 69, 69, 110, 111, 112, 113,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 122, 123, 124, 69, 69, 69,
+        69, 69, 126, 127, 128, 132, 69, 71,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 111, 112, 113, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 126, 127,
+        128, 69, 71, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 112, 113, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 126, 127, 128, 69, 71, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 113, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 126, 127, 128, 69,
+        71, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 126,
+        127, 69, 71, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 127, 69, 71, 69, 71, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        111, 112, 113, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 122, 123, 124,
+        69, 69, 69, 69, 69, 126, 127, 128,
+        132, 69, 71, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 111, 112, 113, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 123, 124, 69, 69, 69, 69,
+        69, 126, 127, 128, 132, 69, 71, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        111, 112, 113, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 124,
+        69, 69, 69, 69, 69, 126, 127, 128,
+        132, 69, 133, 96, 96, 96, 96, 96,
+        96, 96, 96, 96, 96, 96, 96, 98,
+        96, 71, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 111, 112, 113, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        126, 127, 128, 132, 69, 71, 69, 69,
+        69, 69, 69, 69, 69, 109, 110, 111,
+        112, 113, 69, 69, 69, 69, 69, 69,
+        119, 120, 121, 69, 122, 123, 124, 69,
+        69, 69, 69, 69, 126, 127, 128, 132,
+        69, 69, 69, 69, 110, 69, 71, 69,
+        69, 69, 69, 69, 69, 69, 69, 110,
+        111, 112, 113, 69, 69, 69, 69, 69,
+        69, 119, 120, 121, 69, 122, 123, 124,
+        69, 69, 69, 69, 69, 126, 127, 128,
+        132, 69, 69, 69, 69, 110, 69, 71,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        110, 111, 112, 113, 69, 69, 69, 69,
+        69, 69, 69, 120, 121, 69, 122, 123,
+        124, 69, 69, 69, 69, 69, 126, 127,
+        128, 132, 69, 69, 69, 69, 110, 69,
+        71, 69, 69, 69, 69, 69, 69, 69,
+        69, 110, 111, 112, 113, 69, 69, 69,
+        69, 69, 69, 69, 69, 121, 69, 122,
+        123, 124, 69, 69, 69, 69, 69, 126,
+        127, 128, 132, 69, 69, 69, 69, 110,
+        69, 134, 69, 71, 69, 69, 69, 69,
+        69, 69, 69, 109, 110, 111, 112, 113,
+        69, 115, 116, 69, 69, 69, 119, 120,
+        121, 69, 122, 123, 124, 69, 69, 69,
+        69, 69, 126, 127, 128, 132, 69, 69,
+        69, 69, 110, 69, 71, 69, 69, 69,
+        69, 69, 69, 69, 69, 110, 111, 112,
+        113, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 122, 123, 124, 69, 69,
+        69, 69, 69, 126, 127, 128, 132, 69,
+        69, 69, 69, 110, 69, 134, 69, 71,
+        69, 69, 69, 69, 69, 69, 69, 109,
+        110, 111, 112, 113, 69, 69, 116, 69,
+        69, 69, 119, 120, 121, 69, 122, 123,
+        124, 69, 69, 69, 69, 69, 126, 127,
+        128, 132, 69, 69, 69, 69, 110, 69,
+        134, 69, 71, 69, 69, 69, 69, 69,
+        69, 69, 109, 110, 111, 112, 113, 69,
+        69, 69, 69, 69, 69, 119, 120, 121,
+        69, 122, 123, 124, 69, 69, 69, 69,
+        69, 126, 127, 128, 132, 69, 69, 69,
+        69, 110, 69, 134, 69, 71, 69, 69,
+        69, 69, 69, 69, 69, 109, 110, 111,
+        112, 113, 114, 115, 116, 69, 69, 69,
+        119, 120, 121, 69, 122, 123, 124, 69,
+        69, 69, 69, 69, 126, 127, 128, 132,
+        69, 69, 69, 69, 110, 69, 107, 108,
+        69, 71, 69, 69, 69, 69, 69, 69,
+        69, 109, 110, 111, 112, 113, 114, 115,
+        116, 117, 69, 118, 119, 120, 121, 69,
+        122, 123, 124, 69, 69, 69, 69, 125,
+        126, 127, 128, 129, 69, 69, 69, 69,
+        130, 69, 69, 131, 69, 107, 100, 100,
+        100, 100, 100, 100, 100, 100, 100, 100,
+        100, 100, 101, 100, 107, 96, 96, 96,
+        96, 96, 96, 96, 96, 96, 96, 96,
+        96, 98, 96, 107, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        71, 69, 69, 69, 69, 69, 69, 69,
+        69, 110, 111, 112, 113, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 122,
+        123, 124, 69, 69, 69, 69, 69, 126,
+        127, 128, 132, 69, 101, 100, 8, 9,
+        135, 11, 135, 135, 135, 135, 135, 135,
+        135, 13, 14, 15, 16, 17, 18, 19,
+        20, 21, 8, 22, 23, 24, 25, 135,
+        26, 27, 28, 135, 135, 135, 135, 32,
+        33, 34, 38, 32, 135, 135, 135, 135,
+        37, 135, 135, 38, 135, 8, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 11, 135, 135, 135, 135, 135,
+        135, 135, 135, 14, 15, 16, 17, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 26, 27, 28, 135, 135, 135, 135,
+        135, 33, 34, 38, 136, 135, 135, 135,
+        135, 14, 135, 11, 135, 135, 135, 135,
+        135, 135, 135, 135, 14, 15, 16, 17,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 26, 27, 28, 135, 135, 135,
+        135, 135, 33, 34, 38, 136, 135, 11,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 15, 16, 17, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 33, 34,
+        38, 135, 11, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 16, 17, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 33, 34, 38, 135, 11, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 17, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 33, 34, 38, 135,
+        11, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 33,
+        34, 135, 11, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 34, 135, 11, 137, 11, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        15, 16, 17, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 26, 27, 28,
+        135, 135, 135, 135, 135, 33, 34, 38,
+        136, 135, 11, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 15, 16, 17, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 27, 28, 135, 135, 135, 135,
+        135, 33, 34, 38, 136, 135, 11, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        15, 16, 17, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 28,
+        135, 135, 135, 135, 135, 33, 34, 38,
+        136, 135, 138, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 11,
+        135, 11, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 15, 16, 17, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        33, 34, 38, 136, 135, 11, 135, 135,
+        135, 135, 135, 135, 135, 13, 14, 15,
+        16, 17, 135, 135, 135, 135, 135, 135,
+        23, 24, 25, 135, 26, 27, 28, 135,
+        135, 135, 135, 135, 33, 34, 38, 136,
+        135, 135, 135, 135, 14, 135, 11, 135,
+        135, 135, 135, 135, 135, 135, 135, 14,
+        15, 16, 17, 135, 135, 135, 135, 135,
+        135, 23, 24, 25, 135, 26, 27, 28,
+        135, 135, 135, 135, 135, 33, 34, 38,
+        136, 135, 135, 135, 135, 14, 135, 11,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        14, 15, 16, 17, 135, 135, 135, 135,
+        135, 135, 135, 24, 25, 135, 26, 27,
+        28, 135, 135, 135, 135, 135, 33, 34,
+        38, 136, 135, 135, 135, 135, 14, 135,
+        11, 135, 135, 135, 135, 135, 135, 135,
+        135, 14, 15, 16, 17, 135, 135, 135,
+        135, 135, 135, 135, 135, 25, 135, 26,
+        27, 28, 135, 135, 135, 135, 135, 33,
+        34, 38, 136, 135, 135, 135, 135, 14,
+        135, 139, 135, 11, 135, 135, 135, 135,
+        135, 135, 135, 13, 14, 15, 16, 17,
+        135, 19, 20, 135, 135, 135, 23, 24,
+        25, 135, 26, 27, 28, 135, 135, 135,
+        135, 135, 33, 34, 38, 136, 135, 135,
+        135, 135, 14, 135, 11, 135, 135, 135,
+        135, 135, 135, 135, 135, 14, 15, 16,
+        17, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 26, 27, 28, 135, 135,
+        135, 135, 135, 33, 34, 38, 136, 135,
+        135, 135, 135, 14, 135, 139, 135, 11,
+        135, 135, 135, 135, 135, 135, 135, 13,
+        14, 15, 16, 17, 135, 135, 20, 135,
+        135, 135, 23, 24, 25, 135, 26, 27,
+        28, 135, 135, 135, 135, 135, 33, 34,
+        38, 136, 135, 135, 135, 135, 14, 135,
+        139, 135, 11, 135, 135, 135, 135, 135,
+        135, 135, 13, 14, 15, 16, 17, 135,
+        135, 135, 135, 135, 135, 23, 24, 25,
+        135, 26, 27, 28, 135, 135, 135, 135,
+        135, 33, 34, 38, 136, 135, 135, 135,
+        135, 14, 135, 139, 135, 11, 135, 135,
+        135, 135, 135, 135, 135, 13, 14, 15,
+        16, 17, 18, 19, 20, 135, 135, 135,
+        23, 24, 25, 135, 26, 27, 28, 135,
+        135, 135, 135, 135, 33, 34, 38, 136,
+        135, 135, 135, 135, 14, 135, 8, 9,
+        135, 11, 135, 135, 135, 135, 135, 135,
+        135, 13, 14, 15, 16, 17, 18, 19,
+        20, 21, 135, 22, 23, 24, 25, 135,
+        26, 27, 28, 135, 135, 135, 135, 32,
+        33, 34, 38, 32, 135, 135, 135, 135,
+        37, 135, 135, 38, 135, 8, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 11, 135, 8, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 11, 135, 135, 135, 135, 135, 135,
+        135, 135, 14, 15, 16, 17, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        26, 27, 28, 135, 135, 135, 135, 135,
+        33, 34, 38, 136, 135, 140, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 11,
+        135, 10, 11, 135, 4, 135, 135, 135,
+        4, 135, 135, 135, 135, 135, 8, 9,
+        10, 11, 135, 135, 135, 135, 135, 135,
+        135, 13, 14, 15, 16, 17, 18, 19,
+        20, 21, 8, 22, 23, 24, 25, 135,
+        26, 27, 28, 135, 29, 30, 135, 32,
+        33, 34, 38, 32, 135, 135, 135, 135,
+        37, 135, 135, 38, 135, 11, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        29, 30, 135, 11, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 135,
+        135, 135, 135, 135, 135, 135, 135, 30,
+        135, 4, 141, 141, 141, 4, 141, 143,
+        142, 142, 142, 142, 142, 142, 142, 142,
+        142, 142, 142, 142, 142, 142, 142, 142,
+        142, 142, 142, 142, 142, 142, 142, 142,
+        142, 142, 142, 142, 142, 142, 142, 142,
+        142, 142, 142, 144, 142, 145, 142, 145,
+        146, 142, 143, 142, 142, 142, 142, 142,
+        142, 142, 142, 142, 142, 142, 142, 142,
+        142, 142, 142, 142, 142, 142, 142, 142,
+        142, 142, 142, 142, 142, 142, 142, 142,
+        142, 142, 142, 142, 142, 1, 144, 144,
+        142, 143, 142, 142, 142, 142, 142, 142,
+        142, 142, 142, 142, 142, 142, 142, 142,
+        142, 142, 142, 142, 142, 142, 142, 142,
+        142, 142, 142, 142, 142, 142, 142, 142,
+        142, 142, 142, 142, 142, 144, 142, 145,
+        142, 143, 142, 142, 142, 142, 142, 142,
+        142, 142, 142, 142, 142, 142, 142, 142,
+        142, 142, 142, 142, 142, 142, 142, 142,
+        142, 142, 142, 142, 142, 142, 142, 142,
+        142, 142, 142, 142, 142, 144, 142, 145,
+        142, 145, 142, 40, 41, 39, 42, 39,
+        39, 39, 39, 39, 39, 39, 43, 44,
+        45, 46, 47, 48, 49, 50, 51, 40,
+        52, 53, 54, 55, 39, 56, 57, 58,
+        39, 59, 60, 39, 61, 62, 63, 64,
+        61, 1, 39, 2, 39, 65, 39, 39,
+        64, 39, 0
 };
 
 static const char _use_syllable_machine_trans_targs[] = {
-        1, 120, 0, 2, 31, 1, 58, 60,
-        88, 89, 114, 1, 116, 102, 90, 91,
-        92, 93, 106, 108, 109, 110, 111, 103,
-        104, 105, 97, 98, 99, 117, 118, 119,
-        112, 94, 95, 96, 124, 113, 1, 3,
-        4, 1, 17, 5, 6, 7, 8, 21,
-        23, 24, 25, 26, 18, 19, 20, 12,
-        13, 14, 29, 30, 27, 9, 10, 11,
-        28, 15, 16, 22, 1, 32, 1, 45,
-        33, 34, 35, 36, 49, 51, 52, 53,
-        54, 46, 47, 48, 40, 41, 42, 55,
-        37, 38, 39, 56, 57, 43, 1, 44,
-        1, 50, 1, 1, 1, 59, 1, 1,
-        1, 61, 62, 75, 63, 64, 65, 66,
-        79, 81, 82, 83, 84, 76, 77, 78,
-        70, 71, 72, 85, 67, 68, 69, 86,
-        87, 73, 74, 80, 1, 100, 101, 107,
-        115, 1, 1, 1, 121, 122, 123
+        1, 122, 0, 2, 31, 1, 59, 61,
+        90, 91, 116, 1, 118, 104, 92, 93,
+        94, 95, 108, 110, 111, 112, 113, 105,
+        106, 107, 99, 100, 101, 119, 120, 121,
+        114, 96, 97, 98, 126, 115, 98, 1,
+        3, 4, 1, 17, 5, 6, 7, 8,
+        21, 23, 24, 25, 26, 18, 19, 20,
+        12, 13, 14, 29, 30, 27, 9, 10,
+        11, 28, 15, 16, 22, 1, 32, 1,
+        45, 33, 34, 35, 36, 49, 51, 52,
+        53, 54, 46, 47, 48, 40, 41, 42,
+        55, 37, 38, 39, 56, 57, 58, 43,
+        1, 44, 1, 50, 1, 1, 1, 60,
+        1, 1, 1, 62, 63, 76, 64, 65,
+        66, 67, 80, 82, 83, 84, 85, 77,
+        78, 79, 71, 72, 73, 86, 68, 69,
+        70, 87, 88, 89, 74, 75, 81, 1,
+        102, 1, 103, 109, 117, 1, 1, 1,
+        123, 124, 125
 };
 
 static const char _use_syllable_machine_trans_actions[] = {
@@ -737,20 +745,21 @@ static const char _use_syllable_machine_
         0, 0, 0, 5, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 6, 0, 7, 0,
-        0, 8, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 6, 7, 0, 8, 9,
+        0, 0, 10, 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, 12,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 9, 0, 10, 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,
-        12, 0, 13, 14, 15, 0, 16, 17,
-        18, 0, 0, 0, 0, 0, 0, 0,
+        13, 0, 14, 0, 15, 16, 17, 0,
+        18, 19, 20, 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, 19, 0, 0, 0,
-        0, 20, 21, 22, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 21,
+        0, 22, 0, 0, 0, 23, 24, 25,
+        0, 0, 0
 };
 
 static const char _use_syllable_machine_to_state_actions[] = {
@@ -769,7 +778,7 @@ static const char _use_syllable_machine_
         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
 };
 
 static const char _use_syllable_machine_from_state_actions[] = {
@@ -788,26 +797,26 @@ static const char _use_syllable_machine_
         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
 };
 
 static const short _use_syllable_machine_eof_trans[] = {
-        1, 0, 39, 39, 39, 39, 39, 39,
-        39, 39, 39, 39, 39, 39, 39, 39,
-        39, 39, 39, 39, 39, 39, 39, 39,
-        39, 39, 39, 39, 39, 39, 39, 69,
-        69, 69, 69, 69, 69, 69, 69, 69,
-        69, 69, 69, 95, 69, 69, 69, 69,
-        69, 69, 69, 69, 69, 69, 69, 99,
-        95, 69, 101, 104, 69, 69, 69, 69,
-        69, 69, 69, 69, 69, 69, 69, 69,
-        69, 95, 69, 69, 69, 69, 69, 69,
-        69, 69, 69, 69, 69, 99, 95, 69,
-        133, 133, 133, 133, 133, 133, 133, 133,
-        133, 133, 133, 133, 133, 133, 133, 133,
-        133, 133, 133, 133, 133, 133, 133, 133,
-        133, 133, 133, 133, 133, 133, 133, 138,
-        139, 139, 139, 139, 39
+        1, 0, 40, 40, 40, 40, 40, 40,
+        40, 40, 40, 40, 40, 40, 40, 40,
+        40, 40, 40, 40, 40, 40, 40, 40,
+        40, 40, 40, 40, 40, 40, 40, 70,
+        70, 70, 70, 70, 70, 70, 70, 70,
+        70, 70, 70, 97, 70, 70, 70, 70,
+        70, 70, 70, 70, 70, 70, 70, 101,
+        97, 70, 101, 103, 106, 70, 70, 70,
+        70, 70, 70, 70, 70, 70, 70, 70,
+        70, 70, 97, 70, 70, 70, 70, 70,
+        70, 70, 70, 70, 70, 70, 101, 97,
+        70, 101, 136, 136, 136, 136, 136, 136,
+        136, 136, 138, 136, 136, 136, 136, 136,
+        136, 136, 136, 136, 136, 136, 136, 136,
+        136, 136, 136, 136, 136, 136, 136, 136,
+        136, 142, 143, 143, 143, 143, 40
 };
 
 static const int use_syllable_machine_start = 1;
@@ -821,7 +830,7 @@ static const int use_syllable_machine_en
 
 
 
-#line 184 "hb-ot-shaper-use-machine.rl"
+#line 186 "hb-ot-shaper-use-machine.rl"
 
 
 #define found_syllable(syllable_type) \
@@ -920,7 +929,7 @@ find_syllables_use (hb_buffer_t *buffer)
   unsigned int act HB_UNUSED;
   int cs;
 
-#line 924 "hb-ot-shaper-use-machine.hh"
+#line 933 "hb-ot-shaper-use-machine.hh"
         {
         cs = use_syllable_machine_start;
         ts = 0;
@@ -928,12 +937,12 @@ find_syllables_use (hb_buffer_t *buffer)
         act = 0;
         }
 
-#line 284 "hb-ot-shaper-use-machine.rl"
+#line 286 "hb-ot-shaper-use-machine.rl"
 
 
   unsigned int syllable_serial = 1;
 
-#line 937 "hb-ot-shaper-use-machine.hh"
+#line 946 "hb-ot-shaper-use-machine.hh"
         {
         int _slen;
         int _trans;
@@ -947,7 +956,7 @@ _resume:
 #line 1 "NONE"
         {ts = p;}
         break;
-#line 951 "hb-ot-shaper-use-machine.hh"
+#line 960 "hb-ot-shaper-use-machine.hh"
         }
 
         _keys = _use_syllable_machine_trans_keys + (cs<<1);
@@ -965,87 +974,111 @@ _eof_trans:
                 goto _again;
 
         switch ( _use_syllable_machine_trans_actions[_trans] ) {
-        case 6:
+        case 7:
 #line 1 "NONE"
         {te = p+1;}
         break;
-        case 14:
-#line 172 "hb-ot-shaper-use-machine.rl"
+        case 16:
+#line 173 "hb-ot-shaper-use-machine.rl"
         {te = p+1;{ found_syllable (use_virama_terminated_cluster); }}
         break;
-        case 12:
-#line 173 "hb-ot-shaper-use-machine.rl"
+        case 14:
+#line 174 "hb-ot-shaper-use-machine.rl"
         {te = p+1;{ found_syllable (use_sakot_terminated_cluster); }}
         break;
-        case 10:
-#line 174 "hb-ot-shaper-use-machine.rl"
+        case 12:
+#line 175 "hb-ot-shaper-use-machine.rl"
         {te = p+1;{ found_syllable (use_standard_cluster); }}
         break;
-        case 18:
-#line 175 "hb-ot-shaper-use-machine.rl"
+        case 20:
+#line 176 "hb-ot-shaper-use-machine.rl"
         {te = p+1;{ found_syllable (use_number_joiner_terminated_cluster); }}
         break;
-        case 16:
-#line 176 "hb-ot-shaper-use-machine.rl"
+        case 18:
+#line 177 "hb-ot-shaper-use-machine.rl"
         {te = p+1;{ found_syllable (use_numeral_cluster); }}
         break;
-        case 8:
-#line 177 "hb-ot-shaper-use-machine.rl"
+        case 10:
+#line 178 "hb-ot-shaper-use-machine.rl"
         {te = p+1;{ found_syllable (use_symbol_cluster); }}
         break;
-        case 22:
-#line 178 "hb-ot-shaper-use-machine.rl"
+        case 25:
+#line 179 "hb-ot-shaper-use-machine.rl"
         {te = p+1;{ found_syllable (use_hieroglyph_cluster); }}
         break;
         case 5:
-#line 179 "hb-ot-shaper-use-machine.rl"
+#line 181 "hb-ot-shaper-use-machine.rl"
         {te = p+1;{ found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
         break;
         case 4:
-#line 180 "hb-ot-shaper-use-machine.rl"
+#line 182 "hb-ot-shaper-use-machine.rl"
         {te = p+1;{ found_syllable (use_non_cluster); }}
         break;
-        case 13:
-#line 172 "hb-ot-shaper-use-machine.rl"
+        case 15:
+#line 173 "hb-ot-shaper-use-machine.rl"
         {te = p;p--;{ found_syllable (use_virama_terminated_cluster); }}
         break;
-        case 11:
-#line 173 "hb-ot-shaper-use-machine.rl"
+        case 13:
+#line 174 "hb-ot-shaper-use-machine.rl"
         {te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }}
         break;
-        case 9:
-#line 174 "hb-ot-shaper-use-machine.rl"
+        case 11:
+#line 175 "hb-ot-shaper-use-machine.rl"
         {te = p;p--;{ found_syllable (use_standard_cluster); }}
         break;
-        case 17:
-#line 175 "hb-ot-shaper-use-machine.rl"
+        case 19:
+#line 176 "hb-ot-shaper-use-machine.rl"
         {te = p;p--;{ found_syllable (use_number_joiner_terminated_cluster); }}
         break;
-        case 15:
-#line 176 "hb-ot-shaper-use-machine.rl"
+        case 17:
+#line 177 "hb-ot-shaper-use-machine.rl"
         {te = p;p--;{ found_syllable (use_numeral_cluster); }}
         break;
-        case 7:
-#line 177 "hb-ot-shaper-use-machine.rl"
+        case 9:
+#line 178 "hb-ot-shaper-use-machine.rl"
         {te = p;p--;{ found_syllable (use_symbol_cluster); }}
         break;
-        case 21:
-#line 178 "hb-ot-shaper-use-machine.rl"
+        case 24:
+#line 179 "hb-ot-shaper-use-machine.rl"
         {te = p;p--;{ found_syllable (use_hieroglyph_cluster); }}
         break;
-        case 19:
-#line 179 "hb-ot-shaper-use-machine.rl"
+        case 21:
+#line 181 "hb-ot-shaper-use-machine.rl"
         {te = p;p--;{ found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
         break;
-        case 20:
-#line 180 "hb-ot-shaper-use-machine.rl"
+        case 23:
+#line 182 "hb-ot-shaper-use-machine.rl"
         {te = p;p--;{ found_syllable (use_non_cluster); }}
         break;
         case 1:
-#line 177 "hb-ot-shaper-use-machine.rl"
+#line 178 "hb-ot-shaper-use-machine.rl"
         {{p = ((te))-1;}{ found_syllable (use_symbol_cluster); }}
         break;
-#line 1049 "hb-ot-shaper-use-machine.hh"
+        case 22:
+#line 1 "NONE"
+        {       switch( act ) {
+        case 8:
+        {{p = ((te))-1;} found_syllable (use_non_cluster); }
+        break;
+        case 9:
+        {{p = ((te))-1;} found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
+        break;
+        }
+        }
+        break;
+        case 6:
+#line 1 "NONE"
+        {te = p+1;}
+#line 180 "hb-ot-shaper-use-machine.rl"
+        {act = 8;}
+        break;
+        case 8:
+#line 1 "NONE"
+        {te = p+1;}
+#line 181 "hb-ot-shaper-use-machine.rl"
+        {act = 9;}
+        break;
+#line 1082 "hb-ot-shaper-use-machine.hh"
         }
 
 _again:
@@ -1054,7 +1087,7 @@ _again:
 #line 1 "NONE"
         {ts = 0;}
         break;
-#line 1058 "hb-ot-shaper-use-machine.hh"
+#line 1091 "hb-ot-shaper-use-machine.hh"
         }
 
         if ( ++p != pe )
@@ -1070,7 +1103,7 @@ _again:
 
         }
 
-#line 289 "hb-ot-shaper-use-machine.rl"
+#line 291 "hb-ot-shaper-use-machine.rl"
 
 }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -6,18 +6,18 @@
  *
  * on files with these headers:
  *
- * # IndicSyllabicCategory-15.1.0.txt
- * # Date: 2023-01-05
- * # IndicPositionalCategory-15.1.0.txt
- * # Date: 2023-01-05
- * # ArabicShaping-15.1.0.txt
- * # Date: 2023-01-05
- * # DerivedCoreProperties-15.1.0.txt
- * # Date: 2023-08-07, 15:21:24 GMT
- * # Blocks-15.1.0.txt
- * # Date: 2023-07-28, 15:47:20 GMT
- * # Scripts-15.1.0.txt
- * # Date: 2023-07-28, 16:01:07 GMT
+ * # IndicSyllabicCategory-16.0.0.txt
+ * # Date: 2024-04-30, 21:48:21 GMT
+ * # IndicPositionalCategory-16.0.0.txt
+ * # Date: 2024-04-30, 21:48:21 GMT
+ * # ArabicShaping-16.0.0.txt
+ * # Date: 2024-07-30
+ * # DerivedCoreProperties-16.0.0.txt
+ * # Date: 2024-05-31, 18:09:32 GMT
+ * # Blocks-16.0.0.txt
+ * # Date: 2024-02-02
+ * # Scripts-16.0.0.txt
+ * # Date: 2024-04-30, 21:48:40 GMT
  * # Override values For Indic_Syllabic_Category
  * # Not derivable
  * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
@@ -27,6 +27,7 @@
  * # Updated for Unicode 14.0 by Andrew Glass 2021-09-25
  * # Updated for Unicode 15.0 by Andrew Glass 2022-09-16
  * # Updated for Unicode 15.1 by Andrew Glass 2023-09-14
+ * # Updated for Unicode 16.0 by Andrew Glass 2024-09-11
  * # Override values For Indic_Positional_Category
  * # Not derivable
  * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
@@ -38,6 +39,7 @@
  * # Updated for Unicode 14.0 by Andrew Glass 2021-09-28
  * # Updated for Unicode 15.0 by Andrew Glass 2022-09-16
  * # Updated for Unicode 15.1 by Andrew Glass 2023-09-14
+ * # Updated for Unicode 16.0 by Andrew Glass 2024-09-11
  * UnicodeData.txt does not have a header.
  */
 
@@ -65,6 +67,7 @@
 #define N       USE(N)  /* BASE_NUM */
 #define O       USE(O)  /* OTHER */
 #define R       USE(R)  /* REPHA */
+#define RK      USE(RK) /* REORDERING_KILLER */
 #define SB      USE(SB) /* HIEROGLYPH_SEGMENT_BEGIN */
 #define SE      USE(SE) /* HIEROGLYPH_SEGMENT_END */
 #define SUB     USE(SUB)        /* CONS_SUB */
@@ -99,16 +102,16 @@
 #ifndef HB_OPTIMIZE_SIZE
 
 static const uint8_t
-hb_use_u8[3187] =
+hb_use_u8[3345] =
 {
-     16,   50,   51,   51,   51,   52,   51,   83,  118,  131,   51,   57,   58,  179,  195,   61,
+     16,   50,   51,   51,   51,   52,   51,   83,  118,  131,   57,   58,   59,  195,  211,   62,
      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-     14,    0,    1,    2,    2,    2,    2,    3,    2,    2,    2,    2,    2,    4,    2,    2,
+     15,    0,    1,    2,    2,    2,    2,    3,    2,    2,    2,    2,    2,    4,    2,    2,
       5,    6,    2,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,    2,    2,   17,
      18,   19,   20,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,   21,
      22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,    2,   33,    2,    2,    2,
@@ -121,24 +124,26 @@ hb_use_u8[3187] =
       2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
       2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,   47,   48,    2,
      49,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,   50,   51,    2,    2,    2,
-      2,    2,    2,    2,    2,   52,   53,    2,   54,    2,    2,   55,    2,    2,   56,   57,
-     58,   59,   60,   61,   62,   63,   64,   65,    2,   66,   67,    2,   68,   69,   70,   71,
-      2,   72,    2,   73,   74,   75,   76,    2,    2,   77,   78,   79,   80,    2,   81,   82,
-      2,   83,   83,   83,   83,   83,   83,   83,   83,   84,    2,    2,    2,    2,    2,    2,
+      2,    2,    2,    2,    2,   52,   53,    2,   54,    2,    2,   55,   56,    2,   57,   58,
+     59,   60,   61,   62,   63,   64,   65,   66,   67,   68,   69,    2,   70,   71,   72,   73,
+      2,   74,    2,   75,   76,   77,   78,    2,    2,   79,   80,   81,   82,    2,   83,   84,
+      2,   85,   85,   85,   85,   85,   85,   85,   85,   86,   85,   85,   85,   85,   85,   85,
+     85,   85,   85,   85,   85,   85,   85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
+     85,   85,   85,   85,   85,   85,   85,   85,   87,    2,    2,    2,    2,    2,    2,    2,
       2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+      2,    2,    2,   88,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+      2,    2,    2,    2,    2,    2,   89,   90,    2,    2,    2,   91,    2,    2,    2,   92,
+     93,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+      2,    2,    2,    2,    2,    2,    2,   94,   94,   94,   95,    2,    2,    2,    2,    2,
       2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-      2,    2,    2,    2,    2,    2,   85,   86,    2,    2,    2,    2,    2,    2,    2,   87,
-     88,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-      2,    2,    2,    2,    2,    2,    2,   89,   89,   89,   90,    2,    2,    2,    2,    2,
+      2,    2,    2,    2,    2,    2,    2,    2,    2,   96,   97,    2,    2,    2,    2,    2,
+      2,    2,    2,   98,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
       2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-      2,    2,    2,    2,    2,    2,    2,    2,    2,   91,   92,    2,    2,    2,    2,    2,
-      2,    2,    2,   93,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-      2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-      2,    2,    2,   94,    2,    2,   95,    2,    2,    2,   96,    2,    2,    2,    2,    2,
-      2,    2,    2,   97,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-      2,   98,   98,   99,  100,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,
-     98,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,
-     98,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,
+      2,    2,    2,   99,    2,    2,  100,    2,    2,    2,  101,    2,  102,    2,    2,    2,
+      2,    2,    2,  103,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+      2,  104,  104,  105,  106,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,
+    104,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,
+    104,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,
       0,    2,    2,    2,    2,    2,    0,    0,    0,    0,    0,    0,    0,    0,    3,    4,
       0,    5,    0,    0,    0,    0,    0,    6,    0,    0,    7,    0,    0,    0,    0,    0,
       0,    0,    0,    0,    1,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
@@ -167,7 +172,7 @@ hb_use_u8[3187] =
       0,    0,    0,   27,   31,    2,    9,    0,    0,   10,   29,   30,    2,    2,    2,    9,
       2,    2,    2,   30,    2,    2,    0,   17,   45,    0,    0,   35,   47,    0,    0,    0,
       9,   50,   51,    0,    0,    0,    0,    0,    0,   11,   29,    2,    2,    2,    2,    9,
-      2,    2,    2,    2,    2,    2,   52,   53,   23,   23,   19,   31,   48,   33,   48,   34,
+      2,    2,    2,    2,    2,    2,   52,   53,   23,   19,   20,   31,   48,   33,   48,   34,
      54,    0,    0,    0,   35,    0,    0,    0,   30,   12,   29,   30,    2,    2,    2,    2,
       2,    2,    2,    2,    9,    0,    2,    2,    2,    2,   30,    2,    2,    2,    2,   30,
       0,    2,    2,    2,    9,    0,   55,    0,   35,   23,   22,   31,   31,   18,   48,   48,
@@ -195,9 +200,9 @@ hb_use_u8[3187] =
       0,    2,    2,  100,  101,  102,  103,   61,   63,  104,   16,   45,   22,   59,   21,   80,
      48,   48,   76,   11,   11,   11,  105,   46,   40,   11,  106,   74,    2,    2,    2,    2,
       2,    2,    2,  107,   22,   20,   20,   22,   48,   48,   22,  108,    2,    2,    2,    9,
-      0,    0,    0,    0,    0,    0,  109,  110,  111,  111,  111,    0,    0,    0,    0,    0,
-      0,  106,   74,    2,    2,    2,    2,    2,    2,   60,   61,   59,   25,   22,  112,   61,
-      2,    2,    2,    2,  107,   22,   23,   45,   45,  102,   14,    0,    0,    0,    0,    0,
+      0,    0,    0,    0,    0,    0,  109,  110,  110,  110,  110,    0,    0,    0,    0,    0,
+      0,  106,   74,    2,    2,    2,    2,    2,    2,   60,   61,   59,   25,   22,  111,   61,
+      2,    2,    2,    2,  107,   22,   23,   45,   45,  102,  112,    0,    0,    0,    0,    0,
       0,    2,    2,   61,   18,   48,   23,  113,  102,  102,  102,  114,  115,    0,    0,    0,
       0,    2,    2,    2,    2,    2,    0,   30,    2,   11,   46,  116,  116,  116,   11,  116,
     116,   15,  116,  116,  116,   26,    0,   40,    0,    0,    0,  117,   51,   11,    5,    0,
@@ -226,6 +231,7 @@ hb_use_u8[3187] =
     146,    2,    2,   30,    2,   30,    2,    2,    2,    2,    2,    2,    0,   14,   37,    0,
     147,    2,    2,   13,   37,    0,   30,    2,    2,    2,    0,    0,    0,    0,    0,    0,
       0,    0,    0,    0,    0,   30,    2,    2,    9,    2,    2,   11,   41,    0,    0,    0,
+      0,    2,    2,    2,    0,   27,   22,   22,   30,    2,    2,    2,    0,    0,    0,    0,
       0,    2,    2,    2,    2,    2,   27,   38,    0,    2,    2,    2,  116,  116,  116,  116,
     116,  148,    2,    9,    0,    0,    0,    0,    0,    2,   14,   14,    0,    0,    0,    0,
       0,    9,    2,    2,    9,    2,    2,    2,    2,   30,    2,    9,    0,   30,    2,    0,
@@ -244,39 +250,45 @@ hb_use_u8[3187] =
       0,   11,   11,   30,    2,    2,    2,    9,   30,    9,    2,   30,    2,    2,   58,   17,
      23,   16,   23,   47,   32,   33,   32,   34,    0,    0,    0,    0,   35,    0,    0,    0,
       2,    2,   23,    0,   11,   11,   11,   46,    0,   11,   11,   46,    0,    0,    0,    0,
-      0,    2,    2,   65,   25,   20,   20,   20,   22,   23,  126,   15,   17,    0,    0,    0,
-      0,    2,    2,    2,    2,    2,    0,    0,  163,  164,    0,    0,    0,    0,    0,    0,
-      0,   18,   19,   20,   20,   66,   99,   25,  160,   11,  165,    9,    0,    0,    0,    0,
-      0,    2,    2,    2,    2,    2,    2,    2,   65,   25,   20,   20,    0,   48,   48,   11,
-    166,   37,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    2,    2,   20,
-      0,   23,   19,   20,   20,   21,   16,   82,  166,   38,    0,    0,    0,    0,    0,    0,
-      0,    2,    2,    2,    2,    2,   10,  167,   25,   20,   22,   22,  165,    9,    0,    0,
-      0,    2,    2,    2,    2,    2,    9,   43,  136,   23,   22,   20,   76,   21,   22,    0,
-      0,    2,    2,    2,    9,    0,    0,    0,    0,    2,    2,    2,    2,    2,    2,   18,
-     19,   20,   21,   22,  105,  166,   37,    0,    0,    2,    2,    2,    9,   30,    0,    2,
-      2,    2,    2,   30,    9,    2,    2,    2,    2,   23,   23,   18,   32,   33,   12,  168,
-    169,  170,  171,    0,    0,    0,    0,    0,    0,    2,    2,    2,    2,    0,    2,    2,
-      2,   65,   25,   20,   20,    0,   22,   23,   29,  108,    0,   33,    0,    0,    0,    0,
-      0,   52,   20,   22,   22,   22,  140,    2,    2,    2,  172,  173,   11,   15,  174,   72,
-    175,    0,    0,    1,  147,    0,    0,    0,    0,   52,   20,   22,   16,   19,   20,    2,
-      2,    2,    2,  158,  158,  158,  176,  176,  176,  176,  176,  176,   15,  177,    0,   30,
-      0,   22,   20,   20,   31,   22,   22,   11,  166,    0,   61,   61,   61,   61,   61,   61,
-     61,   66,   21,   82,   46,    0,    0,    0,    0,    2,    2,    2,    9,    2,   30,    2,
-      2,   52,   22,   22,   31,    0,   38,   22,   27,   11,  159,  178,  174,    0,    0,    0,
-      0,    2,    2,    2,   30,    9,    2,    2,    2,    2,    2,    2,    2,    2,   23,   23,
-     47,   22,   35,   82,   68,    0,    0,    0,    0,    2,  179,   66,   47,    0,    0,    0,
-      0,   11,  180,    2,    2,    2,    2,    2,    2,    2,    2,   23,   22,   20,   31,    0,
-     48,   16,  143,    0,    0,    0,    0,    0,    0,  181,  181,  181,  181,  181,  181,  181,
-    181,  182,  182,  182,  183,  184,  182,  181,  181,  185,  181,  181,  186,  187,  187,  187,
-    187,  187,  187,  187,    0,    0,    0,    0,    0,   11,   11,   11,   46,    0,    0,    0,
-      0,    2,    2,    2,    2,    2,    9,    0,   58,  188,   20,   20,   20,   20,   20,   20,
-     20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,    0,    0,    0,
-     40,  116,   26,    0,    0,    0,    0,    0,    0,    0,    0,    9,    0,    0,    0,    0,
-      0,    2,    2,    2,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    0,   58,
-     37,    0,    6,  120,  120,  120,  121,    0,    0,   11,   11,   11,   49,    2,    2,    2,
-      0,    2,    2,    2,    2,    2,    0,    0,    2,    2,    2,    2,    2,    2,    2,    2,
-     46,    2,    2,    2,    2,    2,    2,   11,   11,    2,    2,    2,    2,    2,    2,   22,
-     22,    2,    2,   44,   44,   44,   92,    0,    0,    O,    O,    O,   GB,    B,    B,    O,
+      0,    2,    2,    2,    2,    2,   30,    0,    9,    2,    2,    2,   30,   45,   59,   20,
+     20,   31,   33,   32,   32,   25,  163,   29,  164,  165,   37,    0,    0,    0,    0,    0,
+      0,   12,   26,    0,    0,    0,    0,    0,    0,    2,    2,   65,   25,   20,   20,   20,
+     22,   23,  126,   15,   17,    0,    0,    0,    0,    2,    2,    2,    2,    2,    0,    0,
+    166,  167,    0,    0,    0,    0,    0,    0,    0,   18,   19,   20,   20,   66,   99,   25,
+    160,   11,  168,    9,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    2,    2,
+     65,   25,   20,   20,    0,   48,   48,   11,  169,   37,    0,    0,    0,    0,    0,    0,
+      0,    0,    0,    0,    0,    2,    2,   20,    0,   23,   19,   20,   20,   21,   16,   82,
+    169,   38,    0,    0,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,   10,  170,
+     25,   20,   22,   22,  168,    9,    0,    0,    0,    2,    2,    2,    2,    2,    9,   43,
+    136,   23,   22,   20,   76,   21,   22,    0,    0,    2,    2,    2,    9,    0,    0,    0,
+      0,    2,    2,    2,    2,    2,    2,   18,   19,   20,   21,   22,  105,  169,   37,    0,
+      0,    2,    2,    2,    9,   30,    0,    2,    2,    2,    2,   30,    9,    2,    2,    2,
+      2,   23,   23,   18,   32,   33,   12,  171,  165,  172,  173,    0,    0,    0,    0,    0,
+      0,    2,    2,    2,    2,    0,    2,    2,    2,   65,   25,   20,   20,    0,   22,   23,
+     29,  108,    0,   33,    0,    0,    0,    0,    0,   52,   20,   22,   22,   22,  140,    2,
+      2,    2,  174,  175,   11,   15,  176,   61,  177,    0,    0,    1,  147,    0,    0,    0,
+      0,   52,   20,   22,   16,   19,   20,    2,    2,    2,    2,  158,  158,  158,  178,  178,
+    178,  178,  178,  178,   15,  179,    0,   30,    0,   22,   20,   20,   31,   22,   22,   11,
+    169,    0,   61,   61,   61,   61,   61,   61,   61,   66,   21,   82,   46,    0,    0,    0,
+      0,    2,    2,    2,    9,    2,   30,    2,    2,   52,   22,   22,   31,    0,   38,   22,
+     27,   11,  159,  180,  181,    0,    0,    0,    0,    2,    2,    2,   30,    9,    2,    2,
+      2,    2,    2,    2,    2,    2,   23,   23,   47,   22,   35,   82,   68,    0,    0,    0,
+      0,    2,  182,   66,   47,    0,    0,    0,    0,   11,  183,    2,    2,    2,    2,    2,
+      2,    2,    2,   23,   22,   20,   31,    0,   48,   16,  143,    0,    0,    0,    0,    0,
+      0,    2,    2,    2,    2,    2,  156,    0,    0,  184,  184,  184,  184,  184,  184,  184,
+    184,  185,  185,  185,  186,  187,  185,  184,  184,  188,  184,  184,  189,  190,  190,  190,
+    190,  190,  190,  190,    0,    0,    0,    0,    0,  184,  184,  184,  184,  184,  191,    0,
+      0,    2,    2,    2,    2,    2,    2,    2,   22,   22,   22,   22,   22,   22,  192,  193,
+    194,   11,   11,   11,   46,    0,    0,    0,    0,   29,   74,    2,    2,    2,    2,    2,
+      2,    2,    2,    2,    2,    2,   65,   47,    0,    2,    2,    2,    2,    2,    9,    0,
+     58,  195,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
+     20,   20,   20,   20,   20,    0,    0,    0,   40,  116,   26,    0,    0,    0,    0,    0,
+      0,    0,    0,    9,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+     30,    2,    2,    2,    2,    2,    0,   58,   37,    0,    6,  120,  120,  120,  121,    0,
+      0,   11,   11,   11,   49,    2,    2,    2,    0,    2,    2,    2,    2,    2,    0,    0,
+      2,    2,    2,    2,    2,    2,    2,    2,   46,    2,    2,    2,    2,    2,    2,   11,
+     11,    2,    2,    2,    2,    2,    2,   22,   22,    2,    2,    2,    2,    2,    2,    2,
+     20,    2,    2,   44,   44,   44,   92,    0,    0,    O,    O,    O,   GB,    B,    B,    O,
      SB,    O,   SE,   GB,    O,    O,   WJ,FMPst,FMPst,    O,  CGJ,    B,    O,    B,VMAbv,VMAbv,
   VMAbv,    O,VMAbv,    B,CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw,    B, VPst, VPre, VPst,
    VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VPst,    H, VPre, VPst,VMBlw,    O,    O,
@@ -290,20 +302,21 @@ hb_use_u8[3187] =
   FMAbv, FAbv,CMAbv,FMAbv,VMAbv,FMAbv, VAbv,   IS,FMAbv,    B,FMAbv,    B,  CGJ,   WJ,  CGJ,   GB,
   CMAbv,CMAbv,    B,   GB,    B, VAbv,  SUB, FPst, FPst,VMBlw, FPst, FPst, FBlw,VMAbv,FMBlw, VAbv,
    VPre,    B, MPre, MBlw,  SUB, FAbv, FAbv, MAbv,  SUB,   Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv,
-   VPst,    H,    B,    O,SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst,   IS, VBlw, FAbv,VMPre,VMPre,FMAbv,
+   VPst,    H,    B,    O,SMAbv,SMAbv,SMAbv, VPst,   IS,   RK,   RK, VBlw, FAbv,VMPre,VMPre,FMAbv,
   CMBlw,VMBlw,VMBlw,VMAbv,   CS,    O,FMAbv, ZWNJ,  CGJ,   WJ,   WJ,   WJ,    O,FMPst,    O,   SB,
      SE,    O,    H, MPst, VPst,    H,VMAbv, VAbv,VMBlw,    B, VBlw, FPst, VPst, FAbv,VMPst,    B,
   CMAbv, VAbv, MBlw, MPst, MBlw,    H,    O, VBlw, MPst, MPre, MAbv, MBlw,    O,    B, FAbv, FAbv,
    FPst, VBlw,    B,    B, VPre,    O,VMPst,   IS,    O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv,    O,
      IS,VMBlw,    B,VMPst,VMAbv,VMPst,   CS,   CS,    B,    N,    N,    O,   HN, VPre, VBlw, VAbv,
-     IS,CMAbv,    O, VPst,    B,    R,    R,CMBlw, VAbv, VPre,VMAbv,VMAbv,    H, VAbv,CMBlw,FMAbv,
-      B,   CS,   CS,    H,CMBlw,VMPst,    H,VMPst, VAbv,VMAbv, VPst,   IS,    R, MPst,    R, MPst,
-  CMBlw,    B,FMBlw, VBlw,VMAbv,    R, MBlw, MBlw,   GB, FBlw, FBlw,CMAbv,   IS, VBlw,   IS,   GB,
-   VAbv,    R,VMPst,    G,    G,    J,    J,    J,   SB,   SE,    J,   HR,    G,    G,   HM,   HM,
-     HM,    O, VBlw,
+     IS,CMAbv,    O, VPst,    B,    R,    R,CMBlw, VAbv, VPre,VMAbv,VMAbv,    H, VAbv,CMBlw,VMPst,
+      O,VMAbv,CMBlw,   IS,    R,FMAbv,    B,   CS,   CS,    H,CMBlw,VMPst,    H,VMPst, VAbv,VMAbv,
+   VPst, MPst,    R, MPst,CMBlw,    B,FMBlw, VBlw,VMAbv,   CS,  SUB,  SUB,   GB, FBlw, FBlw,CMAbv,
+     IS, VBlw,   IS,    R, MBlw,   GB, VAbv,    R,VMPst,    G,    G,    J,    J,    J,   SB,   SE,
+      J,   HR,    G,    G,   HM,   HM,   HM,    G,    O, MPre, MPre, MPst,VMAbv, MBlw, VBlw,    O,
+   VBlw,
 };
 static const uint16_t
-hb_use_u16[808] =
+hb_use_u16[856] =
 {
     0,  0,  1,  2,  0,  3,  0,  3,  0,  0,  4,  5,  0,  6,  0,  0,
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  7,  0,  0,  0,
@@ -332,28 +345,31 @@ hb_use_u16[808] =
     0,  0,  0,  0,  0,  0,  0,164,  0,  0,  0,  0,  0,  0,  0,165,
     0,  0,  0,  0,  0,  0,  0,166,166,167, 34,168,  0,  0,  0,  0,
   169,170, 10,171, 95,  0,  0,  0,  0,  0,  0,  0, 70, 10,172,  0,
-   10,173,174,  0,  0,  0,  0,  0, 10, 10,175,  2,  0,  0,  0,  0,
-   10, 10,176,173,  0,  0,  0,  0,  0,  0,  0, 10,177,178,  0, 10,
-  179,  0,  0,180,181,  0,  0,  0,182, 10, 10,183,184,185,186,187,
-  188, 10, 10,189,190,  0,  0,  0,191, 10,192,193,194, 10, 10,195,
-  188, 10, 10,196,197,106,198,103, 10, 34,199,200,201,  0,  0,  0,
-  202,203, 95, 10, 10,204,205,  2,206, 21, 22,207,208,209,210,211,
-   10, 10, 10,212,213,214,215,  0,198, 10, 10,216,217,  2,  0,  0,
-   10, 10,218,219,220,221,  0,  0, 10, 10, 10,222,223,  2,  0,  0,
-   10, 10,224,225,  2,  0,  0,  0, 10,226,227,104,228,  0,  0,  0,
-   10, 10,229,230,  0,  0,  0,  0,231,232, 10,233,234,  2,  0,  0,
-    0,  0,235, 10, 10,236,237,  0,238, 10, 10,239,240,241, 10, 10,
-  242,243,  0,  0,  0,  0,  0,  0, 22, 10,218,244,  8, 10, 71, 19,
-   10,245, 74,246,  0,  0,  0,  0,247, 10, 10,248,249,  2,250, 10,
-  251,252,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 10,253,
-  254, 49, 10,255,256,  2,  0,  0,257,257,257,257,257,257,257,257,
-  257,257,257,258,259,260,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,
-   10, 10, 10,261,  0,  0,  0,  0, 10, 10, 10, 10,262,263,264,264,
-  265,266,  0,  0,  0,  0,267,  0, 10, 10, 10, 10, 10, 10, 10, 10,
-   10, 10, 10, 10, 10,268,  0,  0, 10, 10, 10, 10, 10, 10,106, 71,
-   95,269,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,270,
-   10, 10, 71,271,272,  0,  0,  0,  0, 10,273,  0, 10, 10,274,  2,
-    0,  0,  0,  0,  0, 10,275,  2, 10, 10, 10, 10,276,  2,  0,  0,
+   10,173,174,  0,  0,  0,  0,  0, 10, 10,175,  2,  9, 10,176, 10,
+  177,  0,  0,  0,  0,  0,  0,  0, 10, 10,178,173,  0,  0,  0,  0,
+    0,  0,  0, 10,179,180,  0, 10,181,  0,  0,182,183,  0,  0,  0,
+  184, 10, 10,185,186,187,188,189,190, 10, 10,191,192,  0,  0,  0,
+  193, 10,194,195,196, 10, 10,197,190, 10, 10,198,199,106,200,103,
+   10, 34,201,202,203,  0,  0,  0,204,205, 95, 10, 10,206,207,  2,
+  208, 21, 22,209,210,211,212,213,214, 10, 10,215,216,217,218,  0,
+   10, 10, 10,219,220,221,222,  0,200, 10, 10,223,224,  2,  0,  0,
+   10, 10,225,226,227,228,  0,  0, 10, 10, 10,229,230,  2,  0,  0,
+   10, 10,231,232,  2, 10,141,  0, 10,233,234,104,235,  0,  0,  0,
+   10, 10,236,237,  0,  0,  0,  0,238,239, 10,240,241,  2,  0,  0,
+    0,  0,242, 10, 10,243,244,  0,245, 10, 10,246,247,248, 10, 10,
+  249,250,  0,  0,  0,  0,  0,  0, 22, 10,225,251,  8, 10, 71, 19,
+   10,252, 74,253,  0,  0,  0,  0,254, 10, 10,255,256,  2,257, 10,
+  258,259,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 10,260,
+  261, 49, 10,262,263,264,  0,  0,265,265,265,265,265,265,265,265,
+  265,265,265,266,267,268,265,265,265,265,265,265,265,265,265,269,
+   10,270,271,  2,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,
+   10, 10, 10,272,  0,  0,  0,  0,  0,  0,  0,  0,273, 10,274,  2,
+   10, 10, 10, 10,275,276,277,277,278,279,  0,  0,  0,  0,280,  0,
+   10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,177,  0,281,
+   10, 10, 10, 10, 10, 10,106, 71, 95,282,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,283, 10, 10, 71,284,285,  0,  0,  0,
+    0, 10,286,  0, 10, 10,287,  2,  0,  0,  0,  0,  0, 10,288,  2,
+    0,  0,  0,  0,  0, 10,289,106, 10, 10, 10, 10,290,  2,  0,  0,
   130,130,130,130,130,130,130,130,163,163,163,163,163,163,163,163,
   163,163,163,163,163,163,163,130,
 };
@@ -366,23 +382,23 @@ hb_use_b4 (const uint8_t* a, unsigned i)
 static inline uint_fast8_t
 hb_use_get_category (unsigned u)
 {
-  return u<921600u?hb_use_u8[2809+(((hb_use_u8[593+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
+  return u<921600u?hb_use_u8[2953+(((hb_use_u8[625+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
 }
 
 
 #else
 
 static const uint8_t
-hb_use_u8[3483] =
+hb_use_u8[3657] =
 {
-     16,   50,   51,   51,   51,   52,   51,   83,  118,  131,   51,   57,   58,  179,  195,   61,
+     16,   50,   51,   51,   51,   52,   51,   83,  118,  131,   57,   58,   59,  195,  211,   62,
      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
-     14,    0,    1,    1,    2,    1,    1,    3,    4,    5,    6,    7,    8,    9,   10,    1,
+     15,    0,    1,    1,    2,    1,    1,    3,    4,    5,    6,    7,    8,    9,   10,    1,
      11,   12,    1,    1,    1,    1,    1,    1,   13,   14,   15,   16,   17,   18,   19,    1,
       1,   20,    1,    1,    1,    1,   21,    1,   22,    1,    1,    1,    1,    1,   23,   24,
       1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -390,14 +406,15 @@ hb_use_u8[3483] =
       1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   29,
      30,    1,    1,    1,    1,    1,   31,    1,    1,    1,    1,   32,   33,    1,   34,   35,
      36,   37,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,    1,   48,   49,   50,
-     51,   52,   52,   52,   52,   53,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-      1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   54,   55,    1,    1,    1,
-     56,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   57,   58,    1,    1,
-      1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   59,    1,    1,
-      1,    1,   60,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-      1,    1,   61,   62,    1,   63,    1,    1,    1,    1,   64,    1,    1,    1,    1,    1,
-      1,   65,   66,   65,   65,   65,   65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-     65,    0,    1,    2,    2,    0,    3,    4,    0,    0,    0,    0,    0,    0,    0,    0,
+     51,   52,   52,   52,   52,   53,   52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
+     52,   52,   52,   52,   54,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+      1,    1,   55,    1,    1,    1,    1,    1,    1,    1,    1,   56,   57,    1,   58,    1,
+     59,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   60,   61,    1,    1,
+      1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   62,    1,    1,
+      1,    1,   63,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+      1,    1,   64,   65,    1,   66,   67,    1,    1,    1,   68,    1,    1,    1,    1,    1,
+      1,   69,   70,   69,   69,   69,   69,   69,   69,   69,   69,   69,   69,   69,   69,   69,
+     69,    0,    1,    2,    2,    0,    3,    4,    0,    0,    0,    0,    0,    0,    0,    0,
       0,    0,    0,    5,    0,    0,    0,    0,    0,    0,    0,    6,    0,    0,    0,    0,
       0,    0,    0,    0,    0,    0,    0,    7,    8,    0,    0,    9,    0,    0,    0,    0,
       0,   10,   11,   12,   13,   14,   15,   16,   17,   18,   19,   20,   21,   22,   23,   24,
@@ -414,23 +431,25 @@ hb_use_u8[3483] =
     122,    0,    0,    0,    0,    0,    0,   56,  123,  124,    0,    0,    0,    0,    0,    0,
     125,    0,    0,    0,    0,    0,    0,    0,  126,    0,    0,    0,  127,  128,  129,    0,
       0,  130,  131,  132,    0,    0,    0,   51,  133,    0,    0,    0,    0,  134,  135,    0,
-      0,   56,  136,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   56,  137,    0,
-      0,    0,  101,  138,  101,  139,  140,  141,    0,  142,  143,  144,  145,  146,  147,  148,
-      0,  149,  150,  151,  152,  146,  153,  154,  155,  156,  157,  158,    0,  159,  160,  161,
-    162,  163,  164,  165,  166,    0,    0,    0,    0,   56,  167,  168,  169,  170,  171,  172,
-      0,    0,    0,    0,    0,   56,  173,  174,    0,   56,  175,  176,    0,   56,  177,   67,
-      0,  178,  179,  180,    0,    0,    0,    0,    0,   56,  181,    0,    0,    0,    0,    0,
-      0,  182,  183,  184,    0,    0,  185,  186,  187,  188,  189,  190,   56,  191,    0,    0,
-      0,  192,  193,  194,  195,  196,  197,    0,    0,  198,  199,  200,  201,  202,   67,    0,
-      0,    0,    0,    0,    0,    0,    0,    0,  203,  204,  205,  206,    0,    0,    0,    0,
-      0,  207,  207,  207,  207,  207,  207,  207,  207,  207,  208,  209,    0,    0,    0,    0,
-      0,    0,    0,    0,    0,    0,    0,   67,    0,   56,  210,    0,    0,    0,    0,    0,
-      0,   56,   56,  211,  212,  213,    0,    0,  214,   56,   56,   56,   56,   56,   56,   56,
-     56,   56,   56,   56,   56,   56,   56,  215,    0,   56,   56,   56,  216,  217,    0,    0,
-      0,    0,    0,    0,  218,    0,    0,    0,    0,   56,  219,  220,    0,    0,    0,    0,
-      0,    0,    0,    0,    0,  101,  221,   56,  222,    0,    0,    0,    0,    0,    0,  101,
-    223,   56,   56,  224,    0,    0,    0,    0,    0,  225,  225,  225,  225,  225,  225,  225,
-    225,  226,  226,  226,  226,  226,  226,  226,  227,    0,    0,    0,    0,    0,    0,    0,
+      0,   56,  136,    7,  137,  138,    0,    0,    0,    0,    0,    0,    0,   56,  139,    0,
+      0,    0,  101,  140,  101,  141,  142,  143,    0,  144,  145,  146,  147,  148,  149,  150,
+      0,  151,  152,  153,  154,  148,  155,  156,  157,  158,  159,  160,    0,  161,  162,  163,
+    164,  165,  166,  167,  168,  169,  170,  171,  172,   56,  173,  174,  175,  176,  177,  178,
+      0,    0,    0,    0,    0,   56,  179,  180,    0,   56,  181,  182,    0,   56,  183,  184,
+    185,  186,  187,  188,    0,    0,    0,    0,    0,   56,  189,    0,    0,    0,    0,    0,
+      0,  190,  191,  192,    0,    0,  193,  194,  195,  196,  197,  198,   56,  199,    0,    0,
+      0,  200,  201,  202,  203,  204,  205,    0,    0,  206,  207,  208,  209,  210,   67,    0,
+      0,    0,    0,    0,    0,    0,    0,    0,  211,  212,  213,  214,    0,    0,    0,    0,
+      0,  215,  215,  215,  215,  215,  215,  215,  215,  215,  216,  217,  215,  215,  215,  215,
+    215,  215,  215,  215,  215,  215,  215,  215,  218,  219,  220,    0,    0,    0,    0,    0,
+      0,    0,    0,    0,    0,    0,    0,   67,    0,   56,  221,    0,    0,    0,    0,    0,
+      0,    0,    0,  222,  223,    0,    0,    0,    0,   56,   56,  224,  225,  226,    0,    0,
+    227,   56,   56,   56,   56,   56,   56,   56,   56,   56,   56,   56,   56,   56,   56,  228,
+    229,   56,   56,   56,  230,  231,    0,    0,    0,    0,    0,    0,  232,    0,    0,    0,
+      0,   56,  233,  234,    0,    0,    0,    0,    0,    0,    0,    0,    0,  101,  235,   56,
+    236,    0,    0,    0,    0,    0,    0,  101,  237,    0,    0,    0,    0,    0,    0,  101,
+    238,   56,   56,  239,    0,    0,    0,    0,    0,  240,  240,  240,  240,  240,  240,  240,
+    240,  241,  241,  241,  241,  241,  241,  241,  242,    0,    0,    0,    0,    0,    0,    0,
       0,    0,    0,    0,    0,    0,    0,    1,    0,    2,    2,    2,    2,    2,    0,    0,
       0,    0,    0,    0,    0,    0,    3,    4,    0,    5,    0,    0,    0,    0,    0,    6,
       0,    0,    7,    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,    0,    0,    0,
@@ -460,7 +479,7 @@ hb_use_u8[3483] =
       0,   10,   29,   30,    2,    2,    2,    9,    2,    2,    2,   30,    2,    2,    0,   17,
      45,    0,    0,   35,   47,    0,    0,    0,    9,   50,   51,    0,    0,    0,    0,    0,
       0,   11,   29,    2,    2,    2,    2,    9,    2,    2,    2,    2,    2,    2,   52,   53,
-     23,   23,   19,   31,   48,   33,   48,   34,   54,    0,    0,    0,   35,    0,    0,    0,
+     23,   19,   20,   31,   48,   33,   48,   34,   54,    0,    0,    0,   35,    0,    0,    0,
      30,   12,   29,   30,    2,    2,    2,    2,    2,    2,    2,    2,    9,    0,    2,    2,
       2,    2,   30,    2,    2,    2,    2,   30,    0,    2,    2,    2,    9,    0,   55,    0,
      35,   23,   22,   31,   31,   18,   48,   48,   25,    0,   23,    0,    0,    0,    0,    0,
@@ -488,9 +507,9 @@ hb_use_u8[3483] =
      63,  104,   16,   45,   22,   59,   21,   80,   48,   48,   76,   11,   11,   11,  105,   46,
      40,   11,  106,   74,    2,    2,    2,    2,    2,    2,    2,  107,   22,   20,   20,   22,
      48,   48,   22,  108,    2,    2,    2,    9,    0,    0,    0,    0,    0,    0,  109,  110,
-    111,  111,  111,    0,    0,    0,    0,    0,    0,  106,   74,    2,    2,    2,    2,    2,
-      2,   60,   61,   59,   25,   22,  112,   61,    2,    2,    2,    2,  107,   22,   23,   45,
-     45,  102,   14,    0,    0,    0,    0,    0,    0,    2,    2,   61,   18,   48,   23,  113,
+    110,  110,  110,    0,    0,    0,    0,    0,    0,  106,   74,    2,    2,    2,    2,    2,
+      2,   60,   61,   59,   25,   22,  111,   61,    2,    2,    2,    2,  107,   22,   23,   45,
+     45,  102,  112,    0,    0,    0,    0,    0,    0,    2,    2,   61,   18,   48,   23,  113,
     102,  102,  102,  114,  115,    0,    0,    0,    0,    2,    2,    2,    2,    2,    0,   30,
       2,   11,   46,  116,  116,  116,   11,  116,  116,   15,  116,  116,  116,   26,    0,   40,
       0,    0,    0,  117,   51,   11,    5,    0,    0,    0,    0,    0,    0,    0,  118,    0,
@@ -518,7 +537,8 @@ hb_use_u8[3483] =
       0,  128,   20,   27,   31,    0,    0,  145,  146,    2,    2,   30,    2,   30,    2,    2,
       2,    2,    2,    2,    0,   14,   37,    0,  147,    2,    2,   13,   37,    0,   30,    2,
       2,    2,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   30,    2,    2,
-      9,    2,    2,   11,   41,    0,    0,    0,    0,    2,    2,    2,    2,    2,   27,   38,
+      9,    2,    2,   11,   41,    0,    0,    0,    0,    2,    2,    2,    0,   27,   22,   22,
+     30,    2,    2,    2,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,   27,   38,
       0,    2,    2,    2,  116,  116,  116,  116,  116,  148,    2,    9,    0,    0,    0,    0,
       0,    2,   14,   14,    0,    0,    0,    0,    0,    9,    2,    2,    9,    2,    2,    2,
       2,   30,    2,    9,    0,   30,    2,    0,    0,  149,  150,  151,    2,    2,    2,    2,
@@ -536,39 +556,45 @@ hb_use_u8[3483] =
      10,   18,   19,   21,   22,  162,   31,    0,    0,   11,   11,   30,    2,    2,    2,    9,
      30,    9,    2,   30,    2,    2,   58,   17,   23,   16,   23,   47,   32,   33,   32,   34,
       0,    0,    0,    0,   35,    0,    0,    0,    2,    2,   23,    0,   11,   11,   11,   46,
-      0,   11,   11,   46,    0,    0,    0,    0,    0,    2,    2,   65,   25,   20,   20,   20,
-     22,   23,  126,   15,   17,    0,    0,    0,    0,    2,    2,    2,    2,    2,    0,    0,
-    163,  164,    0,    0,    0,    0,    0,    0,    0,   18,   19,   20,   20,   66,   99,   25,
-    160,   11,  165,    9,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    2,    2,
-     65,   25,   20,   20,    0,   48,   48,   11,  166,   37,    0,    0,    0,    0,    0,    0,
-      0,    0,    0,    0,    0,    2,    2,   20,    0,   23,   19,   20,   20,   21,   16,   82,
-    166,   38,    0,    0,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,   10,  167,
-     25,   20,   22,   22,  165,    9,    0,    0,    0,    2,    2,    2,    2,    2,    9,   43,
-    136,   23,   22,   20,   76,   21,   22,    0,    0,    2,    2,    2,    9,    0,    0,    0,
-      0,    2,    2,    2,    2,    2,    2,   18,   19,   20,   21,   22,  105,  166,   37,    0,
-      0,    2,    2,    2,    9,   30,    0,    2,    2,    2,    2,   30,    9,    2,    2,    2,
-      2,   23,   23,   18,   32,   33,   12,  168,  169,  170,  171,    0,    0,    0,    0,    0,
-      0,    2,    2,    2,    2,    0,    2,    2,    2,   65,   25,   20,   20,    0,   22,   23,
-     29,  108,    0,   33,    0,    0,    0,    0,    0,   52,   20,   22,   22,   22,  140,    2,
-      2,    2,  172,  173,   11,   15,  174,   72,  175,    0,    0,    1,  147,    0,    0,    0,
-      0,   52,   20,   22,   16,   19,   20,    2,    2,    2,    2,  158,  158,  158,  176,  176,
-    176,  176,  176,  176,   15,  177,    0,   30,    0,   22,   20,   20,   31,   22,   22,   11,
-    166,    0,   61,   61,   61,   61,   61,   61,   61,   66,   21,   82,   46,    0,    0,    0,
-      0,    2,    2,    2,    9,    2,   30,    2,    2,   52,   22,   22,   31,    0,   38,   22,
-     27,   11,  159,  178,  174,    0,    0,    0,    0,    2,    2,    2,   30,    9,    2,    2,
-      2,    2,    2,    2,    2,    2,   23,   23,   47,   22,   35,   82,   68,    0,    0,    0,
-      0,    2,  179,   66,   47,    0,    0,    0,    0,   11,  180,    2,    2,    2,    2,    2,
-      2,    2,    2,   23,   22,   20,   31,    0,   48,   16,  143,    0,    0,    0,    0,    0,
-      0,  181,  181,  181,  181,  181,  181,  181,  181,  182,  182,  182,  183,  184,  182,  181,
-    181,  185,  181,  181,  186,  187,  187,  187,  187,  187,  187,  187,    0,    0,    0,    0,
-      0,   11,   11,   11,   46,    0,    0,    0,    0,    2,    2,    2,    2,    2,    9,    0,
-     58,  188,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
-     20,   20,   20,   20,   20,    0,    0,    0,   40,  116,   26,    0,    0,    0,    0,    0,
-      0,    0,    0,    9,    0,    0,    0,    0,    0,    2,    2,    2,    0,    0,    0,    0,
-      0,    2,    2,    2,    2,    2,    0,   58,   37,    0,    6,  120,  120,  120,  121,    0,
-      0,   11,   11,   11,   49,    2,    2,    2,    0,    2,    2,    2,    2,    2,    0,    0,
-      2,    2,    2,    2,    2,    2,    2,    2,   46,    2,    2,    2,    2,    2,    2,   11,
-     11,    2,    2,    2,    2,    2,    2,   22,   22,    2,    2,   44,   44,   44,   92,    0,
+      0,   11,   11,   46,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,   30,    0,
+      9,    2,    2,    2,   30,   45,   59,   20,   20,   31,   33,   32,   32,   25,  163,   29,
+    164,  165,   37,    0,    0,    0,    0,    0,    0,   12,   26,    0,    0,    0,    0,    0,
+      0,    2,    2,   65,   25,   20,   20,   20,   22,   23,  126,   15,   17,    0,    0,    0,
+      0,    2,    2,    2,    2,    2,    0,    0,  166,  167,    0,    0,    0,    0,    0,    0,
+      0,   18,   19,   20,   20,   66,   99,   25,  160,   11,  168,    9,    0,    0,    0,    0,
+      0,    2,    2,    2,    2,    2,    2,    2,   65,   25,   20,   20,    0,   48,   48,   11,
+    169,   37,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    2,    2,   20,
+      0,   23,   19,   20,   20,   21,   16,   82,  169,   38,    0,    0,    0,    0,    0,    0,
+      0,    2,    2,    2,    2,    2,   10,  170,   25,   20,   22,   22,  168,    9,    0,    0,
+      0,    2,    2,    2,    2,    2,    9,   43,  136,   23,   22,   20,   76,   21,   22,    0,
+      0,    2,    2,    2,    9,    0,    0,    0,    0,    2,    2,    2,    2,    2,    2,   18,
+     19,   20,   21,   22,  105,  169,   37,    0,    0,    2,    2,    2,    9,   30,    0,    2,
+      2,    2,    2,   30,    9,    2,    2,    2,    2,   23,   23,   18,   32,   33,   12,  171,
+    165,  172,  173,    0,    0,    0,    0,    0,    0,    2,    2,    2,    2,    0,    2,    2,
+      2,   65,   25,   20,   20,    0,   22,   23,   29,  108,    0,   33,    0,    0,    0,    0,
+      0,   52,   20,   22,   22,   22,  140,    2,    2,    2,  174,  175,   11,   15,  176,   61,
+    177,    0,    0,    1,  147,    0,    0,    0,    0,   52,   20,   22,   16,   19,   20,    2,
+      2,    2,    2,  158,  158,  158,  178,  178,  178,  178,  178,  178,   15,  179,    0,   30,
+      0,   22,   20,   20,   31,   22,   22,   11,  169,    0,   61,   61,   61,   61,   61,   61,
+     61,   66,   21,   82,   46,    0,    0,    0,    0,    2,    2,    2,    9,    2,   30,    2,
+      2,   52,   22,   22,   31,    0,   38,   22,   27,   11,  159,  180,  181,    0,    0,    0,
+      0,    2,    2,    2,   30,    9,    2,    2,    2,    2,    2,    2,    2,    2,   23,   23,
+     47,   22,   35,   82,   68,    0,    0,    0,    0,    2,  182,   66,   47,    0,    0,    0,
+      0,   11,  183,    2,    2,    2,    2,    2,    2,    2,    2,   23,   22,   20,   31,    0,
+     48,   16,  143,    0,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,  156,    0,
+      0,  184,  184,  184,  184,  184,  184,  184,  184,  185,  185,  185,  186,  187,  185,  184,
+    184,  188,  184,  184,  189,  190,  190,  190,  190,  190,  190,  190,    0,    0,    0,    0,
+      0,  184,  184,  184,  184,  184,  191,    0,    0,    2,    2,    2,    2,    2,    2,    2,
+     22,   22,   22,   22,   22,   22,  192,  193,  194,   11,   11,   11,   46,    0,    0,    0,
+      0,   29,   74,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,   65,   47,
+      0,    2,    2,    2,    2,    2,    9,    0,   58,  195,   20,   20,   20,   20,   20,   20,
+     20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,    0,    0,    0,
+     40,  116,   26,    0,    0,    0,    0,    0,    0,    0,    0,    9,    0,    0,    0,    0,
+      0,    0,    0,    0,    0,    0,    0,    0,   30,    2,    2,    2,    2,    2,    0,   58,
+     37,    0,    6,  120,  120,  120,  121,    0,    0,   11,   11,   11,   49,    2,    2,    2,
+      0,    2,    2,    2,    2,    2,    0,    0,    2,    2,    2,    2,    2,    2,    2,    2,
+     46,    2,    2,    2,    2,    2,    2,   11,   11,    2,    2,    2,    2,    2,    2,   22,
+     22,    2,    2,    2,    2,    2,    2,    2,   20,    2,    2,   44,   44,   44,   92,    0,
       0,    O,    O,    O,   GB,    B,    B,    O,   SB,    O,   SE,   GB,    O,    O,   WJ,FMPst,
   FMPst,    O,  CGJ,    B,    O,    B,VMAbv,VMAbv,VMAbv,    O,VMAbv,    B,CMBlw,CMBlw,CMBlw,VMAbv,
   VMPst, VAbv, VPst,CMBlw,    B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VPst,
@@ -582,20 +608,21 @@ hb_use_u8[3483] =
   VMPst, VBlw, VPst,  CGJ,  CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,VMAbv,FMAbv, VAbv,   IS,
   FMAbv,    B,FMAbv,    B,  CGJ,   WJ,  CGJ,   GB,CMAbv,CMAbv,    B,   GB,    B, VAbv,  SUB, FPst,
    FPst,VMBlw, FPst, FPst, FBlw,VMAbv,FMBlw, VAbv, VPre,    B, MPre, MBlw,  SUB, FAbv, FAbv, MAbv,
-    SUB,   Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv, VPst,    H,    B,    O,SMAbv,SMBlw,SMAbv,SMAbv,
-  SMAbv, VPst,   IS, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv,   CS,    O,FMAbv, ZWNJ,
+    SUB,   Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv, VPst,    H,    B,    O,SMAbv,SMAbv,SMAbv, VPst,
+     IS,   RK,   RK, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv,   CS,    O,FMAbv, ZWNJ,
     CGJ,   WJ,   WJ,   WJ,    O,FMPst,    O,   SB,   SE,    O,    H, MPst, VPst,    H,VMAbv, VAbv,
   VMBlw,    B, VBlw, FPst, VPst, FAbv,VMPst,    B,CMAbv, VAbv, MBlw, MPst, MBlw,    H,    O, VBlw,
    MPst, MPre, MAbv, MBlw,    O,    B, FAbv, FAbv, FPst, VBlw,    B,    B, VPre,    O,VMPst,   IS,
       O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv,    O,   IS,VMBlw,    B,VMPst,VMAbv,VMPst,   CS,   CS,
       B,    N,    N,    O,   HN, VPre, VBlw, VAbv,   IS,CMAbv,    O, VPst,    B,    R,    R,CMBlw,
-   VAbv, VPre,VMAbv,VMAbv,    H, VAbv,CMBlw,FMAbv,    B,   CS,   CS,    H,CMBlw,VMPst,    H,VMPst,
-   VAbv,VMAbv, VPst,   IS,    R, MPst,    R, MPst,CMBlw,    B,FMBlw, VBlw,VMAbv,    R, MBlw, MBlw,
-     GB, FBlw, FBlw,CMAbv,   IS, VBlw,   IS,   GB, VAbv,    R,VMPst,    G,    G,    J,    J,    J,
-     SB,   SE,    J,   HR,    G,    G,   HM,   HM,   HM,    O, VBlw,
+   VAbv, VPre,VMAbv,VMAbv,    H, VAbv,CMBlw,VMPst,    O,VMAbv,CMBlw,   IS,    R,FMAbv,    B,   CS,
+     CS,    H,CMBlw,VMPst,    H,VMPst, VAbv,VMAbv, VPst, MPst,    R, MPst,CMBlw,    B,FMBlw, VBlw,
+  VMAbv,   CS,  SUB,  SUB,   GB, FBlw, FBlw,CMAbv,   IS, VBlw,   IS,    R, MBlw,   GB, VAbv,    R,
+  VMPst,    G,    G,    J,    J,    J,   SB,   SE,    J,   HR,    G,    G,   HM,   HM,   HM,    G,
+      O, MPre, MPre, MPst,VMAbv, MBlw, VBlw,    O, VBlw,
 };
 static const uint16_t
-hb_use_u16[456] =
+hb_use_u16[486] =
 {
     0,  0,  1,  2,  0,  3,  4,  5,  0,  6,  7,  0,  8,  0,  9, 10,
    11, 12, 10, 13, 14, 10, 10, 15, 16, 17, 18, 19, 20, 21, 22, 23,
@@ -614,18 +641,20 @@ hb_use_u16[456] =
   148,149,150, 10, 10,151,152,  2,153, 99,154,155,156,  2, 10,157,
    10,158,159,  0,160,161,162,  2,163,  0,  0,164,  0,165,  0,166,
   166,167, 34,168,169,170, 10,171, 95,  0,172,  0, 10,173,174,  0,
-  175,  2,176,173,177,178,179,  0,  0,180,181,  0,182, 10, 10,183,
-  184,185,186,187,188, 10, 10,189,190,  0,191, 10,192,193,194, 10,
-   10,195, 10,196,197,106,198,103, 10, 34,199,200,201,  0,202,203,
-   95, 10, 10,204,205,  2,206, 21, 22,207,208,209,210,211, 10,212,
-  213,214,215,  0,198, 10, 10,216,217,  2,218,219,220,221, 10,222,
-  223,  2,224,225, 10,226,227,104,228,  0,229,230,231,232, 10,233,
-  234,  2,235, 10, 10,236,237,  0,238, 10, 10,239,240,241,242,243,
-   22, 10,218,244,  8, 10, 71, 19, 10,245, 74,246,247, 10, 10,248,
-  249,  2,250, 10,251,252, 10,253,254, 49, 10,255,256,  2,257,257,
-  257,258,259,260, 10,261,262,263,264,264,265,266,267,  0, 10,268,
-  106, 71, 95,269,  0,270, 71,271,272,  0,273,  0,274,  2,275,  2,
-  276,  2,130,130,163,163,163,130,
+  175,  2,176, 10,177,  0,178,173,179,180,181,  0,  0,182,183,  0,
+  184, 10, 10,185,186,187,188,189,190, 10, 10,191,192,  0,193, 10,
+  194,195,196, 10, 10,197, 10,198,199,106,200,103, 10, 34,201,202,
+  203,  0,204,205, 95, 10, 10,206,207,  2,208, 21, 22,209,210,211,
+  212,213,214, 10, 10,215,216,217,218,  0, 10,219,220,221,222,  0,
+  200, 10, 10,223,224,  2,225,226,227,228, 10,229,230,  2,231,232,
+    2, 10,141,  0, 10,233,234,104,235,  0,236,237,238,239, 10,240,
+  241,  2,242, 10, 10,243,244,  0,245, 10, 10,246,247,248,249,250,
+   22, 10,225,251,  8, 10, 71, 19, 10,252, 74,253,254, 10, 10,255,
+  256,  2,257, 10,258,259, 10,260,261, 49, 10,262,263,264,265,265,
+  265,266,267,268,265,269, 10,270,271,  2, 10,272,273, 10,274,  2,
+  275,276,277,277,278,279,280,  0, 10,177,  0,281,106, 71, 95,282,
+    0,283, 71,284,285,  0,286,  0,287,  2,288,  2,289,106,290,  2,
+  130,130,163,163,163,130,
 };
 
 static inline unsigned
@@ -636,7 +665,7 @@ hb_use_b4 (const uint8_t* a, unsigned i)
 static inline uint_fast8_t
 hb_use_get_category (unsigned u)
 {
-  return u<921600u?hb_use_u8[3105+(((hb_use_u8[889+(((hb_use_u16[((hb_use_u8[353+(((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>1>>3>>4))<<4)+((u>>1>>3>>1>>3)&15u))])<<3)+((u>>1>>3>>1)&7u))])<<1)+((u>>1>>3)&1u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
+  return u<921600u?hb_use_u8[3265+(((hb_use_u8[937+(((hb_use_u16[((hb_use_u8[369+(((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>1>>3>>4))<<4)+((u>>1>>3>>1>>3)&15u))])<<3)+((u>>1>>3>>1)&7u))])<<1)+((u>>1>>3)&1u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
 }
 
 #endif
@@ -656,6 +685,7 @@ hb_use_get_category (unsigned u)
 #undef N
 #undef O
 #undef R
+#undef RK
 #undef SB
 #undef SE
 #undef SUB
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-vowel-constraints.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-vowel-constraints.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-vowel-constraints.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-vowel-constraints.cc	2025-06-27 08:03:14.000000000 +0000
@@ -10,8 +10,8 @@
  * # Date: 2015-03-12, 21:17:00 GMT [AG]
  * # Date: 2019-11-08, 23:22:00 GMT [AG]
  *
- * # Scripts-15.1.0.txt
- * # Date: 2023-07-28, 16:01:07 GMT
+ * # Scripts-16.0.0.txt
+ * # Date: 2024-04-30, 21:48:40 GMT
  */
 
 #include "hb.hh"
@@ -24,7 +24,7 @@ static void
 _output_dotted_circle (hb_buffer_t *buffer)
 {
   (void) buffer->output_glyph (0x25CCu);
-  _hb_glyph_info_reset_continuation (&buffer->prev());
+  _hb_glyph_info_clear_continuation (&buffer->prev());
 }
 
 static void
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper.hh	2025-06-27 08:03:14.000000000 +0000
@@ -174,9 +174,11 @@ HB_OT_SHAPERS_IMPLEMENT_SHAPERS
 
 
 static inline const hb_ot_shaper_t *
-hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner)
+hb_ot_shaper_categorize (hb_script_t script,
+                         hb_direction_t direction,
+                         hb_tag_t gsub_script)
 {
-  switch ((hb_tag_t) planner->props.script)
+  switch ((hb_tag_t) script)
   {
     default:
       return &_hb_ot_shaper_default;
@@ -192,9 +194,8 @@ hb_ot_shaper_categorize (const hb_ot_sha
        * This is because we do fallback shaping for Arabic script (and not others).
        * But note that Arabic shaping is applicable only to horizontal layout; for
        * vertical text, just use the generic shaper instead. */
-      if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
-           planner->props.script == HB_SCRIPT_ARABIC) &&
-          HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
+      if ((gsub_script != HB_OT_TAG_DEFAULT_SCRIPT || script == HB_SCRIPT_ARABIC) &&
+          HB_DIRECTION_IS_HORIZONTAL (direction))
         return &_hb_ot_shaper_arabic;
       else
         return &_hb_ot_shaper_default;
@@ -235,10 +236,10 @@ hb_ot_shaper_categorize (const hb_ot_sha
        * Otherwise, use the specific shaper.
        *
        * If it's indy3 tag, send to USE. */
-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
-          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
+      if (gsub_script == HB_TAG ('D','F','L','T') ||
+          gsub_script == HB_TAG ('l','a','t','n'))
         return &_hb_ot_shaper_default;
-      else if ((planner->map.chosen_script[0] & 0x000000FF) == '3')
+      else if ((gsub_script & 0x000000FF) == '3')
         return &_hb_ot_shaper_use;
       else
         return &_hb_ot_shaper_indic;
@@ -254,9 +255,9 @@ hb_ot_shaper_categorize (const hb_ot_sha
        * If designer designed for 'mymr' tag, also send to default
        * shaper.  That's tag used from before Myanmar shaping spec
        * was developed.  The shaping spec uses 'mym2' tag. */
-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
-          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n') ||
-          planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
+      if (gsub_script == HB_TAG ('D','F','L','T') ||
+          gsub_script == HB_TAG ('l','a','t','n') ||
+          gsub_script == HB_TAG ('m','y','m','r'))
         return &_hb_ot_shaper_default;
       else
         return &_hb_ot_shaper_myanmar;
@@ -386,13 +387,22 @@ hb_ot_shaper_categorize (const hb_ot_sha
     case HB_SCRIPT_KAWI:
     case HB_SCRIPT_NAG_MUNDARI:
 
+    /* Unicode-16.0 additions */
+    case HB_SCRIPT_GARAY:
+    case HB_SCRIPT_GURUNG_KHEMA:
+    case HB_SCRIPT_KIRAT_RAI:
+    case HB_SCRIPT_OL_ONAL:
+    case HB_SCRIPT_SUNUWAR:
+    case HB_SCRIPT_TODHRI:
+    case HB_SCRIPT_TULU_TIGALARI:
+
       /* If the designer designed the font for the 'DFLT' script,
        * (or we ended up arbitrarily pick 'latn'), use the default shaper.
        * Otherwise, use the specific shaper.
        * Note that for some simple scripts, there may not be *any*
        * GSUB/GPOS needed, so there may be no scripts found! */
-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
-          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
+      if (gsub_script == HB_TAG ('D','F','L','T') ||
+          gsub_script == HB_TAG ('l','a','t','n'))
         return &_hb_ot_shaper_default;
       else
         return &_hb_ot_shaper_use;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-stat-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-stat-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-stat-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-stat-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -63,8 +63,9 @@ static bool axis_value_is_outside_axis_r
   if (!user_axes_location->has (axis_tag))
     return false;
 
+  double axis_value_double = static_cast<double>(axis_value);
   Triple axis_range = user_axes_location->get (axis_tag);
-  return (axis_value < axis_range.minimum || axis_value > axis_range.maximum);
+  return (axis_value_double < axis_range.minimum || axis_value_double > axis_range.maximum);
 }
 
 struct StatAxisRecord
@@ -327,6 +328,7 @@ struct AxisValueFormat4
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
                           axisValues.sanitize (c, axisCount)));
   }
 
@@ -348,15 +350,15 @@ struct AxisValueFormat4
 
 struct AxisValue
 {
-  bool get_value (unsigned int axis_index) const
+  float get_value (unsigned int axis_index) const
   {
     switch (u.format)
     {
-    case 1: return u.format1.get_value ();
-    case 2: return u.format2.get_value ();
-    case 3: return u.format3.get_value ();
-    case 4: return u.format4.get_axis_record (axis_index).get_value ();
-    default:return 0;
+    case 1: hb_barrier (); return u.format1.get_value ();
+    case 2: hb_barrier (); return u.format2.get_value ();
+    case 3: hb_barrier (); return u.format3.get_value ();
+    case 4: hb_barrier (); return u.format4.get_axis_record (axis_index).get_value ();
+    default:return 0.f;
     }
   }
 
@@ -364,9 +366,9 @@ struct AxisValue
   {
     switch (u.format)
     {
-    case 1: return u.format1.get_axis_index ();
-    case 2: return u.format2.get_axis_index ();
-    case 3: return u.format3.get_axis_index ();
+    case 1: hb_barrier (); return u.format1.get_axis_index ();
+    case 2: hb_barrier (); return u.format2.get_axis_index ();
+    case 3: hb_barrier (); return u.format3.get_axis_index ();
     /* case 4: Makes more sense for variable fonts which are handled by fvar in hb-style */
     default:return -1;
     }
@@ -376,10 +378,10 @@ struct AxisValue
   {
     switch (u.format)
     {
-    case 1: return u.format1.get_value_name_id ();
-    case 2: return u.format2.get_value_name_id ();
-    case 3: return u.format3.get_value_name_id ();
-    case 4: return u.format4.get_value_name_id ();
+    case 1: hb_barrier (); return u.format1.get_value_name_id ();
+    case 2: hb_barrier (); return u.format2.get_value_name_id ();
+    case 3: hb_barrier (); return u.format3.get_value_name_id ();
+    case 4: hb_barrier (); return u.format4.get_value_name_id ();
     default:return HB_OT_NAME_ID_INVALID;
     }
   }
@@ -390,10 +392,10 @@ struct AxisValue
     if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
     TRACE_DISPATCH (this, u.format);
     switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
-    case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
-    case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
-    case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
     default:return_trace (c->default_return_value ());
     }
   }
@@ -403,10 +405,10 @@ struct AxisValue
   {
     switch (u.format)
     {
-    case 1: return u.format1.keep_axis_value (axis_records, user_axes_location);
-    case 2: return u.format2.keep_axis_value (axis_records, user_axes_location);
-    case 3: return u.format3.keep_axis_value (axis_records, user_axes_location);
-    case 4: return u.format4.keep_axis_value (axis_records, user_axes_location);
+    case 1: hb_barrier (); return u.format1.keep_axis_value (axis_records, user_axes_location);
+    case 2: hb_barrier (); return u.format2.keep_axis_value (axis_records, user_axes_location);
+    case 3: hb_barrier (); return u.format3.keep_axis_value (axis_records, user_axes_location);
+    case 4: hb_barrier (); return u.format4.keep_axis_value (axis_records, user_axes_location);
     default:return false;
     }
   }
@@ -416,13 +418,14 @@ struct AxisValue
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
       return_trace (false);
+    hb_barrier ();
 
     switch (u.format)
     {
-    case 1: return_trace (u.format1.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    case 3: return_trace (u.format3.sanitize (c));
-    case 4: return_trace (u.format4.sanitize (c));
+    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
+    case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
+    case 3: hb_barrier (); return_trace (u.format3.sanitize (c));
+    case 4: hb_barrier (); return_trace (u.format4.sanitize (c));
     default:return_trace (true);
     }
   }
@@ -483,7 +486,7 @@ struct STAT
     hb_array_t<const Offset16To<AxisValue>> axis_values = get_axis_value_offsets ();
     for (unsigned int i = 0; i < axis_values.length; i++)
     {
-      const AxisValue& axis_value = this+axis_values[i];
+      const AxisValue& axis_value = this+offsetToAxisValueOffsets+axis_values[i];
       if (axis_value.get_axis_index () == axis_index)
       {
         if (value)
@@ -560,6 +563,7 @@ struct STAT
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
+                          hb_barrier () &&
                           version.major == 1 &&
                           version.minor > 0 &&
                           designAxesOffset.sanitize (c, this, designAxisCount) &&
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-tag-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-tag-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-tag-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-tag-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -6,8 +6,8 @@
  *
  * on files with these headers:
  *
- * <meta name="updated_at" content="2022-09-30 11:47 PM" />
- * File-Date: 2023-08-02
+ * <meta name="updated_at" content="2024-12-06 06:35 AM" />
+ * File-Date: 2025-01-21
  */
 
 #ifndef HB_OT_TAG_TABLE_HH
@@ -26,12 +26,12 @@ static const LangTag ot_languages2[] = {
   {HB_TAG('a','y',' ',' '),     HB_TAG('A','Y','M',' ')},       /* Aymara [macrolanguage] */
   {HB_TAG('a','z',' ',' '),     HB_TAG('A','Z','E',' ')},       /* Azerbaijani [macrolanguage] */
   {HB_TAG('b','a',' ',' '),     HB_TAG('B','S','H',' ')},       /* Bashkir */
-  {HB_TAG('b','e',' ',' '),     HB_TAG('B','E','L',' ')},       /* Belarusian -> Belarussian */
+  {HB_TAG('b','e',' ',' '),     HB_TAG('B','E','L',' ')},       /* Belarusian */
   {HB_TAG('b','g',' ',' '),     HB_TAG('B','G','R',' ')},       /* Bulgarian */
   {HB_TAG('b','i',' ',' '),     HB_TAG('B','I','S',' ')},       /* Bislama */
   {HB_TAG('b','i',' ',' '),     HB_TAG('C','P','P',' ')},       /* Bislama -> Creoles */
   {HB_TAG('b','m',' ',' '),     HB_TAG('B','M','B',' ')},       /* Bambara (Bamanankan) */
-  {HB_TAG('b','n',' ',' '),     HB_TAG('B','E','N',' ')},       /* Bengali */
+  {HB_TAG('b','n',' ',' '),     HB_TAG('B','E','N',' ')},       /* Bangla */
   {HB_TAG('b','o',' ',' '),     HB_TAG('T','I','B',' ')},       /* Tibetan */
   {HB_TAG('b','r',' ',' '),     HB_TAG('B','R','E',' ')},       /* Breton */
   {HB_TAG('b','s',' ',' '),     HB_TAG('B','O','S',' ')},       /* Bosnian */
@@ -64,7 +64,8 @@ static const LangTag ot_languages2[] = {
   {HB_TAG('f','r',' ',' '),     HB_TAG('F','R','A',' ')},       /* French */
   {HB_TAG('f','y',' ',' '),     HB_TAG('F','R','I',' ')},       /* Western Frisian -> Frisian */
   {HB_TAG('g','a',' ',' '),     HB_TAG('I','R','I',' ')},       /* Irish */
-  {HB_TAG('g','d',' ',' '),     HB_TAG('G','A','E',' ')},       /* Scottish Gaelic (Gaelic) */
+  {HB_TAG('g','a',' ',' '),     HB_TAG('I','R','T',' ')},       /* Irish -> Irish Traditional */
+  {HB_TAG('g','d',' ',' '),     HB_TAG('G','A','E',' ')},       /* Scottish Gaelic */
   {HB_TAG('g','l',' ',' '),     HB_TAG('G','A','L',' ')},       /* Galician */
   {HB_TAG('g','n',' ',' '),     HB_TAG('G','U','A',' ')},       /* Guarani [macrolanguage] */
   {HB_TAG('g','u',' ',' '),     HB_TAG('G','U','J',' ')},       /* Gujarati */
@@ -153,7 +154,7 @@ static const LangTag ot_languages2[] = {
   {HB_TAG('o','c',' ',' '),     HB_TAG('O','C','I',' ')},       /* Occitan (post 1500) */
   {HB_TAG('o','j',' ',' '),     HB_TAG('O','J','B',' ')},       /* Ojibwa [macrolanguage] -> Ojibway */
   {HB_TAG('o','m',' ',' '),     HB_TAG('O','R','O',' ')},       /* Oromo [macrolanguage] */
-  {HB_TAG('o','r',' ',' '),     HB_TAG('O','R','I',' ')},       /* Odia (formerly Oriya) [macrolanguage] */
+  {HB_TAG('o','r',' ',' '),     HB_TAG('O','R','I',' ')},       /* Odia [macrolanguage] */
   {HB_TAG('o','s',' ',' '),     HB_TAG('O','S','S',' ')},       /* Ossetian */
   {HB_TAG('p','a',' ',' '),     HB_TAG('P','A','N',' ')},       /* Punjabi */
   {HB_TAG('p','i',' ',' '),     HB_TAG('P','A','L',' ')},       /* Pali */
@@ -166,7 +167,7 @@ static const LangTag ot_languages2[] = {
   {HB_TAG('r','o',' ',' '),     HB_TAG('R','O','M',' ')},       /* Romanian */
   {HB_TAG('r','u',' ',' '),     HB_TAG('R','U','S',' ')},       /* Russian */
   {HB_TAG('r','w',' ',' '),     HB_TAG('R','U','A',' ')},       /* Kinyarwanda */
-  {HB_TAG('s','a',' ',' '),     HB_TAG('S','A','N',' ')},       /* Sanskrit */
+  {HB_TAG('s','a',' ',' '),     HB_TAG('S','A','N',' ')},       /* Sanskrit [macrolanguage] */
   {HB_TAG('s','c',' ',' '),     HB_TAG('S','R','D',' ')},       /* Sardinian [macrolanguage] */
   {HB_TAG('s','d',' ',' '),     HB_TAG('S','N','D',' ')},       /* Sindhi */
   {HB_TAG('s','e',' ',' '),     HB_TAG('N','S','M',' ')},       /* Northern Sami */
@@ -223,6 +224,7 @@ static const LangTag ot_languages2[] = {
 static const LangTag ot_languages3[] = {
   {HB_TAG('a','a','e',' '),     HB_TAG('S','Q','I',' ')},       /* Arbëreshë Albanian -> Albanian */
   {HB_TAG('a','a','o',' '),     HB_TAG('A','R','A',' ')},       /* Algerian Saharan Arabic -> Arabic */
+/*{HB_TAG('a','a','q',' '),     HB_TAG('A','A','Q',' ')},*/     /* Eastern Abnaki -> Eastern Abenaki */
   {HB_TAG('a','a','t',' '),     HB_TAG('S','Q','I',' ')},       /* Arvanitika Albanian -> Albanian */
   {HB_TAG('a','b','a',' '),     HB_TAG_NONE            },       /* Abé != Abaza */
   {HB_TAG('a','b','h',' '),     HB_TAG('A','R','A',' ')},       /* Tajiki Arabic -> Arabic */
@@ -238,6 +240,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('a','c','r',' '),     HB_TAG('M','Y','N',' ')},       /* Achi -> Mayan */
   {HB_TAG('a','c','w',' '),     HB_TAG('A','R','A',' ')},       /* Hijazi Arabic -> Arabic */
   {HB_TAG('a','c','x',' '),     HB_TAG('A','R','A',' ')},       /* Omani Arabic -> Arabic */
+  {HB_TAG('a','c','y',' '),     HB_TAG('A','C','Y',' ')},       /* Cypriot Arabic */
   {HB_TAG('a','c','y',' '),     HB_TAG('A','R','A',' ')},       /* Cypriot Arabic -> Arabic */
   {HB_TAG('a','d','a',' '),     HB_TAG('D','N','G',' ')},       /* Adangme -> Dangme */
   {HB_TAG('a','d','f',' '),     HB_TAG('A','R','A',' ')},       /* Dhofari Arabic -> Arabic */
@@ -288,6 +291,7 @@ static const LangTag ot_languages3[] = {
 /*{HB_TAG('a','s','t',' '),     HB_TAG('A','S','T',' ')},*/     /* Asturian */
 /*{HB_TAG('a','t','h',' '),     HB_TAG('A','T','H',' ')},*/     /* Athapascan [collection] -> Athapaskan */
   {HB_TAG('a','t','j',' '),     HB_TAG('R','C','R',' ')},       /* Atikamekw -> R-Cree */
+/*{HB_TAG('a','t','s',' '),     HB_TAG('A','T','S',' ')},*/     /* Gros Ventre (Atsina) */
   {HB_TAG('a','t','v',' '),     HB_TAG('A','L','T',' ')},       /* Northern Altai -> Altai */
   {HB_TAG('a','u','j',' '),     HB_TAG('B','B','R',' ')},       /* Awjilah -> Berber */
   {HB_TAG('a','u','z',' '),     HB_TAG('A','R','A',' ')},       /* Uzbeki Arabic -> Arabic */
@@ -326,6 +330,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('b','c','l',' '),     HB_TAG('B','I','K',' ')},       /* Central Bikol -> Bikol */
   {HB_TAG('b','c','q',' '),     HB_TAG('B','C','H',' ')},       /* Bench */
   {HB_TAG('b','c','r',' '),     HB_TAG('A','T','H',' ')},       /* Babine -> Athapaskan */
+/*{HB_TAG('b','d','c',' '),     HB_TAG('B','D','C',' ')},*/     /* Emberá-Baudó */
 /*{HB_TAG('b','d','y',' '),     HB_TAG('B','D','Y',' ')},*/     /* Bandjalang */
   {HB_TAG('b','e','a',' '),     HB_TAG('A','T','H',' ')},       /* Beaver -> Athapaskan */
   {HB_TAG('b','e','b',' '),     HB_TAG('B','T','I',' ')},       /* Bebele -> Beti */
@@ -421,6 +426,8 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('c','a','f',' '),     HB_TAG('A','T','H',' ')},       /* Southern Carrier -> Athapaskan */
   {HB_TAG('c','a','k',' '),     HB_TAG('C','A','K',' ')},       /* Kaqchikel */
   {HB_TAG('c','a','k',' '),     HB_TAG('M','Y','N',' ')},       /* Kaqchikel -> Mayan */
+/*{HB_TAG('c','a','y',' '),     HB_TAG('C','A','Y',' ')},*/     /* Cayuga */
+/*{HB_TAG('c','b','g',' '),     HB_TAG('C','B','G',' ')},*/     /* Chimila */
   {HB_TAG('c','b','k',' '),     HB_TAG('C','B','K',' ')},       /* Chavacano -> Zamboanga Chavacano */
   {HB_TAG('c','b','k',' '),     HB_TAG('C','P','P',' ')},       /* Chavacano -> Creoles */
   {HB_TAG('c','b','l',' '),     HB_TAG('Q','I','N',' ')},       /* Bualkhaw Chin -> Chin */
@@ -465,7 +472,9 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('c','l','d',' '),     HB_TAG('S','Y','R',' ')},       /* Chaldean Neo-Aramaic -> Syriac */
   {HB_TAG('c','l','e',' '),     HB_TAG('C','C','H','N')},       /* Lealao Chinantec -> Chinantec */
   {HB_TAG('c','l','j',' '),     HB_TAG('Q','I','N',' ')},       /* Laitu Chin -> Chin */
+  {HB_TAG('c','l','s',' '),     HB_TAG('S','A','N',' ')},       /* Classical Sanskrit -> Sanskrit */
   {HB_TAG('c','l','t',' '),     HB_TAG('Q','I','N',' ')},       /* Lautu Chin -> Chin */
+/*{HB_TAG('c','m','i',' '),     HB_TAG('C','M','I',' ')},*/     /* Emberá-Chamí */
   {HB_TAG('c','m','n',' '),     HB_TAG('Z','H','S',' ')},       /* Mandarin Chinese -> Chinese, Simplified */
   {HB_TAG('c','m','r',' '),     HB_TAG('Q','I','N',' ')},       /* Mro-Khimi Chin -> Chin */
   {HB_TAG('c','n','b',' '),     HB_TAG('Q','I','N',' ')},       /* Chinbon Chin -> Chin */
@@ -479,6 +488,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('c','n','w',' '),     HB_TAG('Q','I','N',' ')},       /* Ngawn Chin -> Chin */
   {HB_TAG('c','o','a',' '),     HB_TAG('M','L','Y',' ')},       /* Cocos Islands Malay -> Malay */
   {HB_TAG('c','o','b',' '),     HB_TAG('M','Y','N',' ')},       /* Chicomuceltec -> Mayan */
+/*{HB_TAG('c','o','o',' '),     HB_TAG('C','O','O',' ')},*/     /* Comox */
 /*{HB_TAG('c','o','p',' '),     HB_TAG('C','O','P',' ')},*/     /* Coptic */
   {HB_TAG('c','o','q',' '),     HB_TAG('A','T','H',' ')},       /* Coquille -> Athapaskan */
   {HB_TAG('c','p','a',' '),     HB_TAG('C','C','H','N')},       /* Palantla Chinantec -> Chinantec */
@@ -528,6 +538,7 @@ static const LangTag ot_languages3[] = {
 /*{HB_TAG('c','t','g',' '),     HB_TAG('C','T','G',' ')},*/     /* Chittagonian */
   {HB_TAG('c','t','h',' '),     HB_TAG('Q','I','N',' ')},       /* Thaiphum Chin -> Chin */
   {HB_TAG('c','t','l',' '),     HB_TAG('C','C','H','N')},       /* Tlacoatzintepec Chinantec -> Chinantec */
+/*{HB_TAG('c','t','o',' '),     HB_TAG('C','T','O',' ')},*/     /* Emberá-Catío */
   {HB_TAG('c','t','s',' '),     HB_TAG('B','I','K',' ')},       /* Northern Catanduanes Bikol -> Bikol */
 /*{HB_TAG('c','t','t',' '),     HB_TAG('C','T','T',' ')},*/     /* Wayanad Chetti */
   {HB_TAG('c','t','u',' '),     HB_TAG('M','Y','N',' ')},       /* Chol -> Mayan */
@@ -551,7 +562,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('d','e','p',' '),     HB_TAG('C','P','P',' ')},       /* Pidgin Delaware -> Creoles */
   {HB_TAG('d','g','o',' '),     HB_TAG('D','G','O',' ')},       /* Dogri (individual language) */
   {HB_TAG('d','g','o',' '),     HB_TAG('D','G','R',' ')},       /* Dogri (macrolanguage) */
-  {HB_TAG('d','g','r',' '),     HB_TAG('A','T','H',' ')},       /* Dogrib -> Athapaskan */
+  {HB_TAG('d','g','r',' '),     HB_TAG('A','T','H',' ')},       /* Tlicho -> Athapaskan */
   {HB_TAG('d','h','d',' '),     HB_TAG('M','A','W',' ')},       /* Dhundari -> Marwari */
 /*{HB_TAG('d','h','g',' '),     HB_TAG('D','H','G',' ')},*/     /* Dhangu */
   {HB_TAG('d','h','v',' '),     HB_TAG_NONE            },       /* Dehu != Divehi (Dhivehi, Maldivian) (deprecated) */
@@ -590,6 +601,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('e','k','y',' '),     HB_TAG('K','R','N',' ')},       /* Eastern Kayah -> Karen */
   {HB_TAG('e','m','k',' '),     HB_TAG('E','M','K',' ')},       /* Eastern Maninkakan */
   {HB_TAG('e','m','k',' '),     HB_TAG('M','N','K',' ')},       /* Eastern Maninkakan -> Maninka */
+/*{HB_TAG('e','m','p',' '),     HB_TAG('E','M','P',' ')},*/     /* Northern Emberá */
   {HB_TAG('e','m','y',' '),     HB_TAG('M','Y','N',' ')},       /* Epigraphic Mayan -> Mayan */
   {HB_TAG('e','n','b',' '),     HB_TAG('K','A','L',' ')},       /* Markweeta -> Kalenjin */
   {HB_TAG('e','n','f',' '),     HB_TAG('F','N','E',' ')},       /* Forest Enets */
@@ -637,7 +649,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('g','a','a',' '),     HB_TAG('G','A','D',' ')},       /* Ga */
   {HB_TAG('g','a','c',' '),     HB_TAG('C','P','P',' ')},       /* Mixed Great Andamanese -> Creoles */
   {HB_TAG('g','a','d',' '),     HB_TAG_NONE            },       /* Gaddang != Ga */
-  {HB_TAG('g','a','e',' '),     HB_TAG_NONE            },       /* Guarequena != Scottish Gaelic (Gaelic) */
+  {HB_TAG('g','a','e',' '),     HB_TAG_NONE            },       /* Guarequena != Scottish Gaelic */
 /*{HB_TAG('g','a','g',' '),     HB_TAG('G','A','G',' ')},*/     /* Gagauz */
   {HB_TAG('g','a','l',' '),     HB_TAG_NONE            },       /* Galolen != Galician */
   {HB_TAG('g','a','n',' '),     HB_TAG('Z','H','S',' ')},       /* Gan Chinese -> Chinese, Simplified */
@@ -654,6 +666,7 @@ static const LangTag ot_languages3[] = {
 /*{HB_TAG('g','e','z',' '),     HB_TAG('G','E','Z',' ')},*/     /* Geez */
   {HB_TAG('g','g','o',' '),     HB_TAG('G','O','N',' ')},       /* Southern Gondi (retired code) -> Gondi */
   {HB_TAG('g','h','a',' '),     HB_TAG('B','B','R',' ')},       /* Ghadamès -> Berber */
+  {HB_TAG('g','h','c',' '),     HB_TAG('I','R','T',' ')},       /* Hiberno-Scottish Gaelic -> Irish Traditional */
   {HB_TAG('g','h','k',' '),     HB_TAG('K','R','N',' ')},       /* Geko Karen -> Karen */
   {HB_TAG('g','h','o',' '),     HB_TAG('B','B','R',' ')},       /* Ghomara -> Berber */
   {HB_TAG('g','i','b',' '),     HB_TAG('C','P','P',' ')},       /* Gibanawa -> Creoles */
@@ -732,6 +745,7 @@ static const LangTag ot_languages3[] = {
 /*{HB_TAG('h','n','d',' '),     HB_TAG('H','N','D',' ')},*/     /* Southern Hindko -> Hindko */
   {HB_TAG('h','n','e',' '),     HB_TAG('C','H','H',' ')},       /* Chhattisgarhi -> Chattisgarhi */
   {HB_TAG('h','n','j',' '),     HB_TAG('H','M','N',' ')},       /* Hmong Njua -> Hmong */
+  {HB_TAG('h','n','m',' '),     HB_TAG('Z','H','S',' ')},       /* Hainanese -> Chinese, Simplified */
   {HB_TAG('h','n','o',' '),     HB_TAG('H','N','D',' ')},       /* Northern Hindko -> Hindko */
   {HB_TAG('h','o','c',' '),     HB_TAG('H','O',' ',' ')},       /* Ho */
   {HB_TAG('h','o','i',' '),     HB_TAG('A','T','H',' ')},       /* Holikachuk -> Athapaskan */
@@ -743,6 +757,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('h','s','n',' '),     HB_TAG('Z','H','S',' ')},       /* Xiang Chinese -> Chinese, Simplified */
   {HB_TAG('h','u','j',' '),     HB_TAG('H','M','N',' ')},       /* Northern Guiyang Hmong -> Hmong */
   {HB_TAG('h','u','p',' '),     HB_TAG('A','T','H',' ')},       /* Hupa -> Athapaskan */
+/*{HB_TAG('h','u','r',' '),     HB_TAG('H','U','R',' ')},*/     /* Halkomelem */
   {HB_TAG('h','u','s',' '),     HB_TAG('M','Y','N',' ')},       /* Huastec -> Mayan */
   {HB_TAG('h','w','c',' '),     HB_TAG('C','P','P',' ')},       /* Hawai'i Creole English -> Creoles */
   {HB_TAG('h','y','w',' '),     HB_TAG('H','Y','E',' ')},       /* Western Armenian -> Armenian */
@@ -780,6 +795,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('j','b','n',' '),     HB_TAG('B','B','R',' ')},       /* Nafusi -> Berber */
 /*{HB_TAG('j','b','o',' '),     HB_TAG('J','B','O',' ')},*/     /* Lojban */
 /*{HB_TAG('j','c','t',' '),     HB_TAG('J','C','T',' ')},*/     /* Krymchak */
+/*{HB_TAG('j','d','t',' '),     HB_TAG('J','D','T',' ')},*/     /* Judeo-Tat */
   {HB_TAG('j','g','o',' '),     HB_TAG('B','M','L',' ')},       /* Ngomba -> Bamileke */
   {HB_TAG('j','i','i',' '),     HB_TAG_NONE            },       /* Jiiddu != Yiddish */
   {HB_TAG('j','k','m',' '),     HB_TAG('K','R','N',' ')},       /* Mobwa Karen -> Karen */
@@ -794,6 +810,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('k','a','m',' '),     HB_TAG('K','M','B',' ')},       /* Kamba (Kenya) */
   {HB_TAG('k','a','r',' '),     HB_TAG('K','R','N',' ')},       /* Karen [collection] */
 /*{HB_TAG('k','a','w',' '),     HB_TAG('K','A','W',' ')},*/     /* Kawi (Old Javanese) */
+/*{HB_TAG('k','b','c',' '),     HB_TAG('K','B','C',' ')},*/     /* Kadiwéu */
   {HB_TAG('k','b','d',' '),     HB_TAG('K','A','B',' ')},       /* Kabardian */
   {HB_TAG('k','b','y',' '),     HB_TAG('K','N','R',' ')},       /* Manga Kanuri -> Kanuri */
   {HB_TAG('k','c','a',' '),     HB_TAG('K','H','K',' ')},       /* Khanty -> Khanty-Kazim */
@@ -814,6 +831,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('k','f','x',' '),     HB_TAG('K','U','L',' ')},       /* Kullu Pahari -> Kulvi */
   {HB_TAG('k','f','y',' '),     HB_TAG('K','M','N',' ')},       /* Kumaoni */
   {HB_TAG('k','g','e',' '),     HB_TAG_NONE            },       /* Komering != Khutsuri Georgian */
+/*{HB_TAG('k','g','f',' '),     HB_TAG('K','G','F',' ')},*/     /* Kube */
   {HB_TAG('k','h','a',' '),     HB_TAG('K','S','I',' ')},       /* Khasi */
   {HB_TAG('k','h','b',' '),     HB_TAG('X','B','D',' ')},       /* Lü */
   {HB_TAG('k','h','k',' '),     HB_TAG('M','N','G',' ')},       /* Halh Mongolian -> Mongolian */
@@ -829,6 +847,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('k','j','b',' '),     HB_TAG('M','Y','N',' ')},       /* Q'anjob'al -> Mayan */
 /*{HB_TAG('k','j','d',' '),     HB_TAG('K','J','D',' ')},*/     /* Southern Kiwai */
   {HB_TAG('k','j','h',' '),     HB_TAG('K','H','A',' ')},       /* Khakas -> Khakass */
+/*{HB_TAG('k','j','j',' '),     HB_TAG('K','J','J',' ')},*/     /* Khinalugh -> Khinalug */
   {HB_TAG('k','j','p',' '),     HB_TAG('K','J','P',' ')},       /* Pwo Eastern Karen -> Eastern Pwo Karen */
   {HB_TAG('k','j','p',' '),     HB_TAG('K','R','N',' ')},       /* Pwo Eastern Karen -> Karen */
   {HB_TAG('k','j','t',' '),     HB_TAG('K','R','N',' ')},       /* Phrae Pwo Karen -> Karen */
@@ -838,6 +857,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('k','l','m',' '),     HB_TAG_NONE            },       /* Migum != Kalmyk */
   {HB_TAG('k','l','n',' '),     HB_TAG('K','A','L',' ')},       /* Kalenjin [macrolanguage] */
   {HB_TAG('k','m','b',' '),     HB_TAG('M','B','N',' ')},       /* Kimbundu -> Mbundu */
+/*{HB_TAG('k','m','g',' '),     HB_TAG('K','M','G',' ')},*/     /* Kâte */
   {HB_TAG('k','m','n',' '),     HB_TAG_NONE            },       /* Awtuw != Kumaoni */
   {HB_TAG('k','m','o',' '),     HB_TAG_NONE            },       /* Kwoma != Komo */
   {HB_TAG('k','m','r',' '),     HB_TAG('K','U','R',' ')},       /* Northern Kurdish -> Kurdish */
@@ -881,6 +901,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('k','s','i',' '),     HB_TAG_NONE            },       /* Krisa != Khasi */
   {HB_TAG('k','s','m',' '),     HB_TAG_NONE            },       /* Kumba != Kildin Sami */
   {HB_TAG('k','s','s',' '),     HB_TAG('K','I','S',' ')},       /* Southern Kisi -> Kisii */
+/*{HB_TAG('k','s','u',' '),     HB_TAG('K','S','U',' ')},*/     /* Khamyang */
   {HB_TAG('k','s','w',' '),     HB_TAG('K','S','W',' ')},       /* S’gaw Karen */
   {HB_TAG('k','s','w',' '),     HB_TAG('K','R','N',' ')},       /* S'gaw Karen -> Karen */
   {HB_TAG('k','t','b',' '),     HB_TAG('K','E','B',' ')},       /* Kambaata -> Kebena */
@@ -894,6 +915,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('k','u','y',' '),     HB_TAG_NONE            },       /* Kuuku-Ya'u != Kuy */
   {HB_TAG('k','v','b',' '),     HB_TAG('M','L','Y',' ')},       /* Kubu -> Malay */
   {HB_TAG('k','v','l',' '),     HB_TAG('K','R','N',' ')},       /* Kayaw -> Karen */
+  {HB_TAG('k','v','q',' '),     HB_TAG('K','V','Q',' ')},       /* Geba Karen */
   {HB_TAG('k','v','q',' '),     HB_TAG('K','R','N',' ')},       /* Geba Karen -> Karen */
   {HB_TAG('k','v','r',' '),     HB_TAG('M','L','Y',' ')},       /* Kerinci -> Malay */
   {HB_TAG('k','v','t',' '),     HB_TAG('K','R','N',' ')},       /* Lahta Karen -> Karen */
@@ -930,6 +952,7 @@ static const LangTag ot_languages3[] = {
 /*{HB_TAG('l','i','j',' '),     HB_TAG('L','I','J',' ')},*/     /* Ligurian */
   {HB_TAG('l','i','r',' '),     HB_TAG('C','P','P',' ')},       /* Liberian English -> Creoles */
 /*{HB_TAG('l','i','s',' '),     HB_TAG('L','I','S',' ')},*/     /* Lisu */
+/*{HB_TAG('l','i','v',' '),     HB_TAG('L','I','V',' ')},*/     /* Liv */
   {HB_TAG('l','i','w',' '),     HB_TAG('M','L','Y',' ')},       /* Col -> Malay */
   {HB_TAG('l','i','y',' '),     HB_TAG('B','A','D','0')},       /* Banda-Bambari -> Banda */
 /*{HB_TAG('l','j','p',' '),     HB_TAG('L','J','P',' ')},*/     /* Lampung Api -> Lampung */
@@ -959,9 +982,11 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('l','t','o',' '),     HB_TAG('L','U','H',' ')},       /* Tsotso -> Luyia */
   {HB_TAG('l','t','s',' '),     HB_TAG('L','U','H',' ')},       /* Tachoni -> Luyia */
 /*{HB_TAG('l','u','a',' '),     HB_TAG('L','U','A',' ')},*/     /* Luba-Lulua */
+  {HB_TAG('l','u','h',' '),     HB_TAG('Z','H','S',' ')},       /* Leizhou Chinese -> Chinese, Simplified */
 /*{HB_TAG('l','u','o',' '),     HB_TAG('L','U','O',' ')},*/     /* Luo (Kenya and Tanzania) */
   {HB_TAG('l','u','s',' '),     HB_TAG('M','I','Z',' ')},       /* Lushai -> Mizo */
   {HB_TAG('l','u','s',' '),     HB_TAG('Q','I','N',' ')},       /* Lushai -> Chin */
+/*{HB_TAG('l','u','t',' '),     HB_TAG('L','U','T',' ')},*/     /* Lushootseed */
   {HB_TAG('l','u','y',' '),     HB_TAG('L','U','H',' ')},       /* Luyia [macrolanguage] */
   {HB_TAG('l','u','z',' '),     HB_TAG('L','R','C',' ')},       /* Southern Luri -> Luri */
   {HB_TAG('l','v','i',' '),     HB_TAG_NONE            },       /* Lavi != Latvian */
@@ -995,12 +1020,14 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('m','e','n',' '),     HB_TAG('M','D','E',' ')},       /* Mende (Sierra Leone) */
   {HB_TAG('m','e','o',' '),     HB_TAG('M','L','Y',' ')},       /* Kedah Malay -> Malay */
 /*{HB_TAG('m','e','r',' '),     HB_TAG('M','E','R',' ')},*/     /* Meru */
+/*{HB_TAG('m','e','v',' '),     HB_TAG('M','E','V',' ')},*/     /* Mano */
   {HB_TAG('m','f','a',' '),     HB_TAG('M','F','A',' ')},       /* Pattani Malay */
   {HB_TAG('m','f','a',' '),     HB_TAG('M','L','Y',' ')},       /* Pattani Malay -> Malay */
   {HB_TAG('m','f','b',' '),     HB_TAG('M','L','Y',' ')},       /* Bangka -> Malay */
   {HB_TAG('m','f','e',' '),     HB_TAG('M','F','E',' ')},       /* Morisyen */
   {HB_TAG('m','f','e',' '),     HB_TAG('C','P','P',' ')},       /* Morisyen -> Creoles */
   {HB_TAG('m','f','p',' '),     HB_TAG('C','P','P',' ')},       /* Makassar Malay -> Creoles */
+  {HB_TAG('m','g','a',' '),     HB_TAG('S','G','A',' ')},       /* Middle Irish (900-1200) -> Old Irish */
   {HB_TAG('m','h','c',' '),     HB_TAG('M','Y','N',' ')},       /* Mocho -> Mayan */
   {HB_TAG('m','h','r',' '),     HB_TAG('L','M','A',' ')},       /* Eastern Mari -> Low Mari */
   {HB_TAG('m','h','v',' '),     HB_TAG('A','R','K',' ')},       /* Arakanese (retired code) -> Rakhine */
@@ -1126,6 +1153,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('n','o','d',' '),     HB_TAG('N','T','A',' ')},       /* Northern Thai -> Northern Tai */
 /*{HB_TAG('n','o','e',' '),     HB_TAG('N','O','E',' ')},*/     /* Nimadi */
 /*{HB_TAG('n','o','g',' '),     HB_TAG('N','O','G',' ')},*/     /* Nogai */
+/*{HB_TAG('n','o','p',' '),     HB_TAG('N','O','P',' ')},*/     /* Numanggang */
 /*{HB_TAG('n','o','v',' '),     HB_TAG('N','O','V',' ')},*/     /* Novial */
   {HB_TAG('n','p','i',' '),     HB_TAG('N','E','P',' ')},       /* Nepali */
   {HB_TAG('n','p','l',' '),     HB_TAG('N','A','H',' ')},       /* Southeastern Puebla Nahuatl -> Nahuatl */
@@ -1136,6 +1164,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('n','s','u',' '),     HB_TAG('N','A','H',' ')},       /* Sierra Negra Nahuatl -> Nahuatl */
   {HB_TAG('n','t','o',' '),     HB_TAG_NONE            },       /* Ntomba != Esperanto */
   {HB_TAG('n','u','e',' '),     HB_TAG('B','A','D','0')},       /* Ngundu -> Banda */
+/*{HB_TAG('n','u','k',' '),     HB_TAG('N','U','K',' ')},*/     /* Nuu-chah-nulth */
   {HB_TAG('n','u','u',' '),     HB_TAG('B','A','D','0')},       /* Ngbundu -> Banda */
   {HB_TAG('n','u','z',' '),     HB_TAG('N','A','H',' ')},       /* Tlamacazapa Nahuatl -> Nahuatl */
   {HB_TAG('n','w','e',' '),     HB_TAG('B','M','L',' ')},       /* Ngwe -> Bamileke */
@@ -1153,6 +1182,8 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('o','k','i',' '),     HB_TAG('K','A','L',' ')},       /* Okiek -> Kalenjin */
   {HB_TAG('o','k','m',' '),     HB_TAG('K','O','H',' ')},       /* Middle Korean (10th-16th cent.) -> Korean Old Hangul */
   {HB_TAG('o','k','r',' '),     HB_TAG('I','J','O',' ')},       /* Kirike -> Ijo */
+/*{HB_TAG('o','n','e',' '),     HB_TAG('O','N','E',' ')},*/     /* Oneida */
+/*{HB_TAG('o','n','o',' '),     HB_TAG('O','N','O',' ')},*/     /* Onondaga */
   {HB_TAG('o','n','x',' '),     HB_TAG('C','P','P',' ')},       /* Onin Based Pidgin -> Creoles */
   {HB_TAG('o','o','r',' '),     HB_TAG('C','P','P',' ')},       /* Oorlams -> Creoles */
   {HB_TAG('o','r','c',' '),     HB_TAG('O','R','O',' ')},       /* Orma -> Oromo */
@@ -1160,7 +1191,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('o','r','o',' '),     HB_TAG_NONE            },       /* Orokolo != Oromo */
   {HB_TAG('o','r','r',' '),     HB_TAG('I','J','O',' ')},       /* Oruma -> Ijo */
   {HB_TAG('o','r','s',' '),     HB_TAG('M','L','Y',' ')},       /* Orang Seletar -> Malay */
-  {HB_TAG('o','r','y',' '),     HB_TAG('O','R','I',' ')},       /* Odia (formerly Oriya) */
+  {HB_TAG('o','r','y',' '),     HB_TAG('O','R','I',' ')},       /* Odia */
   {HB_TAG('o','t','w',' '),     HB_TAG('O','J','B',' ')},       /* Ottawa -> Ojibway */
   {HB_TAG('o','u','a',' '),     HB_TAG('B','B','R',' ')},       /* Tagargrent -> Berber */
   {HB_TAG('p','a','a',' '),     HB_TAG_NONE            },       /* Papuan [collection] != Palestinian Aramaic */
@@ -1193,7 +1224,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('p','i','s',' '),     HB_TAG('C','P','P',' ')},       /* Pijin -> Creoles */
   {HB_TAG('p','k','h',' '),     HB_TAG('Q','I','N',' ')},       /* Pankhu -> Chin */
   {HB_TAG('p','k','o',' '),     HB_TAG('K','A','L',' ')},       /* Pökoot -> Kalenjin */
-  {HB_TAG('p','l','g',' '),     HB_TAG_NONE            },       /* Pilagá != Palaung */
+  {HB_TAG('p','l','g',' '),     HB_TAG('P','L','G','0')},       /* Pilagá */
   {HB_TAG('p','l','k',' '),     HB_TAG_NONE            },       /* Kohistani Shina != Polish */
   {HB_TAG('p','l','l',' '),     HB_TAG('P','L','G',' ')},       /* Shwe Palaung -> Palaung */
   {HB_TAG('p','l','n',' '),     HB_TAG('C','P','P',' ')},       /* Palenquero -> Creoles */
@@ -1353,6 +1384,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('s','d','h',' '),     HB_TAG('K','U','R',' ')},       /* Southern Kurdish -> Kurdish */
   {HB_TAG('s','d','n',' '),     HB_TAG('S','R','D',' ')},       /* Gallurese Sardinian -> Sardinian */
   {HB_TAG('s','d','s',' '),     HB_TAG('B','B','R',' ')},       /* Sened -> Berber */
+/*{HB_TAG('s','e','e',' '),     HB_TAG('S','E','E',' ')},*/     /* Seneca */
   {HB_TAG('s','e','h',' '),     HB_TAG('S','N','A',' ')},       /* Sena */
   {HB_TAG('s','e','k',' '),     HB_TAG('A','T','H',' ')},       /* Sekani -> Athapaskan */
 /*{HB_TAG('s','e','l',' '),     HB_TAG('S','E','L',' ')},*/     /* Selkup */
@@ -1374,9 +1406,13 @@ static const LangTag ot_languages3[] = {
 /*{HB_TAG('s','i','d',' '),     HB_TAG('S','I','D',' ')},*/     /* Sidamo */
   {HB_TAG('s','i','g',' '),     HB_TAG_NONE            },       /* Paasaal != Silte Gurage */
   {HB_TAG('s','i','z',' '),     HB_TAG('B','B','R',' ')},       /* Siwi -> Berber */
+/*{HB_TAG('s','j','a',' '),     HB_TAG('S','J','A',' ')},*/     /* Epena */
+  {HB_TAG('s','j','c',' '),     HB_TAG('Z','H','S',' ')},       /* Shaojiang Chinese -> Chinese, Simplified */
   {HB_TAG('s','j','d',' '),     HB_TAG('K','S','M',' ')},       /* Kildin Sami */
+/*{HB_TAG('s','j','e',' '),     HB_TAG('S','J','E',' ')},*/     /* Pite Sami */
   {HB_TAG('s','j','o',' '),     HB_TAG('S','I','B',' ')},       /* Xibe -> Sibe */
   {HB_TAG('s','j','s',' '),     HB_TAG('B','B','R',' ')},       /* Senhaja De Srair -> Berber */
+/*{HB_TAG('s','j','u',' '),     HB_TAG('S','J','U',' ')},*/     /* Ume Sami */
   {HB_TAG('s','k','g',' '),     HB_TAG('M','L','G',' ')},       /* Sakalava Malagasy -> Malagasy */
   {HB_TAG('s','k','r',' '),     HB_TAG('S','R','K',' ')},       /* Saraiki */
   {HB_TAG('s','k','s',' '),     HB_TAG_NONE            },       /* Maia != Skolt Sami */
@@ -1395,7 +1431,7 @@ static const LangTag ot_languages3[] = {
 /*{HB_TAG('s','n','k',' '),     HB_TAG('S','N','K',' ')},*/     /* Soninke */
   {HB_TAG('s','o','g',' '),     HB_TAG_NONE            },       /* Sogdian != Sodo Gurage */
 /*{HB_TAG('s','o','p',' '),     HB_TAG('S','O','P',' ')},*/     /* Songe */
-  {HB_TAG('s','p','v',' '),     HB_TAG('O','R','I',' ')},       /* Sambalpuri -> Odia (formerly Oriya) */
+  {HB_TAG('s','p','v',' '),     HB_TAG('O','R','I',' ')},       /* Sambalpuri -> Odia */
   {HB_TAG('s','p','y',' '),     HB_TAG('K','A','L',' ')},       /* Sabaot -> Kalenjin */
   {HB_TAG('s','r','b',' '),     HB_TAG_NONE            },       /* Sora != Serbian */
   {HB_TAG('s','r','c',' '),     HB_TAG('S','R','D',' ')},       /* Logudorese Sardinian -> Sardinian */
@@ -1410,6 +1446,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('s','s','m',' '),     HB_TAG_NONE            },       /* Semnam != Southern Sami */
   {HB_TAG('s','t','a',' '),     HB_TAG('C','P','P',' ')},       /* Settla -> Creoles */
 /*{HB_TAG('s','t','q',' '),     HB_TAG('S','T','Q',' ')},*/     /* Saterfriesisch -> Saterland Frisian */
+/*{HB_TAG('s','t','r',' '),     HB_TAG('S','T','R',' ')},*/     /* Straits Salish */
   {HB_TAG('s','t','v',' '),     HB_TAG('S','I','G',' ')},       /* Silt'e -> Silte Gurage */
 /*{HB_TAG('s','u','k',' '),     HB_TAG('S','U','K',' ')},*/     /* Sukuma */
   {HB_TAG('s','u','q',' '),     HB_TAG('S','U','R',' ')},       /* Suri */
@@ -1431,10 +1468,12 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('t','a','a',' '),     HB_TAG('A','T','H',' ')},       /* Lower Tanana -> Athapaskan */
 /*{HB_TAG('t','a','b',' '),     HB_TAG('T','A','B',' ')},*/     /* Tabassaran -> Tabasaran */
   {HB_TAG('t','a','j',' '),     HB_TAG_NONE            },       /* Eastern Tamang != Tajiki */
+  {HB_TAG('t','a','q',' '),     HB_TAG('T','A','Q',' ')},       /* Tamasheq */
   {HB_TAG('t','a','q',' '),     HB_TAG('T','M','H',' ')},       /* Tamasheq -> Tamashek */
   {HB_TAG('t','a','q',' '),     HB_TAG('B','B','R',' ')},       /* Tamasheq -> Berber */
   {HB_TAG('t','a','s',' '),     HB_TAG('C','P','P',' ')},       /* Tay Boi -> Creoles */
   {HB_TAG('t','a','u',' '),     HB_TAG('A','T','H',' ')},       /* Upper Tanana -> Athapaskan */
+/*{HB_TAG('t','b','v',' '),     HB_TAG('T','B','V',' ')},*/     /* Tobo */
   {HB_TAG('t','c','b',' '),     HB_TAG('A','T','H',' ')},       /* Tanacross -> Athapaskan */
   {HB_TAG('t','c','e',' '),     HB_TAG('A','T','H',' ')},       /* Southern Tutchone -> Athapaskan */
   {HB_TAG('t','c','h',' '),     HB_TAG('C','P','P',' ')},       /* Turks And Caicos Creole English -> Creoles */
@@ -1442,6 +1481,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('t','c','s',' '),     HB_TAG('C','P','P',' ')},       /* Torres Strait Creole -> Creoles */
   {HB_TAG('t','c','y',' '),     HB_TAG('T','U','L',' ')},       /* Tulu */
   {HB_TAG('t','c','z',' '),     HB_TAG('Q','I','N',' ')},       /* Thado Chin -> Chin */
+/*{HB_TAG('t','d','c',' '),     HB_TAG('T','D','C',' ')},*/     /* Emberá-Tadó */
 /*{HB_TAG('t','d','d',' '),     HB_TAG('T','D','D',' ')},*/     /* Tai Nüa -> Dehong Dai */
   {HB_TAG('t','d','x',' '),     HB_TAG('M','L','G',' ')},       /* Tandroy-Mahafaly Malagasy -> Malagasy */
   {HB_TAG('t','e','c',' '),     HB_TAG('K','A','L',' ')},       /* Terik -> Kalenjin */
@@ -1455,9 +1495,12 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('t','g','r',' '),     HB_TAG_NONE            },       /* Tareng != Tigre */
   {HB_TAG('t','g','x',' '),     HB_TAG('A','T','H',' ')},       /* Tagish -> Athapaskan */
   {HB_TAG('t','g','y',' '),     HB_TAG_NONE            },       /* Togoyo != Tigrinya */
+/*{HB_TAG('t','h','p',' '),     HB_TAG('T','H','P',' ')},*/     /* Thompson */
   {HB_TAG('t','h','t',' '),     HB_TAG('A','T','H',' ')},       /* Tahltan -> Athapaskan */
+  {HB_TAG('t','h','v',' '),     HB_TAG('T','H','V',' ')},       /* Tahaggart Tamahaq */
   {HB_TAG('t','h','v',' '),     HB_TAG('T','M','H',' ')},       /* Tahaggart Tamahaq -> Tamashek */
   {HB_TAG('t','h','v',' '),     HB_TAG('B','B','R',' ')},       /* Tahaggart Tamahaq -> Berber */
+  {HB_TAG('t','h','z',' '),     HB_TAG('T','H','Z',' ')},       /* Tayart Tamajeq */
   {HB_TAG('t','h','z',' '),     HB_TAG('T','M','H',' ')},       /* Tayart Tamajeq -> Tamashek */
   {HB_TAG('t','h','z',' '),     HB_TAG('B','B','R',' ')},       /* Tayart Tamajeq -> Berber */
   {HB_TAG('t','i','a',' '),     HB_TAG('B','B','R',' ')},       /* Tidikelt Tamazight -> Berber */
@@ -1468,6 +1511,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('t','k','g',' '),     HB_TAG('M','L','G',' ')},       /* Tesaka Malagasy -> Malagasy */
   {HB_TAG('t','k','m',' '),     HB_TAG_NONE            },       /* Takelma != Turkmen */
 /*{HB_TAG('t','l','i',' '),     HB_TAG('T','L','I',' ')},*/     /* Tlingit */
+/*{HB_TAG('t','l','y',' '),     HB_TAG('T','L','Y',' ')},*/     /* Talysh */
   {HB_TAG('t','m','g',' '),     HB_TAG('C','P','P',' ')},       /* Ternateño -> Creoles */
   {HB_TAG('t','m','h',' '),     HB_TAG('T','M','H',' ')},       /* Tamashek [macrolanguage] */
   {HB_TAG('t','m','h',' '),     HB_TAG('B','B','R',' ')},       /* Tamashek [macrolanguage] -> Berber */
@@ -1493,11 +1537,13 @@ static const LangTag ot_languages3[] = {
 /*{HB_TAG('t','s','j',' '),     HB_TAG('T','S','J',' ')},*/     /* Tshangla */
   {HB_TAG('t','t','c',' '),     HB_TAG('M','Y','N',' ')},       /* Tektiteko -> Mayan */
   {HB_TAG('t','t','m',' '),     HB_TAG('A','T','H',' ')},       /* Northern Tutchone -> Athapaskan */
+  {HB_TAG('t','t','q',' '),     HB_TAG('T','T','Q',' ')},       /* Tawallammat Tamajaq */
   {HB_TAG('t','t','q',' '),     HB_TAG('T','M','H',' ')},       /* Tawallammat Tamajaq -> Tamashek */
   {HB_TAG('t','t','q',' '),     HB_TAG('B','B','R',' ')},       /* Tawallammat Tamajaq -> Berber */
   {HB_TAG('t','u','a',' '),     HB_TAG_NONE            },       /* Wiarumus != Turoyo Aramaic */
   {HB_TAG('t','u','l',' '),     HB_TAG_NONE            },       /* Tula != Tulu */
 /*{HB_TAG('t','u','m',' '),     HB_TAG('T','U','M',' ')},*/     /* Tumbuka */
+/*{HB_TAG('t','u','s',' '),     HB_TAG('T','U','S',' ')},*/     /* Tuscarora */
   {HB_TAG('t','u','u',' '),     HB_TAG('A','T','H',' ')},       /* Tututni -> Athapaskan */
   {HB_TAG('t','u','v',' '),     HB_TAG_NONE            },       /* Turkana != Tuvin */
   {HB_TAG('t','u','y',' '),     HB_TAG('K','A','L',' ')},       /* Tugen -> Kalenjin */
@@ -1514,6 +1560,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('t','z','o',' '),     HB_TAG('T','Z','O',' ')},       /* Tzotzil */
   {HB_TAG('t','z','o',' '),     HB_TAG('M','Y','N',' ')},       /* Tzotzil -> Mayan */
   {HB_TAG('u','b','l',' '),     HB_TAG('B','I','K',' ')},       /* Buhi'non Bikol -> Bikol */
+/*{HB_TAG('u','d','i',' '),     HB_TAG('U','D','I',' ')},*/     /* Udi */
 /*{HB_TAG('u','d','m',' '),     HB_TAG('U','D','M',' ')},*/     /* Udmurt */
   {HB_TAG('u','k','i',' '),     HB_TAG('K','U','I',' ')},       /* Kui (India) */
   {HB_TAG('u','l','n',' '),     HB_TAG('C','P','P',' ')},       /* Unserdeutsch -> Creoles */
@@ -1532,13 +1579,17 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('v','k','t',' '),     HB_TAG('M','L','Y',' ')},       /* Tenggarong Kutai Malay -> Malay */
   {HB_TAG('v','l','s',' '),     HB_TAG('F','L','E',' ')},       /* Vlaams -> Dutch (Flemish) */
   {HB_TAG('v','m','w',' '),     HB_TAG('M','A','K',' ')},       /* Makhuwa */
-/*{HB_TAG('v','r','o',' '),     HB_TAG('V','R','O',' ')},*/     /* Võro */
+  {HB_TAG('v','r','o',' '),     HB_TAG('V','R','O',' ')},       /* Võro */
+  {HB_TAG('v','r','o',' '),     HB_TAG('E','T','I',' ')},       /* Võro -> Estonian */
+  {HB_TAG('v','s','n',' '),     HB_TAG('S','A','N',' ')},       /* Vedic Sanskrit -> Sanskrit */
   {HB_TAG('w','a','g',' '),     HB_TAG_NONE            },       /* Wa'ema != Wagdi */
 /*{HB_TAG('w','a','r',' '),     HB_TAG('W','A','R',' ')},*/     /* Waray (Philippines) -> Waray-Waray */
+/*{HB_TAG('w','b','l',' '),     HB_TAG('W','B','L',' ')},*/     /* Wakhi */
   {HB_TAG('w','b','m',' '),     HB_TAG('W','A',' ',' ')},       /* Wa */
   {HB_TAG('w','b','r',' '),     HB_TAG('W','A','G',' ')},       /* Wagdi */
   {HB_TAG('w','b','r',' '),     HB_TAG('R','A','J',' ')},       /* Wagdi -> Rajasthani */
 /*{HB_TAG('w','c','i',' '),     HB_TAG('W','C','I',' ')},*/     /* Waci Gbe */
+/*{HB_TAG('w','d','t',' '),     HB_TAG('W','D','T',' ')},*/     /* Wendat */
   {HB_TAG('w','e','a',' '),     HB_TAG('K','R','N',' ')},       /* Wewaw -> Karen */
   {HB_TAG('w','e','s',' '),     HB_TAG('C','P','P',' ')},       /* Cameroon Pidgin -> Creoles */
   {HB_TAG('w','e','u',' '),     HB_TAG('Q','I','N',' ')},       /* Rawngtu Chin -> Chin */
@@ -1550,6 +1601,9 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('w','s','g',' '),     HB_TAG('G','O','N',' ')},       /* Adilabad Gondi -> Gondi */
 /*{HB_TAG('w','t','m',' '),     HB_TAG('W','T','M',' ')},*/     /* Mewati */
   {HB_TAG('w','u','u',' '),     HB_TAG('Z','H','S',' ')},       /* Wu Chinese -> Chinese, Simplified */
+  {HB_TAG('w','y','a',' '),     HB_TAG('W','D','T',' ')},       /* Wyandot (retired code) -> Wendat */
+  {HB_TAG('w','y','a',' '),     HB_TAG('W','Y','N',' ')},       /* Wyandot (retired code) */
+/*{HB_TAG('w','y','n',' '),     HB_TAG('W','Y','N',' ')},*/     /* Wyandot */
   {HB_TAG('x','a','l',' '),     HB_TAG('K','L','M',' ')},       /* Kalmyk */
   {HB_TAG('x','a','l',' '),     HB_TAG('T','O','D',' ')},       /* Kalmyk -> Todo */
   {HB_TAG('x','a','n',' '),     HB_TAG('S','E','K',' ')},       /* Xamtanga -> Sekota */
@@ -1582,7 +1636,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('y','b','a',' '),     HB_TAG_NONE            },       /* Yala != Yoruba */
   {HB_TAG('y','b','b',' '),     HB_TAG('B','M','L',' ')},       /* Yemba -> Bamileke */
   {HB_TAG('y','b','d',' '),     HB_TAG('A','R','K',' ')},       /* Yangbye (retired code) -> Rakhine */
-  {HB_TAG('y','c','r',' '),     HB_TAG_NONE            },       /* Yilan Creole != Y-Cree */
+  {HB_TAG('y','c','r',' '),     HB_TAG('C','P','P',' ')},       /* Yilan Creole -> Creoles */
   {HB_TAG('y','d','d',' '),     HB_TAG('J','I','I',' ')},       /* Eastern Yiddish -> Yiddish */
 /*{HB_TAG('y','g','p',' '),     HB_TAG('Y','G','P',' ')},*/     /* Gepo */
   {HB_TAG('y','i','h',' '),     HB_TAG('J','I','I',' ')},       /* Western Yiddish -> Yiddish */
@@ -1591,6 +1645,7 @@ static const LangTag ot_languages3[] = {
   {HB_TAG('y','o','s',' '),     HB_TAG('Q','I','N',' ')},       /* Yos (retired code) -> Chin */
   {HB_TAG('y','u','a',' '),     HB_TAG('M','Y','N',' ')},       /* Yucateco -> Mayan */
   {HB_TAG('y','u','e',' '),     HB_TAG('Z','H','H',' ')},       /* Yue Chinese -> Chinese, Traditional, Hong Kong SAR */
+/*{HB_TAG('y','u','f',' '),     HB_TAG('Y','U','F',' ')},*/     /* Havasupai-Walapai-Yavapai */
 /*{HB_TAG('y','w','q',' '),     HB_TAG('Y','W','Q',' ')},*/     /* Wuding-Luquan Yi */
   {HB_TAG('z','c','h',' '),     HB_TAG('Z','H','A',' ')},       /* Central Hongshuihe Zhuang -> Zhuang */
   {HB_TAG('z','d','j',' '),     HB_TAG('C','M','R',' ')},       /* Ngazidja Comorian -> Comorian */
@@ -2335,6 +2390,26 @@ out:
       *count = i;
       return true;
     }
+    if (lang_matches (&lang_str[1], limit, "nm-hant-hk", 10))
+    {
+      /* Hainanese; Han (Traditional variant); Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Traditional, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], limit, "nm-hant-mo", 10))
+    {
+      /* Hainanese; Han (Traditional variant); Macao */
+      unsigned int i;
+      hb_tag_t possible_tags[] = {
+        HB_TAG('Z','H','T','M'),  /* Chinese, Traditional, Macao SAR */
+        HB_TAG('Z','H','H',' '),  /* Chinese, Traditional, Hong Kong SAR */
+      };
+      for (i = 0; i < 2 && i < *count; i++)
+        tags[i] = possible_tags[i];
+      *count = i;
+      return true;
+    }
     if (lang_matches (&lang_str[1], limit, "sn-hant-hk", 10))
     {
       /* Xiang Chinese; Han (Traditional variant); Hong Kong */
@@ -2369,6 +2444,20 @@ out:
       *count = 1;
       return true;
     }
+    if (lang_matches (&lang_str[1], limit, "nm-hans", 7))
+    {
+      /* Hainanese; Han (Simplified variant) */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese, Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], limit, "nm-hant", 7))
+    {
+      /* Hainanese; Han (Traditional variant) */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese, Traditional */
+      *count = 1;
+      return true;
+    }
     if (lang_matches (&lang_str[1], limit, "sn-hans", 7))
     {
       /* Xiang Chinese; Han (Simplified variant) */
@@ -2413,6 +2502,36 @@ out:
       *count = 1;
       return true;
     }
+    if (0 == strncmp (&lang_str[1], "nm-", 3)
+        && subtag_matches (lang_str, limit, "-hk", 3))
+    {
+      /* Hainanese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Traditional, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "nm-", 3)
+        && subtag_matches (lang_str, limit, "-mo", 3))
+    {
+      /* Hainanese; Macao */
+      unsigned int i;
+      hb_tag_t possible_tags[] = {
+        HB_TAG('Z','H','T','M'),  /* Chinese, Traditional, Macao SAR */
+        HB_TAG('Z','H','H',' '),  /* Chinese, Traditional, Hong Kong SAR */
+      };
+      for (i = 0; i < 2 && i < *count; i++)
+        tags[i] = possible_tags[i];
+      *count = i;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "nm-", 3)
+        && subtag_matches (lang_str, limit, "-tw", 3))
+    {
+      /* Hainanese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese, Traditional */
+      *count = 1;
+      return true;
+    }
     if (0 == strncmp (&lang_str[1], "sn-", 3)
         && subtag_matches (lang_str, limit, "-hk", 3))
     {
@@ -2474,6 +2593,40 @@ out:
     }
     break;
   case 'l':
+    if (lang_matches (&lang_str[1], limit, "uh-hant-hk", 10))
+    {
+      /* Leizhou Chinese; Han (Traditional variant); Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Traditional, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], limit, "uh-hant-mo", 10))
+    {
+      /* Leizhou Chinese; Han (Traditional variant); Macao */
+      unsigned int i;
+      hb_tag_t possible_tags[] = {
+        HB_TAG('Z','H','T','M'),  /* Chinese, Traditional, Macao SAR */
+        HB_TAG('Z','H','H',' '),  /* Chinese, Traditional, Hong Kong SAR */
+      };
+      for (i = 0; i < 2 && i < *count; i++)
+        tags[i] = possible_tags[i];
+      *count = i;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], limit, "uh-hans", 7))
+    {
+      /* Leizhou Chinese; Han (Simplified variant) */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese, Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], limit, "uh-hant", 7))
+    {
+      /* Leizhou Chinese; Han (Traditional variant) */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese, Traditional */
+      *count = 1;
+      return true;
+    }
     if (lang_matches (&lang_str[1], limit, "zh-hans", 7))
     {
       /* Literary Chinese; Han (Simplified variant) */
@@ -2481,6 +2634,36 @@ out:
       *count = 1;
       return true;
     }
+    if (0 == strncmp (&lang_str[1], "uh-", 3)
+        && subtag_matches (lang_str, limit, "-hk", 3))
+    {
+      /* Leizhou Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Traditional, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "uh-", 3)
+        && subtag_matches (lang_str, limit, "-mo", 3))
+    {
+      /* Leizhou Chinese; Macao */
+      unsigned int i;
+      hb_tag_t possible_tags[] = {
+        HB_TAG('Z','H','T','M'),  /* Chinese, Traditional, Macao SAR */
+        HB_TAG('Z','H','H',' '),  /* Chinese, Traditional, Hong Kong SAR */
+      };
+      for (i = 0; i < 2 && i < *count; i++)
+        tags[i] = possible_tags[i];
+      *count = i;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "uh-", 3)
+        && subtag_matches (lang_str, limit, "-tw", 3))
+    {
+      /* Leizhou Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese, Traditional */
+      *count = 1;
+      return true;
+    }
     break;
   case 'm':
     if (lang_matches (&lang_str[1], limit, "np-hant-hk", 10))
@@ -2652,6 +2835,72 @@ out:
       return true;
     }
     break;
+  case 's':
+    if (lang_matches (&lang_str[1], limit, "jc-hant-hk", 10))
+    {
+      /* Shaojiang Chinese; Han (Traditional variant); Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Traditional, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], limit, "jc-hant-mo", 10))
+    {
+      /* Shaojiang Chinese; Han (Traditional variant); Macao */
+      unsigned int i;
+      hb_tag_t possible_tags[] = {
+        HB_TAG('Z','H','T','M'),  /* Chinese, Traditional, Macao SAR */
+        HB_TAG('Z','H','H',' '),  /* Chinese, Traditional, Hong Kong SAR */
+      };
+      for (i = 0; i < 2 && i < *count; i++)
+        tags[i] = possible_tags[i];
+      *count = i;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], limit, "jc-hans", 7))
+    {
+      /* Shaojiang Chinese; Han (Simplified variant) */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese, Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], limit, "jc-hant", 7))
+    {
+      /* Shaojiang Chinese; Han (Traditional variant) */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese, Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "jc-", 3)
+        && subtag_matches (lang_str, limit, "-hk", 3))
+    {
+      /* Shaojiang Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Traditional, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "jc-", 3)
+        && subtag_matches (lang_str, limit, "-mo", 3))
+    {
+      /* Shaojiang Chinese; Macao */
+      unsigned int i;
+      hb_tag_t possible_tags[] = {
+        HB_TAG('Z','H','T','M'),  /* Chinese, Traditional, Macao SAR */
+        HB_TAG('Z','H','H',' '),  /* Chinese, Traditional, Hong Kong SAR */
+      };
+      for (i = 0; i < 2 && i < *count; i++)
+        tags[i] = possible_tags[i];
+      *count = i;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "jc-", 3)
+        && subtag_matches (lang_str, limit, "-tw", 3))
+    {
+      /* Shaojiang Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese, Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
   case 'w':
     if (lang_matches (&lang_str[1], limit, "uu-hant-hk", 10))
     {
@@ -2816,9 +3065,10 @@ out:
  * @tag: A language tag.
  *
  * Converts @tag to a BCP 47 language tag if it is ambiguous (it corresponds to
- * many language tags) and the best tag is not the alphabetically first, or if
- * the best tag consists of multiple subtags, or if the best tag does not appear
- * in #ot_languages.
+ * many language tags) and the best tag is not the first (sorted alphabetically,
+ * with two-letter tags having priority over all three-letter tags), or if the
+ * best tag consists of multiple subtags, or if the best tag does not appear in
+ * #ot_languages2 or #ot_languages3.
  *
  * Return value: The #hb_language_t corresponding to the BCP 47 language tag,
  * or #HB_LANGUAGE_INVALID if @tag is not ambiguous.
@@ -2832,8 +3082,6 @@ hb_ot_ambiguous_tag_to_language (hb_tag_
     return hb_language_from_string ("alt", -1);  /* Southern Altai */
   case HB_TAG('A','P','P','H'):  /* Phonetic transcription—Americanist conventions */
     return hb_language_from_string ("und-fonnapa", -1);  /* Undetermined; North American Phonetic Alphabet */
-  case HB_TAG('A','R','A',' '):  /* Arabic */
-    return hb_language_from_string ("ar", -1);  /* Arabic [macrolanguage] */
   case HB_TAG('A','R','K',' '):  /* Rakhine */
     return hb_language_from_string ("rki", -1);  /* Rakhine */
   case HB_TAG('A','T','H',' '):  /* Athapaskan */
@@ -2854,12 +3102,6 @@ hb_ot_ambiguous_tag_to_language (hb_tag_
     return hb_language_from_string ("din", -1);  /* Dinka [macrolanguage] */
   case HB_TAG('D','R','I',' '):  /* Dari */
     return hb_language_from_string ("prs", -1);  /* Dari */
-  case HB_TAG('D','Z','N',' '):  /* Dzongkha */
-    return hb_language_from_string ("dz", -1);  /* Dzongkha */
-  case HB_TAG('E','T','I',' '):  /* Estonian */
-    return hb_language_from_string ("et", -1);  /* Estonian [macrolanguage] */
-  case HB_TAG('F','A','R',' '):  /* Persian */
-    return hb_language_from_string ("fa", -1);  /* Persian [macrolanguage] */
   case HB_TAG('G','O','N',' '):  /* Gondi */
     return hb_language_from_string ("gon", -1);  /* Gondi [macrolanguage] */
   case HB_TAG('H','M','A',' '):  /* High Mari */
@@ -2874,50 +3116,34 @@ hb_ot_ambiguous_tag_to_language (hb_tag_
     return hb_language_from_string ("iba", -1);  /* Iban */
   case HB_TAG('I','J','O',' '):  /* Ijo */
     return hb_language_from_string ("ijo", -1);  /* Ijo [collection] */
-  case HB_TAG('I','N','U',' '):  /* Inuktitut */
-    return hb_language_from_string ("iu", -1);  /* Inuktitut [macrolanguage] */
-  case HB_TAG('I','P','K',' '):  /* Inupiat */
-    return hb_language_from_string ("ik", -1);  /* Inupiaq [macrolanguage] */
   case HB_TAG('I','P','P','H'):  /* Phonetic transcription—IPA conventions */
     return hb_language_from_string ("und-fonipa", -1);  /* Undetermined; International Phonetic Alphabet */
   case HB_TAG('I','R','T',' '):  /* Irish Traditional */
-    return hb_language_from_string ("ga-Latg", -1);  /* Irish; Latin (Gaelic variant) */
+    return hb_language_from_string ("ghc", -1);  /* Hiberno-Scottish Gaelic */
   case HB_TAG('J','I','I',' '):  /* Yiddish */
     return hb_language_from_string ("yi", -1);  /* Yiddish [macrolanguage] */
   case HB_TAG('K','A','L',' '):  /* Kalenjin */
     return hb_language_from_string ("kln", -1);  /* Kalenjin [macrolanguage] */
   case HB_TAG('K','G','E',' '):  /* Khutsuri Georgian */
     return hb_language_from_string ("und-Geok", -1);  /* Undetermined; Khutsuri (Asomtavruli and Nuskhuri) */
-  case HB_TAG('K','N','R',' '):  /* Kanuri */
-    return hb_language_from_string ("kr", -1);  /* Kanuri [macrolanguage] */
   case HB_TAG('K','O','H',' '):  /* Korean Old Hangul */
     return hb_language_from_string ("okm", -1);  /* Middle Korean (10th-16th cent.) */
   case HB_TAG('K','O','K',' '):  /* Konkani */
     return hb_language_from_string ("kok", -1);  /* Konkani [macrolanguage] */
-  case HB_TAG('K','O','M',' '):  /* Komi */
-    return hb_language_from_string ("kv", -1);  /* Komi [macrolanguage] */
   case HB_TAG('K','P','L',' '):  /* Kpelle */
     return hb_language_from_string ("kpe", -1);  /* Kpelle [macrolanguage] */
   case HB_TAG('K','R','N',' '):  /* Karen */
     return hb_language_from_string ("kar", -1);  /* Karen [collection] */
   case HB_TAG('K','U','I',' '):  /* Kui */
     return hb_language_from_string ("uki", -1);  /* Kui (India) */
-  case HB_TAG('K','U','R',' '):  /* Kurdish */
-    return hb_language_from_string ("ku", -1);  /* Kurdish [macrolanguage] */
   case HB_TAG('L','M','A',' '):  /* Low Mari */
     return hb_language_from_string ("mhr", -1);  /* Eastern Mari */
   case HB_TAG('L','U','H',' '):  /* Luyia */
     return hb_language_from_string ("luy", -1);  /* Luyia [macrolanguage] */
-  case HB_TAG('L','V','I',' '):  /* Latvian */
-    return hb_language_from_string ("lv", -1);  /* Latvian [macrolanguage] */
   case HB_TAG('M','A','W',' '):  /* Marwari */
     return hb_language_from_string ("mwr", -1);  /* Marwari [macrolanguage] */
-  case HB_TAG('M','L','G',' '):  /* Malagasy */
-    return hb_language_from_string ("mg", -1);  /* Malagasy [macrolanguage] */
   case HB_TAG('M','L','Y',' '):  /* Malay */
     return hb_language_from_string ("ms", -1);  /* Malay [macrolanguage] */
-  case HB_TAG('M','N','G',' '):  /* Mongolian */
-    return hb_language_from_string ("mn", -1);  /* Mongolian [macrolanguage] */
   case HB_TAG('M','N','K',' '):  /* Maninka */
     return hb_language_from_string ("man", -1);  /* Mandingo [macrolanguage] */
   case HB_TAG('M','O','L',' '):  /* Moldavian */
@@ -2928,26 +3154,16 @@ hb_ot_ambiguous_tag_to_language (hb_tag_
     return hb_language_from_string ("myn", -1);  /* Mayan [collection] */
   case HB_TAG('N','A','H',' '):  /* Nahuatl */
     return hb_language_from_string ("nah", -1);  /* Nahuatl [collection] */
-  case HB_TAG('N','E','P',' '):  /* Nepali */
-    return hb_language_from_string ("ne", -1);  /* Nepali [macrolanguage] */
   case HB_TAG('N','I','S',' '):  /* Nisi */
     return hb_language_from_string ("njz", -1);  /* Nyishi */
   case HB_TAG('N','O','R',' '):  /* Norwegian */
     return hb_language_from_string ("no", -1);  /* Norwegian [macrolanguage] */
-  case HB_TAG('O','J','B',' '):  /* Ojibway */
-    return hb_language_from_string ("oj", -1);  /* Ojibwa [macrolanguage] */
-  case HB_TAG('O','R','O',' '):  /* Oromo */
-    return hb_language_from_string ("om", -1);  /* Oromo [macrolanguage] */
-  case HB_TAG('P','A','S',' '):  /* Pashto */
-    return hb_language_from_string ("ps", -1);  /* Pashto [macrolanguage] */
   case HB_TAG('P','G','R',' '):  /* Polytonic Greek */
     return hb_language_from_string ("el-polyton", -1);  /* Modern Greek (1453-); Polytonic Greek */
   case HB_TAG('P','R','O',' '):  /* Provençal / Old Provençal */
     return hb_language_from_string ("pro", -1);  /* Old Provençal (to 1500) */
   case HB_TAG('Q','U','H',' '):  /* Quechua (Bolivia) */
     return hb_language_from_string ("quh", -1);  /* South Bolivian Quechua */
-  case HB_TAG('Q','U','Z',' '):  /* Quechua */
-    return hb_language_from_string ("qu", -1);  /* Quechua [macrolanguage] */
   case HB_TAG('Q','V','I',' '):  /* Quechua (Ecuador) */
     return hb_language_from_string ("qvi", -1);  /* Imbabura Highland Quichua */
   case HB_TAG('Q','W','H',' '):  /* Quechua (Peru) */
@@ -2958,8 +3174,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_
     return hb_language_from_string ("ro", -1);  /* Romanian */
   case HB_TAG('R','O','Y',' '):  /* Romany */
     return hb_language_from_string ("rom", -1);  /* Romany [macrolanguage] */
-  case HB_TAG('S','Q','I',' '):  /* Albanian */
-    return hb_language_from_string ("sq", -1);  /* Albanian [macrolanguage] */
+  case HB_TAG('S','G','A',' '):  /* Old Irish */
+    return hb_language_from_string ("sga", -1);  /* Old Irish (to 900) */
   case HB_TAG('S','R','B',' '):  /* Serbian */
     return hb_language_from_string ("sr", -1);  /* Serbian */
   case HB_TAG('S','X','T',' '):  /* Sutu */
@@ -2976,6 +3192,10 @@ hb_ot_ambiguous_tag_to_language (hb_tag_
     return hb_language_from_string ("tmh", -1);  /* Tamashek [macrolanguage] */
   case HB_TAG('T','O','D',' '):  /* Todo */
     return hb_language_from_string ("xwo", -1);  /* Written Oirat */
+  case HB_TAG('W','D','T',' '):  /* Wendat */
+    return hb_language_from_string ("wdt", -1);  /* Wendat */
+  case HB_TAG('W','Y','N',' '):  /* Wyandot */
+    return hb_language_from_string ("wyn", -1);  /* Wyandot */
   case HB_TAG('Z','H','H',' '):  /* Chinese, Traditional, Hong Kong SAR */
     return hb_language_from_string ("zh-HK", -1);  /* Chinese [macrolanguage]; Hong Kong */
   case HB_TAG('Z','H','S',' '):  /* Chinese, Simplified */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc	2025-06-27 08:03:14.000000000 +0000
@@ -547,7 +547,7 @@ hb_ot_tag_to_language (hb_tag_t tag)
       buf[3] = '-';
       str += 4;
     }
-    snprintf (str, 16, "x-hbot-%08x", tag);
+    snprintf (str, 16, "x-hbot-%08" PRIx32, tag);
     return hb_language_from_string (&*buf, -1);
   }
 }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-avar-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-avar-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-avar-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-avar-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -57,7 +57,7 @@ struct avarV2Tail
 
   protected:
   Offset32To<DeltaSetIndexMap>  varIdxMap;      /* Offset from the beginning of 'avar' table. */
-  Offset32To<VariationStore>    varStore;       /* Offset from the beginning of 'avar' table. */
+  Offset32To<ItemVariationStore>        varStore;       /* Offset from the beginning of 'avar' table. */
 
   public:
   DEFINE_SIZE_STATIC (8);
@@ -80,7 +80,7 @@ struct AxisValueMap
 
   bool is_outside_axis_range (const Triple& axis_range) const
   {
-    float from_coord = coords[0].to_float ();
+    double from_coord = (double) coords[0].to_float ();
     return !axis_range.contains (from_coord);
   }
 
@@ -100,8 +100,8 @@ struct AxisValueMap
     float from_coord = coords[0].to_float ();
     float to_coord = coords[1].to_float ();
 
-    from_coord = renormalizeValue (from_coord, unmapped_range, triple_distances);
-    to_coord = renormalizeValue (to_coord, axis_range, triple_distances);
+    from_coord = renormalizeValue ((double) from_coord, unmapped_range, triple_distances);
+    to_coord = renormalizeValue ((double) to_coord, axis_range, triple_distances);
 
     coords[0].set_float (from_coord);
     coords[1].set_float (to_coord);
@@ -197,7 +197,7 @@ struct SegmentMaps : Array16Of<AxisValue
     unmapped_val.set_int (unmap (val.to_int ()));
     float unmapped_max = unmapped_val.to_float ();
 
-    return Triple{unmapped_min, unmapped_middle, unmapped_max};
+    return Triple{(double) unmapped_min, (double) unmapped_middle, (double) unmapped_max};
   }
 
   bool subset (hb_subset_context_t *c, hb_tag_t axis_tag) const
@@ -230,7 +230,7 @@ struct SegmentMaps : Array16Of<AxisValue
        * duplicates here */
       if (mapping.must_include ())
         continue;
-      value_mappings.push (std::move (mapping));
+      value_mappings.push (mapping);
     }
 
     AxisValueMap m;
@@ -273,6 +273,7 @@ struct avar
   {
     TRACE_SANITIZE (this);
     if (!(version.sanitize (c) &&
+          hb_barrier () &&
           (version.major == 1
 #ifndef HB_NO_AVAR2
            || version.major == 2
@@ -293,6 +294,7 @@ struct avar
 #ifndef HB_NO_AVAR2
     if (version.major < 2)
       return_trace (true);
+    hb_barrier ();
 
     const auto &v2 = * (const avarV2Tail *) map;
     if (unlikely (!v2.sanitize (c, this)))
@@ -316,6 +318,7 @@ struct avar
 #ifndef HB_NO_AVAR2
     if (version.major < 2)
       return;
+    hb_barrier ();
 
     for (; count < axisCount; count++)
       map = &StructAfter<SegmentMaps> (*map);
@@ -340,7 +343,7 @@ struct avar
     for (unsigned i = 0; i < coords_length; i++)
       coords[i] = out[i];
 
-    OT::VariationStore::destroy_cache (var_store_cache);
+    OT::ItemVariationStore::destroy_cache (var_store_cache);
 #endif
   }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-common.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-common.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-common.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-common.hh	2025-06-27 08:03:14.000000000 +0000
@@ -28,215 +28,11 @@
 
 #include "hb-ot-layout-common.hh"
 #include "hb-priority-queue.hh"
+#include "hb-subset-instancer-iup.hh"
 
 
 namespace OT {
 
-template <typename MapCountT>
-struct DeltaSetIndexMapFormat01
-{
-  friend struct DeltaSetIndexMap;
-
-  unsigned get_size () const
-  { return min_size + mapCount * get_width (); }
-
-  private:
-  DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const
-  {
-    TRACE_SERIALIZE (this);
-    return_trace (c->embed (this));
-  }
-
-  template <typename T>
-  bool serialize (hb_serialize_context_t *c, const T &plan)
-  {
-    unsigned int width = plan.get_width ();
-    unsigned int inner_bit_count = plan.get_inner_bit_count ();
-    const hb_array_t<const uint32_t> output_map = plan.get_output_map ();
-
-    TRACE_SERIALIZE (this);
-    if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0))))
-      return_trace (false);
-    if (unlikely (!c->extend_min (this))) return_trace (false);
-
-    entryFormat = ((width-1)<<4)|(inner_bit_count-1);
-    mapCount = output_map.length;
-    HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length);
-    if (unlikely (!p)) return_trace (false);
-    for (unsigned int i = 0; i < output_map.length; i++)
-    {
-      unsigned int v = output_map.arrayZ[i];
-      if (v)
-      {
-        unsigned int outer = v >> 16;
-        unsigned int inner = v & 0xFFFF;
-        unsigned int u = (outer << inner_bit_count) | inner;
-        for (unsigned int w = width; w > 0;)
-        {
-          p[--w] = u;
-          u >>= 8;
-        }
-      }
-      p += width;
-    }
-    return_trace (true);
-  }
-
-  uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */
-  {
-    /* If count is zero, pass value unchanged.  This takes
-     * care of direct mapping for advance map. */
-    if (!mapCount)
-      return v;
-
-    if (v >= mapCount)
-      v = mapCount - 1;
-
-    unsigned int u = 0;
-    { /* Fetch it. */
-      unsigned int w = get_width ();
-      const HBUINT8 *p = mapDataZ.arrayZ + w * v;
-      for (; w; w--)
-        u = (u << 8) + *p++;
-    }
-
-    { /* Repack it. */
-      unsigned int n = get_inner_bit_count ();
-      unsigned int outer = u >> n;
-      unsigned int inner = u & ((1 << n) - 1);
-      u = (outer<<16) | inner;
-    }
-
-    return u;
-  }
-
-  unsigned get_map_count () const       { return mapCount; }
-  unsigned get_width () const           { return ((entryFormat >> 4) & 3) + 1; }
-  unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; }
-
-
-  bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  c->check_range (mapDataZ.arrayZ,
-                                  mapCount,
-                                  get_width ()));
-  }
-
-  protected:
-  HBUINT8       format;         /* Format identifier--format = 0 */
-  HBUINT8       entryFormat;    /* A packed field that describes the compressed
-                                 * representation of delta-set indices. */
-  MapCountT     mapCount;       /* The number of mapping entries. */
-  UnsizedArrayOf<HBUINT8>
-                mapDataZ;       /* The delta-set index mapping data. */
-
-  public:
-  DEFINE_SIZE_ARRAY (2+MapCountT::static_size, mapDataZ);
-};
-
-struct DeltaSetIndexMap
-{
-  template <typename T>
-  bool serialize (hb_serialize_context_t *c, const T &plan)
-  {
-    TRACE_SERIALIZE (this);
-    unsigned length = plan.get_output_map ().length;
-    u.format = length <= 0xFFFF ? 0 : 1;
-    switch (u.format) {
-    case 0: return_trace (u.format0.serialize (c, plan));
-    case 1: return_trace (u.format1.serialize (c, plan));
-    default:return_trace (false);
-    }
-  }
-
-  uint32_t map (unsigned v) const
-  {
-    switch (u.format) {
-    case 0: return (u.format0.map (v));
-    case 1: return (u.format1.map (v));
-    default:return v;
-    }
-  }
-
-  unsigned get_map_count () const
-  {
-    switch (u.format) {
-    case 0: return u.format0.get_map_count ();
-    case 1: return u.format1.get_map_count ();
-    default:return 0;
-    }
-  }
-
-  unsigned get_width () const
-  {
-    switch (u.format) {
-    case 0: return u.format0.get_width ();
-    case 1: return u.format1.get_width ();
-    default:return 0;
-    }
-  }
-
-  unsigned get_inner_bit_count () const
-  {
-    switch (u.format) {
-    case 0: return u.format0.get_inner_bit_count ();
-    case 1: return u.format1.get_inner_bit_count ();
-    default:return 0;
-    }
-  }
-
-  bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 0: return_trace (u.format0.sanitize (c));
-    case 1: return_trace (u.format1.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  DeltaSetIndexMap* copy (hb_serialize_context_t *c) const
-  {
-    TRACE_SERIALIZE (this);
-    switch (u.format) {
-    case 0: return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format0.copy (c)));
-    case 1: return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format1.copy (c)));
-    default:return_trace (nullptr);
-    }
-  }
-
-  protected:
-  union {
-  HBUINT8                            format;         /* Format identifier */
-  DeltaSetIndexMapFormat01<HBUINT16> format0;
-  DeltaSetIndexMapFormat01<HBUINT32> format1;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (1, format);
-};
-
-
-struct VarStoreInstancer
-{
-  VarStoreInstancer (const VariationStore *varStore,
-                     const DeltaSetIndexMap *varIdxMap,
-                     hb_array_t<int> coords) :
-    varStore (varStore), varIdxMap (varIdxMap), coords (coords) {}
-
-  operator bool () const { return varStore && bool (coords); }
-
-  /* according to the spec, if colr table has varStore but does not have
-   * varIdxMap, then an implicit identity mapping is used */
-  float operator() (uint32_t varIdx, unsigned short offset = 0) const
-  { return coords ? varStore->get_delta (varIdxMap ? varIdxMap->map (VarIdx::add (varIdx, offset)) : varIdx + offset, coords) : 0; }
-
-  const VariationStore *varStore;
-  const DeltaSetIndexMap *varIdxMap;
-  hb_array_t<int> coords;
-};
 
 /* https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader */
 struct TupleVariationHeader
@@ -296,15 +92,15 @@ struct TupleVariationHeader
         start = hb_min (peak, 0.f);
         end = hb_max (peak, 0.f);
       }
-      axis_tuples.set (*axis_tag, Triple (start, peak, end));
+      axis_tuples.set (*axis_tag, Triple ((double) start, (double) peak, (double) end));
     }
 
     return true;
   }
 
-  float calculate_scalar (hb_array_t<int> coords, unsigned int coord_count,
-                          const hb_array_t<const F2DOT14> shared_tuples,
-                          const hb_vector_t<hb_pair_t<int,int>> *shared_tuple_active_idx = nullptr) const
+  double calculate_scalar (hb_array_t<const int> coords, unsigned int coord_count,
+                           const hb_array_t<const F2DOT14> shared_tuples,
+                           const hb_vector_t<hb_pair_t<int,int>> *shared_tuple_active_idx = nullptr) const
   {
     const F2DOT14 *peak_tuple;
 
@@ -318,13 +114,13 @@ struct TupleVariationHeader
     {
       unsigned int index = get_index ();
       if (unlikely ((index + 1) * coord_count > shared_tuples.length))
-        return 0.f;
+        return 0.0;
       peak_tuple = shared_tuples.sub_array (coord_count * index, coord_count).arrayZ;
 
       if (shared_tuple_active_idx)
       {
         if (unlikely (index >= shared_tuple_active_idx->length))
-          return 0.f;
+          return 0.0;
         auto _ = (*shared_tuple_active_idx).arrayZ[index];
         if (_.second != -1)
         {
@@ -349,7 +145,7 @@ struct TupleVariationHeader
       end_tuple = get_end_tuple (coord_count).arrayZ;
     }
 
-    float scalar = 1.f;
+    double scalar = 1.0;
     for (unsigned int i = start_idx; i < end_idx; i += step)
     {
       int peak = peak_tuple[i].to_int ();
@@ -364,15 +160,15 @@ struct TupleVariationHeader
         int end = end_tuple[i].to_int ();
         if (unlikely (start > peak || peak > end ||
                       (start < 0 && end > 0 && peak))) continue;
-        if (v < start || v > end) return 0.f;
+        if (v < start || v > end) return 0.0;
         if (v < peak)
-        { if (peak != start) scalar *= (float) (v - start) / (peak - start); }
+        { if (peak != start) scalar *= (double) (v - start) / (peak - start); }
         else
-        { if (peak != end) scalar *= (float) (end - v) / (end - peak); }
+        { if (peak != end) scalar *= (double) (end - v) / (end - peak); }
       }
-      else if (!v || v < hb_min (0, peak) || v > hb_max (0, peak)) return 0.f;
+      else if (!v || v < hb_min (0, peak) || v > hb_max (0, peak)) return 0.0;
       else
-        scalar *= (float) v / peak;
+        scalar *= (double) v / peak;
     }
     return scalar;
   }
@@ -425,15 +221,10 @@ struct TupleVariationHeader
   DEFINE_SIZE_MIN (4);
 };
 
-enum packed_delta_flag_t
-{
-  DELTAS_ARE_ZERO      = 0x80,
-  DELTAS_ARE_WORDS     = 0x40,
-  DELTA_RUN_COUNT_MASK = 0x3F
-};
-
 struct tuple_delta_t
 {
+  static constexpr bool realloc_move = true;  // Watch out when adding new members!
+
   public:
   hb_hashmap_t<hb_tag_t, Triple> axis_tuples;
 
@@ -447,8 +238,8 @@ struct tuple_delta_t
   /* compiled data: header and deltas
    * compiled point data is saved in a hashmap within tuple_variations_t cause
    * some point sets might be reused by different tuple variations */
-  hb_vector_t<char> compiled_tuple_header;
-  hb_vector_t<char> compiled_deltas;
+  hb_vector_t<unsigned char> compiled_tuple_header;
+  hb_vector_t<unsigned char> compiled_deltas;
 
   /* compiled peak coords, empty for non-gvar tuples */
   hb_vector_t<char> compiled_peak_coords;
@@ -456,7 +247,7 @@ struct tuple_delta_t
   tuple_delta_t () = default;
   tuple_delta_t (const tuple_delta_t& o) = default;
 
-  friend void swap (tuple_delta_t& a, tuple_delta_t& b)
+  friend void swap (tuple_delta_t& a, tuple_delta_t& b) noexcept
   {
     hb_swap (a.axis_tuples, b.axis_tuples);
     hb_swap (a.indices, b.indices);
@@ -467,10 +258,10 @@ struct tuple_delta_t
     hb_swap (a.compiled_peak_coords, b.compiled_peak_coords);
   }
 
-  tuple_delta_t (tuple_delta_t&& o) : tuple_delta_t ()
+  tuple_delta_t (tuple_delta_t&& o)  noexcept : tuple_delta_t ()
   { hb_swap (*this, o); }
 
-  tuple_delta_t& operator = (tuple_delta_t&& o)
+  tuple_delta_t& operator = (tuple_delta_t&& o) noexcept
   {
     hb_swap (*this, o);
     return *this;
@@ -514,14 +305,19 @@ struct tuple_delta_t
       return *this;
 
     unsigned num = indices.length;
-    for (unsigned i = 0; i < num; i++)
-    {
-      if (!indices.arrayZ[i]) continue;
-
-      deltas_x[i] *= scalar;
-      if (deltas_y)
+    if (deltas_y)
+      for (unsigned i = 0; i < num; i++)
+      {
+        if (!indices.arrayZ[i]) continue;
+        deltas_x[i] *= scalar;
         deltas_y[i] *= scalar;
-    }
+      }
+    else
+      for (unsigned i = 0; i < num; i++)
+      {
+        if (!indices.arrayZ[i]) continue;
+        deltas_x[i] *= scalar;
+      }
     return *this;
   }
 
@@ -536,18 +332,18 @@ struct tuple_delta_t
       return out;
     }
 
-    if ((tent->minimum < 0.f && tent->maximum > 0.f) ||
+    if ((tent->minimum < 0.0 && tent->maximum > 0.0) ||
         !(tent->minimum <= tent->middle && tent->middle <= tent->maximum))
       return out;
 
-    if (tent->middle == 0.f)
+    if (tent->middle == 0.0)
     {
       out.push (*this);
       return out;
     }
 
-    result_t solutions = rebase_tent (*tent, axis_limit, axis_triple_distances);
-    for (auto t : solutions)
+    rebase_tent_result_t solutions = rebase_tent (*tent, axis_limit, axis_triple_distances);
+    for (auto &t : solutions)
     {
       tuple_delta_t new_var = *this;
       if (t.second == Triple ())
@@ -600,7 +396,9 @@ struct tuple_delta_t
                                  const hb_map_t& axes_old_index_tag_map,
                                  const hb_hashmap_t<const hb_vector_t<char>*, unsigned>* shared_tuples_idx_map)
   {
-    if (!compiled_deltas) return false;
+    /* compiled_deltas could be empty after iup delta optimization, we can skip
+     * compiling this tuple and return true */
+    if (!compiled_deltas) return true;
 
     unsigned cur_axis_count = axes_index_map.get_population ();
     /* allocate enough memory: 1 peak + 2 intermediate coords + fixed header size */
@@ -714,37 +512,42 @@ struct tuple_delta_t
   }
 
   bool compile_deltas ()
+  { return compile_deltas (indices, deltas_x, deltas_y, compiled_deltas); }
+
+  static bool compile_deltas (hb_array_t<const bool> point_indices,
+                              hb_array_t<const float> x_deltas,
+                              hb_array_t<const float> y_deltas,
+                              hb_vector_t<unsigned char> &compiled_deltas /* OUT */)
   {
     hb_vector_t<int> rounded_deltas;
-    if (unlikely (!rounded_deltas.alloc (indices.length)))
+    if (unlikely (!rounded_deltas.alloc (point_indices.length)))
       return false;
 
-    for (unsigned i = 0; i < indices.length; i++)
+    for (unsigned i = 0; i < point_indices.length; i++)
     {
-      if (!indices[i]) continue;
-      int rounded_delta = (int) roundf (deltas_x[i]);
+      if (!point_indices[i]) continue;
+      int rounded_delta = (int) roundf (x_deltas.arrayZ[i]);
       rounded_deltas.push (rounded_delta);
     }
 
-    if (!rounded_deltas) return false;
-    /* allocate enough memories 3 * num_deltas */
-    unsigned alloc_len = 3 * rounded_deltas.length;
-    if (deltas_y)
+    if (!rounded_deltas) return true;
+    /* allocate enough memories 5 * num_deltas */
+    unsigned alloc_len = 5 * rounded_deltas.length;
+    if (y_deltas)
       alloc_len *= 2;
 
     if (unlikely (!compiled_deltas.resize (alloc_len))) return false;
 
-    unsigned i = 0;
-    unsigned encoded_len = encode_delta_run (i, compiled_deltas.as_array (), rounded_deltas);
+    unsigned encoded_len = compile_deltas (compiled_deltas, rounded_deltas);
 
-    if (deltas_y)
+    if (y_deltas)
     {
-      /* reuse the rounded_deltas vector, check that deltas_y have the same num of deltas as deltas_x */
+      /* reuse the rounded_deltas vector, check that y_deltas have the same num of deltas as x_deltas */
       unsigned j = 0;
-      for (unsigned idx = 0; idx < indices.length; idx++)
+      for (unsigned idx = 0; idx < point_indices.length; idx++)
       {
-        if (!indices[idx]) continue;
-        int rounded_delta = (int) roundf (deltas_y[idx]);
+        if (!point_indices[idx]) continue;
+        int rounded_delta = (int) roundf (y_deltas.arrayZ[idx]);
 
         if (j >= rounded_deltas.length) return false;
 
@@ -752,174 +555,15 @@ struct tuple_delta_t
       }
 
       if (j != rounded_deltas.length) return false;
-      /* reset i because we reuse rounded_deltas for deltas_y */
-      i = 0;
-      encoded_len += encode_delta_run (i, compiled_deltas.as_array ().sub_array (encoded_len), rounded_deltas);
+      encoded_len += compile_deltas (compiled_deltas.as_array ().sub_array (encoded_len), rounded_deltas);
     }
     return compiled_deltas.resize (encoded_len);
   }
 
-  unsigned encode_delta_run (unsigned& i,
-                             hb_array_t<char> encoded_bytes,
-                             const hb_vector_t<int>& deltas) const
-  {
-    unsigned num_deltas = deltas.length;
-    unsigned encoded_len = 0;
-    while (i < num_deltas)
-    {
-      int val = deltas[i];
-      if (val == 0)
-        encoded_len += encode_delta_run_as_zeroes (i, encoded_bytes.sub_array (encoded_len), deltas);
-      else if (val >= -128 && val <= 127)
-        encoded_len += encode_delta_run_as_bytes (i, encoded_bytes.sub_array (encoded_len), deltas);
-      else
-        encoded_len += encode_delta_run_as_words (i, encoded_bytes.sub_array (encoded_len), deltas);
-    }
-    return encoded_len;
-  }
-
-  unsigned encode_delta_run_as_zeroes (unsigned& i,
-                                       hb_array_t<char> encoded_bytes,
-                                       const hb_vector_t<int>& deltas) const
+  static unsigned compile_deltas (hb_array_t<unsigned char> encoded_bytes,
+                                  hb_array_t<const int> deltas)
   {
-    unsigned num_deltas = deltas.length;
-    unsigned run_length = 0;
-    auto it = encoded_bytes.iter ();
-    unsigned encoded_len = 0;
-    while (i < num_deltas && deltas[i] == 0)
-    {
-      i++;
-      run_length++;
-    }
-
-    while (run_length >= 64)
-    {
-      *it++ = char (DELTAS_ARE_ZERO | 63);
-      run_length -= 64;
-      encoded_len++;
-    }
-
-    if (run_length)
-    {
-      *it++ = char (DELTAS_ARE_ZERO | (run_length - 1));
-      encoded_len++;
-    }
-    return encoded_len;
-  }
-
-  unsigned encode_delta_run_as_bytes (unsigned &i,
-                                      hb_array_t<char> encoded_bytes,
-                                      const hb_vector_t<int>& deltas) const
-  {
-    unsigned start = i;
-    unsigned num_deltas = deltas.length;
-    while (i < num_deltas)
-    {
-      int val = deltas[i];
-      if (val > 127 || val < -128)
-        break;
-
-      /* from fonttools: if there're 2 or more zeros in a sequence,
-       * it is better to start a new run to save bytes. */
-      if (val == 0 && i + 1 < num_deltas && deltas[i+1] == 0)
-        break;
-
-      i++;
-    }
-    unsigned run_length = i - start;
-
-    unsigned encoded_len = 0;
-    auto it = encoded_bytes.iter ();
-
-    while (run_length >= 64)
-    {
-      *it++ = 63;
-      encoded_len++;
-
-      for (unsigned j = 0; j < 64; j++)
-      {
-        *it++ = static_cast<char> (deltas[start + j]);
-        encoded_len++;
-      }
-
-      start += 64;
-      run_length -= 64;
-    }
-
-    if (run_length)
-    {
-      *it++ = run_length - 1;
-      encoded_len++;
-
-      while (start < i)
-      {
-        *it++ = static_cast<char> (deltas[start++]);
-        encoded_len++;
-      }
-    }
-
-    return encoded_len;
-  }
-
-  unsigned encode_delta_run_as_words (unsigned &i,
-                                      hb_array_t<char> encoded_bytes,
-                                      const hb_vector_t<int>& deltas) const
-  {
-    unsigned start = i;
-    unsigned num_deltas = deltas.length;
-    while (i < num_deltas)
-    {
-      int val = deltas[i];
-
-      /* start a new run for a single zero value*/
-      if (val == 0) break;
-
-      /* from fonttools: continue word-encoded run if there's only one
-       * single value in the range [-128, 127] because it is more compact.
-       * Only start a new run when there're 2 continuous such values. */
-      if (val >= -128 && val <= 127 &&
-          i + 1 < num_deltas &&
-          deltas[i+1] >= -128 && deltas[i+1] <= 127)
-        break;
-
-      i++;
-    }
-
-    unsigned run_length = i - start;
-    auto it = encoded_bytes.iter ();
-    unsigned encoded_len = 0;
-    while (run_length >= 64)
-    {
-      *it++ = (DELTAS_ARE_WORDS | 63);
-      encoded_len++;
-
-      for (unsigned j = 0; j < 64; j++)
-      {
-        int16_t delta_val = deltas[start + j];
-        *it++ = static_cast<char> (delta_val >> 8);
-        *it++ = static_cast<char> (delta_val & 0xFF);
-
-        encoded_len += 2;
-      }
-
-      start += 64;
-      run_length -= 64;
-    }
-
-    if (run_length)
-    {
-      *it++ = (DELTAS_ARE_WORDS | (run_length - 1));
-      encoded_len++;
-      while (start < i)
-      {
-        int16_t delta_val = deltas[start++];
-        *it++ = static_cast<char> (delta_val >> 8);
-        *it++ = static_cast<char> (delta_val & 0xFF);
-
-        encoded_len += 2;
-      }
-    }
-    return encoded_len;
+    return TupleValues::compile (deltas, encoded_bytes);
   }
 
   bool calc_inferred_deltas (const contour_point_vector_t& orig_points)
@@ -982,10 +626,14 @@ struct tuple_delta_t
         {
           i = next_index (i, start_point, end_point);
           if (i == next) break;
-          deltas_x.arrayZ[i] = infer_delta (orig_points.arrayZ[i].x, orig_points.arrayZ[prev].x, orig_points.arrayZ[next].x,
-                                            deltas_x.arrayZ[prev], deltas_x.arrayZ[next]);
-          deltas_y.arrayZ[i] = infer_delta (orig_points.arrayZ[i].y, orig_points.arrayZ[prev].y, orig_points.arrayZ[next].y,
-                                            deltas_y.arrayZ[prev], deltas_y.arrayZ[next]);
+          deltas_x.arrayZ[i] = infer_delta ((double) orig_points.arrayZ[i].x,
+                                            (double) orig_points.arrayZ[prev].x,
+                                            (double) orig_points.arrayZ[next].x,
+                                            (double) deltas_x.arrayZ[prev], (double) deltas_x.arrayZ[next]);
+          deltas_y.arrayZ[i] = infer_delta ((double) orig_points.arrayZ[i].y,
+                                            (double) orig_points.arrayZ[prev].y,
+                                            (double) orig_points.arrayZ[next].y,
+                                            (double) deltas_y.arrayZ[prev], (double) deltas_y.arrayZ[next]);
           inferred_idxes.add (i);
           if (--unref_count == 0) goto no_more_gaps;
         }
@@ -1002,8 +650,8 @@ struct tuple_delta_t
       {
         if (!inferred_idxes.has (i))
         {
-          deltas_x.arrayZ[i] = 0.f;
-          deltas_y.arrayZ[i] = 0.f;
+          deltas_x.arrayZ[i] = 0.0;
+          deltas_y.arrayZ[i] = 0.0;
         }
         indices[i] = true;
       }
@@ -1011,16 +659,181 @@ struct tuple_delta_t
     return true;
   }
 
-  static float infer_delta (float target_val, float prev_val, float next_val, float prev_delta, float next_delta)
+  bool optimize (const contour_point_vector_t& contour_points,
+                 bool is_composite,
+                 double tolerance = 0.5 + 1e-10)
+  {
+    unsigned count = contour_points.length;
+    if (deltas_x.length != count ||
+        deltas_y.length != count)
+      return false;
+
+    hb_vector_t<bool> opt_indices;
+    hb_vector_t<int> rounded_x_deltas, rounded_y_deltas;
+
+    if (unlikely (!rounded_x_deltas.alloc (count) ||
+                  !rounded_y_deltas.alloc (count)))
+      return false;
+
+    for (unsigned i = 0; i < count; i++)
+    {
+      int rounded_x_delta = (int) roundf (deltas_x.arrayZ[i]);
+      int rounded_y_delta = (int) roundf (deltas_y.arrayZ[i]);
+      rounded_x_deltas.push (rounded_x_delta);
+      rounded_y_deltas.push (rounded_y_delta);
+    }
+
+    if (!iup_delta_optimize (contour_points, rounded_x_deltas, rounded_y_deltas, opt_indices, tolerance))
+      return false;
+
+    unsigned ref_count = 0;
+    for (bool ref_flag : opt_indices)
+       ref_count += ref_flag;
+
+    if (ref_count == count) return true;
+
+    hb_vector_t<float> opt_deltas_x, opt_deltas_y;
+    bool is_comp_glyph_wo_deltas = (is_composite && ref_count == 0);
+    if (is_comp_glyph_wo_deltas)
+    {
+      if (unlikely (!opt_deltas_x.resize (count) ||
+                    !opt_deltas_y.resize (count)))
+        return false;
+
+      opt_indices.arrayZ[0] = true;
+      for (unsigned i = 1; i < count; i++)
+        opt_indices.arrayZ[i] = false;
+    }
+
+    hb_vector_t<unsigned char> opt_point_data;
+    if (!compile_point_set (opt_indices, opt_point_data))
+      return false;
+    hb_vector_t<unsigned char> opt_deltas_data;
+    if (!compile_deltas (opt_indices,
+                         is_comp_glyph_wo_deltas ? opt_deltas_x : deltas_x,
+                         is_comp_glyph_wo_deltas ? opt_deltas_y : deltas_y,
+                         opt_deltas_data))
+      return false;
+
+    hb_vector_t<unsigned char> point_data;
+    if (!compile_point_set (indices, point_data))
+      return false;
+    hb_vector_t<unsigned char> deltas_data;
+    if (!compile_deltas (indices, deltas_x, deltas_y, deltas_data))
+      return false;
+
+    if (opt_point_data.length + opt_deltas_data.length < point_data.length + deltas_data.length)
+    {
+      indices.fini ();
+      indices = std::move (opt_indices);
+
+      if (is_comp_glyph_wo_deltas)
+      {
+        deltas_x.fini ();
+        deltas_x = std::move (opt_deltas_x);
+
+        deltas_y.fini ();
+        deltas_y = std::move (opt_deltas_y);
+      }
+    }
+    return !indices.in_error () && !deltas_x.in_error () && !deltas_y.in_error ();
+  }
+
+  static bool compile_point_set (const hb_vector_t<bool> &point_indices,
+                                 hb_vector_t<unsigned char>& compiled_points /* OUT */)
+  {
+    unsigned num_points = 0;
+    for (bool i : point_indices)
+      if (i) num_points++;
+
+    /* when iup optimization is enabled, num of referenced points could be 0 */
+    if (!num_points) return true;
+
+    unsigned indices_length = point_indices.length;
+    /* If the points set consists of all points in the glyph, it's encoded with a
+     * single zero byte */
+    if (num_points == indices_length)
+      return compiled_points.resize (1);
+
+    /* allocate enough memories: 2 bytes for count + 3 bytes for each point */
+    unsigned num_bytes = 2 + 3 *num_points;
+    if (unlikely (!compiled_points.resize (num_bytes, false)))
+      return false;
+
+    unsigned pos = 0;
+    /* binary data starts with the total number of reference points */
+    if (num_points < 0x80)
+      compiled_points.arrayZ[pos++] = num_points;
+    else
+    {
+      compiled_points.arrayZ[pos++] = ((num_points >> 8) | 0x80);
+      compiled_points.arrayZ[pos++] = num_points & 0xFF;
+    }
+
+    const unsigned max_run_length = 0x7F;
+    unsigned i = 0;
+    unsigned last_value = 0;
+    unsigned num_encoded = 0;
+    while (i < indices_length && num_encoded < num_points)
+    {
+      unsigned run_length = 0;
+      unsigned header_pos = pos;
+      compiled_points.arrayZ[pos++] = 0;
+
+      bool use_byte_encoding = false;
+      bool new_run = true;
+      while (i < indices_length && num_encoded < num_points &&
+             run_length <= max_run_length)
+      {
+        // find out next referenced point index
+        while (i < indices_length && !point_indices[i])
+          i++;
+
+        if (i >= indices_length) break;
+
+        unsigned cur_value = i;
+        unsigned delta = cur_value - last_value;
+
+        if (new_run)
+        {
+          use_byte_encoding = (delta <= 0xFF);
+          new_run = false;
+        }
+
+        if (use_byte_encoding && delta > 0xFF)
+          break;
+
+        if (use_byte_encoding)
+          compiled_points.arrayZ[pos++] = delta;
+        else
+        {
+          compiled_points.arrayZ[pos++] = delta >> 8;
+          compiled_points.arrayZ[pos++] = delta & 0xFF;
+        }
+        i++;
+        last_value = cur_value;
+        run_length++;
+        num_encoded++;
+      }
+
+      if (use_byte_encoding)
+        compiled_points.arrayZ[header_pos] = run_length - 1;
+      else
+        compiled_points.arrayZ[header_pos] = (run_length - 1) | 0x80;
+    }
+    return compiled_points.resize (pos, false);
+  }
+
+  static double infer_delta (double target_val, double prev_val, double next_val, double prev_delta, double next_delta)
   {
     if (prev_val == next_val)
-      return (prev_delta == next_delta) ? prev_delta : 0.f;
+      return (prev_delta == next_delta) ? prev_delta : 0.0;
     else if (target_val <= hb_min (prev_val, next_val))
       return (prev_val < next_val) ? prev_delta : next_delta;
     else if (target_val >= hb_max (prev_val, next_val))
       return (prev_val > next_val) ? prev_delta : next_delta;
 
-    float r = (target_val - prev_val) / (next_val - prev_val);
+    double r = (target_val - prev_val) / (next_val - prev_val);
     return prev_delta + r * (next_delta - prev_delta);
   }
 
@@ -1028,6 +841,7 @@ struct tuple_delta_t
   { return (i >= end) ? start : (i + 1); }
 };
 
+template <typename OffType = HBUINT16>
 struct TupleVariationData
 {
   bool sanitize (hb_sanitize_context_t *c) const
@@ -1062,19 +876,22 @@ struct TupleVariationData
 
     private:
     /* referenced point set->compiled point data map */
-    hb_hashmap_t<const hb_vector_t<bool>*, hb_bytes_t> point_data_map;
+    hb_hashmap_t<const hb_vector_t<bool>*, hb_vector_t<unsigned char>> point_data_map;
     /* referenced point set-> count map, used in finding shared points */
     hb_hashmap_t<const hb_vector_t<bool>*, unsigned> point_set_count_map;
 
     /* empty for non-gvar tuples.
-     * shared_points_bytes is just a copy of some value in the point_data_map,
+     * shared_points_bytes is a pointer to some value in the point_data_map,
      * which will be freed during map destruction. Save it for serialization, so
      * no need to do find_shared_points () again */
-    hb_bytes_t shared_points_bytes;
+    hb_vector_t<unsigned char> *shared_points_bytes = nullptr;
 
-    /* total compiled byte size as TupleVariationData format, initialized to its
-     * min_size: 4 */
-    unsigned compiled_byte_size = 4;
+    /* total compiled byte size as TupleVariationData format, initialized to 0 */
+    unsigned compiled_byte_size = 0;
+    bool needs_padding = false;
+
+    /* for gvar iup delta optimization: whether this is a composite glyph */
+    bool is_composite = false;
 
     public:
     tuple_variations_t () = default;
@@ -1082,21 +899,18 @@ struct TupleVariationData
     tuple_variations_t& operator=(const tuple_variations_t&) = delete;
     tuple_variations_t (tuple_variations_t&&) = default;
     tuple_variations_t& operator=(tuple_variations_t&&) = default;
-    ~tuple_variations_t () { fini (); }
-    void fini ()
-    {
-      for (auto _ : point_data_map.values ())
-        _.fini ();
-
-      point_set_count_map.fini ();
-      tuple_vars.fini ();
-    }
+    ~tuple_variations_t () = default;
 
     explicit operator bool () const { return bool (tuple_vars); }
     unsigned get_var_count () const
     {
-      unsigned count = tuple_vars.length;
-      if (shared_points_bytes.length)
+      unsigned count = 0;
+      /* when iup delta opt is enabled, compiled_deltas could be empty and we
+       * should skip this tuple */
+      for (auto& tuple: tuple_vars)
+        if (tuple.compiled_deltas) count++;
+
+      if (shared_points_bytes && shared_points_bytes->length)
         count |= TupleVarCount::SharedPointNumbers;
       return count;
     }
@@ -1110,26 +924,27 @@ struct TupleVariationData
                                      bool is_gvar,
                                      const hb_map_t *axes_old_index_tag_map,
                                      const hb_vector_t<unsigned> &shared_indices,
-                                     const hb_array_t<const F2DOT14> shared_tuples)
+                                     const hb_array_t<const F2DOT14> shared_tuples,
+                                     bool is_composite_glyph)
     {
       do
       {
         const HBUINT8 *p = iterator.get_serialized_data ();
         unsigned int length = iterator.current_tuple->get_data_size ();
         if (unlikely (!iterator.var_data_bytes.check_range (p, length)))
-        { fini (); return false; }
+          return false;
 
         hb_hashmap_t<hb_tag_t, Triple> axis_tuples;
         if (!iterator.current_tuple->unpack_axis_tuples (iterator.get_axis_count (), shared_tuples, axes_old_index_tag_map, axis_tuples)
             || axis_tuples.is_empty ())
-        { fini (); return false; }
+          return false;
 
         hb_vector_t<unsigned> private_indices;
         bool has_private_points = iterator.current_tuple->has_private_points ();
         const HBUINT8 *end = p + length;
         if (has_private_points &&
-            !TupleVariationData::unpack_points (p, private_indices, end))
-        { fini (); return false; }
+            !TupleVariationData::decompile_points (p, private_indices, end))
+          return false;
 
         const hb_vector_t<unsigned> &indices = has_private_points ? private_indices : shared_indices;
         bool apply_to_all = (indices.length == 0);
@@ -1138,43 +953,46 @@ struct TupleVariationData
         hb_vector_t<int> deltas_x;
 
         if (unlikely (!deltas_x.resize (num_deltas, false) ||
-                      !TupleVariationData::unpack_deltas (p, deltas_x, end)))
-        { fini (); return false; }
+                      !TupleVariationData::decompile_deltas (p, deltas_x, end)))
+          return false;
 
         hb_vector_t<int> deltas_y;
         if (is_gvar)
         {
           if (unlikely (!deltas_y.resize (num_deltas, false) ||
-                        !TupleVariationData::unpack_deltas (p, deltas_y, end)))
-          { fini (); return false; }
+                        !TupleVariationData::decompile_deltas (p, deltas_y, end)))
+            return false;
         }
 
         tuple_delta_t var;
         var.axis_tuples = std::move (axis_tuples);
         if (unlikely (!var.indices.resize (point_count) ||
                       !var.deltas_x.resize (point_count, false)))
-        { fini (); return false; }
+          return false;
 
         if (is_gvar && unlikely (!var.deltas_y.resize (point_count, false)))
-        { fini (); return false; }
+          return false;
 
         for (unsigned i = 0; i < num_deltas; i++)
         {
           unsigned idx = apply_to_all ? i : indices[i];
           if (idx >= point_count) continue;
           var.indices[idx] = true;
-          var.deltas_x[idx] = static_cast<float> (deltas_x[i]);
+          var.deltas_x[idx] = deltas_x[i];
           if (is_gvar)
-            var.deltas_y[idx] = static_cast<float> (deltas_y[i]);
+            var.deltas_y[idx] = deltas_y[i];
         }
         tuple_vars.push (std::move (var));
       } while (iterator.move_to_next ());
+
+      is_composite = is_composite_glyph;
       return true;
     }
 
     bool create_from_item_var_data (const VarData &var_data,
                                     const hb_vector_t<hb_hashmap_t<hb_tag_t, Triple>>& regions,
                                     const hb_map_t& axes_old_index_tag_map,
+                                    unsigned& item_count,
                                     const hb_inc_bimap_t* inner_map = nullptr)
     {
       /* NULL offset, to keep original varidx valid, just return */
@@ -1184,7 +1002,8 @@ struct TupleVariationData
       unsigned num_regions = var_data.get_region_index_count ();
       if (!tuple_vars.alloc (num_regions)) return false;
 
-      unsigned item_count = inner_map ? inner_map->get_population () : var_data.get_item_count ();
+      item_count = inner_map ? inner_map->get_population () : var_data.get_item_count ();
+      if (!item_count) return true;
       unsigned row_size = var_data.get_row_size ();
       const HBUINT8 *delta_bytes = var_data.get_delta_bytes ();
 
@@ -1237,7 +1056,7 @@ struct TupleVariationData
         Triple *axis_limit;
         if (!normalized_axes_location.has (axis_tag, &axis_limit))
           return false;
-        TripleDistances axis_triple_distances{1.f, 1.f};
+        TripleDistances axis_triple_distances{1.0, 1.0};
         if (axes_triple_distances.has (axis_tag))
           axis_triple_distances = axes_triple_distances.get (axis_tag);
 
@@ -1250,7 +1069,7 @@ struct TupleVariationData
           unsigned new_len = new_vars.length + out.length;
 
           if (unlikely (!new_vars.alloc (new_len, false)))
-          { fini (); return false;}
+            return false;
 
           for (unsigned i = 0; i < out.length; i++)
             new_vars.push (std::move (out[i]));
@@ -1261,8 +1080,9 @@ struct TupleVariationData
       return true;
     }
 
-    /* merge tuple variations with overlapping tents */
-    void merge_tuple_variations ()
+    /* merge tuple variations with overlapping tents, if iup delta optimization
+     * is enabled, add default deltas to contour_points */
+    bool merge_tuple_variations (contour_point_vector_t* contour_points = nullptr)
     {
       hb_vector_t<tuple_delta_t> new_vars;
       hb_hashmap_t<const hb_hashmap_t<hb_tag_t, Triple>*, unsigned> m;
@@ -1270,7 +1090,15 @@ struct TupleVariationData
       for (const tuple_delta_t& var : tuple_vars)
       {
         /* if all axes are pinned, drop the tuple variation */
-        if (var.axis_tuples.is_empty ()) continue;
+        if (var.axis_tuples.is_empty ())
+        {
+          /* if iup_delta_optimize is enabled, add deltas to contour coords */
+          if (contour_points && !contour_points->add_deltas (var.deltas_x,
+                                                             var.deltas_y,
+                                                             var.indices))
+            return false;
+          continue;
+        }
 
         unsigned *idx;
         if (m.has (&(var.axis_tuples), &idx))
@@ -1280,98 +1108,14 @@ struct TupleVariationData
         else
         {
           new_vars.push (var);
-          m.set (&(var.axis_tuples), i);
+          if (!m.set (&(var.axis_tuples), i))
+            return false;
           i++;
         }
       }
       tuple_vars.fini ();
       tuple_vars = std::move (new_vars);
-    }
-
-    hb_bytes_t compile_point_set (const hb_vector_t<bool> &point_indices)
-    {
-      unsigned num_points = 0;
-      for (bool i : point_indices)
-        if (i) num_points++;
-
-      unsigned indices_length = point_indices.length;
-      /* If the points set consists of all points in the glyph, it's encoded with a
-       * single zero byte */
-      if (num_points == indices_length)
-      {
-        char *p = (char *) hb_calloc (1, sizeof (char));
-        if (unlikely (!p)) return hb_bytes_t ();
-
-        return hb_bytes_t (p, 1);
-      }
-
-      /* allocate enough memories: 2 bytes for count + 3 bytes for each point */
-      unsigned num_bytes = 2 + 3 *num_points;
-      char *p = (char *) hb_calloc (num_bytes, sizeof (char));
-      if (unlikely (!p)) return hb_bytes_t ();
-
-      unsigned pos = 0;
-      /* binary data starts with the total number of reference points */
-      if (num_points < 0x80)
-        p[pos++] = num_points;
-      else
-      {
-        p[pos++] = ((num_points >> 8) | 0x80);
-        p[pos++] = num_points & 0xFF;
-      }
-
-      const unsigned max_run_length = 0x7F;
-      unsigned i = 0;
-      unsigned last_value = 0;
-      unsigned num_encoded = 0;
-      while (i < indices_length && num_encoded < num_points)
-      {
-        unsigned run_length = 0;
-        unsigned header_pos = pos;
-        p[pos++] = 0;
-
-        bool use_byte_encoding = false;
-        bool new_run = true;
-        while (i < indices_length && num_encoded < num_points &&
-               run_length <= max_run_length)
-        {
-          // find out next referenced point index
-          while (i < indices_length && !point_indices[i])
-            i++;
-
-          if (i >= indices_length) break;
-
-          unsigned cur_value = i;
-          unsigned delta = cur_value - last_value;
-
-          if (new_run)
-          {
-            use_byte_encoding = (delta <= 0xFF);
-            new_run = false;
-          }
-
-          if (use_byte_encoding && delta > 0xFF)
-            break;
-
-          if (use_byte_encoding)
-            p[pos++] = delta;
-          else
-          {
-            p[pos++] = delta >> 8;
-            p[pos++] = delta & 0xFF;
-          }
-          i++;
-          last_value = cur_value;
-          run_length++;
-          num_encoded++;
-        }
-
-        if (use_byte_encoding)
-          p[header_pos] = run_length - 1;
-        else
-          p[header_pos] = (run_length - 1) | 0x80;
-      }
-      return hb_bytes_t (p, pos);
+      return true;
     }
 
     /* compile all point set and store byte data in a point_set->hb_bytes_t hashmap,
@@ -1391,11 +1135,11 @@ struct TupleVariationData
           continue;
         }
 
-        hb_bytes_t compiled_data = compile_point_set (*points_set);
-        if (unlikely (compiled_data == hb_bytes_t ()))
+        hb_vector_t<unsigned char> compiled_point_data;
+        if (!tuple_delta_t::compile_point_set (*points_set, compiled_point_data))
           return false;
 
-        if (!point_data_map.set (points_set, compiled_data) ||
+        if (!point_data_map.set (points_set, std::move (compiled_point_data)) ||
             !point_set_count_map.set (points_set, 1))
           return false;
       }
@@ -1403,31 +1147,33 @@ struct TupleVariationData
     }
 
     /* find shared points set which saves most bytes */
-    hb_bytes_t find_shared_points ()
+    void find_shared_points ()
     {
       unsigned max_saved_bytes = 0;
-      hb_bytes_t res{};
 
-      for (const auto& _ : point_data_map.iter ())
+      for (const auto& _ : point_data_map.iter_ref ())
       {
         const hb_vector_t<bool>* points_set = _.first;
         unsigned data_length = _.second.length;
+        if (!data_length) continue;
         unsigned *count;
         if (unlikely (!point_set_count_map.has (points_set, &count) ||
                       *count <= 1))
-          return hb_bytes_t ();
+        {
+          shared_points_bytes = nullptr;
+          return;
+        }
 
         unsigned saved_bytes = data_length * ((*count) -1);
         if (saved_bytes > max_saved_bytes)
         {
           max_saved_bytes = saved_bytes;
-          res = _.second;
+          shared_points_bytes = &(_.second);
         }
       }
-      return res;
     }
 
-    bool calc_inferred_deltas (contour_point_vector_t& contour_points)
+    bool calc_inferred_deltas (const contour_point_vector_t& contour_points)
     {
       for (tuple_delta_t& var : tuple_vars)
         if (!var.calc_inferred_deltas (contour_points))
@@ -1436,10 +1182,21 @@ struct TupleVariationData
       return true;
     }
 
+    bool iup_optimize (const contour_point_vector_t& contour_points)
+    {
+      for (tuple_delta_t& var : tuple_vars)
+      {
+        if (!var.optimize (contour_points, is_composite))
+          return false;
+      }
+      return true;
+    }
+
     public:
     bool instantiate (const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location,
                       const hb_hashmap_t<hb_tag_t, TripleDistances>& axes_triple_distances,
-                      contour_point_vector_t* contour_points = nullptr)
+                      contour_point_vector_t* contour_points = nullptr,
+                      bool optimize = false)
     {
       if (!tuple_vars) return true;
       if (!change_tuple_variations_axis_limits (normalized_axes_location, axes_triple_distances))
@@ -1449,41 +1206,70 @@ struct TupleVariationData
         if (!calc_inferred_deltas (*contour_points))
           return false;
 
-      merge_tuple_variations ();
+      /* if iup delta opt is on, contour_points can't be null */
+      if (optimize && !contour_points)
+        return false;
+
+      if (!merge_tuple_variations (optimize ? contour_points : nullptr))
+        return false;
+
+      if (optimize && !iup_optimize (*contour_points)) return false;
       return !tuple_vars.in_error ();
     }
 
     bool compile_bytes (const hb_map_t& axes_index_map,
                         const hb_map_t& axes_old_index_tag_map,
                         bool use_shared_points,
+                        bool is_gvar = false,
                         const hb_hashmap_t<const hb_vector_t<char>*, unsigned>* shared_tuples_idx_map = nullptr)
     {
+      // return true for empty glyph
+      if (!tuple_vars)
+        return true;
+
       // compile points set and store data in hashmap
       if (!compile_all_point_sets ())
         return false;
 
+      /* total compiled byte size as TupleVariationData format, initialized to its
+       * min_size: 4 */
+      compiled_byte_size += 4;
+
       if (use_shared_points)
       {
-        shared_points_bytes = find_shared_points ();
-        compiled_byte_size += shared_points_bytes.length;
+        find_shared_points ();
+        if (shared_points_bytes)
+          compiled_byte_size += shared_points_bytes->length;
       }
       // compile delta and tuple var header for each tuple variation
       for (auto& tuple: tuple_vars)
       {
         const hb_vector_t<bool>* points_set = &(tuple.indices);
-        hb_bytes_t *points_data;
+        hb_vector_t<unsigned char> *points_data;
         if (unlikely (!point_data_map.has (points_set, &points_data)))
           return false;
 
+        /* when iup optimization is enabled, num of referenced points could be 0
+         * and thus the compiled points bytes is empty, we should skip compiling
+         * this tuple */
+        if (!points_data->length)
+          continue;
         if (!tuple.compile_deltas ())
           return false;
 
-        unsigned points_data_length = (*points_data != shared_points_bytes) ? points_data->length : 0;
+        unsigned points_data_length = (points_data != shared_points_bytes) ? points_data->length : 0;
         if (!tuple.compile_tuple_var_header (axes_index_map, points_data_length, axes_old_index_tag_map,
                                              shared_tuples_idx_map))
           return false;
         compiled_byte_size += tuple.compiled_tuple_header.length + points_data_length + tuple.compiled_deltas.length;
       }
+
+      if (is_gvar && (compiled_byte_size % 2))
+      {
+        needs_padding = true;
+        compiled_byte_size += 1;
+      }
+
       return true;
     }
 
@@ -1502,25 +1288,31 @@ struct TupleVariationData
     bool serialize_var_data (hb_serialize_context_t *c, bool is_gvar) const
     {
       TRACE_SERIALIZE (this);
-      if (is_gvar)
-        shared_points_bytes.copy (c);
+      if (is_gvar && shared_points_bytes)
+      {
+        hb_ubytes_t s (shared_points_bytes->arrayZ, shared_points_bytes->length);
+        s.copy (c);
+      }
 
       for (const auto& tuple: tuple_vars)
       {
         const hb_vector_t<bool>* points_set = &(tuple.indices);
-        hb_bytes_t *point_data;
+        hb_vector_t<unsigned char> *point_data;
         if (!point_data_map.has (points_set, &point_data))
           return_trace (false);
 
-        if (!is_gvar || *point_data != shared_points_bytes)
-          point_data->copy (c);
+        if (!is_gvar || point_data != shared_points_bytes)
+        {
+          hb_ubytes_t s (point_data->arrayZ, point_data->length);
+          s.copy (c);
+        }
 
         tuple.compiled_deltas.as_array ().copy (c);
         if (c->in_error ()) return_trace (false);
       }
 
       /* padding for gvar */
-      if (is_gvar && (compiled_byte_size % 2))
+      if (is_gvar && needs_padding)
       {
         HBUINT8 pad;
         pad = 0;
@@ -1551,7 +1343,7 @@ struct TupleVariationData
       {
         const HBUINT8 *base = &(table_base+var_data->data);
         const HBUINT8 *p = base;
-        if (!unpack_points (p, shared_indices, (const HBUINT8 *) (var_data_bytes.arrayZ + var_data_bytes.length))) return false;
+        if (!decompile_points (p, shared_indices, (const HBUINT8 *) (var_data_bytes.arrayZ + var_data_bytes.length))) return false;
         data_offset = p - base;
       }
       return true;
@@ -1601,9 +1393,9 @@ struct TupleVariationData
 
   bool has_shared_point_numbers () const { return tupleVarCount.has_shared_point_numbers (); }
 
-  static bool unpack_points (const HBUINT8 *&p /* IN/OUT */,
-                             hb_vector_t<unsigned int> &points /* OUT */,
-                             const HBUINT8 *end)
+  static bool decompile_points (const HBUINT8 *&p /* IN/OUT */,
+                                hb_vector_t<unsigned int> &points /* OUT */,
+                                const HBUINT8 *end)
   {
     enum packed_point_flag_t
     {
@@ -1653,43 +1445,13 @@ struct TupleVariationData
     return true;
   }
 
-  static bool unpack_deltas (const HBUINT8 *&p /* IN/OUT */,
-                             hb_vector_t<int> &deltas /* IN/OUT */,
-                             const HBUINT8 *end)
+  template <typename T>
+  static bool decompile_deltas (const HBUINT8 *&p /* IN/OUT */,
+                                hb_vector_t<T> &deltas /* IN/OUT */,
+                                const HBUINT8 *end,
+                                bool consume_all = false)
   {
-    unsigned i = 0;
-    unsigned count = deltas.length;
-    while (i < count)
-    {
-      if (unlikely (p + 1 > end)) return false;
-      unsigned control = *p++;
-      unsigned run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
-      unsigned stop = i + run_count;
-      if (unlikely (stop > count)) return false;
-      if (control & DELTAS_ARE_ZERO)
-      {
-        for (; i < stop; i++)
-          deltas.arrayZ[i] = 0;
-      }
-      else if (control & DELTAS_ARE_WORDS)
-      {
-        if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
-        for (; i < stop; i++)
-        {
-          deltas.arrayZ[i] = * (const HBINT16 *) p;
-          p += HBUINT16::static_size;
-        }
-      }
-      else
-      {
-        if (unlikely (p + run_count > end)) return false;
-        for (; i < stop; i++)
-        {
-          deltas.arrayZ[i] = * (const HBINT8 *) p++;
-        }
-      }
-    }
-    return true;
+    return TupleValues::decompile (p, deltas, end, consume_all);
   }
 
   bool has_data () const { return tupleVarCount; }
@@ -1700,13 +1462,15 @@ struct TupleVariationData
                                    const hb_map_t *axes_old_index_tag_map,
                                    const hb_vector_t<unsigned> &shared_indices,
                                    const hb_array_t<const F2DOT14> shared_tuples,
-                                   tuple_variations_t& tuple_variations /* OUT */) const
+                                   tuple_variations_t& tuple_variations, /* OUT */
+                                   bool is_composite_glyph = false) const
   {
     return tuple_variations.create_from_tuple_var_data (iterator, tupleVarCount,
                                                         point_count, is_gvar,
                                                         axes_old_index_tag_map,
                                                         shared_indices,
-                                                        shared_tuples);
+                                                        shared_tuples,
+                                                        is_composite_glyph);
   }
 
   bool serialize (hb_serialize_context_t *c,
@@ -1758,15 +1522,16 @@ struct TupleVariationData
                                  * low 12 bits are the number of tuple variation tables
                                  * for this glyph. The number of tuple variation tables
                                  * can be any number between 1 and 4095. */
-  Offset16To<HBUINT8>
+  OffsetTo<HBUINT8, OffType>
                 data;           /* Offset from the start of the base table
                                  * to the serialized data. */
   /* TupleVariationHeader tupleVariationHeaders[] *//* Array of tuple variation headers. */
   public:
-  DEFINE_SIZE_MIN (4);
+  DEFINE_SIZE_MIN (2 + OffType::static_size);
 };
 
-using tuple_variations_t = TupleVariationData::tuple_variations_t;
+// TODO: Move tuple_variations_t to outside of TupleVariationData
+using tuple_variations_t = TupleVariationData<HBUINT16>::tuple_variations_t;
 struct item_variations_t
 {
   using region_t = const hb_hashmap_t<hb_tag_t, Triple>*;
@@ -1775,6 +1540,14 @@ struct item_variations_t
    * have the same num of deltas (rows) */
   hb_vector_t<tuple_variations_t> vars;
 
+  /* num of retained rows for each subtable, there're 2 cases when var_data is empty:
+   * 1. retained item_count is zero
+   * 2. regions is empty and item_count is non-zero.
+   * when converting to tuples, both will be dropped because the tuple is empty,
+   * however, we need to retain 2. as all-zero rows to keep original varidx
+   * valid, so we need a way to remember the num of rows for each subtable */
+  hb_vector_t<unsigned> var_data_num_rows;
+
   /* original region list, decompiled from item varstore, used when rebuilding
    * region list after instantiation */
   hb_vector_t<hb_hashmap_t<hb_tag_t, Triple>> orig_region_list;
@@ -1812,7 +1585,7 @@ struct item_variations_t
   const hb_map_t& get_varidx_map () const
   { return varidx_map; }
 
-  bool instantiate (const VariationStore& varStore,
+  bool instantiate (const ItemVariationStore& varStore,
                     const hb_subset_plan_t *plan,
                     bool optimize=true,
                     bool use_no_variation_idx=true,
@@ -1826,7 +1599,7 @@ struct item_variations_t
   }
 
   /* keep below APIs public only for unit test: test-item-varstore */
-  bool create_from_item_varstore (const VariationStore& varStore,
+  bool create_from_item_varstore (const ItemVariationStore& varStore,
                                   const hb_map_t& axes_old_index_tag_map,
                                   const hb_array_t <const hb_inc_bimap_t> inner_maps = hb_array_t<const hb_inc_bimap_t> ())
   {
@@ -1836,22 +1609,26 @@ struct item_variations_t
 
     unsigned num_var_data = varStore.get_sub_table_count ();
     if (inner_maps && inner_maps.length != num_var_data) return false;
-    if (!vars.alloc (num_var_data)) return false;
+    if (!vars.alloc (num_var_data) ||
+        !var_data_num_rows.alloc (num_var_data)) return false;
 
     for (unsigned i = 0; i < num_var_data; i++)
     {
       if (inner_maps && !inner_maps.arrayZ[i].get_population ())
           continue;
       tuple_variations_t var_data_tuples;
+      unsigned item_count = 0;
       if (!var_data_tuples.create_from_item_var_data (varStore.get_sub_table (i),
                                                       orig_region_list,
                                                       axes_old_index_tag_map,
+                                                      item_count,
                                                       inner_maps ? &(inner_maps.arrayZ[i]) : nullptr))
         return false;
 
+      var_data_num_rows.push (item_count);
       vars.push (std::move (var_data_tuples));
     }
-    return !vars.in_error ();
+    return !vars.in_error () && !var_data_num_rows.in_error () && vars.length == var_data_num_rows.length;
   }
 
   bool instantiate_tuple_vars (const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location,
@@ -1904,7 +1681,9 @@ struct item_variations_t
       }
     }
 
-    if (!all_regions || !all_unique_regions) return false;
+    /* regions are empty means no variation data, return true */
+    if (!all_regions || !all_unique_regions) return true;
+
     if (!region_list.alloc (all_regions.get_population ()))
       return false;
 
@@ -1969,16 +1748,13 @@ struct item_variations_t
 
   bool as_item_varstore (bool optimize=true, bool use_no_variation_idx=true)
   {
-    if (!region_list) return false;
+    /* return true if no variation data */
+    if (!region_list) return true;
     unsigned num_cols = region_list.length;
     /* pre-alloc a 2D vector for all sub_table's VarData rows */
     unsigned total_rows = 0;
-    for (unsigned major = 0; major < vars.length; major++)
-    {
-      const tuple_variations_t& tuples = vars[major];
-      /* all tuples in each sub_table should have same num of deltas(num rows) */
-      total_rows += tuples.tuple_vars[0].deltas_x.length;
-    }
+    for (unsigned major = 0; major < var_data_num_rows.length; major++)
+      total_rows += var_data_num_rows[major];
 
     if (!delta_rows.resize (total_rows)) return false;
     /* init all rows to [0]*num_cols */
@@ -1998,7 +1774,7 @@ struct item_variations_t
       /* deltas are stored in tuples(column based), convert them back into items
        * (row based) delta */
       const tuple_variations_t& tuples = vars[major];
-      unsigned num_rows = tuples.tuple_vars[0].deltas_x.length;
+      unsigned num_rows = var_data_num_rows[major];
       for (const tuple_delta_t& tuple: tuples.tuple_vars)
       {
         if (tuple.deltas_x.length != num_rows)
@@ -2223,6 +1999,7 @@ struct item_variations_t
   }
 };
 
+
 } /* namespace OT */
 
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-cvar-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-cvar-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-cvar-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-cvar-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -45,11 +45,12 @@ struct cvar
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  version.sanitize (c) && likely (version.major == 1) &&
+                  hb_barrier () &&
+                  likely (version.major == 1) &&
                   tupleVariationData.sanitize (c));
   }
 
-  const TupleVariationData* get_tuple_var_data (void) const
+  const TupleVariationData<>* get_tuple_var_data (void) const
   { return &tupleVariationData; }
 
   bool decompile_tuple_variations (unsigned axis_count,
@@ -57,12 +58,12 @@ struct cvar
                                    hb_blob_t *blob,
                                    bool is_gvar,
                                    const hb_map_t *axes_old_index_tag_map,
-                                   TupleVariationData::tuple_variations_t& tuple_variations /* OUT */) const
+                                   TupleVariationData<>::tuple_variations_t& tuple_variations /* OUT */) const
   {
     hb_vector_t<unsigned> shared_indices;
-    TupleVariationData::tuple_iterator_t iterator;
+    TupleVariationData<>::tuple_iterator_t iterator;
     hb_bytes_t var_data_bytes = blob->as_bytes ().sub_array (4);
-    if (!TupleVariationData::get_tuple_iterator (var_data_bytes, axis_count, this,
+    if (!TupleVariationData<>::get_tuple_iterator (var_data_bytes, axis_count, this,
                                                  shared_indices, &iterator))
       return false;
 
@@ -76,16 +77,16 @@ struct cvar
   static bool calculate_cvt_deltas (unsigned axis_count,
                                     hb_array_t<int> coords,
                                     unsigned num_cvt_item,
-                                    const TupleVariationData *tuple_var_data,
+                                    const TupleVariationData<> *tuple_var_data,
                                     const void *base,
                                     hb_vector_t<float>& cvt_deltas /* OUT */)
   {
     if (!coords) return true;
     hb_vector_t<unsigned> shared_indices;
-    TupleVariationData::tuple_iterator_t iterator;
+    TupleVariationData<>::tuple_iterator_t iterator;
     unsigned var_data_length = tuple_var_data->get_size (axis_count);
     hb_bytes_t var_data_bytes = hb_bytes_t (reinterpret_cast<const char*> (tuple_var_data), var_data_length);
-    if (!TupleVariationData::get_tuple_iterator (var_data_bytes, axis_count, base,
+    if (!TupleVariationData<>::get_tuple_iterator (var_data_bytes, axis_count, base,
                                                  shared_indices, &iterator))
       return true; /* isn't applied at all */
 
@@ -106,14 +107,14 @@ struct cvar
 
       bool has_private_points = iterator.current_tuple->has_private_points ();
       if (has_private_points &&
-          !TupleVariationData::unpack_points (p, private_indices, end))
+          !TupleVariationData<>::decompile_points (p, private_indices, end))
         return false;
       const hb_vector_t<unsigned int> &indices = has_private_points ? private_indices : shared_indices;
 
       bool apply_to_all = (indices.length == 0);
       unsigned num_deltas = apply_to_all ? num_cvt_item : indices.length;
       if (unlikely (!unpacked_deltas.resize (num_deltas, false))) return false;
-      if (unlikely (!TupleVariationData::unpack_deltas (p, unpacked_deltas, end))) return false;
+      if (unlikely (!TupleVariationData<>::decompile_deltas (p, unpacked_deltas, end))) return false;
 
       for (unsigned int i = 0; i < num_deltas; i++)
       {
@@ -128,7 +129,7 @@ struct cvar
   }
 
   bool serialize (hb_serialize_context_t *c,
-                  TupleVariationData::tuple_variations_t& tuple_variations) const
+                  TupleVariationData<>::tuple_variations_t& tuple_variations) const
   {
     TRACE_SERIALIZE (this);
     if (!tuple_variations) return_trace (false);
@@ -143,7 +144,7 @@ struct cvar
     if (c->plan->all_axes_pinned)
       return_trace (false);
 
-    OT::TupleVariationData::tuple_variations_t tuple_variations;
+    OT::TupleVariationData<>::tuple_variations_t tuple_variations;
     unsigned axis_count = c->plan->axes_old_index_tag_map.get_population ();
 
     const hb_tag_t cvt = HB_TAG('c','v','t',' ');
@@ -168,7 +169,7 @@ struct cvar
   }
 
   static bool add_cvt_and_apply_deltas (hb_subset_plan_t *plan,
-                                        const TupleVariationData *tuple_var_data,
+                                        const TupleVariationData<> *tuple_var_data,
                                         const void *base)
   {
     const hb_tag_t cvt = HB_TAG('c','v','t',' ');
@@ -208,7 +209,7 @@ struct cvar
   protected:
   FixedVersion<>version;                /* Version of the CVT variation table
                                          * initially set to 0x00010000u */
-  TupleVariationData tupleVariationData; /* TupleVariationDate for cvar table */
+  TupleVariationData<> tupleVariationData; /* TupleVariationDate for cvar table */
   public:
   DEFINE_SIZE_MIN (8);
 };
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-fvar-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-fvar-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-fvar-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-fvar-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -43,7 +43,7 @@ static bool axis_coord_pinned_or_within_
                                                     unsigned axis_index,
                                                     Triple axis_limit)
 {
-  float axis_coord = coords[axis_index].to_float ();
+  double axis_coord = static_cast<double>(coords[axis_index].to_float ());
   if (axis_limit.is_point ())
   {
     if (axis_limit.minimum != axis_coord)
@@ -131,6 +131,7 @@ struct InstanceRecord
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   c->check_array (coordinatesZ.arrayZ, axis_count));
   }
 
@@ -232,7 +233,10 @@ struct AxisRecord
   {
     float min, default_, max;
     get_coordinates (min, default_, max);
-    return TripleDistances (min, default_, max);
+    return TripleDistances (
+      static_cast<double>(min),
+      static_cast<double>(default_),
+      static_cast<double>(max));
   }
 
   bool subset (hb_subset_context_t *c) const
@@ -277,8 +281,10 @@ struct fvar
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
+                  hb_barrier () &&
                   likely (version.major == 1) &&
                   c->check_struct (this) &&
+                  hb_barrier () &&
                   axisSize == 20 && /* Assumed in our code. */
                   instanceSize >= axisCount * 4 + 4 &&
                   get_axes ().sanitize (c) &&
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -28,6 +28,7 @@
 #ifndef HB_OT_VAR_GVAR_TABLE_HH
 #define HB_OT_VAR_GVAR_TABLE_HH
 
+#include "hb-decycler.hh"
 #include "hb-open-type.hh"
 #include "hb-ot-var-common.hh"
 
@@ -36,15 +37,37 @@
  * https://docs.microsoft.com/en-us/typography/opentype/spec/gvar
  */
 #define HB_OT_TAG_gvar HB_TAG('g','v','a','r')
+#define HB_OT_TAG_GVAR HB_TAG('G','V','A','R')
 
-namespace OT {
+struct hb_glyf_scratch_t
+{
+  // glyf
+  contour_point_vector_t all_points;
+  contour_point_vector_t comp_points;
+  hb_decycler_t decycler;
+
+  // gvar
+  contour_point_vector_t orig_points;
+  hb_vector_t<int> x_deltas;
+  hb_vector_t<int> y_deltas;
+  contour_point_vector_t deltas;
+  hb_vector_t<unsigned int> shared_indices;
+  hb_vector_t<unsigned int> private_indices;
+
+  // VARC
+  hb_vector_t<unsigned> axisIndices;
+  hb_vector_t<float> axisValues;
+};
 
-struct GlyphVariationData : TupleVariationData
-{};
+namespace OT {
 
+template <typename OffsetType>
 struct glyph_variations_t
 {
-  using tuple_variations_t = TupleVariationData::tuple_variations_t;
+  // TODO: Move tuple_variations_t to outside of TupleVariationData
+  using tuple_variations_t = typename TupleVariationData<OffsetType>::tuple_variations_t;
+  using GlyphVariationData = TupleVariationData<OffsetType>;
+
   hb_vector_t<tuple_variations_t> glyph_variations;
 
   hb_vector_t<char> compiled_shared_tuples;
@@ -72,7 +95,7 @@ struct glyph_variations_t
                                     const hb_subset_plan_t *plan,
                                     const hb_hashmap_t<hb_codepoint_t, hb_bytes_t>& new_gid_var_data_map)
   {
-    if (unlikely (!glyph_variations.alloc (plan->new_to_old_gid_list.length, true)))
+    if (unlikely (!glyph_variations.alloc_exact (plan->new_to_old_gid_list.length)))
       return false;
 
     auto it = hb_iter (plan->new_to_old_gid_list);
@@ -86,10 +109,11 @@ struct glyph_variations_t
       hb_bytes_t var_data = new_gid_var_data_map.get (new_gid);
 
       const GlyphVariationData* p = reinterpret_cast<const GlyphVariationData*> (var_data.arrayZ);
-      hb_vector_t<unsigned> shared_indices;
-      GlyphVariationData::tuple_iterator_t iterator;
+      typename GlyphVariationData::tuple_iterator_t iterator;
       tuple_variations_t tuple_vars;
 
+      hb_vector_t<unsigned> shared_indices;
+
       /* in case variation data is empty, push an empty struct into the vector,
        * keep the vector in sync with the new_to_old_gid_list */
       if (!var_data || ! p->has_data () || !all_contour_points->length ||
@@ -101,10 +125,14 @@ struct glyph_variations_t
         continue;
       }
 
+      bool is_composite_glyph = false;
+      is_composite_glyph = plan->composite_new_gids.has (new_gid);
+
       if (!p->decompile_tuple_variations (all_contour_points->length, true /* is_gvar */,
                                           iterator, &(plan->axes_old_index_tag_map),
                                           shared_indices, shared_tuples,
-                                          tuple_vars /* OUT */))
+                                          tuple_vars, /* OUT */
+                                          is_composite_glyph))
         return false;
       glyph_variations.push (std::move (tuple_vars));
     }
@@ -114,13 +142,15 @@ struct glyph_variations_t
   bool instantiate (const hb_subset_plan_t *plan)
   {
     unsigned count = plan->new_to_old_gid_list.length;
+    bool iup_optimize = false;
+    iup_optimize = plan->flags & HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS;
     for (unsigned i = 0; i < count; i++)
     {
       hb_codepoint_t new_gid = plan->new_to_old_gid_list[i].first;
       contour_point_vector_t *all_points;
       if (!plan->new_gid_contour_points_map.has (new_gid, &all_points))
         return false;
-      if (!glyph_variations[i].instantiate (plan->axes_location, plan->axes_triple_distances, all_points))
+      if (!glyph_variations[i].instantiate (plan->axes_location, plan->axes_triple_distances, all_points, iup_optimize))
         return false;
     }
     return true;
@@ -134,6 +164,7 @@ struct glyph_variations_t
     for (tuple_variations_t& vars: glyph_variations)
       if (!vars.compile_bytes (axes_index_map, axes_old_index_tag_map,
                                true, /* use shared points*/
+                               true,
                                &shared_tuples_idx_map))
         return false;
 
@@ -252,7 +283,7 @@ struct glyph_variations_t
     hb_codepoint_t last_gid = 0;
     unsigned idx = 0;
 
-    TupleVariationData* cur_glyph = c->start_embed<TupleVariationData> ();
+    GlyphVariationData* cur_glyph = c->start_embed<GlyphVariationData> ();
     if (!cur_glyph) return_trace (false);
     for (auto &_ : it)
     {
@@ -266,7 +297,7 @@ struct glyph_variations_t
 
       if (idx >= glyph_variations.length) return_trace (false);
       if (!cur_glyph->serialize (c, true, glyph_variations[idx])) return_trace (false);
-      TupleVariationData* next_glyph = c->start_embed<TupleVariationData> ();
+      GlyphVariationData* next_glyph = c->start_embed<GlyphVariationData> ();
       glyph_offset += (char *) next_glyph - (char *) cur_glyph;
 
       if (long_offset)
@@ -289,14 +320,21 @@ struct glyph_variations_t
   }
 };
 
-struct gvar
+template <typename GidOffsetType, unsigned TableTag>
+struct gvar_GVAR
 {
-  static constexpr hb_tag_t tableTag = HB_OT_TAG_gvar;
+  static constexpr hb_tag_t tableTag = TableTag;
+
+  using GlyphVariationData = TupleVariationData<GidOffsetType>;
+
+  bool has_data () const { return version.to_int () != 0; }
 
   bool sanitize_shallow (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && (version.major == 1) &&
+    return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
+                  (version.major == 1) &&
                   sharedTuples.sanitize (c, this, axisCount * sharedTupleCount) &&
                   (is_long_offset () ?
                      c->check_array (get_long_offset_array (), c->get_num_glyphs () + 1) :
@@ -308,7 +346,7 @@ struct gvar
   { return sanitize_shallow (c); }
 
   bool decompile_glyph_variations (hb_subset_context_t *c,
-                                   glyph_variations_t& glyph_vars /* OUT */) const
+                                   glyph_variations_t<GidOffsetType>& glyph_vars /* OUT */) const
   {
     hb_hashmap_t<hb_codepoint_t, hb_bytes_t> new_gid_var_data_map;
     auto it = hb_iter (c->plan->new_to_old_gid_list);
@@ -335,13 +373,14 @@ struct gvar
   template<typename Iterator,
            hb_requires (hb_is_iterator (Iterator))>
   bool serialize (hb_serialize_context_t *c,
-                  const glyph_variations_t& glyph_vars,
+                  const glyph_variations_t<GidOffsetType>& glyph_vars,
                   Iterator it,
                   unsigned axis_count,
-                  unsigned num_glyphs) const
+                  unsigned num_glyphs,
+                  bool force_long_offsets) const
   {
     TRACE_SERIALIZE (this);
-    gvar *out = c->allocate_min<gvar> ();
+    gvar_GVAR *out = c->allocate_min<gvar_GVAR> ();
     if (unlikely (!out)) return_trace (false);
 
     out->version.major = 1;
@@ -350,7 +389,10 @@ struct gvar
     out->glyphCountX = hb_min (0xFFFFu, num_glyphs);
 
     unsigned glyph_var_data_size = glyph_vars.compiled_byte_size ();
-    bool long_offset = glyph_var_data_size & ~0xFFFFu;
+    /* According to the spec: If the short format (Offset16) is used for offsets,
+     * the value stored is the offset divided by 2, so the maximum data size should
+     * be 2 * 0xFFFFu, which is 0x1FFFEu */
+    bool long_offset = glyph_var_data_size > 0x1FFFEu || force_long_offsets;
     out->flags = long_offset ? 1 : 0;
 
     HBUINT8 *glyph_var_data_offsets = c->allocate_size<HBUINT8> ((long_offset ? 4 : 2) * (num_glyphs + 1), false);
@@ -380,7 +422,7 @@ struct gvar
   bool instantiate (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    glyph_variations_t glyph_vars;
+    glyph_variations_t<GidOffsetType> glyph_vars;
     if (!decompile_glyph_variations (c, glyph_vars))
       return_trace (false);
 
@@ -391,7 +433,12 @@ struct gvar
     unsigned axis_count = c->plan->axes_index_map.get_population ();
     unsigned num_glyphs = c->plan->num_output_glyphs ();
     auto it = hb_iter (c->plan->new_to_old_gid_list);
-    return_trace (serialize (c->serializer, glyph_vars, it, axis_count, num_glyphs));
+
+    bool force_long_offsets = false;
+#ifdef HB_EXPERIMENTAL_API
+    force_long_offsets = c->plan->flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS;
+#endif
+    return_trace (serialize (c->serializer, glyph_vars, it, axis_count, num_glyphs, force_long_offsets));
   }
 
   bool subset (hb_subset_context_t *c) const
@@ -405,7 +452,7 @@ struct gvar
 
     unsigned glyph_count = version.to_int () ? c->plan->source->get_num_glyphs () : 0;
 
-    gvar *out = c->serializer->allocate_min<gvar> ();
+    gvar_GVAR *out = c->serializer->allocate_min<gvar_GVAR> ();
     if (unlikely (!out)) return_trace (false);
 
     out->version.major = 1;
@@ -426,7 +473,13 @@ struct gvar
       subset_data_size += get_glyph_var_data_bytes (c->source_blob, glyph_count, old_gid).length;
     }
 
-    bool long_offset = subset_data_size & ~0xFFFFu;
+    /* According to the spec: If the short format (Offset16) is used for offsets,
+     * the value stored is the offset divided by 2, so the maximum data size should
+     * be 2 * 0xFFFFu, which is 0x1FFFEu */
+    bool long_offset = subset_data_size > 0x1FFFEu;
+#ifdef HB_EXPERIMENTAL_API
+    long_offset = long_offset || (c->plan->flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS);
+#endif
     out->flags = long_offset ? 1 : 0;
 
     HBUINT8 *subset_offsets = c->serializer->allocate_size<HBUINT8> ((long_offset ? 4 : 2) * (num_glyphs + 1), false);
@@ -444,6 +497,8 @@ struct gvar
       hb_memcpy (tuples, this+sharedTuples, shared_tuple_size);
     }
 
+    /* This ordering relative to the shared tuples array, which puts the glyphVariationData
+       last in the table, is required when HB_SUBSET_FLAGS_IFTB_REQUIREMENTS is set */
     char *subset_data = c->serializer->allocate_size<char> (subset_data_size, false);
     if (!subset_data) return_trace (false);
     out->dataZ = subset_data - (char *) out;
@@ -521,7 +576,7 @@ struct gvar
   unsigned get_offset (unsigned glyph_count, unsigned i) const
   {
     if (unlikely (i > glyph_count)) return 0;
-    _hb_compiler_memory_r_barrier ();
+    hb_barrier ();
     return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2;
   }
 
@@ -531,9 +586,11 @@ struct gvar
   public:
   struct accelerator_t
   {
+    bool has_data () const { return table->has_data (); }
+
     accelerator_t (hb_face_t *face)
     {
-      table = hb_sanitize_context_t ().reference_table<gvar> (face);
+      table = hb_sanitize_context_t ().reference_table<gvar_GVAR> (face);
       /* If sanitize failed, set glyphCount to 0. */
       glyphCount = table->version.to_int () ? face->get_num_glyphs () : 0;
 
@@ -599,37 +656,42 @@ struct gvar
 
     public:
     bool apply_deltas_to_points (hb_codepoint_t glyph,
-                                 hb_array_t<int> coords,
+                                 hb_array_t<const int> coords,
                                  const hb_array_t<contour_point_t> points,
+                                 hb_glyf_scratch_t &scratch,
                                  bool phantom_only = false) const
     {
       if (unlikely (glyph >= glyphCount)) return true;
 
       hb_bytes_t var_data_bytes = table->get_glyph_var_data_bytes (table.get_blob (), glyphCount, glyph);
       if (!var_data_bytes.as<GlyphVariationData> ()->has_data ()) return true;
-      hb_vector_t<unsigned int> shared_indices;
-      GlyphVariationData::tuple_iterator_t iterator;
+
+      auto &shared_indices = scratch.shared_indices;
+      shared_indices.clear ();
+
+      typename GlyphVariationData::tuple_iterator_t iterator;
       if (!GlyphVariationData::get_tuple_iterator (var_data_bytes, table->axisCount,
                                                    var_data_bytes.arrayZ,
                                                    shared_indices, &iterator))
         return true; /* so isn't applied at all */
 
       /* Save original points for inferred delta calculation */
-      contour_point_vector_t orig_points_vec; // Populated lazily
+      auto &orig_points_vec = scratch.orig_points;
+      orig_points_vec.clear (); // Populated lazily
       auto orig_points = orig_points_vec.as_array ();
 
       /* flag is used to indicate referenced point */
-      contour_point_vector_t deltas_vec; // Populated lazily
+      auto &deltas_vec = scratch.deltas;
+      deltas_vec.clear (); // Populated lazily
       auto deltas = deltas_vec.as_array ();
 
-      hb_vector_t<unsigned> end_points; // Populated lazily
-
       unsigned num_coords = table->axisCount;
       hb_array_t<const F2DOT14> shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * num_coords);
 
-      hb_vector_t<unsigned int> private_indices;
-      hb_vector_t<int> x_deltas;
-      hb_vector_t<int> y_deltas;
+      auto &private_indices = scratch.private_indices;
+      auto &x_deltas = scratch.x_deltas;
+      auto &y_deltas = scratch.y_deltas;
+
       unsigned count = points.length;
       bool flush = false;
       do
@@ -654,16 +716,16 @@ struct gvar
 
         bool has_private_points = iterator.current_tuple->has_private_points ();
         if (has_private_points &&
-            !GlyphVariationData::unpack_points (p, private_indices, end))
+            !GlyphVariationData::decompile_points (p, private_indices, end))
           return false;
         const hb_array_t<unsigned int> &indices = has_private_points ? private_indices : shared_indices;
 
         bool apply_to_all = (indices.length == 0);
         unsigned int num_deltas = apply_to_all ? points.length : indices.length;
         if (unlikely (!x_deltas.resize (num_deltas, false))) return false;
-        if (unlikely (!GlyphVariationData::unpack_deltas (p, x_deltas, end))) return false;
+        if (unlikely (!GlyphVariationData::decompile_deltas (p, x_deltas, end))) return false;
         if (unlikely (!y_deltas.resize (num_deltas, false))) return false;
-        if (unlikely (!GlyphVariationData::unpack_deltas (p, y_deltas, end))) return false;
+        if (unlikely (!GlyphVariationData::decompile_deltas (p, y_deltas, end))) return false;
 
         if (!apply_to_all)
         {
@@ -700,8 +762,8 @@ struct gvar
             if (phantom_only && pt_index < count - 4) continue;
             auto &delta = deltas.arrayZ[pt_index];
             delta.flag = 1;     /* this point is referenced, i.e., explicit deltas specified */
-            delta.x += x_deltas.arrayZ[i] * scalar;
-            delta.y += y_deltas.arrayZ[i] * scalar;
+            delta.add_delta (x_deltas.arrayZ[i] * scalar,
+                             y_deltas.arrayZ[i] * scalar);
           }
         }
         else
@@ -712,10 +774,9 @@ struct gvar
             if (apply_to_all)
               for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++)
               {
-                unsigned int pt_index = i;
-                auto &delta = deltas.arrayZ[pt_index];
-                delta.x += x_deltas.arrayZ[i] * scalar;
-                delta.y += y_deltas.arrayZ[i] * scalar;
+                auto &delta = deltas.arrayZ[i];
+                delta.add_delta (x_deltas.arrayZ[i] * scalar,
+                                 y_deltas.arrayZ[i] * scalar);
               }
             else
               for (unsigned int i = 0; i < num_deltas; i++)
@@ -725,8 +786,8 @@ struct gvar
                 if (phantom_only && pt_index < count - 4) continue;
                 auto &delta = deltas.arrayZ[pt_index];
                 delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */
-                delta.x += x_deltas.arrayZ[i] * scalar;
-                delta.y += y_deltas.arrayZ[i] * scalar;
+                delta.add_delta (x_deltas.arrayZ[i] * scalar,
+                                 y_deltas.arrayZ[i] * scalar);
               }
           }
           else
@@ -734,10 +795,9 @@ struct gvar
             if (apply_to_all)
               for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++)
               {
-                unsigned int pt_index = i;
-                auto &delta = deltas.arrayZ[pt_index];
-                delta.x += x_deltas.arrayZ[i];
-                delta.y += y_deltas.arrayZ[i];
+                auto &delta = deltas.arrayZ[i];
+                delta.add_delta (x_deltas.arrayZ[i],
+                                 y_deltas.arrayZ[i]);
               }
             else
               for (unsigned int i = 0; i < num_deltas; i++)
@@ -747,8 +807,8 @@ struct gvar
                 if (phantom_only && pt_index < count - 4) continue;
                 auto &delta = deltas.arrayZ[pt_index];
                 delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */
-                delta.x += x_deltas.arrayZ[i];
-                delta.y += y_deltas.arrayZ[i];
+                delta.add_delta (x_deltas.arrayZ[i],
+                                 y_deltas.arrayZ[i]);
               }
           }
         }
@@ -756,17 +816,14 @@ struct gvar
         /* infer deltas for unreferenced points */
         if (!apply_to_all && !phantom_only)
         {
-          if (!end_points)
-          {
-            for (unsigned i = 0; i < count; ++i)
-              if (points.arrayZ[i].is_end_point)
-                end_points.push (i);
-            if (unlikely (end_points.in_error ())) return false;
-          }
-
           unsigned start_point = 0;
-          for (unsigned end_point : end_points)
+          unsigned end_point = 0;
+          while (true)
           {
+            while (end_point < count && !points.arrayZ[end_point].is_end_point)
+              end_point++;
+            if (unlikely (end_point == count)) break;
+
             /* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */
             unsigned unref_count = 0;
             for (unsigned i = start_point; i < end_point + 1; i++)
@@ -809,7 +866,7 @@ struct gvar
               }
             }
           no_more_gaps:
-            start_point = end_point + 1;
+            start_point = end_point = end_point + 1;
           }
         }
 
@@ -829,7 +886,7 @@ struct gvar
     unsigned int get_axis_count () const { return table->axisCount; }
 
     private:
-    hb_blob_ptr_t<gvar> table;
+    hb_blob_ptr_t<gvar_GVAR> table;
     unsigned glyphCount;
     hb_vector_t<hb_pair_t<int, int>> shared_tuple_active_idx;
   };
@@ -847,7 +904,7 @@ struct gvar
   NNOffset32To<UnsizedArrayOf<F2DOT14>>
                 sharedTuples;   /* Offset from the start of this table to the shared tuple records.
                                  * Array of tuple records shared across all glyph variation data tables. */
-  HBUINT16      glyphCountX;    /* The number of glyphs in this font. This must match the number of
+  GidOffsetType glyphCountX;    /* The number of glyphs in this font. This must match the number of
                                  * glyphs stored elsewhere in the font. */
   HBUINT16      flags;          /* Bit-field that gives the format of the offset array that follows.
                                  * If bit 0 is clear, the offsets are uint16; if bit 0 is set, the
@@ -862,9 +919,15 @@ struct gvar
   DEFINE_SIZE_ARRAY (20, offsetZ);
 };
 
+using gvar = gvar_GVAR<HBUINT16, HB_OT_TAG_gvar>;
+using GVAR = gvar_GVAR<HBUINT24, HB_OT_TAG_GVAR>;
+
 struct gvar_accelerator_t : gvar::accelerator_t {
   gvar_accelerator_t (hb_face_t *face) : gvar::accelerator_t (face) {}
 };
+struct GVAR_accelerator_t : GVAR::accelerator_t {
+  GVAR_accelerator_t (hb_face_t *face) : GVAR::accelerator_t (face) {}
+};
 
 } /* namespace OT */
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-hvar-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-hvar-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-hvar-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-hvar-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -188,7 +188,7 @@ struct hvarvvar_subset_plan_t
   ~hvarvvar_subset_plan_t() { fini (); }
 
   void init (const hb_array_t<const DeltaSetIndexMap *> &index_maps,
-             const VariationStore &_var_store,
+             const ItemVariationStore &_var_store,
              const hb_subset_plan_t *plan)
   {
     index_map_plans.resize (index_maps.length);
@@ -263,7 +263,7 @@ struct hvarvvar_subset_plan_t
   hb_inc_bimap_t outer_map;
   hb_vector_t<hb_inc_bimap_t> inner_maps;
   hb_vector_t<index_map_subset_plan_t> index_map_plans;
-  const VariationStore *var_store;
+  const ItemVariationStore *var_store;
 
   protected:
   hb_vector_t<hb_set_t *> inner_sets;
@@ -288,6 +288,7 @@ struct HVARVVAR
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
+                  hb_barrier () &&
                   likely (version.major == 1) &&
                   varStore.sanitize (c, this) &&
                   advMap.sanitize (c, this) &&
@@ -295,7 +296,7 @@ struct HVARVVAR
                   rsbMap.sanitize (c, this));
   }
 
-  const VariationStore& get_var_store () const
+  const ItemVariationStore& get_var_store () const
   { return this+varStore; }
 
   void listup_index_maps (hb_vector_t<const DeltaSetIndexMap *> &index_maps) const
@@ -383,7 +384,7 @@ struct HVARVVAR
 
   float get_advance_delta_unscaled (hb_codepoint_t  glyph,
                                     const int *coords, unsigned int coord_count,
-                                    VariationStore::cache_t *store_cache = nullptr) const
+                                    ItemVariationStore::cache_t *store_cache = nullptr) const
   {
     uint32_t varidx = (this+advMap).map (glyph);
     return (this+varStore).get_delta (varidx,
@@ -404,7 +405,7 @@ struct HVARVVAR
   public:
   FixedVersion<>version;        /* Version of the metrics variation table
                                  * initially set to 0x00010000u */
-  Offset32To<VariationStore>
+  Offset32To<ItemVariationStore>
                 varStore;       /* Offset to item variation store table. */
   Offset32To<DeltaSetIndexMap>
                 advMap;         /* Offset to advance var-idx mapping. */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-mvar-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-mvar-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-mvar-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-mvar-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -56,7 +56,7 @@ struct VariationValueRecord
 
   public:
   Tag           valueTag;       /* Four-byte tag identifying a font-wide measure. */
-  VarIdx        varIdx;         /* Outer/inner index into VariationStore item. */
+  VarIdx        varIdx;         /* Outer/inner index into ItemVariationStore item. */
 
   public:
   DEFINE_SIZE_STATIC (8);
@@ -77,8 +77,10 @@ struct MVAR
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
+                  hb_barrier () &&
                   likely (version.major == 1) &&
                   c->check_struct (this) &&
+                  hb_barrier () &&
                   valueRecordSize >= VariationValueRecord::static_size &&
                   varStore.sanitize (c, this) &&
                   c->check_range (valuesZ.arrayZ,
@@ -104,7 +106,7 @@ struct MVAR
     out->valueRecordCount = valueRecordCount;
 
     item_variations_t item_vars;
-    const VariationStore& src_var_store = this+varStore;
+    const ItemVariationStore& src_var_store = this+varStore;
 
     if (!item_vars.instantiate (src_var_store, c->plan))
       return_trace (false);
@@ -157,7 +159,7 @@ protected:
   HBUINT16      valueRecordSize;/* The size in bytes of each value record —
                                  * must be greater than zero. */
   HBUINT16      valueRecordCount;/* The number of value records — may be zero. */
-  Offset16To<VariationStore>
+  Offset16To<ItemVariationStore>
                 varStore;       /* Offset to item variation store table. */
   UnsizedArrayOf<HBUINT8>
                 valuesZ;        /* Array of value records. The records must be
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-varc-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-varc-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-varc-table.hh	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-var-varc-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2024  Google, Inc.
+ *
+ *  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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_VAR_VARC_TABLE_HH
+#define HB_OT_VAR_VARC_TABLE_HH
+
+#include "OT/Var/VARC/VARC.hh"
+
+#endif /* HB_OT_VAR_VARC_TABLE_HH */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-vorg-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-vorg-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ot-vorg-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ot-vorg-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -117,6 +117,7 @@ struct VORG
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+                  hb_barrier () &&
                   version.major == 1 &&
                   vertYOrigins.sanitize (c));
   }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh	2025-06-27 08:03:14.000000000 +0000
@@ -28,169 +28,8 @@
 #include "hb.hh"
 #include "hb-paint.h"
 
+#include "hb-geometry.hh"
 
-typedef struct hb_extents_t
-{
-  hb_extents_t () {}
-  hb_extents_t (float xmin, float ymin, float xmax, float ymax) :
-    xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {}
-
-  bool is_empty () const { return xmin >= xmax || ymin >= ymax; }
-  bool is_void () const { return xmin > xmax; }
-
-  void union_ (const hb_extents_t &o)
-  {
-    xmin = hb_min (xmin, o.xmin);
-    ymin = hb_min (ymin, o.ymin);
-    xmax = hb_max (xmax, o.xmax);
-    ymax = hb_max (ymax, o.ymax);
-  }
-
-  void intersect (const hb_extents_t &o)
-  {
-    xmin = hb_max (xmin, o.xmin);
-    ymin = hb_max (ymin, o.ymin);
-    xmax = hb_min (xmax, o.xmax);
-    ymax = hb_min (ymax, o.ymax);
-  }
-
-  void
-  add_point (float x, float y)
-  {
-    if (unlikely (is_void ()))
-    {
-      xmin = xmax = x;
-      ymin = ymax = y;
-    }
-    else
-    {
-      xmin = hb_min (xmin, x);
-      ymin = hb_min (ymin, y);
-      xmax = hb_max (xmax, x);
-      ymax = hb_max (ymax, y);
-    }
-  }
-
-  float xmin = 0.f;
-  float ymin = 0.f;
-  float xmax = -1.f;
-  float ymax = -1.f;
-} hb_extents_t;
-
-typedef struct hb_transform_t
-{
-  hb_transform_t () {}
-  hb_transform_t (float xx, float yx,
-                  float xy, float yy,
-                  float x0, float y0) :
-    xx (xx), yx (yx), xy (xy), yy (yy), x0 (x0), y0 (y0) {}
-
-  void multiply (const hb_transform_t &o)
-  {
-    /* Copied from cairo, with "o" being "a" there and "this" being "b" there. */
-    hb_transform_t r;
-
-    r.xx = o.xx * xx + o.yx * xy;
-    r.yx = o.xx * yx + o.yx * yy;
-
-    r.xy = o.xy * xx + o.yy * xy;
-    r.yy = o.xy * yx + o.yy * yy;
-
-    r.x0 = o.x0 * xx + o.y0 * xy + x0;
-    r.y0 = o.x0 * yx + o.y0 * yy + y0;
-
-    *this = r;
-  }
-
-  void transform_distance (float &dx, float &dy) const
-  {
-    float new_x = xx * dx + xy * dy;
-    float new_y = yx * dx + yy * dy;
-    dx = new_x;
-    dy = new_y;
-  }
-
-  void transform_point (float &x, float &y) const
-  {
-    transform_distance (x, y);
-    x += x0;
-    y += y0;
-  }
-
-  void transform_extents (hb_extents_t &extents) const
-  {
-    float quad_x[4], quad_y[4];
-
-    quad_x[0] = extents.xmin;
-    quad_y[0] = extents.ymin;
-    quad_x[1] = extents.xmin;
-    quad_y[1] = extents.ymax;
-    quad_x[2] = extents.xmax;
-    quad_y[2] = extents.ymin;
-    quad_x[3] = extents.xmax;
-    quad_y[3] = extents.ymax;
-
-    extents = hb_extents_t {};
-    for (unsigned i = 0; i < 4; i++)
-    {
-      transform_point (quad_x[i], quad_y[i]);
-      extents.add_point (quad_x[i], quad_y[i]);
-    }
-  }
-
-  float xx = 1.f;
-  float yx = 0.f;
-  float xy = 0.f;
-  float yy = 1.f;
-  float x0 = 0.f;
-  float y0 = 0.f;
-} hb_transform_t;
-
-typedef struct hb_bounds_t
-{
-  enum status_t {
-    UNBOUNDED,
-    BOUNDED,
-    EMPTY,
-  };
-
-  hb_bounds_t (status_t status) : status (status) {}
-  hb_bounds_t (const hb_extents_t &extents) :
-    status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {}
-
-  void union_ (const hb_bounds_t &o)
-  {
-    if (o.status == UNBOUNDED)
-      status = UNBOUNDED;
-    else if (o.status == BOUNDED)
-    {
-      if (status == EMPTY)
-        *this = o;
-      else if (status == BOUNDED)
-        extents.union_ (o.extents);
-    }
-  }
-
-  void intersect (const hb_bounds_t &o)
-  {
-    if (o.status == EMPTY)
-      status = EMPTY;
-    else if (o.status == BOUNDED)
-    {
-      if (status == UNBOUNDED)
-        *this = o;
-      else if (status == BOUNDED)
-      {
-        extents.intersect (o.extents);
-        if (extents.is_empty ())
-          status = EMPTY;
-      }
-    }
-  }
-
-  status_t status;
-  hb_extents_t extents;
-} hb_bounds_t;
 
 typedef struct  hb_paint_extents_context_t hb_paint_extents_context_t;
 
@@ -231,7 +70,10 @@ struct hb_paint_extents_context_t
     const hb_transform_t &t = transforms.tail ();
     t.transform_extents (extents);
 
-    clips.push (hb_bounds_t {extents});
+    auto bounds = hb_bounds_t {extents};
+    bounds.intersect (clips.tail ());
+
+    clips.push (bounds);
   }
 
   void pop_clip ()
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-paint.h 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-paint.h
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-paint.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-paint.h	2025-06-27 08:03:14.000000000 +0000
@@ -146,7 +146,7 @@ typedef void (*hb_paint_pop_transform_fu
  *
  * A virtual method for the #hb_paint_funcs_t to render a color glyph by glyph index.
  *
- * Return value: %true if the glyph was painted, %false otherwise.
+ * Return value: `true` if the glyph was painted, `false` otherwise.
  *
  * Since: 8.2.0
  */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-priority-queue.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-priority-queue.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-priority-queue.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-priority-queue.hh	2025-06-27 08:03:14.000000000 +0000
@@ -55,6 +55,9 @@ struct hb_priority_queue_t
 
   bool in_error () const { return heap.in_error (); }
 
+  bool alloc (unsigned size)
+  { return heap.alloc (size); }
+
 #ifndef HB_OPTIMIZE_SIZE
   HB_ALWAYS_INLINE
 #endif
@@ -160,7 +163,7 @@ struct hb_priority_queue_t
     goto repeat;
   }
 
-  void swap (unsigned a, unsigned b)
+  void swap (unsigned a, unsigned b) noexcept
   {
     assert (a < heap.length);
     assert (b < heap.length);
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-repacker.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-repacker.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-repacker.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-repacker.hh	2025-06-27 08:03:14.000000000 +0000
@@ -239,6 +239,54 @@ bool _try_isolating_subgraphs (const hb_
 }
 
 static inline
+bool _resolve_shared_overflow(const hb_vector_t<graph::overflow_record_t>& overflows,
+                              int overflow_index,
+                              graph_t& sorted_graph)
+{
+  const graph::overflow_record_t& r = overflows[overflow_index];
+
+  // Find all of the parents in overflowing links that link to this
+  // same child node. We will then try duplicating the child node and
+  // re-assigning all of these parents to the duplicate.
+  hb_set_t parents;
+  parents.add(r.parent);
+  for (int i = overflow_index - 1; i >= 0; i--) {
+    const graph::overflow_record_t& r2 = overflows[i];
+    if (r2.child == r.child) {
+      parents.add(r2.parent);
+    }
+  }
+
+  unsigned result = sorted_graph.duplicate(&parents, r.child);
+  if (result == (unsigned) -1 && parents.get_population() > 2) {
+    // All links to the child are overflowing, so we can't include all
+    // in the duplication. Remove one parent from the duplication.
+    // Remove the lowest index parent, which will be the closest to the child.
+    parents.del(parents.get_min());
+    result = sorted_graph.duplicate(&parents, r.child);
+  }
+
+  if (result == (unsigned) -1) return result;
+
+  if (parents.get_population() > 1) {
+    // If the duplicated node has more than one parent pre-emptively raise it's priority to the maximum.
+    // This will place it close to the parents. Node's with only one parent, don't need this as normal overflow
+    // resolution will raise priority if needed.
+    //
+    // Reasoning: most of the parents to this child are likely at the same layer in the graph. Duplicating
+    // the child will theoretically allow it to be placed closer to it's parents. However, due to the shortest
+    // distance sort by default it's placement will remain in the same layer, thus it will remain in roughly the
+    // same position (and distance from parents) as the original child node. The overflow resolution will attempt
+    // to move nodes closer, but only for non-shared nodes. Since this node is shared, it will simply be given
+    // further duplication which defeats the attempt to duplicate with multiple parents. To fix this we
+    // pre-emptively raise priority now which allows the duplicated node to pack into the same layer as it's parents.
+    sorted_graph.vertices_[result].give_max_priority();
+  }
+
+  return result;
+}
+
+static inline
 bool _process_overflows (const hb_vector_t<graph::overflow_record_t>& overflows,
                          hb_set_t& priority_bumped_parents,
                          graph_t& sorted_graph)
@@ -254,7 +302,7 @@ bool _process_overflows (const hb_vector
     {
       // The child object is shared, we may be able to eliminate the overflow
       // by duplicating it.
-      if (sorted_graph.duplicate (r.parent, r.child) == (unsigned) -1) continue;
+      if (!_resolve_shared_overflow(overflows, i, sorted_graph)) continue;
       return true;
     }
 
@@ -289,9 +337,10 @@ bool _process_overflows (const hb_vector
 inline bool
 hb_resolve_graph_overflows (hb_tag_t table_tag,
                             unsigned max_rounds ,
-                            bool recalculate_extensions,
+                            bool always_recalculate_extensions,
                             graph_t& sorted_graph /* IN/OUT */)
 {
+  DEBUG_MSG (SUBSET_REPACK, nullptr, "Repacking %c%c%c%c.", HB_UNTAG(table_tag));
   sorted_graph.sort_shortest_distance ();
   if (sorted_graph.in_error ())
   {
@@ -303,12 +352,12 @@ hb_resolve_graph_overflows (hb_tag_t tab
   if (!will_overflow)
     return true;
 
+  bool is_gsub_or_gpos = (table_tag == HB_OT_TAG_GPOS ||  table_tag == HB_OT_TAG_GSUB);
   graph::gsubgpos_graph_context_t ext_context (table_tag, sorted_graph);
-  if ((table_tag == HB_OT_TAG_GPOS
-       ||  table_tag == HB_OT_TAG_GSUB)
-      && will_overflow)
+  if (is_gsub_or_gpos && will_overflow)
   {
-    if (recalculate_extensions)
+    DEBUG_MSG (SUBSET_REPACK, nullptr, "Applying GSUB/GPOS repacking specializations.");
+    if (always_recalculate_extensions)
     {
       DEBUG_MSG (SUBSET_REPACK, nullptr, "Splitting subtables if needed.");
       if (!_presplit_subtables_if_needed (ext_context)) {
@@ -364,6 +413,13 @@ hb_resolve_graph_overflows (hb_tag_t tab
 
   if (graph::will_overflow (sorted_graph))
   {
+    if (is_gsub_or_gpos && !always_recalculate_extensions) {
+      // If this a GSUB/GPOS table and we didn't try to extension promotion and table splitting then
+      // as a last ditch effort, re-run the repacker with it enabled.
+      DEBUG_MSG (SUBSET_REPACK, nullptr, "Failed to find a resolution. Re-running with extension promotion and table splitting enabled.");
+      return hb_resolve_graph_overflows (table_tag, max_rounds, true, sorted_graph);
+    }
+
     DEBUG_MSG (SUBSET_REPACK, nullptr, "Offset overflow resolution failed.");
     return false;
   }
@@ -388,7 +444,7 @@ template<typename T>
 inline hb_blob_t*
 hb_resolve_overflows (const T& packed,
                       hb_tag_t table_tag,
-                      unsigned max_rounds = 20,
+                      unsigned max_rounds = 32,
                       bool recalculate_extensions = false) {
   graph_t sorted_graph (packed);
   if (sorted_graph.in_error ())
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-sanitize.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-sanitize.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-sanitize.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-sanitize.hh	2025-06-27 08:03:14.000000000 +0000
@@ -72,8 +72,8 @@
  *
  * === The sanitize() contract ===
  *
- * The sanitize() method of each object type shall return true if it's safe to
- * call other methods of the object, and %false otherwise.
+ * The sanitize() method of each object type shall return `true` if it's safe to
+ * call other methods of the object, and `false` otherwise.
  *
  * Note that what sanitize() checks for might align with what the specification
  * describes as valid table data, but does not have to be.  In particular, we
@@ -134,7 +134,10 @@ struct hb_sanitize_context_t :
   const char *get_name () { return "SANITIZE"; }
   template <typename T, typename F>
   bool may_dispatch (const T *obj HB_UNUSED, const F *format)
-  { return format->sanitize (this); }
+  {
+    return format->sanitize (this) &&
+           hb_barrier ();
+  }
   static return_t default_return_value () { return true; }
   static return_t no_dispatch_return_value () { return false; }
   bool stop_sublookup_iteration (const return_t r) const { return !r; }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh	2025-06-27 08:03:14.000000000 +0000
@@ -36,9 +36,7 @@
 #include "hb-map.hh"
 #include "hb-pool.hh"
 
-#ifdef HB_EXPERIMENTAL_API
-#include "hb-subset-repacker.h"
-#endif
+#include "hb-subset-serialize.h"
 
 /*
  * Serialize
@@ -75,23 +73,41 @@ struct hb_serialize_context_t
 
     object_t () = default;
 
-#ifdef HB_EXPERIMENTAL_API
-    object_t (const hb_object_t &o)
+    object_t (const hb_subset_serialize_object_t &o)
     {
       head = o.head;
       tail = o.tail;
       next = nullptr;
-      real_links.alloc (o.num_real_links, true);
+      real_links.alloc_exact (o.num_real_links);
       for (unsigned i = 0 ; i < o.num_real_links; i++)
         real_links.push (o.real_links[i]);
 
-      virtual_links.alloc (o.num_virtual_links, true);
+      virtual_links.alloc_exact (o.num_virtual_links);
       for (unsigned i = 0; i < o.num_virtual_links; i++)
         virtual_links.push (o.virtual_links[i]);
     }
-#endif
 
-    friend void swap (object_t& a, object_t& b)
+    bool add_virtual_link (objidx_t objidx)
+    {
+      if (!objidx)
+        return false;
+
+      auto& link = *virtual_links.push ();
+      if (virtual_links.in_error ())
+        return false;
+
+      link.objidx = objidx;
+      // Remaining fields were previously zero'd by push():
+      // link.width = 0;
+      // link.is_signed = 0;
+      // link.whence = 0;
+      // link.position = 0;
+      // link.bias = 0;
+
+      return true;
+    }
+
+    friend void swap (object_t& a, object_t& b) noexcept
     {
       hb_swap (a.head, b.head);
       hb_swap (a.tail, b.tail);
@@ -128,8 +144,7 @@ struct hb_serialize_context_t
 
       link_t () = default;
 
-#ifdef HB_EXPERIMENTAL_API
-      link_t (const hb_link_t &o)
+      link_t (const hb_subset_serialize_link_t &o)
       {
         width = o.width;
         is_signed = 0;
@@ -138,7 +153,6 @@ struct hb_serialize_context_t
         bias = 0;
         objidx = o.objidx;
       }
-#endif
 
       HB_INTERNAL static int cmp (const void* a, const void* b)
       {
@@ -156,9 +170,9 @@ struct hb_serialize_context_t
     object_t *next;
 
     auto all_links () const HB_AUTO_RETURN
-        (( hb_concat (this->real_links, this->virtual_links) ));
+        (( hb_concat (real_links, virtual_links) ));
     auto all_links_writer () HB_AUTO_RETURN
-        (( hb_concat (this->real_links.writer (), this->virtual_links.writer ()) ));
+        (( hb_concat (real_links.writer (), virtual_links.writer ()) ));
   };
 
   struct snapshot_t
@@ -380,6 +394,7 @@ struct hb_serialize_context_t
       {
         merge_virtual_links (obj, objidx);
         obj->fini ();
+        object_pool.release (obj);
         return objidx;
       }
     }
@@ -443,9 +458,11 @@ struct hb_serialize_context_t
     while (packed.length > 1 &&
            packed.tail ()->head < tail)
     {
-      packed_map.del (packed.tail ());
-      assert (!packed.tail ()->next);
-      packed.tail ()->fini ();
+      object_t *obj = packed.tail ();
+      packed_map.del (obj);
+      assert (!obj->next);
+      obj->fini ();
+      object_pool.release (obj);
       packed.pop ();
     }
     if (packed.length > 1)
@@ -469,16 +486,40 @@ struct hb_serialize_context_t
 
     assert (current);
 
-    auto& link = *current->virtual_links.push ();
-    if (current->virtual_links.in_error ())
+    if (!current->add_virtual_link(objidx))
       err (HB_SERIALIZE_ERROR_OTHER);
+  }
+
+  objidx_t last_added_child_index() const {
+    if (unlikely (in_error ())) return (objidx_t) -1;
+
+    assert (current);
+    if (!bool(current->real_links)) {
+      return (objidx_t) -1;
+    }
 
-    link.width = 0;
-    link.objidx = objidx;
-    link.is_signed = 0;
-    link.whence = 0;
-    link.position = 0;
-    link.bias = 0;
+    return current->real_links[current->real_links.length - 1].objidx;
+  }
+
+  // For the current object ensure that the sub-table bytes for child objidx are always placed
+  // after the subtable bytes for any other existing children. This only ensures that the
+  // repacker will not move the target subtable before the other children
+  // (by adding virtual links). It is up to the caller to ensure the initial serialization
+  // order is correct.
+  void repack_last(objidx_t objidx) {
+    if (unlikely (in_error ())) return;
+
+    if (!objidx)
+      return;
+
+    assert (current);
+    for (auto& l : current->real_links) {
+      if (l.objidx == objidx) {
+        continue;
+      }
+
+      packed[l.objidx]->add_virtual_link(objidx);
+    }
   }
 
   template <typename T>
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh	2025-06-27 08:03:14.000000000 +0000
@@ -56,7 +56,7 @@
  *   - For each glyph, if it doesn't match the subtable digest,
  *     skip it.
  *
- * The main filter we use is a combination of three bits-pattern
+ * The main filter we use is a combination of four bits-pattern
  * filters. A bits-pattern filter checks a number of bits (5 or 6)
  * of the input number (glyph-id in this case) and checks whether
  * its pattern is amongst the patterns of any of the accepted values.
@@ -64,43 +64,60 @@
  * check is done using four bitwise operations only.
  */
 
-template <typename mask_t, unsigned int shift>
-struct hb_set_digest_bits_pattern_t
+static constexpr unsigned hb_set_digest_shifts[] = {4, 0, 6};
+
+struct hb_set_digest_t
 {
+  // No science in these. Intuition and testing only.
+  using mask_t = uint64_t;
+
+  static constexpr unsigned n = ARRAY_LENGTH_CONST (hb_set_digest_shifts);
   static constexpr unsigned mask_bytes = sizeof (mask_t);
   static constexpr unsigned mask_bits = sizeof (mask_t) * 8;
-  static constexpr unsigned num_bits = 0
-                                     + (mask_bytes >= 1 ? 3 : 0)
-                                     + (mask_bytes >= 2 ? 1 : 0)
-                                     + (mask_bytes >= 4 ? 1 : 0)
-                                     + (mask_bytes >= 8 ? 1 : 0)
-                                     + (mask_bytes >= 16? 1 : 0)
-                                     + 0;
+  static constexpr hb_codepoint_t mb1 = mask_bits - 1;
+  static constexpr mask_t one = 1;
+  static constexpr mask_t all = (mask_t) -1;
 
-  static_assert ((shift < sizeof (hb_codepoint_t) * 8), "");
-  static_assert ((shift + num_bits <= sizeof (hb_codepoint_t) * 8), "");
+  void init ()
+  { for (unsigned i = 0; i < n; i++) masks[i] = 0; }
 
-  void init () { mask = 0; }
+  void clear () { init (); }
 
-  void add (const hb_set_digest_bits_pattern_t &o) { mask |= o.mask; }
+  static hb_set_digest_t full ()
+  {
+    hb_set_digest_t d;
+    for (unsigned i = 0; i < n; i++) d.masks[i] = all;
+    return d;
+  }
 
-  void add (hb_codepoint_t g) { mask |= mask_for (g); }
+  void union_ (const hb_set_digest_t &o)
+  { for (unsigned i = 0; i < n; i++) masks[i] |= o.masks[i]; }
 
   bool add_range (hb_codepoint_t a, hb_codepoint_t b)
   {
-    if (mask == (mask_t) -1) return false;
-    if ((b >> shift) - (a >> shift) >= mask_bits - 1)
-    {
-      mask = (mask_t) -1;
-      return false;
-    }
-    else
+    bool ret;
+
+    ret = false;
+    for (unsigned i = 0; i < n; i++)
+      if (masks[i] != all)
+        ret = true;
+    if (!ret) return false;
+
+    ret = false;
+    for (unsigned i = 0; i < n; i++)
     {
-      mask_t ma = mask_for (a);
-      mask_t mb = mask_for (b);
-      mask |= mb + (mb - ma) - (mb < ma);
-      return true;
+      mask_t shift = hb_set_digest_shifts[i];
+      if ((b >> shift) - (a >> shift) >= mb1)
+        masks[i] = all;
+      else
+      {
+        mask_t ma = one << ((a >> shift) & mb1);
+        mask_t mb = one << ((b >> shift) & mb1);
+        masks[i] |= mb + (mb - ma) - (mb < ma);
+        ret = true;
+      }
     }
+    return ret;
   }
 
   template <typename T>
@@ -123,95 +140,37 @@ struct hb_set_digest_bits_pattern_t
   template <typename T>
   bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
 
-  bool may_have (const hb_set_digest_bits_pattern_t &o) const
-  { return mask & o.mask; }
-
-  bool may_have (hb_codepoint_t g) const
-  { return mask & mask_for (g); }
-
-  private:
-
-  static mask_t mask_for (hb_codepoint_t g)
-  { return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1)); }
-  mask_t mask;
-};
-
-template <typename head_t, typename tail_t>
-struct hb_set_digest_combiner_t
-{
-  void init ()
-  {
-    head.init ();
-    tail.init ();
-  }
+  bool operator [] (hb_codepoint_t g) const
+  { return may_have (g); }
 
-  void add (const hb_set_digest_combiner_t &o)
-  {
-    head.add (o.head);
-    tail.add (o.tail);
-  }
 
   void add (hb_codepoint_t g)
   {
-    head.add (g);
-    tail.add (g);
+    for (unsigned i = 0; i < n; i++)
+      masks[i] |= one << ((g >> hb_set_digest_shifts[i]) & mb1);
   }
 
-  bool add_range (hb_codepoint_t a, hb_codepoint_t b)
-  {
-    return (int) head.add_range (a, b) | (int) tail.add_range (a, b);
-  }
-  template <typename T>
-  void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    head.add_array (array, count, stride);
-    tail.add_array (array, count, stride);
-  }
-  template <typename T>
-  void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
-  template <typename T>
-  bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    return head.add_sorted_array (array, count, stride) &&
-           tail.add_sorted_array (array, count, stride);
-  }
-  template <typename T>
-  bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
-
-  bool may_have (const hb_set_digest_combiner_t &o) const
+  HB_ALWAYS_INLINE
+  bool may_have (hb_codepoint_t g) const
   {
-    return head.may_have (o.head) && tail.may_have (o.tail);
+    for (unsigned i = 0; i < n; i++)
+      if (!(masks[i] & (one << ((g >> hb_set_digest_shifts[i]) & mb1))))
+        return false;
+    return true;
   }
 
-  bool may_have (hb_codepoint_t g) const
+  bool may_intersect (const hb_set_digest_t &o) const
   {
-    return head.may_have (g) && tail.may_have (g);
+    for (unsigned i = 0; i < n; i++)
+      if (!(masks[i] & o.masks[i]))
+        return false;
+    return true;
   }
 
   private:
-  head_t head;
-  tail_t tail;
-};
-
 
-/*
- * hb_set_digest_t
- *
- * This is a combination of digests that performs "best".
- * There is not much science to this: it's a result of intuition
- * and testing.
- */
-using hb_set_digest_t =
-  hb_set_digest_combiner_t
-  <
-    hb_set_digest_bits_pattern_t<unsigned long, 4>,
-    hb_set_digest_combiner_t
-    <
-      hb_set_digest_bits_pattern_t<unsigned long, 0>,
-      hb_set_digest_bits_pattern_t<unsigned long, 9>
-    >
-  >
-;
+  mask_t masks[n] = {};
+};
 
 
 #endif /* HB_SET_DIGEST_HH */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-set.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-set.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-set.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-set.hh	2025-06-27 08:03:14.000000000 +0000
@@ -35,6 +35,8 @@
 template <typename impl_t>
 struct hb_sparseset_t
 {
+  static constexpr bool realloc_move = true;
+
   hb_object_header_t header;
   impl_t s;
 
@@ -42,10 +44,10 @@ struct hb_sparseset_t
   ~hb_sparseset_t () { fini (); }
 
   hb_sparseset_t (const hb_sparseset_t& other) : hb_sparseset_t () { set (other); }
-  hb_sparseset_t (hb_sparseset_t&& other) : hb_sparseset_t () { s = std::move (other.s); }
+  hb_sparseset_t (hb_sparseset_t&& other)  noexcept : hb_sparseset_t () { s = std::move (other.s); }
   hb_sparseset_t& operator = (const hb_sparseset_t& other) { set (other); return *this; }
-  hb_sparseset_t& operator = (hb_sparseset_t&& other) { s = std::move (other.s); return *this; }
-  friend void swap (hb_sparseset_t& a, hb_sparseset_t& b) { hb_swap (a.s, b.s); }
+  hb_sparseset_t& operator = (hb_sparseset_t&& other)  noexcept { s = std::move (other.s); return *this; }
+  friend void swap (hb_sparseset_t& a, hb_sparseset_t& b)  noexcept { hb_swap (a.s, b.s); }
 
   hb_sparseset_t (std::initializer_list<hb_codepoint_t> lst) : hb_sparseset_t ()
   {
@@ -84,7 +86,7 @@ struct hb_sparseset_t
   uint32_t hash () const { return s.hash (); }
 
   void add (hb_codepoint_t g) { s.add (g); }
-  bool add_range (hb_codepoint_t a, hb_codepoint_t b) { return s.add_range (a, b); }
+  bool add_range (hb_codepoint_t first, hb_codepoint_t last) { return s.add_range (first, last); }
 
   template <typename T>
   void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
@@ -104,6 +106,7 @@ struct hb_sparseset_t
   void del_range (hb_codepoint_t a, hb_codepoint_t b) { s.del_range (a, b); }
 
   bool get (hb_codepoint_t g) const { return s.get (g); }
+  bool may_have (hb_codepoint_t g) const { return get (g); }
 
   /* Has interface. */
   bool operator [] (hb_codepoint_t k) const { return get (k); }
@@ -118,6 +121,9 @@ struct hb_sparseset_t
   hb_sparseset_t& operator << (const hb_codepoint_pair_t& range)
   { add_range (range.first, range.second); return *this; }
 
+  bool may_intersect (const hb_sparseset_t &other) const
+  { return s.may_intersect (other.s); }
+
   bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
   { return s.intersects (first, last); }
 
@@ -164,7 +170,7 @@ struct hb_set_t : hb_sparseset_t<hb_bit_
   ~hb_set_t () = default;
   hb_set_t () : sparseset () {};
   hb_set_t (const hb_set_t &o) : sparseset ((sparseset &) o) {};
-  hb_set_t (hb_set_t&& o) : sparseset (std::move ((sparseset &) o)) {}
+  hb_set_t (hb_set_t&& o)  noexcept : sparseset (std::move ((sparseset &) o)) {}
   hb_set_t& operator = (const hb_set_t&) = default;
   hb_set_t& operator = (hb_set_t&&) = default;
   hb_set_t (std::initializer_list<hb_codepoint_t> lst) : sparseset (lst) {}
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-shape-plan.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-shape-plan.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-shape-plan.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-shape-plan.cc	2025-06-27 08:03:14.000000000 +0000
@@ -233,7 +233,7 @@ hb_shape_plan_create2 (hb_face_t
                   num_coords,
                   shaper_list);
 
-  if (unlikely (props->direction == HB_DIRECTION_INVALID))
+  if (unlikely (!HB_DIRECTION_IS_VALID (props->direction)))
     return hb_shape_plan_get_empty ();
 
   hb_shape_plan_t *shape_plan;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-shape.h 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-shape.h
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-shape.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-shape.h	2025-06-27 08:03:14.000000000 +0000
@@ -53,6 +53,7 @@ hb_shape_full (hb_font_t          *font,
                unsigned int        num_features,
                const char * const *shaper_list);
 
+#ifdef HB_EXPERIMENTAL_API
 HB_EXTERN hb_bool_t
 hb_shape_justify (hb_font_t          *font,
                   hb_buffer_t        *buffer,
@@ -64,6 +65,7 @@ hb_shape_justify (hb_font_t          *fo
                   float              *advance, /* IN/OUT */
                   hb_tag_t           *var_tag, /* OUT */
                   float              *var_value /* OUT */);
+#endif
 
 HB_EXTERN const char **
 hb_shape_list_shapers (void);
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-style.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-style.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-style.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-style.cc	2025-06-27 08:03:14.000000000 +0000
@@ -61,8 +61,8 @@ _hb_ratio_to_angle (float r)
  * @style_tag: a style tag.
  *
  * Searches variation axes of a #hb_font_t object for a specific axis first,
- * if not set, then tries to get default style values from different
- * tables of the font.
+ * if not set, first tries to get default style values in `STAT` table
+ * then tries to polyfill from different tables of the font.
  *
  * Returns: Corresponding axis or default value to a style tag.
  *
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh	2025-06-27 08:03:14.000000000 +0000
@@ -115,7 +115,7 @@ struct str_encoder_t
       encode_byte (OpCode_BCD);
 
       // Based on:
-      // https://github.com/fonttools/fonttools/blob/97ed3a61cde03e17b8be36f866192fbd56f1d1a7/Lib/fontTools/misc/psCharStrings.py#L265-L294
+      // https://github.com/fonttools/fonttools/blob/0738c41dfbcbc213ab9263f486ef0cccc6eb5ce5/Lib/fontTools/misc/psCharStrings.py#L267-L316
 
       char buf[16];
       /* FontTools has the following comment:
@@ -133,6 +133,10 @@ struct str_encoder_t
       (void) hb_uselocale (((void) freelocale (clocale), oldlocale));
 
       char *s = buf;
+      size_t len;
+      char *comma = strchr (s, ',');
+      if (comma) // Comma for some European locales in case no uselocale available.
+        *comma = '.';
       if (s[0] == '0' && s[1] == '.')
         s++;
       else if (s[0] == '-' && s[1] == '0' && s[2] == '.')
@@ -140,6 +144,45 @@ struct str_encoder_t
         s[1] = '-';
         s++;
       }
+      else if ((len = strlen (s)) > 3 && !strcmp (s + len - 3, "000"))
+      {
+        unsigned exponent = len - 3;
+        char *s2 = s + exponent - 1;
+        while (*s2 == '0' && exponent > 1)
+        {
+          s2--;
+          exponent++;
+        }
+        snprintf (s2 + 1, sizeof (buf) - (s2 + 1 - buf), "E%u", exponent);
+      }
+      else
+      {
+        char *dot = strchr (s, '.');
+        char *e = strchr (s, 'E');
+        if (dot && e)
+        {
+          memmove (dot, dot + 1, e - (dot + 1));
+          int exponent = atoi (e + 1);
+          int new_exponent = exponent - (e - (dot + 1));
+          if (new_exponent == 1)
+          {
+            e[-1] = '0';
+            e[0] = '\0';
+          }
+          else
+            snprintf (e - 1, sizeof (buf) - (e - 1 - buf), "E%d", new_exponent);
+        }
+      }
+      if ((s[0] == '.' && s[1] == '0') || (s[0] == '-' && s[1] == '.' && s[2] == '0'))
+      {
+        int sign = s[0] == '-';
+        char *s2 = s + sign + 1;
+        while (*s2 == '0')
+          s2++;
+        len = strlen (s2);
+        memmove (s + sign, s2, len);
+        snprintf (s + sign + len, sizeof (buf) - (s + sign + len - buf), "E-%u", (unsigned) (strlen (s + sign) - 1));
+      }
       hb_vector_t<char> nibbles;
       while (*s)
       {
@@ -155,20 +198,22 @@ struct str_encoder_t
             {
               s++;
               nibbles.push (0x0C); // E-
-              continue;
+            } else {
+              if (c2 == '+')
+                s++;
+              nibbles.push (0x0B); // E
             }
-            if (c2 == '+')
+            if (*s == '0')
               s++;
-            nibbles.push (0x0B); // E
             continue;
           }
 
-          case '.': case ',': // Comma for some European locales in case no uselocale available.
+          case '.':
             nibbles.push (0x0A); // .
             continue;
 
           case '-':
-            nibbles.push (0x0E); // .
+            nibbles.push (0x0E); // -
             continue;
         }
 
@@ -1083,7 +1128,7 @@ struct subr_subsetter_t
       if (opstr.op == OpCode_callsubr || opstr.op == OpCode_callgsubr)
         size += 3;
     }
-    if (!buff.alloc (buff.length + size, true))
+    if (!buff.alloc_exact (buff.length + size))
       return false;
 
     for (auto &opstr : str.values)
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-cff1.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-cff1.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-cff1.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-cff1.cc	2025-06-27 08:03:14.000000000 +0000
@@ -45,7 +45,7 @@ struct remap_sid_t
   void alloc (unsigned size)
   {
     map.alloc (size);
-    vector.alloc (size, true);
+    vector.alloc_exact (size);
   }
 
   bool in_error () const
@@ -620,6 +620,12 @@ struct cff1_subset_plan
     drop_hints = plan->flags & HB_SUBSET_FLAGS_NO_HINTING;
     desubroutinize = plan->flags & HB_SUBSET_FLAGS_DESUBROUTINIZE;
 
+ #ifdef HB_EXPERIMENTAL_API
+    min_charstrings_off_size = (plan->flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS) ? 4 : 0;
+ #else
+    min_charstrings_off_size = 0;
+ #endif
+
     subset_charset = !acc.is_predef_charset ();
     if (!subset_charset)
       /* check whether the subset renumbers any glyph IDs */
@@ -778,13 +784,43 @@ struct cff1_subset_plan
   unsigned int  topDictModSIDs[name_dict_values_t::ValCount];
 
   bool          desubroutinize = false;
+
+  unsigned      min_charstrings_off_size = 0;
 };
 } // namespace OT
 
+static bool _serialize_cff1_charstrings (hb_serialize_context_t *c,
+                                         struct OT::cff1_subset_plan &plan,
+                                         const OT::cff1::accelerator_subset_t  &acc)
+{
+  c->push<CFF1CharStrings> ();
+
+  unsigned data_size = 0;
+  unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings, &data_size, plan.min_charstrings_off_size);
+  if (unlikely (!c->start_zerocopy (total_size)))
+    return false;
+
+  auto *cs = c->start_embed<CFF1CharStrings> ();
+  if (unlikely (!cs->serialize (c, plan.subset_charstrings, &data_size, plan.min_charstrings_off_size))) {
+    c->pop_discard ();
+    return false;
+  }
+
+  plan.info.char_strings_link = c->pop_pack (false);
+  return true;
+}
+
 bool
 OT::cff1::accelerator_subset_t::serialize (hb_serialize_context_t *c,
                                            struct OT::cff1_subset_plan &plan) const
 {
+  /* push charstrings onto the object stack first which will ensure it packs as the last
+     object in the table. Keeping the chastrings last satisfies the requirements for patching
+     via IFTB. If this ordering needs to be changed in the future, charstrings should be left
+     at the end whenever HB_SUBSET_FLAGS_ITFB_REQUIREMENTS is enabled. */
+  if (!_serialize_cff1_charstrings(c, plan, *this))
+    return false;
+
   /* private dicts & local subrs */
   for (int i = (int) privateDicts.length; --i >= 0 ;)
   {
@@ -823,25 +859,6 @@ OT::cff1::accelerator_subset_t::serializ
   if (!is_CID ())
     plan.info.privateDictInfo = plan.fontdicts_mod[0].privateDictInfo;
 
-  /* CharStrings */
-  {
-    c->push<CFF1CharStrings> ();
-
-    unsigned data_size = 0;
-    unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings, &data_size);
-    if (unlikely (!c->start_zerocopy (total_size)))
-       return false;
-
-    auto *cs = c->start_embed<CFF1CharStrings> ();
-    if (likely (cs->serialize (c, plan.subset_charstrings, &data_size)))
-      plan.info.char_strings_link = c->pop_pack (false);
-    else
-    {
-      c->pop_discard ();
-      return false;
-    }
-  }
-
   /* FDArray (FD Index) */
   if (fdArray != &Null (CFF1FDArray))
   {
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-cff2.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-cff2.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-cff2.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-cff2.cc	2025-06-27 08:03:14.000000000 +0000
@@ -248,7 +248,7 @@ struct cff2_subr_subsetter_t : subr_subs
 struct cff2_private_blend_encoder_param_t
 {
   cff2_private_blend_encoder_param_t (hb_serialize_context_t *c,
-                                      const CFF2VariationStore *varStore,
+                                      const CFF2ItemVariationStore *varStore,
                                       hb_array_t<int> normalized_coords) :
     c (c), varStore (varStore), normalized_coords (normalized_coords) {}
 
@@ -284,7 +284,7 @@ struct cff2_private_blend_encoder_param_
   unsigned ivs = 0;
   unsigned region_count = 0;
   hb_vector_t<float> scalars;
-  const  CFF2VariationStore *varStore = nullptr;
+  const  CFF2ItemVariationStore *varStore = nullptr;
   hb_array_t<int> normalized_coords;
 };
 
@@ -378,7 +378,7 @@ struct cff2_private_dict_blend_opset_t :
 struct cff2_private_dict_op_serializer_t : op_serializer_t
 {
   cff2_private_dict_op_serializer_t (bool desubroutinize_, bool drop_hints_, bool pinned_,
-                                     const CFF::CFF2VariationStore* varStore_,
+                                     const CFF::CFF2ItemVariationStore* varStore_,
                                      hb_array_t<int> normalized_coords_)
     : desubroutinize (desubroutinize_), drop_hints (drop_hints_), pinned (pinned_),
       varStore (varStore_), normalized_coords (normalized_coords_) {}
@@ -416,7 +416,7 @@ struct cff2_private_dict_op_serializer_t
   const bool desubroutinize;
   const bool drop_hints;
   const bool pinned;
-  const CFF::CFF2VariationStore* varStore;
+  const CFF::CFF2ItemVariationStore* varStore;
   hb_array_t<int> normalized_coords;
 };
 
@@ -439,6 +439,12 @@ struct cff2_subset_plan
     desubroutinize = plan->flags & HB_SUBSET_FLAGS_DESUBROUTINIZE ||
                      pinned; // For instancing we need this path
 
+ #ifdef HB_EXPERIMENTAL_API
+    min_charstrings_off_size = (plan->flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS) ? 4 : 0;
+ #else
+    min_charstrings_off_size = 0;
+ #endif
+
     if (desubroutinize)
     {
       /* Flatten global & local subrs */
@@ -510,14 +516,45 @@ struct cff2_subset_plan
 
   bool      drop_hints = false;
   bool      desubroutinize = false;
+
+  unsigned  min_charstrings_off_size = 0;
 };
 } // namespace OT
 
+static bool _serialize_cff2_charstrings (hb_serialize_context_t *c,
+                             cff2_subset_plan &plan,
+                             const OT::cff2::accelerator_subset_t  &acc)
+{
+  c->push ();
+
+  unsigned data_size = 0;
+  unsigned total_size = CFF2CharStrings::total_size (plan.subset_charstrings, &data_size, plan.min_charstrings_off_size);
+  if (unlikely (!c->start_zerocopy (total_size)))
+    return false;
+
+  auto *cs = c->start_embed<CFF2CharStrings> ();
+  if (unlikely (!cs->serialize (c, plan.subset_charstrings, &data_size, plan.min_charstrings_off_size)))
+  {
+    c->pop_discard ();
+    return false;
+  }
+
+  plan.info.char_strings_link = c->pop_pack (false);
+  return true;
+}
+
 bool
 OT::cff2::accelerator_subset_t::serialize (hb_serialize_context_t *c,
                                            struct cff2_subset_plan &plan,
                                            hb_array_t<int> normalized_coords) const
 {
+  /* push charstrings onto the object stack first which will ensure it packs as the last
+     object in the table. Keeping the chastrings last satisfies the requirements for patching
+     via IFTB. If this ordering needs to be changed in the future, charstrings should be left
+     at the end whenever HB_SUBSET_FLAGS_ITFB_REQUIREMENTS is enabled. */
+  if (!_serialize_cff2_charstrings(c, plan, *this))
+    return false;
+
   /* private dicts & local subrs */
   hb_vector_t<table_info_t>  private_dict_infos;
   if (unlikely (!private_dict_infos.resize (plan.subset_fdcount))) return false;
@@ -556,25 +593,6 @@ OT::cff2::accelerator_subset_t::serializ
     }
   }
 
-  /* CharStrings */
-  {
-    c->push ();
-
-    unsigned data_size = 0;
-    unsigned total_size = CFF2CharStrings::total_size (plan.subset_charstrings, &data_size);
-    if (unlikely (!c->start_zerocopy (total_size)))
-       return false;
-
-    auto *cs = c->start_embed<CFF2CharStrings> ();
-    if (likely (cs->serialize (c, plan.subset_charstrings, &data_size)))
-      plan.info.char_strings_link = c->pop_pack (false);
-    else
-    {
-      c->pop_discard ();
-      return false;
-    }
-  }
-
   /* FDSelect */
   if (fdSelect != &Null (CFF2FDSelect))
   {
@@ -610,10 +628,10 @@ OT::cff2::accelerator_subset_t::serializ
   }
 
   /* variation store */
-  if (varStore != &Null (CFF2VariationStore) &&
+  if (varStore != &Null (CFF2ItemVariationStore) &&
       !plan.pinned)
   {
-    auto *dest = c->push<CFF2VariationStore> ();
+    auto *dest = c->push<CFF2ItemVariationStore> ();
     if (unlikely (!dest->serialize (c, varStore)))
     {
       c->pop_discard ();
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc	2025-06-27 08:03:14.000000000 +0000
@@ -24,6 +24,7 @@
  * Google Author(s): Garret Rieger, Rod Sheeter, Behdad Esfahbod
  */
 
+#include "hb-subset-instancer-solver.hh"
 #include "hb-subset.hh"
 #include "hb-set.hh"
 #include "hb-utf.hh"
@@ -50,7 +51,6 @@ hb_subset_input_t::hb_subset_input_t ()
     HB_TAG ('k', 'e', 'r', 'n'),
 
     // Copied from fontTools:
-    HB_TAG ('B', 'A', 'S', 'E'),
     HB_TAG ('J', 'S', 'T', 'F'),
     HB_TAG ('D', 'S', 'I', 'G'),
     HB_TAG ('E', 'B', 'D', 'T'),
@@ -123,6 +123,12 @@ hb_subset_input_t::hb_subset_input_t ()
     //justify
     HB_TAG ('j', 'a', 'l', 't'), // HarfBuzz doesn't use; others might
 
+    //East Asian spacing
+    HB_TAG ('c', 'h', 'w', 's'),
+    HB_TAG ('v', 'c', 'h', 'w'),
+    HB_TAG ('h', 'a', 'l', 't'),
+    HB_TAG ('v', 'h', 'a', 'l'),
+
     //private
     HB_TAG ('H', 'a', 'r', 'f'),
     HB_TAG ('H', 'A', 'R', 'F'),
@@ -406,12 +412,53 @@ hb_subset_input_keep_everything (hb_subs
   hb_subset_input_set_flags (input,
                              HB_SUBSET_FLAGS_NOTDEF_OUTLINE |
                              HB_SUBSET_FLAGS_GLYPH_NAMES |
+                             HB_SUBSET_FLAGS_NAME_LEGACY |
                              HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES |
                              HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED);
 }
 
 #ifndef HB_NO_VAR
 /**
+ * hb_subset_input_pin_all_axes_to_default: (skip)
+ * @input: a #hb_subset_input_t object.
+ * @face: a #hb_face_t object.
+ *
+ * Pin all axes to default locations in the given subset input object.
+ *
+ * All axes in a font must be pinned. Additionally, `CFF2` table, if present,
+ * will be de-subroutinized.
+ *
+ * Return value: `true` if success, `false` otherwise
+ *
+ * Since: 8.3.1
+ **/
+HB_EXTERN hb_bool_t
+hb_subset_input_pin_all_axes_to_default (hb_subset_input_t  *input,
+                                         hb_face_t          *face)
+{
+  unsigned axis_count = hb_ot_var_get_axis_count (face);
+  if (!axis_count) return false;
+
+  hb_ot_var_axis_info_t *axis_infos = (hb_ot_var_axis_info_t *) hb_calloc (axis_count, sizeof (hb_ot_var_axis_info_t));
+  if (unlikely (!axis_infos)) return false;
+
+  (void) hb_ot_var_get_axis_infos (face, 0, &axis_count, axis_infos);
+
+  for (unsigned i = 0; i < axis_count; i++)
+  {
+    hb_tag_t axis_tag = axis_infos[i].tag;
+    double default_val = (double) axis_infos[i].default_value;
+    if (!input->axes_location.set (axis_tag, Triple (default_val, default_val, default_val)))
+    {
+      hb_free (axis_infos);
+      return false;
+    }
+  }
+  hb_free (axis_infos);
+  return true;
+}
+
+/**
  * hb_subset_input_pin_axis_to_default: (skip)
  * @input: a #hb_subset_input_t object.
  * @face: a #hb_face_t object.
@@ -435,7 +482,7 @@ hb_subset_input_pin_axis_to_default (hb_
   if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
     return false;
 
-  float default_val = axis_info.default_value;
+  double default_val = (double) axis_info.default_value;
   return input->axes_location.set (axis_tag, Triple (default_val, default_val, default_val));
 }
 
@@ -465,37 +512,32 @@ hb_subset_input_pin_axis_location (hb_su
   if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
     return false;
 
-  float val = hb_clamp(axis_value, axis_info.min_value, axis_info.max_value);
+  double val = hb_clamp((double) axis_value, (double) axis_info.min_value, (double) axis_info.max_value);
   return input->axes_location.set (axis_tag, Triple (val, val, val));
 }
 
-#ifdef HB_EXPERIMENTAL_API
 /**
  * hb_subset_input_set_axis_range: (skip)
  * @input: a #hb_subset_input_t object.
  * @face: a #hb_face_t object.
  * @axis_tag: Tag of the axis
- * @axis_min_value: Minimum value of the axis variation range to set
- * @axis_max_value: Maximum value of the axis variation range to set
- * @axis_def_value: Default value of the axis variation range to set, in case of
- * null, it'll be determined automatically
+ * @axis_min_value: Minimum value of the axis variation range to set, if NaN the existing min will be used.
+ * @axis_max_value: Maximum value of the axis variation range to set  if NaN the existing max will be used.
+ * @axis_def_value: Default value of the axis variation range to set, if NaN the existing default will be used.
  *
  * Restricting the range of variation on an axis in the given subset input object.
  * New min/default/max values will be clamped if they're not within the fvar axis range.
- * If the new default value is null:
- * If the fvar axis default value is within the new range, then new default
- * value is the same as original default value.
+ *
  * If the fvar axis default value is not within the new range, the new default
  * value will be changed to the new min or max value, whichever is closer to the fvar
  * axis default.
  *
  * Note: input min value can not be bigger than input max value. If the input
  * default value is not within the new min/max range, it'll be clamped.
- * Note: currently it supports gvar and cvar tables only.
  *
  * Return value: `true` if success, `false` otherwise
  *
- * XSince: EXPERIMENTAL
+ * Since: 8.5.0
  **/
 HB_EXTERN hb_bool_t
 hb_subset_input_set_axis_range (hb_subset_input_t  *input,
@@ -503,22 +545,195 @@ hb_subset_input_set_axis_range (hb_subse
                                 hb_tag_t            axis_tag,
                                 float               axis_min_value,
                                 float               axis_max_value,
-                                float              *axis_def_value /* IN, maybe NULL */)
+                                float               axis_def_value)
 {
-  if (axis_min_value > axis_max_value)
-    return false;
-
   hb_ot_var_axis_info_t axis_info;
   if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
     return false;
 
-  float new_min_val = hb_clamp(axis_min_value, axis_info.min_value, axis_info.max_value);
-  float new_max_val = hb_clamp(axis_max_value, axis_info.min_value, axis_info.max_value);
-  float new_default_val = axis_def_value ? *axis_def_value : axis_info.default_value;
-  new_default_val = hb_clamp(new_default_val, new_min_val, new_max_val);
-  return input->axes_location.set (axis_tag, Triple (new_min_val, new_default_val, new_max_val));
+  float min = !std::isnan(axis_min_value) ? axis_min_value : axis_info.min_value;
+  float max = !std::isnan(axis_max_value) ? axis_max_value : axis_info.max_value;
+  float def = !std::isnan(axis_def_value) ? axis_def_value : axis_info.default_value;
+
+  if (min > max)
+    return false;
+
+  float new_min_val = hb_clamp(min, axis_info.min_value, axis_info.max_value);
+  float new_max_val = hb_clamp(max, axis_info.min_value, axis_info.max_value);
+  float new_default_val = hb_clamp(def, new_min_val, new_max_val);
+  return input->axes_location.set (axis_tag, Triple ((double) new_min_val, (double) new_default_val, (double) new_max_val));
+}
+
+/**
+ * hb_subset_input_get_axis_range: (skip)
+ * @input: a #hb_subset_input_t object.
+ * @axis_tag: Tag of the axis
+ * @axis_min_value: Set to the previously configured minimum value of the axis variation range.
+ * @axis_max_value: Set to the previously configured maximum value of the axis variation range.
+ * @axis_def_value: Set to the previously configured default value of the axis variation range.
+ *
+ * Gets the axis range assigned by previous calls to hb_subset_input_set_axis_range.
+ *
+ * Return value: `true` if a range has been set for this axis tag, `false` otherwise.
+ *
+ * Since: 8.5.0
+ **/
+HB_EXTERN hb_bool_t
+hb_subset_input_get_axis_range (hb_subset_input_t  *input,
+                                hb_tag_t            axis_tag,
+                                float              *axis_min_value,
+                                float              *axis_max_value,
+                                float              *axis_def_value)
+
+{
+  Triple* triple;
+  if (!input->axes_location.has(axis_tag, &triple)) {
+    return false;
+  }
+
+  *axis_min_value = triple->minimum;
+  *axis_def_value = triple->middle;
+  *axis_max_value = triple->maximum;
+  return true;
+}
+
+/**
+ * hb_subset_axis_range_from_string:
+ * @str: a string to parse
+ * @len: length of @str, or -1 if str is NULL terminated
+ * @axis_min_value: (out): the axis min value to initialize with the parsed value
+ * @axis_max_value: (out): the axis max value to initialize with the parsed value
+ * @axis_def_value: (out): the axis default value to initialize with the parse
+ * value
+ *
+ * Parses a string into a subset axis range(min, def, max).
+ * Axis positions string is in the format of min:def:max or min:max
+ * When parsing axis positions, empty values as meaning the existing value for that part
+ * E.g: :300:500
+ * Specifies min = existing, def = 300, max = 500
+ * In the output axis_range, if a value should be set to it's default value,
+ * then it will be set to NaN
+ *
+ * Return value:
+ * `true` if @str is successfully parsed, `false` otherwise
+ *
+ * Since: 10.2.0
+ */
+HB_EXTERN hb_bool_t
+hb_subset_axis_range_from_string (const char *str, int len,
+                                  float *axis_min_value,
+                                  float *axis_max_value,
+                                  float *axis_def_value)
+{
+  if (len < 0)
+    len = strlen (str);
+
+  const char *end = str + len;
+  const char* part = strpbrk (str, ":");
+  if (!part)
+  {
+    // Single value.
+    if (strcmp (str, "drop") == 0)
+    {
+      *axis_min_value = NAN;
+      *axis_def_value = NAN;
+      *axis_max_value = NAN;
+      return true;
+    }
+
+    double v;
+    if (!hb_parse_double (&str, end, &v)) return false;
+
+    *axis_min_value = v;
+    *axis_def_value = v;
+    *axis_max_value = v;
+    return true;
+  }
+
+  float values[3];
+  int count = 0;
+  for (int i = 0; i < 3; i++) {
+    count++;
+    if (!*str || part == str)
+    {
+      values[i] = NAN;
+
+      if (part == NULL) break;
+      str = part + 1;
+      part = strpbrk (str, ":");
+      continue;
+    }
+
+    double v;
+    if (!hb_parse_double (&str, part, &v)) return false;
+    values[i] = v;
+
+    if (part == NULL) break;
+    str = part + 1;
+    part = strpbrk (str, ":");
+  }
+
+  if (count == 2)
+  {
+    *axis_min_value = values[0];
+    *axis_def_value = NAN;
+    *axis_max_value = values[1];
+    return true;
+  }
+  else if (count == 3)
+  {
+    *axis_min_value = values[0];
+    *axis_def_value = values[1];
+    *axis_max_value = values[2];
+    return true;
+  }
+  return false;
+}
+
+/**
+ * hb_subset_axis_range_to_string:
+ * @input: a #hb_subset_input_t object.
+ * @axis_tag: an axis to convert
+ * @buf: (array length=size) (out caller-allocates): output string
+ * @size: the allocated size of @buf
+ *
+ * Converts an axis range into a `NULL`-terminated string in the format
+ * understood by hb_subset_axis_range_from_string(). The client in responsible for
+ * allocating big enough size for @buf, 128 bytes is more than enough.
+ *
+ * Since: 10.2.0
+ */
+HB_EXTERN void
+hb_subset_axis_range_to_string (hb_subset_input_t *input,
+                                hb_tag_t axis_tag,
+                                char *buf, unsigned size)
+{
+  if (unlikely (!size)) return;
+  Triple* triple;
+  if (!input->axes_location.has(axis_tag, &triple)) {
+    return;
+  }
+
+  char s[128];
+  unsigned len = 0;
+
+  hb_locale_t clocale HB_UNUSED;
+  hb_locale_t oldlocale HB_UNUSED;
+  oldlocale = hb_uselocale (clocale = newlocale (LC_ALL_MASK, "C", NULL));
+  len += hb_max (0, snprintf (s, ARRAY_LENGTH (s) - len, "%g", (double) triple->minimum));
+  s[len++] = ':';
+
+  len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) triple->middle));
+  s[len++] = ':';
+
+  len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) triple->maximum));
+  (void) hb_uselocale (((void) freelocale (clocale), oldlocale));
+
+  assert (len < ARRAY_LENGTH (s));
+  len = hb_min (len, size - 1);
+  hb_memcpy (buf, s, len);
+  buf[len] = '\0';
 }
-#endif
 #endif
 
 /**
@@ -653,7 +868,7 @@ hb_subset_input_override_name_table (hb_
         src = hb_utf8_t::next (src, src_end, &unicode, replacement);
         if (unicode >= 0x0080u)
         {
-          printf ("Non-ascii character detected, ignored...This API supports acsii characters only for mac platform\n");
+          printf ("Non-ascii character detected, ignored...This API supports ascii characters only for mac platform\n");
           return false;
         }
       }
@@ -667,5 +882,4 @@ hb_subset_input_override_name_table (hb_
   input->name_table_overrides.set (hb_ot_name_record_ids_t (platform_id, encoding_id, language_id, name_id), name_bytes);
   return true;
 }
-
 #endif
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-iup.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-iup.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-iup.hh	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-iup.hh	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2024  Google, Inc.
+ *
+ *  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.
+ */
+
+#ifndef HB_SUBSET_INSTANCER_IUP_HH
+#define HB_SUBSET_INSTANCER_IUP_HH
+
+#include "hb-subset-plan.hh"
+/* given contour points and deltas, optimize a set of referenced points within error
+ * tolerance. Returns optimized referenced point indices */
+HB_INTERNAL bool iup_delta_optimize (const contour_point_vector_t& contour_points,
+                                     const hb_vector_t<int>& x_deltas,
+                                     const hb_vector_t<int>& y_deltas,
+                                     hb_vector_t<bool>& opt_indices, /* OUT */
+                                     double tolerance = 0.0);
+
+#endif /* HB_SUBSET_INSTANCER_IUP_HH */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.cc	2025-06-27 08:03:14.000000000 +0000
@@ -32,17 +32,17 @@
  * This should be safe.
  */
 
-constexpr static float EPSILON = 1.f / (1 << 14);
-constexpr static float MAX_F2DOT14 = float (0x7FFF) / (1 << 14);
+constexpr static double EPSILON = 1.0 / (1 << 14);
+constexpr static double MAX_F2DOT14 = double (0x7FFF) / (1 << 14);
 
 static inline Triple _reverse_negate(const Triple &v)
 { return {-v.maximum, -v.middle, -v.minimum}; }
 
 
-static inline float supportScalar (float coord, const Triple &tent)
+static inline double supportScalar (double coord, const Triple &tent)
 {
   /* Copied from VarRegionAxis::evaluate() */
-  float start = tent.minimum, peak = tent.middle, end = tent.maximum;
+  double start = tent.minimum, peak = tent.middle, end = tent.maximum;
 
   if (unlikely (start > peak || peak > end))
     return 1.;
@@ -62,20 +62,20 @@ static inline float supportScalar (float
     return  (end - coord) / (end - peak);
 }
 
-static inline result_t
+static inline rebase_tent_result_t
 _solve (Triple tent, Triple axisLimit, bool negative = false)
 {
-  float axisMin = axisLimit.minimum;
-  float axisDef = axisLimit.middle;
-  float axisMax = axisLimit.maximum;
-  float lower = tent.minimum;
-  float peak  = tent.middle;
-  float upper = tent.maximum;
+  double axisMin = axisLimit.minimum;
+  double axisDef = axisLimit.middle;
+  double axisMax = axisLimit.maximum;
+  double lower = tent.minimum;
+  double peak  = tent.middle;
+  double upper = tent.maximum;
 
   // Mirror the problem such that axisDef <= peak
   if (axisDef > peak)
   {
-    result_t vec = _solve (_reverse_negate (tent),
+    rebase_tent_result_t vec = _solve (_reverse_negate (tent),
                            _reverse_negate (axisLimit),
                            !negative);
 
@@ -98,7 +98,7 @@ _solve (Triple tent, Triple axisLimit, b
    *    axisMin     axisDef    axisMax   lower     upper
    */
   if (axisMax <= lower && axisMax < peak)
-      return result_t{};  // No overlap
+      return rebase_tent_result_t{};  // No overlap
 
   /* case 2: Only the peak and outermost bound fall outside the new limit;
    * we keep the deltaset, update peak and outermost bound and scale deltas
@@ -130,10 +130,10 @@ _solve (Triple tent, Triple axisLimit, b
    */
   if (axisMax < peak)
   {
-    float mult = supportScalar (axisMax, tent);
+    double mult = supportScalar (axisMax, tent);
     tent = Triple{lower, axisMax, axisMax};
 
-    result_t vec = _solve (tent, axisLimit);
+    rebase_tent_result_t vec = _solve (tent, axisLimit);
 
     for (auto &p : vec)
       p = hb_pair (p.first * mult, p.second);
@@ -143,13 +143,13 @@ _solve (Triple tent, Triple axisLimit, b
 
   // lower <= axisDef <= peak <= axisMax
 
-  float gain = supportScalar (axisDef, tent);
-  result_t out {hb_pair (gain, Triple{})};
+  double gain = supportScalar (axisDef, tent);
+  rebase_tent_result_t out {hb_pair (gain, Triple{})};
 
   // First, the positive side
 
   // outGain is the scalar of axisMax at the tent.
-  float outGain = supportScalar (axisMax, tent);
+  double outGain = supportScalar (axisMax, tent);
 
   /* Case 3a: Gain is more than outGain. The tent down-slope crosses
    * the axis into negative. We have to split it into multiples.
@@ -168,13 +168,15 @@ _solve (Triple tent, Triple axisLimit, b
    *                           |
    *                      crossing
    */
-  if (gain > outGain)
+  if (gain >= outGain)
   {
+    // Note that this is the branch taken if both gain and outGain are 0.
+
     // Crossing point on the axis.
-    float crossing = peak + (1 - gain) * (upper - peak);
+    double crossing = peak + (1 - gain) * (upper - peak);
 
-    Triple loc{axisDef, peak, crossing};
-    float scalar = 1.f;
+    Triple loc{hb_max (lower, axisDef), peak, crossing};
+    double scalar = 1.0;
 
     // The part before the crossing point.
     out.push (hb_pair (scalar - gain, loc));
@@ -189,7 +191,7 @@ _solve (Triple tent, Triple axisLimit, b
     if (upper >= axisMax)
     {
       Triple loc {crossing, axisMax, axisMax};
-      float scalar = outGain;
+      double scalar = outGain;
 
       out.push (hb_pair (scalar - gain, loc));
     }
@@ -219,11 +221,11 @@ _solve (Triple tent, Triple axisLimit, b
 
       // Downslope.
       Triple loc1 {crossing, upper, axisMax};
-      float scalar1 = 0.f;
+      double scalar1 = 0.0;
 
       // Eternity justify.
       Triple loc2 {upper, axisMax, axisMax};
-      float scalar2 = 0.f;
+      double scalar2 = 0.0;
 
       out.push (hb_pair (scalar1 - gain, loc1));
       out.push (hb_pair (scalar2 - gain, loc2));
@@ -252,9 +254,12 @@ _solve (Triple tent, Triple axisLimit, b
      *                    |      |  newUpper
      *              axisDef      axisMax
      */
-    float newUpper = peak + (1 - gain) * (upper - peak);
-    assert (axisMax <= newUpper);  // Because outGain >= gain
-    if (newUpper <= axisDef + (axisMax - axisDef) * 2)
+    double newUpper = peak + (1 - gain) * (upper - peak);
+    assert (axisMax <= newUpper);  // Because outGain > gain
+    /* Disabled because ots doesn't like us:
+     * https://github.com/fonttools/fonttools/issues/3350 */
+
+    if (false && (newUpper <= axisDef + (axisMax - axisDef) * 2))
     {
       upper = newUpper;
       if (!negative && axisDef + (axisMax - axisDef) * MAX_F2DOT14 < upper)
@@ -265,7 +270,7 @@ _solve (Triple tent, Triple axisLimit, b
       }
 
       Triple loc {hb_max (axisDef, lower), peak, upper};
-      float scalar = 1.f;
+      double scalar = 1.0;
 
       out.push (hb_pair (scalar - gain, loc));
     }
@@ -289,10 +294,10 @@ _solve (Triple tent, Triple axisLimit, b
     else
     {
       Triple loc1 {hb_max (axisDef, lower), peak, axisMax};
-      float scalar1 = 1.f;
+      double scalar1 = 1.0;
 
       Triple loc2 {peak, axisMax, axisMax};
-      float scalar2 = outGain;
+      double scalar2 = outGain;
 
       out.push (hb_pair (scalar1 - gain, loc1));
       // Don't add a dirac delta!
@@ -320,7 +325,7 @@ _solve (Triple tent, Triple axisLimit, b
   if (lower <= axisMin)
   {
     Triple loc {axisMin, axisMin, axisDef};
-    float scalar = supportScalar (axisMin, tent);
+    double scalar = supportScalar (axisMin, tent);
 
     out.push (hb_pair (scalar - gain, loc));
   }
@@ -348,11 +353,11 @@ _solve (Triple tent, Triple axisLimit, b
 
     // Downslope.
     Triple loc1 {axisMin, lower, axisDef};
-    float scalar1 = 0.f;
+    double scalar1 = 0.0;
 
     // Eternity justify.
     Triple loc2 {axisMin, axisMin, lower};
-    float scalar2 = 0.f;
+    double scalar2 = 0.0;
 
     out.push (hb_pair (scalar1 - gain, loc1));
     out.push (hb_pair (scalar2 - gain, loc2));
@@ -364,19 +369,19 @@ _solve (Triple tent, Triple axisLimit, b
 static inline TripleDistances _reverse_triple_distances (const TripleDistances &v)
 { return TripleDistances (v.positive, v.negative); }
 
-float renormalizeValue (float v, const Triple &triple,
-                        const TripleDistances &triple_distances, bool extrapolate)
+double renormalizeValue (double v, const Triple &triple,
+                         const TripleDistances &triple_distances, bool extrapolate)
 {
-  float lower = triple.minimum, def = triple.middle, upper = triple.maximum;
+  double lower = triple.minimum, def = triple.middle, upper = triple.maximum;
   assert (lower <= def && def <= upper);
 
   if (!extrapolate)
-      v = hb_max (hb_min (v, upper), lower);
+    v = hb_clamp (v, lower, upper);
 
   if (v == def)
-    return 0.f;
+    return 0.0;
 
-  if (def < 0.f)
+  if (def < 0.0)
     return -renormalizeValue (-v, _reverse_negate (triple),
                               _reverse_triple_distances (triple_distances), extrapolate);
 
@@ -385,14 +390,14 @@ float renormalizeValue (float v, const T
     return (v - def) / (upper - def);
 
   /* v < def */
-  if (lower >= 0.f)
+  if (lower >= 0.0)
     return (v - def) / (def - lower);
 
   /* lower < 0 and v < default */
-  float total_distance = triple_distances.negative * (-lower) + triple_distances.positive * def;
+  double total_distance = triple_distances.negative * (-lower) + triple_distances.positive * def;
 
-  float v_distance;
-  if (v >= 0.f)
+  double v_distance;
+  if (v >= 0.0)
     v_distance = (def - v) * triple_distances.positive;
   else
     v_distance = (-v) * triple_distances.negative + triple_distances.positive * def;
@@ -400,18 +405,18 @@ float renormalizeValue (float v, const T
   return (-v_distance) /total_distance;
 }
 
-result_t
+rebase_tent_result_t
 rebase_tent (Triple tent, Triple axisLimit, TripleDistances axis_triple_distances)
 {
-  assert (-1.f <= axisLimit.minimum && axisLimit.minimum <= axisLimit.middle && axisLimit.middle <= axisLimit.maximum && axisLimit.maximum <= +1.f);
-  assert (-2.f <= tent.minimum && tent.minimum <= tent.middle && tent.middle <= tent.maximum && tent.maximum <= +2.f);
-  assert (tent.middle != 0.f);
+  assert (-1.0 <= axisLimit.minimum && axisLimit.minimum <= axisLimit.middle && axisLimit.middle <= axisLimit.maximum && axisLimit.maximum <= +1.0);
+  assert (-2.0 <= tent.minimum && tent.minimum <= tent.middle && tent.middle <= tent.maximum && tent.maximum <= +2.0);
+  assert (tent.middle != 0.0);
 
-  result_t sols = _solve (tent, axisLimit);
+  rebase_tent_result_t sols = _solve (tent, axisLimit);
 
-  auto n = [&axisLimit, &axis_triple_distances] (float v) { return renormalizeValue (v, axisLimit, axis_triple_distances); };
+  auto n = [&axisLimit, &axis_triple_distances] (double v) { return renormalizeValue (v, axisLimit, axis_triple_distances); };
 
-  result_t out;
+  rebase_tent_result_t out;
   for (auto &p : sols)
   {
     if (!p.first) continue;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.hh	2025-06-27 08:03:14.000000000 +0000
@@ -30,24 +30,24 @@
 /* pre-normalized distances */
 struct TripleDistances
 {
-  TripleDistances (): negative (1.f), positive (1.f) {}
-  TripleDistances (float neg_, float pos_): negative (neg_), positive (pos_) {}
-  TripleDistances (float min, float default_, float max)
+  TripleDistances (): negative (1.0), positive (1.0) {}
+  TripleDistances (double neg_, double pos_): negative (neg_), positive (pos_) {}
+  TripleDistances (double min, double default_, double max)
   {
     negative = default_ - min;
     positive = max - default_;
   }
 
-  float negative;
-  float positive;
+  double negative;
+  double positive;
 };
 
 struct Triple {
 
   Triple () :
-    minimum (0.f), middle (0.f), maximum (0.f) {}
+    minimum (0.0), middle (0.0), maximum (0.0) {}
 
-  Triple (float minimum_, float middle_, float maximum_) :
+  Triple (double minimum_, double middle_, double maximum_) :
     minimum (minimum_), middle (middle_), maximum (maximum_) {}
 
   bool operator == (const Triple &o) const
@@ -63,7 +63,7 @@ struct Triple {
   bool is_point () const
   { return minimum == middle && middle == maximum; }
 
-  bool contains (float point) const
+  bool contains (double point) const
   { return minimum <= point && point <= maximum; }
 
   /* from hb_array_t hash ()*/
@@ -82,18 +82,18 @@ struct Triple {
   }
 
 
-  float minimum;
-  float middle;
-  float maximum;
+  double minimum;
+  double middle;
+  double maximum;
 };
 
-using result_item_t = hb_pair_t<float, Triple>;
-using result_t = hb_vector_t<result_item_t>;
+using rebase_tent_result_item_t = hb_pair_t<double, Triple>;
+using rebase_tent_result_t = hb_vector_t<rebase_tent_result_item_t>;
 
 /* renormalize a normalized value v to the range of an axis,
  * considering the prenormalized distances as well as the new axis limits.
  * Ported from fonttools */
-HB_INTERNAL float renormalizeValue (float v, const Triple &triple,
+HB_INTERNAL double renormalizeValue (double v, const Triple &triple,
                                     const TripleDistances &triple_distances,
                                     bool extrapolate = true);
 /* Given a tuple (lower,peak,upper) "tent" and new axis limits
@@ -107,6 +107,8 @@ HB_INTERNAL float renormalizeValue (floa
  * If tent value is Triple{}, that is a special deltaset that should
  * be always-enabled (called "gain").
  */
-HB_INTERNAL result_t rebase_tent (Triple tent, Triple axisLimit, TripleDistances axis_triple_distances);
+HB_INTERNAL rebase_tent_result_t rebase_tent (Triple tent,
+                                              Triple axisLimit,
+                                              TripleDistances axis_triple_distances);
 
 #endif /* HB_SUBSET_INSTANCER_SOLVER_HH */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-plan-member-list.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-plan-member-list.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-plan-member-list.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-plan-member-list.hh	2025-06-27 08:03:14.000000000 +0000
@@ -70,6 +70,9 @@ HB_SUBSET_PLAN_MEMBER (hb_set_t, _glyphs
 HB_SUBSET_PLAN_MEMBER (hb_map_t, gsub_lookups)
 HB_SUBSET_PLAN_MEMBER (hb_map_t, gpos_lookups)
 
+//use_mark_sets mapping: old->new
+HB_SUBSET_PLAN_MEMBER (hb_map_t, used_mark_sets_map)
+
 //active langsys we'd like to retain
 HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<unsigned, hb::unique_ptr<hb_set_t>>), gsub_langsys)
 HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<unsigned, hb::unique_ptr<hb_set_t>>), gpos_langsys)
@@ -87,9 +90,24 @@ HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<u
 HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<unsigned, const OT::Feature*>), gsub_feature_substitutes_map)
 HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<unsigned, const OT::Feature*>), gpos_feature_substitutes_map)
 
+// old feature_indexes set, used to reinstate the old features
+HB_SUBSET_PLAN_MEMBER (hb_set_t, gsub_old_features)
+HB_SUBSET_PLAN_MEMBER (hb_set_t, gpos_old_features)
+
+//feature_index->pair of (address of old feature, feature tag), used for inserting a catch all record
+//if necessary
+HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<unsigned, hb_pair_t E(<const void*, const void*>)>), gsub_old_feature_idx_tag_map)
+HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<unsigned, hb_pair_t E(<const void*, const void*>)>), gpos_old_feature_idx_tag_map)
+
 //active layers/palettes we'd like to retain
 HB_SUBSET_PLAN_MEMBER (hb_map_t, colrv1_layers)
 HB_SUBSET_PLAN_MEMBER (hb_map_t, colr_palettes)
+//colrv1 varstore retained varidx mapping
+HB_SUBSET_PLAN_MEMBER (hb_vector_t<hb_inc_bimap_t>, colrv1_varstore_inner_maps)
+//colrv1 retained varidx -> (new varidx, delta) mapping
+HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(<unsigned, hb_pair_t E(<unsigned, int>)>), colrv1_variation_idx_delta_map)
+//colrv1 retained new delta set index -> new varidx mapping
+HB_SUBSET_PLAN_MEMBER (hb_map_t, colrv1_new_deltaset_idx_varidx_map)
 
 //Old layout item variation index -> (New varidx, delta) mapping
 HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(<unsigned, hb_pair_t E(<unsigned, int>)>), layout_variation_idx_delta_map)
@@ -128,6 +146,15 @@ HB_SUBSET_PLAN_MEMBER (mutable hb_vector
 //map: new_gid -> contour points vector
 HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(<hb_codepoint_t, contour_point_vector_t>), new_gid_contour_points_map)
 
+//new gids set for composite glyphs
+HB_SUBSET_PLAN_MEMBER (hb_set_t, composite_new_gids)
+
+//Old BASE item variation index -> (New varidx, 0) mapping
+HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(<unsigned, hb_pair_t E(<unsigned, int>)>), base_variation_idx_map)
+
+//BASE table varstore retained varidx mapping
+HB_SUBSET_PLAN_MEMBER (hb_vector_t<hb_inc_bimap_t>, base_varstore_inner_maps)
+
 #ifdef HB_EXPERIMENTAL_API
 // name table overrides map: hb_ot_name_record_ids_t-> name string new value or
 // None to indicate should remove
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc	2025-06-27 08:03:14.000000000 +0000
@@ -32,6 +32,7 @@
 
 #include "hb-ot-cmap-table.hh"
 #include "hb-ot-glyf-table.hh"
+#include "hb-ot-layout-base-table.hh"
 #include "hb-ot-layout-gdef-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
 #include "hb-ot-layout-gsub-table.hh"
@@ -150,7 +151,8 @@ static void _collect_layout_indices (hb_
                                      hb_set_t             *feature_indices, /* OUT */
                                      hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* OUT */
                                      hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map, /* OUT */
-                                     bool& insert_catch_all_feature_variation_record)
+                                     hb_set_t& catch_all_record_feature_idxes, /* OUT */
+                                     hb_hashmap_t<unsigned, hb_pair_t<const void*, const void*>>& catch_all_record_idx_feature_map /* OUT */)
 {
   unsigned num_features = table.get_feature_count ();
   hb_vector_t<hb_tag_t> features;
@@ -186,7 +188,7 @@ static void _collect_layout_indices (hb_
       &plan->axes_location,
       feature_record_cond_idx_map,
       feature_substitutes_map,
-      insert_catch_all_feature_variation_record,
+      catch_all_record_feature_idxes,
       feature_indices,
       false,
       false,
@@ -208,17 +210,25 @@ static void _collect_layout_indices (hb_
     f->add_lookup_indexes_to (lookup_indices);
   }
 
+#ifndef HB_NO_VAR
+  if (catch_all_record_feature_idxes)
+  {
+    for (unsigned feature_index : catch_all_record_feature_idxes)
+    {
+      const OT::Feature& f = table.get_feature (feature_index);
+      f.add_lookup_indexes_to (lookup_indices);
+      const void *tag = reinterpret_cast<const void*> (&(table.get_feature_list ().get_tag (feature_index)));
+      catch_all_record_idx_feature_map.set (feature_index, hb_pair (&f, tag));
+    }
+  }
+
   // If all axes are pinned then all feature variations will be dropped so there's no need
   // to collect lookups from them.
   if (!plan->all_axes_pinned)
-  {
-    // TODO(qxliu76): this collection doesn't work correctly for feature variations that are dropped
-    //                but not applied. The collection will collect and retain the lookup indices
-    //                associated with those dropped but not activated rules. Since partial instancing
-    //                isn't yet supported this isn't an issue yet but will need to be fixed for
-    //                partial instancing.
-    table.feature_variation_collect_lookups (feature_indices, feature_substitutes_map, lookup_indices);
-  }
+    table.feature_variation_collect_lookups (feature_indices,
+                                             plan->user_axes_location.is_empty () ? nullptr: feature_record_cond_idx_map,
+                                             lookup_indices);
+#endif
 }
 
 
@@ -302,7 +312,8 @@ _closure_glyphs_lookups_features (hb_sub
                                   script_langsys_map *langsys_map,
                                   hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
                                   hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map,
-                                  bool& insert_catch_all_feature_variation_record)
+                                  hb_set_t &catch_all_record_feature_idxes,
+                                  hb_hashmap_t<unsigned, hb_pair_t<const void*, const void*>>& catch_all_record_idx_feature_map)
 {
   hb_blob_ptr_t<T> table = plan->source_table<T> ();
   hb_tag_t table_tag = table->tableTag;
@@ -313,7 +324,8 @@ _closure_glyphs_lookups_features (hb_sub
                               &feature_indices,
                               feature_record_cond_idx_map,
                               feature_substitutes_map,
-                              insert_catch_all_feature_variation_record);
+                              catch_all_record_feature_idxes,
+                              catch_all_record_idx_feature_map);
 
   if (table_tag == HB_OT_TAG_GSUB && !(plan->flags & HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE))
     hb_ot_layout_lookups_substitute_closure (plan->source,
@@ -387,12 +399,55 @@ _get_hb_font_with_variations (const hb_s
 }
 
 static inline void
+_remap_variation_indices (const OT::ItemVariationStore &var_store,
+                          const hb_set_t &variation_indices,
+                          const hb_vector_t<int>& normalized_coords,
+                          bool calculate_delta, /* not pinned at default */
+                          bool no_variations, /* all axes pinned */
+                          hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map /* OUT */)
+{
+  if (&var_store == &Null (OT::ItemVariationStore)) return;
+  unsigned subtable_count = var_store.get_sub_table_count ();
+  float *store_cache = var_store.create_cache ();
+
+  unsigned new_major = 0, new_minor = 0;
+  unsigned last_major = (variation_indices.get_min ()) >> 16;
+  for (unsigned idx : variation_indices)
+  {
+    int delta = 0;
+    if (calculate_delta)
+      delta = roundf (var_store.get_delta (idx, normalized_coords.arrayZ,
+                                           normalized_coords.length, store_cache));
+
+    if (no_variations)
+    {
+      variation_idx_delta_map.set (idx, hb_pair_t<unsigned, int> (HB_OT_LAYOUT_NO_VARIATIONS_INDEX, delta));
+      continue;
+    }
+
+    uint16_t major = idx >> 16;
+    if (major >= subtable_count) break;
+    if (major != last_major)
+    {
+      new_minor = 0;
+      ++new_major;
+    }
+
+    unsigned new_idx = (new_major << 16) + new_minor;
+    variation_idx_delta_map.set (idx, hb_pair_t<unsigned, int> (new_idx, delta));
+    ++new_minor;
+    last_major = major;
+  }
+  var_store.destroy_cache (store_cache);
+}
+
+static inline void
 _collect_layout_variation_indices (hb_subset_plan_t* plan)
 {
   hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> ();
   hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> ();
 
-  if (!gdef->has_data ())
+  if (!gdef->has_data () || !gdef->has_var_store ())
   {
     gdef.destroy ();
     gpos.destroy ();
@@ -408,18 +463,47 @@ _collect_layout_variation_indices (hb_su
   if (hb_ot_layout_has_positioning (plan->source))
     gpos->collect_variation_indices (&c);
 
-  gdef->remap_layout_variation_indices (&varidx_set,
-                                        plan->normalized_coords,
-                                        !plan->pinned_at_default,
-                                        plan->all_axes_pinned,
-                                        &plan->layout_variation_idx_delta_map);
+  _remap_variation_indices (gdef->get_var_store (),
+                            varidx_set, plan->normalized_coords,
+                            !plan->pinned_at_default,
+                            plan->all_axes_pinned,
+                            plan->layout_variation_idx_delta_map);
 
-  unsigned subtable_count = gdef->has_var_store () ? gdef->get_var_store ().get_sub_table_count () : 0;
+  unsigned subtable_count = gdef->get_var_store ().get_sub_table_count ();
   _generate_varstore_inner_maps (varidx_set, subtable_count, plan->gdef_varstore_inner_maps);
 
   gdef.destroy ();
   gpos.destroy ();
 }
+
+#ifndef HB_NO_BASE
+static inline void
+_collect_base_variation_indices (hb_subset_plan_t* plan)
+{
+  hb_blob_ptr_t<OT::BASE> base = plan->source_table<OT::BASE> ();
+  if (!base->has_var_store ())
+  {
+    base.destroy ();
+    return;
+  }
+
+  hb_set_t varidx_set;
+  base->collect_variation_indices (plan, varidx_set);
+  const OT::ItemVariationStore &var_store = base->get_var_store ();
+  unsigned subtable_count = var_store.get_sub_table_count ();
+
+
+  _remap_variation_indices (var_store, varidx_set,
+                            plan->normalized_coords,
+                            !plan->pinned_at_default,
+                            plan->all_axes_pinned,
+                            plan->base_variation_idx_map);
+  _generate_varstore_inner_maps (varidx_set, subtable_count, plan->base_varstore_inner_maps);
+
+  base.destroy ();
+}
+
+#endif
 #endif
 
 static inline void
@@ -431,12 +515,45 @@ _cmap_closure (hb_face_t           *face
   cmap.table->closure_glyphs (unicodes, glyphset);
 }
 
-static void _colr_closure (hb_face_t *face,
-                           hb_map_t *layers_map,
-                           hb_map_t *palettes_map,
+#ifndef HB_NO_VAR
+static void
+_remap_colrv1_delta_set_index_indices (const OT::DeltaSetIndexMap &index_map,
+                                       const hb_set_t &delta_set_idxes,
+                                       hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map, /* IN/OUT */
+                                       hb_map_t &new_deltaset_idx_varidx_map /* OUT */)
+{
+  if (!index_map.get_map_count ())
+    return;
+
+  hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> delta_set_idx_delta_map;
+  unsigned new_delta_set_idx = 0;
+  for (unsigned delta_set_idx : delta_set_idxes)
+  {
+    unsigned var_idx = index_map.map (delta_set_idx);
+    unsigned new_varidx = HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
+    int delta = 0;
+
+    if (var_idx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
+    {
+      hb_pair_t<unsigned, int> *new_varidx_delta;
+      if (!variation_idx_delta_map.has (var_idx, &new_varidx_delta)) continue;
+
+      new_varidx = hb_first (*new_varidx_delta);
+      delta = hb_second (*new_varidx_delta);
+    }
+
+    new_deltaset_idx_varidx_map.set (new_delta_set_idx, new_varidx);
+    delta_set_idx_delta_map.set (delta_set_idx, hb_pair_t<unsigned, int> (new_delta_set_idx, delta));
+    new_delta_set_idx++;
+  }
+  variation_idx_delta_map = std::move (delta_set_idx_delta_map);
+}
+#endif
+
+static void _colr_closure (hb_subset_plan_t* plan,
                            hb_set_t *glyphs_colred)
 {
-  OT::COLR::accelerator_t colr (face);
+  OT::COLR::accelerator_t colr (plan->source);
   if (!colr.is_valid ()) return;
 
   hb_set_t palette_indices, layer_indices;
@@ -448,11 +565,45 @@ static void _colr_closure (hb_face_t *fa
   glyphs_colred->union_ (glyphset_colrv0);
 
   //closure for COLRv1
-  colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices);
+  hb_set_t variation_indices, delta_set_indices;
+  colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices, &variation_indices, &delta_set_indices);
 
   colr.closure_V0palette_indices (glyphs_colred, &palette_indices);
-  _remap_indexes (&layer_indices, layers_map);
-  _remap_palette_indexes (&palette_indices, palettes_map);
+  _remap_indexes (&layer_indices, &plan->colrv1_layers);
+  _remap_palette_indexes (&palette_indices, &plan->colr_palettes);
+
+#ifndef HB_NO_VAR
+  if (!colr.has_var_store () || !variation_indices) return;
+
+  const OT::ItemVariationStore &var_store = colr.get_var_store ();
+  // generated inner_maps is used by ItemVariationStore serialize(), which is subset only
+  unsigned subtable_count = var_store.get_sub_table_count ();
+  _generate_varstore_inner_maps (variation_indices, subtable_count, plan->colrv1_varstore_inner_maps);
+
+  /* colr variation indices mapping during planning phase:
+   * generate colrv1_variation_idx_delta_map. When delta set index map is not
+   * included, it's a mapping from varIdx-> (new varIdx,delta). Otherwise, it's
+   * a mapping from old delta set idx-> (new delta set idx, delta). Mapping
+   * delta set indices is the same as gid mapping.
+   * Besides, we need to generate a delta set idx-> new var_idx map for updating
+   * delta set index map if exists. This map will be updated again after
+   * instancing. */
+  if (!plan->all_axes_pinned)
+  {
+    _remap_variation_indices (var_store,
+                              variation_indices,
+                              plan->normalized_coords,
+                              false, /* no need to calculate delta for COLR during planning */
+                              plan->all_axes_pinned,
+                              plan->colrv1_variation_idx_delta_map);
+
+    if (colr.has_delta_set_index_map ())
+      _remap_colrv1_delta_set_index_indices (colr.get_delta_set_index_map (),
+                                             delta_set_indices,
+                                             plan->colrv1_variation_idx_delta_map,
+                                             plan->colrv1_new_deltaset_idx_varidx_map);
+  }
+#endif
 }
 
 static inline void
@@ -465,6 +616,24 @@ _math_closure (hb_subset_plan_t *plan,
   math.destroy ();
 }
 
+static inline void
+_remap_used_mark_sets (hb_subset_plan_t *plan,
+                       hb_map_t& used_mark_sets_map)
+{
+  hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> ();
+
+  if (!gdef->has_data () || !gdef->has_mark_glyph_sets ())
+  {
+    gdef.destroy ();
+    return;
+  }
+
+  hb_set_t used_mark_sets;
+  gdef->get_mark_glyph_sets ().collect_used_mark_sets (plan->_glyphset_gsub, used_mark_sets);
+  gdef.destroy ();
+
+  _remap_indexes (&used_mark_sets, &used_mark_sets_map);
+}
 
 static inline void
 _remove_invalid_gids (hb_set_t *glyphs,
@@ -473,6 +642,36 @@ _remove_invalid_gids (hb_set_t *glyphs,
   glyphs->del_range (num_glyphs, HB_SET_VALUE_INVALID);
 }
 
+template<bool GID_ALWAYS_EXISTS = false, typename I, typename F, typename G, hb_requires (hb_is_iterator (I))>
+static void
+_fill_unicode_and_glyph_map(hb_subset_plan_t *plan,
+                            I unicode_iterator,
+                            F unicode_to_gid_for_iterator,
+                            G unicode_to_gid_general)
+{
+  for (hb_codepoint_t cp : unicode_iterator)
+  {
+    hb_codepoint_t gid = unicode_to_gid_for_iterator(cp);
+    if (!GID_ALWAYS_EXISTS && gid == HB_MAP_VALUE_INVALID)
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
+      continue;
+    }
+
+    plan->codepoint_to_glyph->set (cp, gid);
+    plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+  }
+}
+
+template<bool GID_ALWAYS_EXISTS = false, typename I, typename F, hb_requires (hb_is_iterator (I))>
+static void
+_fill_unicode_and_glyph_map(hb_subset_plan_t *plan,
+                            I unicode_iterator,
+                            F unicode_to_gid_for_iterator)
+{
+  _fill_unicode_and_glyph_map(plan, unicode_iterator, unicode_to_gid_for_iterator, unicode_to_gid_for_iterator);
+}
+
 static void
 _populate_unicodes_to_retain (const hb_set_t *unicodes,
                               const hb_set_t *glyphs,
@@ -480,6 +679,7 @@ _populate_unicodes_to_retain (const hb_s
 {
   OT::cmap::accelerator_t cmap (plan->source);
   unsigned size_threshold = plan->source->get_num_glyphs ();
+
   if (glyphs->is_empty () && unicodes->get_population () < size_threshold)
   {
 
@@ -492,35 +692,21 @@ _populate_unicodes_to_retain (const hb_s
     // not excessively large (eg. an inverted set).
     plan->unicode_to_new_gid_list.alloc (unicodes->get_population ());
     if (!unicode_to_gid) {
-      for (hb_codepoint_t cp : *unicodes)
-      {
+      _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) {
         hb_codepoint_t gid;
-        if (!cmap.get_nominal_glyph (cp, &gid))
-        {
-          DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
-          continue;
+        if (!cmap.get_nominal_glyph (cp, &gid)) {
+          return HB_MAP_VALUE_INVALID;
         }
-
-        plan->codepoint_to_glyph->set (cp, gid);
-        plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
-      }
+        return gid;
+      });
     } else {
       // Use in memory unicode to gid map it's faster then looking up from
       // the map. This code is mostly duplicated from above to avoid doing
       // conditionals on the presence of the unicode_to_gid map each
       // iteration.
-      for (hb_codepoint_t cp : *unicodes)
-      {
-        hb_codepoint_t gid = unicode_to_gid->get (cp);
-        if (gid == HB_MAP_VALUE_INVALID)
-        {
-          DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
-          continue;
-        }
-
-        plan->codepoint_to_glyph->set (cp, gid);
-        plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
-      }
+      _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) {
+        return unicode_to_gid->get (cp);
+      });
     }
   }
   else
@@ -550,42 +736,46 @@ _populate_unicodes_to_retain (const hb_s
       plan->codepoint_to_glyph->alloc (unicodes->get_population () + glyphs->get_population ());
 
       auto &gid_to_unicodes = plan->accelerator->gid_to_unicodes;
+
       for (hb_codepoint_t gid : *glyphs)
       {
         auto unicodes = gid_to_unicodes.get (gid);
-
-        for (hb_codepoint_t cp : unicodes)
-        {
-          plan->codepoint_to_glyph->set (cp, gid);
-          plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
-        }
+        _fill_unicode_and_glyph_map<true>(plan, unicodes, [&] (hb_codepoint_t cp) {
+          return gid;
+        },
+        [&] (hb_codepoint_t cp) {
+          return unicode_glyphid_map->get(cp);
+        });
       }
-      for (hb_codepoint_t cp : *unicodes)
-      {
-        /* Don't double-add entry. */
+
+      _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) {
+          /* Don't double-add entry. */
         if (plan->codepoint_to_glyph->has (cp))
-          continue;
+          return HB_MAP_VALUE_INVALID;
 
-        hb_codepoint_t *gid;
-        if (!unicode_glyphid_map->has(cp, &gid))
-          continue;
+        return unicode_glyphid_map->get(cp);
+      },
+      [&] (hb_codepoint_t cp) {
+          return unicode_glyphid_map->get(cp);
+      });
 
-        plan->codepoint_to_glyph->set (cp, *gid);
-        plan->unicode_to_new_gid_list.push (hb_pair (cp, *gid));
-      }
       plan->unicode_to_new_gid_list.qsort ();
     }
     else
     {
       plan->codepoint_to_glyph->alloc (cmap_unicodes->get_population ());
-      for (hb_codepoint_t cp : *cmap_unicodes)
+      hb_codepoint_t first = HB_SET_VALUE_INVALID, last = HB_SET_VALUE_INVALID;
+      for (; cmap_unicodes->next_range (&first, &last); )
       {
-        hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
-        if (!unicodes->has (cp) && !glyphs->has (gid))
-          continue;
-
-        plan->codepoint_to_glyph->set (cp, gid);
-        plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+        _fill_unicode_and_glyph_map(plan, hb_range(first, last + 1), [&] (hb_codepoint_t cp) {
+          hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
+          if (!unicodes->has (cp) && !glyphs->has (gid))
+            return HB_MAP_VALUE_INVALID;
+          return gid;
+        },
+        [&] (hb_codepoint_t cp) {
+          return unicode_glyphid_map->get(cp);
+        });
       }
     }
 
@@ -608,11 +798,22 @@ _populate_unicodes_to_retain (const hb_s
     plan->unicodes.add_sorted_array (&arr.arrayZ->first, arr.length, sizeof (*arr.arrayZ));
     plan->_glyphset_gsub.add_array (&arr.arrayZ->second, arr.length, sizeof (*arr.arrayZ));
   }
-}
 
-#ifndef HB_COMPOSITE_OPERATIONS_PER_GLYPH
-#define HB_COMPOSITE_OPERATIONS_PER_GLYPH 64
-#endif
+  // Variation selectors don't have glyphs associated with them in the cmap so they will have been filtered out above
+  // but should still be retained. Add them back here.
+
+  // However, the min and max codepoints for OS/2 should be calculated without considering variation selectors,
+  // so record those first.
+  plan->os2_info.min_cmap_codepoint = plan->unicodes.get_min();
+  plan->os2_info.max_cmap_codepoint = plan->unicodes.get_max();
+
+  hb_set_t variation_selectors_to_retain;
+  cmap.collect_variation_selectors(&variation_selectors_to_retain);
+  + variation_selectors_to_retain.iter()
+  | hb_filter(unicodes)
+  | hb_sink(&plan->unicodes)
+  ;
+}
 
 static unsigned
 _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
@@ -639,18 +840,6 @@ _glyf_add_gid_and_children (const OT::gl
                                   operation_count,
                                   depth);
 
-#ifndef HB_NO_VAR_COMPOSITES
-  for (auto &item : glyph.get_var_composite_iterator ())
-   {
-    operation_count =
-      _glyf_add_gid_and_children (glyf,
-                                  item.get_gid (),
-                                  gids_to_retain,
-                                  operation_count,
-                                  depth);
-   }
-#endif
-
   return operation_count;
 }
 
@@ -714,7 +903,8 @@ _populate_gids_to_retain (hb_subset_plan
         &plan->gsub_langsys,
         &plan->gsub_feature_record_cond_idx_map,
         &plan->gsub_feature_substitutes_map,
-        plan->gsub_insert_catch_all_feature_variation_rec);
+        plan->gsub_old_features,
+        plan->gsub_old_feature_idx_tag_map);
 
   if (!drop_tables->has (HB_OT_TAG_GPOS))
     _closure_glyphs_lookups_features<GPOS> (
@@ -725,7 +915,8 @@ _populate_gids_to_retain (hb_subset_plan
         &plan->gpos_langsys,
         &plan->gpos_feature_record_cond_idx_map,
         &plan->gpos_feature_substitutes_map,
-        plan->gpos_insert_catch_all_feature_variation_rec);
+        plan->gpos_old_features,
+        plan->gpos_old_feature_idx_tag_map);
 #endif
   _remove_invalid_gids (&plan->_glyphset_gsub, plan->source->get_num_glyphs ());
 
@@ -739,19 +930,21 @@ _populate_gids_to_retain (hb_subset_plan
   hb_set_t cur_glyphset = plan->_glyphset_mathed;
   if (!drop_tables->has (HB_OT_TAG_COLR))
   {
-    _colr_closure (plan->source, &plan->colrv1_layers, &plan->colr_palettes, &cur_glyphset);
+    _colr_closure (plan, &cur_glyphset);
     _remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
   }
 
   plan->_glyphset_colred = cur_glyphset;
 
+  // XXX TODO VARC closure / subset
+
   _nameid_closure (plan, drop_tables);
   /* Populate a full set of glyphs to retain by adding all referenced
    * composite glyphs. */
   if (glyf.has_data ())
     for (hb_codepoint_t gid : cur_glyphset)
       _glyf_add_gid_and_children (glyf, gid, &plan->_glyphset,
-                                  cur_glyphset.get_population () * HB_COMPOSITE_OPERATIONS_PER_GLYPH);
+                                  cur_glyphset.get_population () * HB_MAX_COMPOSITE_OPERATIONS_PER_GLYPH);
   else
     plan->_glyphset.union_ (cur_glyphset);
 #ifndef HB_NO_SUBSET_CFF
@@ -871,9 +1064,11 @@ _create_old_gid_to_new_gid_map (const hb
     *num_glyphs = max_glyph + 1;
   }
 
+  reverse_glyph_map->alloc (reverse_glyph_map->get_population () + new_to_old_gid_list->length);
   + hb_iter (new_to_old_gid_list)
   | hb_sink (reverse_glyph_map)
   ;
+  glyph_map->alloc (glyph_map->get_population () + new_to_old_gid_list->length);
   + hb_iter (new_to_old_gid_list)
   | hb_map (&hb_codepoint_pair_t::reverse)
   | hb_sink (glyph_map)
@@ -932,9 +1127,9 @@ _normalize_axes_location (hb_face_t *fac
         normalized_default = seg_maps->map (normalized_default);
         normalized_max = seg_maps->map (normalized_max);
       }
-      plan->axes_location.set (axis_tag, Triple (static_cast<float> (normalized_min / 16384.f),
-                                                 static_cast<float> (normalized_default / 16384.f),
-                                                 static_cast<float> (normalized_max / 16384.f)));
+      plan->axes_location.set (axis_tag, Triple (static_cast<double> (normalized_min / 16384.0),
+                                                 static_cast<double> (normalized_default / 16384.0),
+                                                 static_cast<double> (normalized_max / 16384.0)));
 
       if (normalized_default != 0)
         plan->pinned_at_default = false;
@@ -957,8 +1152,8 @@ _update_instance_metrics_map_from_cff2 (
   OT::cff2::accelerator_t cff2 (plan->source);
   if (!cff2.is_valid ()) return;
 
-  hb_font_t *font = nullptr;
-  if (unlikely (!plan->check_success (font = _get_hb_font_with_variations (plan))))
+  hb_font_t *font = _get_hb_font_with_variations (plan);
+  if (unlikely (!plan->check_success (font != nullptr)))
   {
     hb_font_destroy (font);
     return;
@@ -1036,8 +1231,8 @@ _update_instance_metrics_map_from_cff2 (
 static bool
 _get_instance_glyphs_contour_points (hb_subset_plan_t *plan)
 {
-  /* contour_points vector only needed for updating gvar table (infer delta)
-   * during partial instancing */
+  /* contour_points vector only needed for updating gvar table (infer delta and
+   * iup delta optimization) during partial instancing */
   if (plan->user_axes_location.is_empty () || plan->all_axes_pinned)
     return true;
 
@@ -1055,10 +1250,15 @@ _get_instance_glyphs_contour_points (hb_
     }
 
     hb_codepoint_t old_gid = _.second;
-    if (unlikely (!glyf.glyph_for_gid (old_gid).get_all_points_without_var (plan->source, all_points)))
+    auto glyph = glyf.glyph_for_gid (old_gid);
+    if (unlikely (!glyph.get_all_points_without_var (plan->source, all_points)))
       return false;
     if (unlikely (!plan->new_gid_contour_points_map.set (new_gid, all_points)))
       return false;
+
+    /* composite new gids are only needed by iup delta optimization */
+    if ((plan->flags & HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS) && glyph.is_composite ())
+      plan->composite_new_gids.add (new_gid);
   }
   return true;
 }
@@ -1093,6 +1293,7 @@ hb_subset_plan_t::hb_subset_plan_t (hb_f
   user_axes_location = input->axes_location;
   all_axes_pinned = false;
   pinned_at_default = true;
+  has_gdef_varstore = false;
 
 #ifdef HB_EXPERIMENTAL_API
   for (auto _ : input->name_table_overrides)
@@ -1112,6 +1313,10 @@ hb_subset_plan_t::hb_subset_plan_t (hb_f
 
   attach_accelerator_data = input->attach_accelerator_data;
   force_long_loca = input->force_long_loca;
+#ifdef HB_EXPERIMENTAL_API
+  force_long_loca = force_long_loca || (flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS);
+#endif
+
   if (accel)
     accelerator = (hb_subset_accelerator_t*) accel;
 
@@ -1160,6 +1365,16 @@ hb_subset_plan_t::hb_subset_plan_t (hb_f
   for (auto &v : bounds_height_vec)
     v = 0xFFFFFFFF;
 
+  if (!drop_tables.has (HB_OT_TAG_GDEF))
+    _remap_used_mark_sets (this, used_mark_sets_map);
+
+#ifndef HB_NO_VAR
+#ifndef HB_NO_BASE
+  if (!drop_tables.has (HB_OT_TAG_BASE))
+    _collect_base_variation_indices (this);
+#endif
+#endif
+
   if (unlikely (in_error ()))
     return;
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh	2025-06-27 08:03:14.000000000 +0000
@@ -41,6 +41,13 @@ namespace OT {
 struct Feature;
 }
 
+struct os2_info_t {
+  hb_codepoint_t min_cmap_codepoint;
+  hb_codepoint_t max_cmap_codepoint;
+};
+
+typedef struct os2_info_t os2_info_t;
+
 struct head_maxp_info_t
 {
   head_maxp_info_t ()
@@ -78,10 +85,16 @@ struct contour_point_t
           y  = x * matrix[1] + y * matrix[3];
     x  = x_;
   }
+
+  void add_delta (float delta_x, float delta_y)
+  {
+    x += delta_x;
+    y += delta_y;
+  }
+
   HB_ALWAYS_INLINE
   void translate (const contour_point_t &p) { x += p.x; y += p.y; }
 
-
   float x;
   float y;
   uint8_t flag;
@@ -90,14 +103,20 @@ struct contour_point_t
 
 struct contour_point_vector_t : hb_vector_t<contour_point_t>
 {
-  void extend (const hb_array_t<contour_point_t> &a)
+  bool add_deltas (hb_array_t<const float> deltas_x,
+                   hb_array_t<const float> deltas_y,
+                   hb_array_t<const bool> indices)
   {
-    unsigned int old_len = length;
-    if (unlikely (!resize (old_len + a.length, false)))
-      return;
-    auto arrayZ = this->arrayZ + old_len;
-    unsigned count = a.length;
-    hb_memcpy (arrayZ, a.arrayZ, count * sizeof (arrayZ[0]));
+    if (indices.length != deltas_x.length ||
+        indices.length != deltas_y.length)
+      return false;
+
+    for (unsigned i = 0; i < indices.length; i++)
+    {
+      if (!indices.arrayZ[i]) continue;
+      arrayZ[i].add_delta (deltas_x.arrayZ[i], deltas_y.arrayZ[i]);
+    }
+    return true;
   }
 };
 
@@ -147,6 +166,9 @@ struct hb_subset_plan_t
   bool gsub_insert_catch_all_feature_variation_rec;
   bool gpos_insert_catch_all_feature_variation_rec;
 
+  // whether GDEF ItemVariationStore is retained
+  mutable bool has_gdef_varstore;
+
 #define HB_SUBSET_PLAN_MEMBER(Type, Name) Type Name;
 #include "hb-subset-plan-member-list.hh"
 #undef HB_SUBSET_PLAN_MEMBER
@@ -154,6 +176,8 @@ struct hb_subset_plan_t
   //recalculated head/maxp table info after instancing
   mutable head_maxp_info_t head_maxp_info;
 
+  os2_info_t os2_info;
+
   const hb_subset_accelerator_t* accelerator;
   hb_subset_accelerator_t* inprogress_accelerator;
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-serialize.h 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-serialize.h
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset-serialize.h	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset-serialize.h	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,83 @@
+/*
+ * Copyright © 2022  Google, Inc.
+ *
+ *  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.
+ *
+ */
+
+#ifndef HB_SUBSET_SERIALIZE_H
+#define HB_SUBSET_SERIALIZE_H
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+
+/**
+ * hb_subset_serialize_link_t:
+ * @width: offsetSize in bytes
+ * @position: position of the offset field in bytes from
+ *            beginning of subtable
+ * @objidx: index of subtable
+ *
+ * Represents a link between two objects in the object graph
+ * to be serialized.
+ *
+ * Since: 10.2.0
+ */
+typedef struct hb_subset_serialize_link_t {
+  unsigned int width;
+  unsigned int position;
+  unsigned int objidx;
+} hb_subset_serialize_link_t;
+
+/**
+ * hb_subset_serialize_object_t:
+ * @head: start of object data
+ * @tail: end of object data
+ * @num_real_links: number of offset field in the object
+ * @real_links: array of offset info
+ * @num_virtual_links: number of objects that must be packed
+ *                     after current object in the final
+ *                     serialized order
+ * @virtual_links: array of virtual link info
+ *
+ * Represents an object in the object graph to be serialized.
+ *
+ * Since: 10.2.0
+ */
+typedef struct hb_subset_serialize_object_t {
+  char *head;
+  char *tail;
+  unsigned int num_real_links;
+  hb_subset_serialize_link_t *real_links;
+  unsigned int num_virtual_links;
+  hb_subset_serialize_link_t *virtual_links;
+} hb_subset_serialize_object_t;
+
+HB_EXTERN hb_blob_t *
+hb_subset_serialize_or_fail (hb_tag_t                      table_tag,
+                             hb_subset_serialize_object_t *hb_objects,
+                             unsigned                      num_hb_objs);
+
+
+HB_END_DECLS
+
+#endif /* HB_SUBSET_SERIALIZE_H */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset.cc 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset.cc
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset.cc	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset.cc	2025-06-27 08:03:14.000000000 +0000
@@ -48,6 +48,7 @@
 #include "hb-ot-cff2-table.hh"
 #include "hb-ot-vorg-table.hh"
 #include "hb-ot-name-table.hh"
+#include "hb-ot-layout-base-table.hh"
 #include "hb-ot-layout-gsub-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
 #include "hb-ot-var-avar-table.hh"
@@ -294,8 +295,8 @@ _try_subset (const TableType *table,
   DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.",
              HB_UNTAG (c->table_tag), buf_size);
 
-  if (unlikely (buf_size > c->source_blob->length * 16 ||
-                !buf->alloc (buf_size, true)))
+  if (unlikely (buf_size > c->source_blob->length * 256 ||
+                !buf->alloc_exact (buf_size)))
   {
     DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.",
                HB_UNTAG (c->table_tag), buf_size);
@@ -460,9 +461,10 @@ _dependencies_satisfied (hb_subset_plan_
   case HB_OT_TAG_hmtx:
   case HB_OT_TAG_vmtx:
   case HB_OT_TAG_maxp:
+  case HB_OT_TAG_OS2:
     return !plan->normalized_coords || !pending_subset_tags.has (HB_OT_TAG_glyf);
   case HB_OT_TAG_GPOS:
-    return !plan->normalized_coords || plan->all_axes_pinned || !pending_subset_tags.has (HB_OT_TAG_GDEF);
+    return plan->all_axes_pinned || !pending_subset_tags.has (HB_OT_TAG_GDEF);
   default:
     return true;
   }
@@ -502,6 +504,7 @@ _subset_table (hb_subset_plan_t *plan,
   case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan, buf);
   case HB_OT_TAG_CBDT: return true; /* skip CBDT, handled by CBLC */
   case HB_OT_TAG_MATH: return _subset<const OT::MATH> (plan, buf);
+  case HB_OT_TAG_BASE: return _subset<const OT::BASE> (plan, buf);
 
 #ifndef HB_NO_SUBSET_CFF
   case HB_OT_TAG_CFF1: return _subset<const OT::cff1> (plan, buf);
@@ -547,6 +550,7 @@ _subset_table (hb_subset_plan_t *plan,
     }
 #endif
     return _passthrough (plan, tag);
+
   default:
     if (plan->flags & HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED)
       return _passthrough (plan, tag);
@@ -590,14 +594,20 @@ static void _attach_accelerator_data (hb
  * @input: input to use for the subsetting.
  *
  * Subsets a font according to provided input. Returns nullptr
- * if the subset operation fails.
+ * if the subset operation fails or the face has no glyphs.
  *
  * Since: 2.9.0
  **/
 hb_face_t *
 hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
 {
-  if (unlikely (!input || !source)) return hb_face_get_empty ();
+  if (unlikely (!input || !source)) return nullptr;
+
+  if (unlikely (!source->get_num_glyphs ()))
+  {
+    DEBUG_MSG (SUBSET, nullptr, "No glyphs in source font.");
+    return nullptr;
+  }
 
   hb_subset_plan_t *plan = hb_subset_plan_create_or_fail (source, input);
   if (unlikely (!plan)) {
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset.h 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset.h
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-subset.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-subset.h	2025-06-27 08:03:14.000000000 +0000
@@ -73,6 +73,11 @@ typedef struct hb_subset_plan_t hb_subse
  * OS/2 will not be recalculated.
  * @HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE: If set don't perform glyph closure on layout
  * substitution rules (GSUB). Since: 7.2.0.
+ * @HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS: If set perform IUP delta optimization on the
+ * remaining gvar table's deltas. Since: 8.5.0
+ * @HB_SUBSET_FLAGS_IFTB_REQUIREMENTS: If set enforce requirements on the output subset
+ * to allow it to be used with incremental font transfer IFTB patches. Primarily,
+ * this forces all outline data to use long (32 bit) offsets. Since: EXPERIMENTAL
  *
  * List of boolean properties that can be configured on the subset input.
  *
@@ -90,6 +95,10 @@ typedef enum { /*< flags >*/
   HB_SUBSET_FLAGS_GLYPH_NAMES =              0x00000080u,
   HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES =  0x00000100u,
   HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE =        0x00000200u,
+  HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS     =  0x00000400u,
+#ifdef HB_EXPERIMENTAL_API
+  HB_SUBSET_FLAGS_IFTB_REQUIREMENTS       =  0x00000800u,
+#endif
 } hb_subset_flags_t;
 
 /**
@@ -165,6 +174,10 @@ hb_subset_input_set_flags (hb_subset_inp
                            unsigned value);
 
 HB_EXTERN hb_bool_t
+hb_subset_input_pin_all_axes_to_default (hb_subset_input_t  *input,
+                                         hb_face_t          *face);
+
+HB_EXTERN hb_bool_t
 hb_subset_input_pin_axis_to_default (hb_subset_input_t  *input,
                                      hb_face_t          *face,
                                      hb_tag_t            axis_tag);
@@ -175,15 +188,34 @@ hb_subset_input_pin_axis_location (hb_su
                                    hb_tag_t            axis_tag,
                                    float               axis_value);
 
-#ifdef HB_EXPERIMENTAL_API
+HB_EXTERN hb_bool_t
+hb_subset_input_get_axis_range (hb_subset_input_t  *input,
+                                hb_tag_t            axis_tag,
+                                float              *axis_min_value,
+                                float              *axis_max_value,
+                                float              *axis_def_value);
+
 HB_EXTERN hb_bool_t
 hb_subset_input_set_axis_range (hb_subset_input_t  *input,
                                 hb_face_t          *face,
                                 hb_tag_t            axis_tag,
                                 float               axis_min_value,
                                 float               axis_max_value,
-                                float              *axis_def_value);
+                                float               axis_def_value);
+
+HB_EXTERN hb_bool_t
+hb_subset_axis_range_from_string (const char *str, int len,
+                                  float *axis_min_value,
+                                  float *axis_max_value,
+                                  float *axis_def_value);
 
+HB_EXTERN void
+hb_subset_axis_range_to_string (hb_subset_input_t *input,
+                                hb_tag_t axis_tag,
+                                char *buf,
+                                unsigned size);
+
+#ifdef HB_EXPERIMENTAL_API
 HB_EXTERN hb_bool_t
 hb_subset_input_override_name_table (hb_subset_input_t  *input,
                                      hb_ot_name_id_t     name_id,
@@ -192,7 +224,6 @@ hb_subset_input_override_name_table (hb_
                                      unsigned            language_id,
                                      const char         *name_str,
                                      int                 str_len);
-
 #endif
 
 HB_EXTERN hb_face_t *
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ucd-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ucd-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-ucd-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-ucd-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -4,7 +4,7 @@
  *
  *   ./gen-ucd-table.py ucd.nounihan.grouped.xml
  *
- * on file with this description: Unicode 15.1.0
+ * on file with this description: Unicode 16.0.0
  */
 
 #ifndef HB_UCD_TABLE_HH
@@ -13,7 +13,7 @@
 #include "hb.hh"
 
 static const hb_script_t
-_hb_ucd_sc_map[165] =
+_hb_ucd_sc_map[172] =
 {
                    HB_SCRIPT_COMMON,              HB_SCRIPT_INHERITED,
                   HB_SCRIPT_UNKNOWN,                 HB_SCRIPT_ARABIC,
@@ -97,7 +97,10 @@ _hb_ucd_sc_map[165] =
                HB_SCRIPT_OLD_UYGHUR,                 HB_SCRIPT_TANGSA,
                      HB_SCRIPT_TOTO,               HB_SCRIPT_VITHKUQI,
                      HB_SCRIPT_MATH,                   HB_SCRIPT_KAWI,
-              HB_SCRIPT_NAG_MUNDARI,
+              HB_SCRIPT_NAG_MUNDARI,                  HB_SCRIPT_GARAY,
+             HB_SCRIPT_GURUNG_KHEMA,              HB_SCRIPT_KIRAT_RAI,
+                  HB_SCRIPT_OL_ONAL,                HB_SCRIPT_SUNUWAR,
+                   HB_SCRIPT_TODHRI,          HB_SCRIPT_TULU_TIGALARI,
 };
 static const uint16_t
 _hb_ucd_dm1_p0_map[825] =
@@ -868,7 +871,7 @@ _hb_ucd_dm2_u32_map[638] =
    HB_CODEPOINT_ENCODE3_11_7_14 (0x04E9u, 0x0308u, 0x04EBu),
 };
 static const uint64_t
-_hb_ucd_dm2_u64_map[388] =
+_hb_ucd_dm2_u64_map[408] =
 {
      HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B8u, 0x0000u),
      HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D1u, 0x05BCu, 0x0000u),
@@ -1051,13 +1054,23 @@ _hb_ucd_dm2_u64_map[388] =
      HB_CODEPOINT_ENCODE3 (0x30F0u, 0x3099u, 0x30F8u),   HB_CODEPOINT_ENCODE3 (0x30F1u, 0x3099u, 0x30F9u),
      HB_CODEPOINT_ENCODE3 (0x30F2u, 0x3099u, 0x30FAu),   HB_CODEPOINT_ENCODE3 (0x30FDu, 0x3099u, 0x30FEu),
      HB_CODEPOINT_ENCODE3 (0xFB49u, 0x05C1u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0xFB49u, 0x05C2u, 0x0000u),
+   HB_CODEPOINT_ENCODE3 (0x105D2u, 0x0307u, 0x105C9u), HB_CODEPOINT_ENCODE3 (0x105DAu, 0x0307u, 0x105E4u),
   HB_CODEPOINT_ENCODE3 (0x11099u, 0x110BAu, 0x1109Au),HB_CODEPOINT_ENCODE3 (0x1109Bu, 0x110BAu, 0x1109Cu),
   HB_CODEPOINT_ENCODE3 (0x110A5u, 0x110BAu, 0x110ABu),HB_CODEPOINT_ENCODE3 (0x11131u, 0x11127u, 0x1112Eu),
   HB_CODEPOINT_ENCODE3 (0x11132u, 0x11127u, 0x1112Fu),HB_CODEPOINT_ENCODE3 (0x11347u, 0x1133Eu, 0x1134Bu),
-  HB_CODEPOINT_ENCODE3 (0x11347u, 0x11357u, 0x1134Cu),HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114B0u, 0x114BCu),
-  HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BAu, 0x114BBu),HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BDu, 0x114BEu),
-  HB_CODEPOINT_ENCODE3 (0x115B8u, 0x115AFu, 0x115BAu),HB_CODEPOINT_ENCODE3 (0x115B9u, 0x115AFu, 0x115BBu),
-  HB_CODEPOINT_ENCODE3 (0x11935u, 0x11930u, 0x11938u), HB_CODEPOINT_ENCODE3 (0x1D157u, 0x1D165u, 0x0000u),
+  HB_CODEPOINT_ENCODE3 (0x11347u, 0x11357u, 0x1134Cu),HB_CODEPOINT_ENCODE3 (0x11382u, 0x113C9u, 0x11383u),
+  HB_CODEPOINT_ENCODE3 (0x11384u, 0x113BBu, 0x11385u),HB_CODEPOINT_ENCODE3 (0x1138Bu, 0x113C2u, 0x1138Eu),
+  HB_CODEPOINT_ENCODE3 (0x11390u, 0x113C9u, 0x11391u),HB_CODEPOINT_ENCODE3 (0x113C2u, 0x113B8u, 0x113C7u),
+  HB_CODEPOINT_ENCODE3 (0x113C2u, 0x113C2u, 0x113C5u),HB_CODEPOINT_ENCODE3 (0x113C2u, 0x113C9u, 0x113C8u),
+  HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114B0u, 0x114BCu),HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BAu, 0x114BBu),
+  HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BDu, 0x114BEu),HB_CODEPOINT_ENCODE3 (0x115B8u, 0x115AFu, 0x115BAu),
+  HB_CODEPOINT_ENCODE3 (0x115B9u, 0x115AFu, 0x115BBu),HB_CODEPOINT_ENCODE3 (0x11935u, 0x11930u, 0x11938u),
+  HB_CODEPOINT_ENCODE3 (0x1611Eu, 0x1611Eu, 0x16121u),HB_CODEPOINT_ENCODE3 (0x1611Eu, 0x1611Fu, 0x16123u),
+  HB_CODEPOINT_ENCODE3 (0x1611Eu, 0x16120u, 0x16125u),HB_CODEPOINT_ENCODE3 (0x1611Eu, 0x16129u, 0x16122u),
+  HB_CODEPOINT_ENCODE3 (0x16121u, 0x1611Fu, 0x16126u),HB_CODEPOINT_ENCODE3 (0x16121u, 0x16120u, 0x16128u),
+  HB_CODEPOINT_ENCODE3 (0x16122u, 0x1611Fu, 0x16127u),HB_CODEPOINT_ENCODE3 (0x16129u, 0x1611Fu, 0x16124u),
+  HB_CODEPOINT_ENCODE3 (0x16D63u, 0x16D67u, 0x16D69u),HB_CODEPOINT_ENCODE3 (0x16D67u, 0x16D67u, 0x16D68u),
+  HB_CODEPOINT_ENCODE3 (0x16D69u, 0x16D67u, 0x16D6Au), HB_CODEPOINT_ENCODE3 (0x1D157u, 0x1D165u, 0x0000u),
    HB_CODEPOINT_ENCODE3 (0x1D158u, 0x1D165u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D16Eu, 0x0000u),
    HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D16Fu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D170u, 0x0000u),
    HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D171u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D172u, 0x0000u),
@@ -1069,90 +1082,59 @@ _hb_ucd_dm2_u64_map[388] =
 #ifndef HB_OPTIMIZE_SIZE
 
 static const uint8_t
-_hb_ucd_u8[17884] =
+_hb_ucd_u8[17612] =
 {
-    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,
-    7,  7,  7,  7,  9, 10,  7,  7,  7,  7, 11, 12, 13, 13, 13, 14,
-   15, 16, 17, 18, 19, 20, 21, 22, 23, 22, 22, 22, 22, 24,  7,  7,
-   25, 26, 22, 22, 22, 27, 28, 29, 22, 30, 31, 32, 33, 34, 35, 36,
-    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-    7,  7,  7,  7, 37,  7, 38, 39,  7, 40,  7,  7,  7, 41, 22, 42,
-    7,  7, 43,  7, 44, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   45, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 46,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 47,
+    0,  1,  2,  3,  4,  5,  5,  5,  5,  5,  6,  5,  5,  7,  8,  9,
+   10, 11, 12, 13, 14, 15, 16,  5, 17, 15, 18, 19, 20, 21, 22, 23,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 24, 25, 26,  5, 27, 28,
+    5, 29, 30, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   31, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8, 32,
+    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8, 33,
     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
-   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-   32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43,
-   44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
-   60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 69, 72, 73,
-   69, 69, 64, 74, 64, 64, 75, 76, 77, 78, 79, 80, 81, 82, 69, 83,
-   84, 85, 86, 87, 88, 89, 69, 69, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34,
-   91, 34, 34, 34, 34, 34, 34, 34, 34, 92, 34, 34, 93, 94, 95, 96,
-   97, 98, 99,100,101,102,103,104, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,105,
-  106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
-  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
-  107,107, 34, 34,108,109,110,111, 34, 34,112,113,114,115,116,117,
-  118,119,120,121,122,123,124,125,126,127,128,129, 34, 34,130,131,
-  132,133,134,135,136,137,138,139,140,141,142,122,143,144,145,146,
-  147,148,149,150,151,152,153,122,154,155,122,156,157,158,159,122,
-  160,161,162,163,164,165,166,122,167,168,169,170,122,171,172,173,
-   34, 34, 34, 34, 34, 34, 34,174,175, 34,176,122,122,122,122,122,
-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,177,
-   34, 34, 34, 34, 34, 34, 34, 34,178,122,122,122,122,122,122,122,
-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,
-  122,122,122,122,122,122,122,122, 34, 34, 34, 34,179,122,122,122,
-   34, 34, 34, 34,180,181,182,183,122,122,122,122,184,185,186,187,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,188,
-   34, 34, 34, 34, 34, 34, 34, 34, 34,189,190,122,122,122,122,122,
-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,191,
-   34, 34,192, 34, 34,193,122,122,122,122,122,122,122,122,122,122,
-  122,122,122,122,122,122,122,122,194,195,122,122,122,122,122,122,
-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,196,197,
-   69,198,199,200,201,202,203,122,204,205,206,207,208,209,210,211,
-   69, 69, 69, 69,212,213,122,122,122,122,122,122,122,122,214,122,
-  215,216,217,122,122,218,122,122,122,219,122,122,122,122,122,220,
-   34,221,222,122,122,122,122,122,223,224,225,122,226,227,122,122,
-  228,229,230,231,232,122, 69,233, 69, 69, 69, 69, 69,234,235,236,
-  237,238, 69, 69,239,240, 69,241,122,122,122,122,122,122,122,122,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,242, 34, 34,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,243, 34,
-  244, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,245, 34, 34,
-   34, 34, 34, 34, 34, 34, 34,246, 34, 34, 34, 34,247,122,122,122,
-   34, 34, 34, 34,248,122,122,122,122,122,122,122,122,122,122,122,
-   34, 34, 34, 34, 34, 34,249, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34, 34, 34, 34, 34,250,122,122,122,122,122,122,122,122,
-  251,122,252,253,122,122,122,122,122,122,122,122,122,122,122,122,
-  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,254,
-  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,255,
+   16, 17, 18, 19, 20, 17, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+   31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 33, 41, 42, 43, 44, 45,
+   46, 47, 48, 39, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   50, 17, 17, 17, 51, 17, 52, 53, 54, 55, 56, 57, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 58, 59, 59, 59, 59, 59, 59, 59, 59,
+   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+   60, 60, 60, 60, 60, 60, 60, 60, 60, 17, 61, 62, 17, 63, 64, 65,
+   66, 67, 68, 69, 70, 71, 17, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+   81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+   17, 17, 17, 97, 98, 99,100,100,100,100,100,100,100,100,100,101,
+   17, 17, 17, 17,102, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17,103, 17, 17,104,100,100,100,100,100,100,100,100,100,
+  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
+  100,105,100,100,100,100,100,100, 17, 17,106,107,100,108,109,110,
+   17, 17, 17, 17, 17, 17, 17,111, 17, 17, 17, 17,112,113,100,100,
+  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,114,
+   17,115,116,100,100,100,100,100,100,100,100,100,117,100,100,100,
+  100,100,100,100,100,100,100,100,100,100,100,100,118, 39,119,120,
+  121,122,123,124,125,126,127,128, 39, 39,129,100,100,100,100,130,
+  131,132,133,100,134,135,100,136,137,138,100,100,139,140,141,100,
+  142,143,144,145, 39, 39,146,147,148, 39,149,150,100,100,100,100,
+   17, 17, 17, 17, 17, 17,151, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17,152,153, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,154, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,155, 17, 17,156,100,
+  100,100,100,100,100,100,100,100, 17, 17,157,100,100,100,100,100,
+   17, 17, 17,158, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17,159,100,100,100,100,100,100,100,100,100,100,100,100,
+  160,161,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
+   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,162,
+   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,163,
     0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  2,  4,  5,  6,  2,
     7,  7,  7,  7,  7,  2,  8,  9, 10, 11, 11, 11, 11, 11, 11, 11,
    11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
@@ -1189,7 +1171,7 @@ _hb_ucd_u8[17884] =
    43, 43, 40, 21,  2, 81, 57, 20, 36, 36, 36, 43, 43, 75, 43, 43,
    43, 43, 75, 43, 75, 43, 43, 44,  2,  2,  2,  2,  2,  2,  2, 64,
    36, 36, 36, 36, 70, 43, 44, 64, 36, 36, 36, 36, 36, 61, 44, 44,
-   36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 44, 43, 43, 43, 43,
+   36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 57, 43, 43, 43, 43,
    36, 36, 36, 36, 83, 43, 43, 43, 43, 84, 43, 43, 43, 43, 43, 43,
    43, 85, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 85, 71, 86,
    87, 43, 43, 43, 85, 86, 87, 86, 70, 43, 43, 43, 36, 36, 36, 36,
@@ -1262,13 +1244,13 @@ _hb_ucd_u8[17884] =
    85, 85, 87, 43, 43, 43, 85, 86, 86, 87, 43, 43, 43, 43, 80, 57,
     2,  2,  2, 88,  2,  2,  2, 44, 43, 43, 43, 43, 43, 43, 43,109,
    43, 43, 43, 43, 43, 43, 43, 80, 43, 43, 98, 36, 36, 36, 36, 36,
-   36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61, 44,
-   97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21, 64,
+   36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61,  2,
+   97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21,  2,
    43, 98, 36, 36, 36, 36, 36, 36, 94, 43, 43, 86, 43, 87, 43, 36,
    36, 36, 36, 85, 43, 86, 87, 87, 43, 86, 44, 44, 44, 44,  2,  2,
    36, 36, 86, 86, 86, 86, 43, 43, 43, 43, 86, 43, 44, 93,  2,  2,
     7,  7,  7,  7,  7, 44, 62, 36, 36, 36, 36, 36, 40, 40, 40,  2,
-   16, 16, 16, 16,110, 44, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11,
+   16, 16, 16, 16, 34,110, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11,
     2,  2,  2,  2, 44, 44, 44, 44, 43, 60, 43, 43, 43, 43, 43, 43,
    85, 43, 43, 43, 71, 36, 70, 36, 36, 36, 71, 94, 43, 61, 44, 44,
    16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 45, 16, 16,
@@ -1296,33 +1278,33 @@ _hb_ucd_u8[17884] =
    67, 67, 67, 67,  4,  4, 67, 67,  8, 67, 67, 67,145,146, 67, 67,
    67, 67, 67, 67, 67, 67,144, 67, 67, 67, 67, 67, 67, 26,  8,  8,
     8,  8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,
-    8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44,
-   67, 67, 67, 67, 67, 92, 44, 44, 27, 27, 27, 27, 27, 27, 67, 67,
-   67, 67, 67, 67, 67, 27, 27, 27, 67, 67, 67, 26, 67, 67, 67, 67,
-   26, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,  8,  8,
-   67, 67, 67, 67, 67, 67, 67, 26, 67, 67, 67, 67,  4,  4,  4,  4,
-    4,  4,  4, 27, 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67,
-    8,  8,129,147,  8,  8,  8,  8,  8,  8,  8,  4,  4,  4,  4,  4,
-    8,129,148,148,148,148,148,148,148,148,148,148,147,  8,  8,  8,
-    8,  8,  8,  8,  4,  4,  8,  8,  8,  8,  8,  8,  8,  8,  4,  8,
-    8,  8,144, 26,  8,  8,144, 67, 67, 67, 44, 67, 67, 67, 67, 67,
-   67, 67, 67, 55, 67, 67, 67, 67, 32, 11, 32, 34, 34, 34, 34, 11,
-   32, 32, 34, 16, 16, 16, 40, 11, 32, 32,140, 67, 67,138, 34,149,
-   43, 32, 44, 44, 93,  2, 99,  2, 16, 16, 16,150, 44, 44,150, 44,
-   36, 36, 36, 36, 44, 44, 44, 52, 64, 44, 44, 44, 44, 44, 44, 57,
-   36, 36, 36, 61, 44, 44, 44, 44, 36, 36, 36, 61, 36, 36, 36, 61,
-    2,121,121,  2,125,126,121,  2,  2,  2,  2,  6,  2,108,121,  2,
-  121,  4,  4,  4,  4,  2,  2, 88,  2,  2,  2,  2,  2,120,  2,  2,
-  108,151,  2,  2,  2,  2,  2,  2, 67,  2,152,148,148,148,153, 44,
-   67, 67, 67, 67, 67, 55, 67, 67, 67, 67, 44, 44, 44, 44, 44, 44,
-   67, 67, 67, 44, 44, 44, 44, 44,  1,  2,154,155,  4,  4,  4,  4,
-    4, 67,  4,  4,  4,  4,156,157,158,105,105,105,105, 43, 43, 86,
-  159, 40, 40, 67,105,160, 63, 67, 36, 36, 36, 61, 57,161,162, 69,
-   36, 36, 36, 36, 36, 63, 40, 69, 44, 44, 62, 36, 36, 36, 36, 36,
-   67, 27, 27, 67, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, 44, 55,
-   67, 67, 67, 67, 67, 67, 67, 92, 27, 27, 27, 27, 27, 67, 67, 67,
-   67, 67, 67, 67, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27,
-   36, 36, 83, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,164,  2,
+    8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44,
+   27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27,
+   67, 67, 67, 26, 67, 67, 67, 67, 26, 67, 67, 67, 67, 67, 67, 67,
+   67, 67, 67, 67,  8,  8,  8,  8, 67, 67, 67, 67, 67, 67, 67, 26,
+   67, 67, 67, 67,  4,  4,  4,  4,  4,  4,  4, 27, 27, 27, 27, 27,
+   27, 27, 67, 67, 67, 67, 67, 67,  8,  8,129,147,  8,  8,  8,  8,
+    8,  8,  8,  4,  4,  4,  4,  4,  8,129,148,148,148,148,148,148,
+  148,148,148,148,147,  8,  8,  8,  8,  8,  8,  8,  4,  4,  8,  8,
+    8,  8,  8,  8,  8,  8,  4,  8,  8,  8,144, 26,  8,  8,144, 67,
+   67, 67, 44, 67, 67, 67, 67, 67, 67, 67, 67, 55, 67, 67, 67, 67,
+   32, 11, 32, 34, 34, 34, 34, 11, 32, 32, 34, 16, 16, 16, 40, 11,
+   32, 32,140, 67, 67,138, 34,149, 43, 32, 44, 44, 93,  2, 99,  2,
+   16, 16, 16,150, 44, 44,150, 44, 36, 36, 36, 36, 44, 44, 44, 52,
+   64, 44, 44, 44, 44, 44, 44, 57, 36, 36, 36, 61, 44, 44, 44, 44,
+   36, 36, 36, 61, 36, 36, 36, 61,  2,121,121,  2,125,126,121,  2,
+    2,  2,  2,  6,  2,108,121,  2,121,  4,  4,  4,  4,  2,  2, 88,
+    2,  2,  2,  2,  2,120,  2,  2,108,151,  2,  2,  2,  2,  2,  2,
+   67,  2,152,148,148,148,153, 44, 67, 67, 67, 67, 67, 55, 67, 67,
+   67, 67, 44, 44, 44, 44, 44, 44, 67, 67, 67, 44, 44, 44, 44, 44,
+    1,  2,154,155,  4,  4,  4,  4,  4, 67,  4,  4,  4,  4,156,157,
+  158,105,105,105,105, 43, 43, 86,159, 40, 40, 67,105,160, 63, 67,
+   36, 36, 36, 61, 57,161,162, 69, 36, 36, 36, 36, 36, 63, 40, 69,
+   44, 44, 62, 36, 36, 36, 36, 36, 67, 27, 27, 67, 67, 67, 67, 67,
+   67, 67, 67, 44, 44, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67, 92,
+   27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, 27,
+  163, 27, 27, 27, 27, 27, 27, 27, 36, 36, 83, 36, 36, 36, 36, 36,
+   67, 67, 67, 92, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36,164,  2,
     7,  7,  7,  7,  7, 36, 44, 44, 32, 32, 32, 32, 32, 32, 32, 70,
    51,165, 43, 43, 43, 43, 43, 88, 32, 32, 32, 32, 32, 32, 40, 43,
    36, 36, 36,105,105,105,105,105, 43,  2,  2,  2, 44, 44, 44, 44,
@@ -1330,7 +1312,7 @@ _hb_ucd_u8[17884] =
    16, 32, 32, 32, 32, 32, 32, 32, 45, 16, 16, 16, 34, 34, 34, 32,
    32, 32, 32, 32, 42,166, 34, 35, 32, 32, 16, 32, 32, 32, 32, 32,
    32, 32, 32, 32, 32, 11, 11, 32, 11, 11, 32, 32, 32, 32, 32, 32,
-   32, 32, 11, 11, 34,110, 44, 44, 32,150,150, 32, 32, 44, 44, 44,
+   32, 32, 11, 11, 34, 34, 32, 44, 32,150,150, 32, 32, 32, 47, 44,
    44, 40,167, 35, 40, 35, 36, 36, 36, 71, 36, 71, 36, 70, 36, 36,
    36, 94, 87, 85, 67, 67, 80, 44, 27, 27, 27, 67,168, 44, 44, 44,
    36, 36,  2,  2, 44, 44, 44, 44, 86, 36, 36, 36, 36, 36, 36, 36,
@@ -1391,8 +1373,10 @@ _hb_ucd_u8[17884] =
    36, 61, 44, 44, 27, 27, 27, 27, 36, 44, 44, 44, 93,  2, 64, 44,
    44, 44, 44, 44,179, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44,
    16,110, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44,
-   27, 27, 27, 27, 27, 27, 27,100, 36, 36, 36, 36, 36, 57,184, 44,
-   36, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 57, 43,
+    7,  7,  7,  7,  7, 36, 36, 69, 11, 11, 11, 44, 57, 43, 43,159,
+   16, 16, 16, 44, 44, 44, 44,  8, 27, 27, 27, 27, 27, 27, 27,100,
+   36, 36, 36, 36, 36, 57,184, 44, 36, 44, 44, 44, 44, 44, 44, 44,
+   44, 36, 61, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43,
    27, 27, 27, 95, 44, 44, 44, 44,180, 27, 30,  2,  2, 44, 44, 44,
    36, 43, 43,  2,  2, 44, 44, 44, 36, 36,183, 27, 27, 27, 44, 44,
    87, 98, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43,
@@ -1410,14 +1394,18 @@ _hb_ucd_u8[17884] =
    86, 87, 43, 43, 43, 80, 44, 44, 43, 86, 62, 36, 36, 36, 61, 62,
    61, 36, 62, 36, 36, 57, 71, 86, 85, 86, 90, 89, 90, 89, 86, 44,
    61, 44, 44, 89, 44, 44, 62, 36, 36, 86, 44, 43, 43, 43, 80, 44,
-   43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 94, 86, 43, 43, 43, 43,
-   86, 43, 85, 71, 36, 63,  2,  2,  7,  7,  7,  7,  7,  2, 93, 71,
-   86, 87, 43, 43, 85, 85, 86, 87, 85, 43, 36, 72, 44, 44, 44, 44,
-   36, 36, 36, 36, 36, 36, 36, 94, 86, 43, 43, 44, 86, 86, 43, 87,
-   60,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 43, 44,
-   86, 87, 43, 43, 43, 85, 87, 87, 60,  2, 61, 44, 44, 44, 44, 44,
-    2,  2,  2,  2,  2,  2, 64, 44, 36, 36, 36, 36, 36, 70, 87, 86,
-   43, 43, 43, 87, 63, 44, 44, 44, 86, 43, 43, 87, 43, 43, 44, 44,
+   43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 62, 44, 61,
+   36, 36, 36, 62, 86, 87, 43, 43, 80, 90, 89, 89, 86, 90, 86, 85,
+   71, 71,  2, 93, 64, 44, 44, 44, 57, 80, 44, 44, 44, 44, 44, 44,
+   36, 36, 94, 86, 43, 43, 43, 43, 86, 43, 85, 71, 36, 63,  2,  2,
+    7,  7,  7,  7,  7,  2, 93, 71, 86, 87, 43, 43, 85, 85, 86, 87,
+   85, 43, 36, 72, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 94,
+   86, 43, 43, 44, 86, 86, 43, 87, 60,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2, 36, 36, 43, 44, 86, 87, 43, 43, 43, 85, 87, 87,
+   60,  2, 61, 44, 44, 44, 44, 44,  2,  2,  2,  2,  2,  2, 64, 44,
+   36, 36, 36, 36, 36, 70, 87, 86, 43, 43, 43, 87, 63, 44, 44, 44,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 44, 44, 44, 44, 44, 44,
+   36, 36, 36, 36, 36, 61, 57, 87, 86, 43, 43, 87, 43, 43, 44, 44,
     7,  7,  7,  7,  7, 27,  2, 97, 43, 43, 43, 43, 87, 60, 44, 44,
    27,100, 44, 44, 44, 44, 44, 62, 36, 36, 36, 61, 62, 44, 36, 36,
    36, 36, 62, 61, 36, 36, 36, 36, 86, 86, 86, 89, 90, 57, 85, 71,
@@ -1427,49 +1415,52 @@ _hb_ucd_u8[17884] =
     2,  2,  2, 59, 44, 44, 44, 44, 70, 43, 43, 85, 87, 43, 36, 36,
    36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 85, 43,  2, 72,  2,
     2, 64, 44, 44, 44, 44, 44, 44,  2,  2,  2,  2,  2, 44, 44, 44,
-   43, 43, 43, 80, 43, 43, 43, 87, 63,  2,  2, 44, 44, 44, 44, 44,
-    2, 36, 36, 36, 36, 36, 36, 36, 44, 43, 43, 43, 43, 43, 43, 43,
-   43, 43, 43, 43, 89, 43, 43, 43, 85, 43, 87, 80, 44, 44, 44, 44,
-   36, 36, 36, 61, 36, 62, 36, 36, 70, 43, 43, 80, 44, 80, 43, 57,
-   43, 43, 43, 70, 44, 44, 44, 44, 36, 36, 36, 62, 61, 36, 36, 36,
-   36, 36, 36, 36, 36, 86, 86, 90, 43, 89, 87, 87, 61, 44, 44, 44,
-   36, 70, 85,107, 64, 44, 44, 44, 43, 94, 36, 36, 36, 36, 36, 36,
-   36, 36, 86, 43, 43, 80, 44, 86, 85, 60,  2,  2,  2,  2,  2,  2,
+   63, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 80, 43, 43, 43, 87,
+   63,  2,  2, 44, 44, 44, 44, 44,  2, 36, 36, 36, 36, 36, 36, 36,
+   44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 89, 43, 43, 43,
+   85, 43, 87, 80, 44, 44, 44, 44, 36, 36, 36, 61, 36, 62, 36, 36,
+   70, 43, 43, 80, 44, 80, 43, 57, 43, 43, 43, 70, 44, 44, 44, 44,
+   36, 36, 36, 62, 61, 36, 36, 36, 36, 36, 36, 36, 36, 86, 86, 90,
+   43, 89, 87, 87, 61, 44, 44, 44, 36, 70, 85,107, 64, 44, 44, 44,
+   43, 94, 36, 36, 36, 36, 36, 36, 36, 36, 86, 43, 43, 80, 44, 86,
+   85, 60,  2,  2,  2,  2,  2,  2,  7,  7,  7,  7,  7, 80, 44, 44,
    27, 27, 91, 67, 67, 67, 56, 20,168, 67, 67, 67, 67, 67, 67, 67,
    67, 44, 44, 44, 44, 44, 44, 93,105,105,105,105,105,105,105,181,
     2,  2, 64, 44, 44, 44, 44, 44, 63, 64, 44, 44, 44, 44, 44, 44,
    65, 65, 65, 65, 65, 65, 65, 65, 71, 36, 36, 70, 43, 43, 43, 43,
-   43, 43, 43, 44, 44, 44, 44, 44, 43, 43, 60, 44, 44, 44, 44, 44,
+   43, 43, 43, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 43,
+   43, 43, 43, 43, 43, 86, 87, 43, 43, 43, 60, 44, 44, 44, 44, 44,
    43, 43, 43, 60,  2,  2, 67, 67, 40, 40, 97, 44, 44, 44, 44, 44,
     7,  7,  7,  7,  7,179, 27, 27, 27, 62, 36, 36, 36, 36, 36, 36,
-   36, 36, 36, 36, 44, 44, 62, 36, 27, 27, 27, 30,  2, 64, 44, 44,
+   36, 36, 36, 36, 44, 44, 62, 36, 40, 69, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 83,164,  2, 27, 27, 27, 30,  2, 64, 44, 44,
    36, 36, 36, 36, 36, 61, 44, 57, 94, 86, 86, 86, 86, 86, 86, 86,
    86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 44, 44, 44, 57,
    43, 74, 40, 40, 40, 40, 40, 40, 40, 88, 80, 44, 44, 44, 44, 44,
-   86, 44, 44, 44, 44, 44, 44, 44, 40, 40, 52, 40, 40, 40, 52, 81,
-   36, 61, 44, 44, 44, 44, 44, 44, 44, 61, 44, 44, 44, 44, 44, 44,
-   36, 61, 62, 44, 44, 44, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44,
-   36, 36, 36, 36, 36, 44, 50, 60, 65, 65, 44, 44, 44, 44, 44, 44,
-   43, 43, 43, 43, 43, 43, 43, 44, 43, 43, 43, 80, 44, 44, 44, 44,
-   67, 67, 67, 92, 55, 67, 67, 67, 67, 67,186, 87, 43, 67,186, 86,
-   86,187, 65, 65, 65, 84, 43, 43, 43, 76, 50, 43, 43, 43, 67, 67,
-   67, 67, 67, 67, 67, 43, 43, 67, 67, 43, 76, 44, 44, 44, 44, 44,
-   27, 27, 44, 44, 44, 44, 44, 44, 11, 11, 11, 11, 11, 16, 16, 16,
-   16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16,
-   16, 16,110, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
-   16, 16, 16, 16, 16, 16, 47, 11, 44, 47, 48, 47, 48, 11, 47, 11,
-   11, 11, 11, 16, 16,150,150, 16, 16, 16,150, 16, 16, 16, 16, 16,
-   16, 16, 11, 48, 11, 47, 48, 11, 11, 11, 47, 11, 11, 11, 47, 16,
-   16, 16, 16, 16, 11, 48, 11, 47, 11, 11, 47, 47, 44, 11, 11, 11,
-   47, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11,
-   11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 44, 11, 11, 11, 11,
-   31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16,
-   16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16,
-   16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16,
-   16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11,
-   11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16,
-   11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 44,  7,
-    7,  7,  7,  7,  7,  7,  7,  7, 43, 43, 43, 76, 67, 50, 43, 43,
+   86, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 62,
+   40, 40, 52, 40, 40, 40, 52, 81, 36, 61, 44, 44, 44, 44, 44, 44,
+   44, 61, 44, 44, 44, 44, 44, 44, 36, 61, 62, 44, 44, 44, 44, 44,
+   44, 44, 36, 36, 44, 44, 44, 44, 36, 36, 36, 36, 36, 44, 50, 60,
+   65, 65, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 44,
+   43, 43, 43, 80, 44, 44, 44, 44, 67, 67, 67, 92, 55, 67, 67, 67,
+   67, 67,186, 87, 43, 67,186, 86, 86,187, 65, 65, 65, 84, 43, 43,
+   43, 76, 50, 43, 43, 43, 67, 67, 67, 67, 67, 67, 67, 43, 43, 67,
+   67, 43, 76, 44, 44, 44, 44, 44, 27, 27, 44, 44, 44, 44, 44, 44,
+   11, 11, 11, 11, 11, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 11,
+   11, 11, 11, 11, 11, 11, 11, 16, 16, 16,110, 16, 16, 16, 16, 16,
+   11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 47, 11,
+   44, 47, 48, 47, 48, 11, 47, 11, 11, 11, 11, 16, 16,150,150, 16,
+   16, 16,150, 16, 16, 16, 16, 16, 16, 16, 11, 48, 11, 47, 48, 11,
+   11, 11, 47, 11, 11, 11, 47, 16, 16, 16, 16, 16, 11, 48, 11, 47,
+   11, 11, 47, 47, 44, 11, 11, 11, 47, 16, 16, 16, 16, 16, 16, 16,
+   16, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 16, 16, 16, 16, 16,
+   16, 16, 16, 44, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16, 16, 16,
+   16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, 11, 11,
+   11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11,
+   11, 11, 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33,
+   16, 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31,
+   16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16,
+   16, 33, 16, 16, 16, 32, 44,  7, 43, 43, 43, 76, 67, 50, 43, 43,
    43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67,
    67, 67, 76, 21,  2,  2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43,
    16, 16, 16, 16, 16, 39, 16, 16, 16, 16, 16, 16, 16, 16, 16,110,
@@ -1479,22 +1470,23 @@ _hb_ucd_u8[17884] =
    43, 43, 43, 74, 40, 40, 40, 44,  7,  7,  7,  7,  7, 44, 44, 77,
    36, 36, 36, 36, 36, 36, 36, 80, 36, 36, 36, 36, 36, 36, 43, 43,
     7,  7,  7,  7,  7, 44, 44, 96, 36, 36, 36, 36, 36, 83, 43, 43,
-   36, 36, 36, 61, 36, 36, 62, 61, 36, 36, 61,179, 27, 27, 27, 27,
-   16, 16, 43, 43, 43, 74, 44, 44, 27, 27, 27, 27, 27, 27,163, 27,
-  188, 27,100, 44, 44, 44, 44, 44, 27, 27, 27, 27, 27, 27, 27,163,
-   27, 27, 27, 27, 27, 27, 27, 44, 36, 36, 62, 36, 36, 36, 36, 36,
-   62, 61, 61, 62, 62, 36, 36, 36, 36, 61, 36, 36, 62, 62, 44, 44,
-   44, 61, 44, 62, 62, 62, 62, 36, 62, 61, 61, 62, 62, 62, 62, 62,
-   62, 61, 61, 62, 36, 61, 36, 36, 36, 61, 36, 36, 62, 36, 61, 61,
-   36, 36, 36, 36, 36, 62, 36, 36, 62, 36, 62, 36, 36, 62, 36, 36,
-    8, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 44, 44,
-   55, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, 27, 27, 27, 91, 67,
-   67, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 67, 67, 67,
-   67, 92, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 92, 44, 44, 44,
-   67, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 25, 41, 41,
-   67, 67, 67, 67, 44, 44, 67, 67, 67, 67, 67, 92, 44, 55, 67, 67,
-   67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 67, 55,
-   67, 67, 67, 44, 44, 44, 44, 67, 67, 92, 67, 67, 67, 67, 67, 67,
+  188,  7,  7,  7,  7,189, 44, 93, 36, 36, 36, 61, 36, 36, 62, 61,
+   36, 36, 61,179, 27, 27, 27, 27, 16, 16, 43, 43, 43, 74, 44, 44,
+   27, 27, 27, 27, 27, 27,163, 27,190, 27,100, 44, 44, 44, 44, 44,
+   27, 27, 27, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27, 44,
+   36, 36, 62, 36, 36, 36, 36, 36, 62, 61, 61, 62, 62, 36, 36, 36,
+   36, 61, 36, 36, 62, 62, 44, 44, 44, 61, 44, 62, 62, 62, 62, 36,
+   62, 61, 61, 62, 62, 62, 62, 62, 62, 61, 61, 62, 36, 61, 36, 36,
+   36, 61, 36, 36, 62, 36, 61, 61, 36, 36, 36, 36, 36, 62, 36, 36,
+   62, 36, 62, 36, 36, 62, 36, 36,  8, 44, 44, 44, 44, 44, 44, 44,
+   67, 67, 67, 67, 67, 67, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67,
+   27, 27, 27, 27, 27, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 44,
+   44, 44, 44, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, 44, 44,
+   67, 67, 67, 67, 92, 44, 44, 44, 67, 44, 44, 44, 44, 44, 44, 44,
+   67, 67, 67, 67, 67, 25, 41, 41, 67, 67, 67, 67, 44, 44, 67, 67,
+   67, 67, 67, 92, 44, 55, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44,
+   67, 67, 67, 67, 67, 44, 44, 55, 67, 67, 67, 92, 44, 44, 44, 67,
+   67, 67, 67, 67, 67, 67, 92, 55, 67, 92, 67, 67, 67, 67, 67, 67,
    79, 44, 44, 44, 44, 44, 44, 44,171,171,171,171,171,171,171, 44,
   171,171,171,171,171,171,171,  0,  0,  0, 29, 21, 21, 21, 23, 21,
    22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21,  9,  9,  9,
@@ -1520,366 +1512,350 @@ _hb_ucd_u8[17884] =
     6, 21, 11, 21, 24,  9,  6,  9, 23, 26,  6, 10,  4,  4,  3,  3,
     7, 25, 17, 16, 16, 22, 16, 16, 25, 17, 25,  2, 25, 24,  2, 15,
    12, 15, 14,  2, 21, 14,  7, 15, 12, 17, 21,  1, 26, 10, 10,  1,
-   23, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0, 10, 11, 12,
-   13,  0, 14,  0,  0,  0,  0,  0, 15,  0, 16,  0,  0,  0,  0,  0,
+    7, 13, 13,  2, 23, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+    0, 10, 11, 12, 13,  0, 14,  0,  0,  0,  0,  0, 15,  0, 16,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0, 17, 18, 19,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0, 17, 18, 19,  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, 20,
-    0, 21, 22, 23,  0,  0,  0, 24, 25, 26, 27, 28, 29, 30, 31, 32,
-   33, 34,  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, 35,  0, 36,  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,
-   37,  0,  0,  0,  0,  0,  0,  0,  0,  0, 38, 39,  0,  0,  0,  0,
-    0,  0, 40, 41, 42,  0, 43,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  1,  2,  0,  0,  0,  0,  3,  0,  0,  0,  4,  5,
-    6,  7,  0,  8,  9, 10,  0, 11, 12, 13, 14, 15, 16, 17, 16, 18,
-   16, 19, 16, 19, 16, 19,  0, 19, 16, 20, 16, 19, 21, 19,  0, 22,
-   23, 24, 25, 26, 27, 28, 29, 30, 31,  0, 32,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0, 33,  0,  0,  0,  0,  0,  0, 34,  0,  0, 35,
-    0,  0, 36,  0, 37,  0,  0,  0, 38, 39, 40, 41, 42, 43, 44, 45,
-   46,  0,  0, 47,  0,  0,  0, 48,  0,  0,  0, 49,  0,  0,  0,  0,
-    0,  0,  0, 50,  0, 51,  0, 52, 53,  0, 54,  0,  0,  0,  0,  0,
-    0, 55, 56, 57,  0,  0,  0,  0, 58,  0,  0, 59, 60, 61, 62, 63,
-    0,  0, 64, 65,  0,  0,  0, 66,  0,  0,  0,  0, 67,  0,  0,  0,
-   68,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 69,
-    0,  0,  0, 70,  0, 71,  0,  0, 72,  0,  0, 73,  0,  0,  0,  0,
-    0,  0,  0,  0, 74,  0,  0,  0,  0,  0, 75, 76,  0, 77, 78,  0,
-    0, 79, 80,  0, 81, 62,  0, 82, 83,  0,  0, 84, 85, 86,  0,  0,
-    0, 87,  0, 88,  0,  0, 51, 89, 51,  0, 90,  0, 91,  0,  0,  0,
-   80,  0,  0,  0, 92, 93,  0, 94, 95, 96, 97,  0,  0,  0,  0,  0,
-   51,  0,  0,  0,  0, 98, 99,  0,  0,  0,  0,  0,  0,100,  0,  0,
-    0,  0,  0,101,102,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,103,
-    0,  0,104,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,106,  0,
-    0,107,  0,  0,  0,  0,  0,  0,108,  0,109,  0,102,  0,  0,  0,
-    0,  0,110,111,  0,  0,  0,  0,  0,  0,  0,112,  0,  0,  0,  0,
-    0,  0,  0,113,  0,114,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,
-    5,  6,  7,  0,  8,  0,  0,  0,  0,  9, 10, 11, 12,  0,  0,  0,
-    0, 13,  0,  0, 14, 15,  0, 16,  0, 17, 18,  0,  0, 19,  0, 20,
-   21,  0,  0,  0,  0,  0, 22, 23,  0, 24, 25,  0,  0, 26,  0,  0,
-    0, 27,  0,  0, 28, 29, 30, 31,  0,  0,  0, 32, 33, 34,  0,  0,
-   33,  0,  0, 35, 33,  0,  0,  0, 33, 36,  0,  0,  0,  0,  0, 37,
-   38,  0,  0,  0,  0,  0,  0, 39, 40,  0,  0,  0,  0,  0,  0, 41,
-   42,  0,  0,  0,  0, 43,  0, 44,  0,  0,  0, 45, 46,  0,  0,  0,
-   47,  0,  0,  0,  0,  0,  0, 48, 49,  0,  0,  0,  0, 50,  0,  0,
-    0, 51,  0, 52,  0, 53,  0,  0,  0,  0, 54,  0,  0,  0,  0, 55,
-    0, 56,  0,  0,  0,  0, 57, 58,  0,  0,  0, 59, 60,  0,  0,  0,
-    0,  0,  0, 61, 52,  0, 62, 63,  0,  0, 64,  0,  0,  0, 65, 66,
-    0,  0,  0, 67,  0, 68, 69, 70, 71, 72,  1, 73,  0, 74, 75, 76,
-    0,  0, 77, 78,  0,  0,  0, 79,  0,  0,  1,  1,  0,  0, 80,  0,
-    0, 81,  0,  0,  0,  0, 77, 82,  0, 83,  0,  0,  0,  0,  0, 78,
-   84,  0, 85,  0, 52,  0,  1, 78,  0,  0, 86,  0,  0, 87,  0,  0,
-    0,  0,  0, 88, 57,  0,  0,  0,  0,  0,  0, 89, 90,  0,  0, 84,
-    0,  0, 33,  0,  0, 91,  0,  0,  0,  0, 92,  0,  0,  0,  0, 49,
-    0,  0, 93,  0,  0,  0,  0, 94, 95,  0,  0, 96,  0,  0, 97,  0,
-    0,  0, 98,  0,  0,  0, 99,  0,  0,  0,  0,100,101, 93,  0,  0,
-  102,  0,  0,  0, 84,  0,  0,103,  0,  0,  0,104,105,  0,  0,106,
-  107,  0,  0,  0,  0,  0,  0,108,  0,  0,109,  0,  0,  0,  0,110,
-   33,  0,111,112,113, 35,  0,  0,114,  0,  0,  0,115,  0,  0,  0,
-    0,  0,  0,116,  0,  0,117,  0,  0,  0,  0,118, 88,  0,  0,  0,
-    0,  0, 57,  0,  0,  0,  0, 52,119,  0,  0,  0,  0,120,  0,  0,
-  121,  0,  0,  0,  0,119,  0,  0,122,  0,  0,  0,  0,  0,  0,123,
-    0,  0,  0,124,  0,  0,  0,125,  0,126,  0,  0,  0,  0,127,128,
-  129,  0,130,  0,131,  0,  0,  0,132,133,134,  0, 77,  0,  0,  0,
-    0,  0, 35,  0,  0,  0,135,  0,  0,  0,136,  0,  0,137,  0,  0,
-  138,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  3,  4,
-    5,  6,  7,  4,  4,  8,  9, 10,  1, 11, 12, 13, 14, 15, 16, 17,
-   18,  1,  1,  1, 19,  1,  0,  0, 20, 21, 22,  1, 23,  4, 21, 24,
-   25, 26, 27, 28, 29, 30,  0,  0,  1,  1, 31,  0,  0,  0, 32, 33,
-   34, 35,  1, 36, 37,  0,  0,  0,  0, 38,  1, 39, 14, 39, 40, 41,
-   42,  0,  0,  0, 43, 36, 44, 45, 21, 45, 46,  0,  0,  0, 19,  1,
-   21,  0,  0, 47,  0, 38, 48,  1,  1, 49, 49, 50,  0,  0, 51,  0,
-    0,  0, 52,  1,  0,  0, 38, 14,  4,  1,  1,  1, 53, 21, 43, 52,
-   54, 21, 35,  1,  0,  0,  0, 55,  0,  0,  0, 56, 57, 58,  0,  0,
-    0,  0,  0, 59,  0, 60,  0,  0,  0,  0, 61, 62,  0,  0, 63,  0,
-    0,  0, 64,  0,  0,  0, 65,  0,  0,  0, 66,  0,  0,  0, 67,  0,
-    0,  0, 68,  0,  0, 69, 70,  0, 71, 72, 73, 74, 75, 76,  0,  0,
-    0, 77,  0,  0,  0, 78, 79,  0,  0,  0,  0, 47,  0,  0,  0, 49,
-    0, 80,  0,  0,  0, 62,  0,  0, 63,  0,  0, 81,  0,  0, 82,  0,
-    0,  0, 83,  0,  0, 19, 84,  0, 62,  0,  0,  0,  0, 49,  1, 85,
-    1, 52, 15, 86, 36, 10, 21, 87,  0, 55,  0,  0,  0,  0, 19, 10,
-    1,  0,  0,  0,  0,  0, 88,  0,  0, 89,  0,  0, 88,  0,  0,  0,
-    0, 78,  0,  0, 87,  9, 12,  4, 90,  8, 91, 47,  0, 58, 50,  0,
-   21,  1, 21, 92, 93,  1,  1,  1,  1, 94, 95, 96, 97,  1, 98, 58,
-   81, 99,100,  4, 58,  0,  0,  0,  0,  0,  0, 19, 50,  0,  0,  0,
-    0,  0,  0, 61,  0,  0,101,102,  0,  0,103,  0,  0,  1,  1, 50,
-    0,  0,  0, 38,  0, 63,  0,  0,  0,  0,  0, 62,  0,  0,104, 68,
-   61,  0,  0,  0, 78,  0,  0,  0,105,106, 58, 38, 81,  0,  0,  0,
-    0,  0,  0,107,  1, 14,  4, 12, 84,  0,  0,  0,  0, 38, 87,  0,
-    0,  0,  0,108,  0,  0,109, 61,  0,110,  0,  0,  0,  1,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0, 20,  0, 21, 22, 23,  0,  0,  0, 24, 25, 26, 27, 28,
+   29, 30, 31, 32, 33, 34,  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, 35,  0,  0,  0,  0, 36,  0, 37,  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, 38,  0,  0,  0,  0,  0,  0,  0,  0,  0, 39, 40,
+    0,  0,  0,  0,  0,  0, 41, 42, 43,  0, 44,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  0,  0,  0,  0,  3,  0,
+    0,  0,  4,  5,  6,  7,  0,  8,  9, 10,  0, 11, 12, 13, 14, 15,
+   16, 17, 16, 18, 16, 19, 16, 19, 16, 19,  0, 19, 16, 20, 16, 19,
+   21, 19,  0, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,  0, 32,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0, 33,  0,  0,  0,  0,  0,  0,
+   34,  0,  0, 35,  0,  0, 36,  0, 37,  0,  0,  0, 38, 39, 40, 41,
+   42, 43, 44, 45, 46,  0,  0, 47,  0,  0,  0, 48,  0,  0,  0, 49,
+    0,  0,  0,  0,  0,  0,  0, 50,  0, 51,  0, 52, 53,  0, 54,  0,
+    0,  0,  0,  0,  0, 55, 56, 57,  0,  0,  0,  0, 58,  0,  0, 59,
+   60, 61, 62, 63,  0,  0, 64, 65,  0,  0,  0, 66,  0,  0,  0,  0,
+   67,  0,  0,  0, 68,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0, 69,  0,  0,  0, 70,  0, 71,  0,  0, 72,  0,  0, 73,
+    0,  0,  0,  0,  0,  0,  0,  0, 74, 75,  0,  0,  0,  0, 76, 77,
+    0, 78, 79,  0,  0, 80, 81,  0, 82, 62,  0, 83, 84,  0,  0, 85,
+   86, 87,  0, 88,  0, 89,  0, 90,  0,  0, 51, 91, 51,  0, 92,  0,
+   93,  0,  0,  0, 81,  0,  0,  0, 94, 95,  0, 96, 97, 98, 99,  0,
+    0,  0,  0,  0, 51,  0,  0,  0,  0,100,101,  0,  0,  0,  0,  0,
+    0,102,  0,  0,  0,  0,  0,  0,103,  0,  0,  0,  0,  0,  0,104,
+  105,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,106,  0,  0,107,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,108,109,  0,  0,110,  0,  0,
+    0,  0,  0,  0,111,  0,112,  0,105,  0,  0,  0,  0,  0,113,114,
+    0,  0,  0,  0,  0,  0,  0,115,  0,  0,  0,116,  0,  0,  0,117,
+    0,118,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  0,
+    8,  0,  0,  0,  0,  9, 10, 11, 12,  0,  0,  0,  0, 13,  0,  0,
+   14, 15,  0, 16,  0, 17, 18,  0,  0, 19,  0, 20, 21,  0,  0,  0,
+    0,  0, 22, 23,  0, 24, 25,  0,  0, 26,  0,  0,  0, 27,  0,  0,
+   28, 29, 30, 31,  0,  0,  0, 32, 33, 34,  0,  0, 33,  0,  0, 35,
+   33,  0,  0,  0, 33, 36,  0,  0,  0,  0,  0, 37, 38,  0,  0,  0,
+    0,  0,  0, 39, 40,  0,  0,  0,  0,  0,  0, 41, 42,  0,  0,  0,
+    0, 43,  0, 44,  0,  0,  0, 45, 46,  0,  0,  0, 47,  0,  0,  0,
+    0,  0,  0, 48, 49,  0,  0,  0,  0, 50,  0,  0,  0, 51,  0, 52,
+    0, 53,  0,  0,  0,  0, 54,  0,  0,  0,  0, 55,  0, 56,  0,  0,
+    0,  0, 57, 58,  0,  0,  0, 59, 60,  0,  0,  0,  0,  0,  0, 61,
+   52,  0, 62, 63,  0,  0, 64,  0,  0,  0, 65, 66,  0,  0,  0, 67,
+    0, 68, 69, 70, 71, 72,  1, 73,  0, 74, 75, 76,  0,  0, 77, 78,
+    0,  0,  0, 79,  0,  0,  1,  1,  0,  0, 80,  0,  0, 81,  0,  0,
+    0,  0, 77, 82,  0, 83,  0,  0,  0,  0,  0, 78, 84,  0, 85,  0,
+   52,  0,  1, 78,  0,  0, 86,  0,  0, 87,  0,  0,  0,  0,  0, 88,
+   57,  0,  0,  0,  0,  0,  0, 89, 90,  0,  0, 84,  0,  0, 33,  0,
+    0, 91,  0,  0,  0,  0, 92,  0,  0,  0,  0, 49,  0,  0, 93,  0,
+    0,  0,  0, 94, 95,  0,  0, 96,  0,  0, 97,  0,  0,  0, 98,  0,
+    0,  0, 99,  0,  0,  0,100,  0,  0,  0,  0,101,102, 93,  0,  0,
+  103,  0,  0,  0, 84,  0,  0,104,  0,  0,  0,105,106,  0,  0,107,
+  108,  0,  0,  0,  0,  0,  0,109,  0,  0,110,  0,  0,  0,  0,111,
+   33,  0,112,113,114, 57,  0,  0,115, 35,  0,  0,116,  0,  0,  0,
+  117,  0,  0,  0,  0,  0,  0,118,  0,  0,119,  0,  0,  0,  0,120,
+   88,  0,  0,  0,  0,  0, 57,  0,  0,  0,  0, 52,121,  0,  0,  0,
+    0,122,  0,  0,123,  0,  0,  0,  0,121,  0,  0,124,  0,  0,  0,
+    0,  0, 79,  0,  0,  0,  0,125,  0,  0,  0,126,  0,  0,  0,127,
+    0,128,  0,  0,  0,  0,129,130,131,  0,132,  0,133,  0,  0,  0,
+  134,135,136,  0, 77,  0,  0,  0,  0,  0, 35,  0,  0,  0,137,  0,
+    0,  0,138,  0,  0,  0,139,  0,  0,140,  0,  0,141,  0,  0,  0,
+    0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  3,  4,  5,  6,  7,  4,
+    4,  8,  9, 10,  1, 11, 12, 13, 14, 15, 16, 17, 18,  1,  1,  1,
+   19,  1,  0,  0, 20, 21, 22,  1, 23,  4, 21, 24, 25, 26, 27, 28,
+   29, 30,  0,  0,  1,  1, 31,  0,  0,  0, 32, 33, 34, 35,  1, 36,
+   37,  0,  0,  0,  0, 38,  1, 39, 14, 39, 40, 41, 42,  0,  0,  0,
+   43, 36, 44, 45, 21, 45, 46,  0,  0,  0, 19,  1, 21,  0,  0, 47,
+    0, 38, 48,  1,  1, 49, 49, 50,  0,  0, 51,  0,  0, 19, 52,  1,
+    0,  0, 38, 14,  4,  1,  1,  1, 53, 21, 43, 52, 54, 21, 35,  1,
+    0,  0,  0, 55,  0,  0,  0, 56, 57, 58,  0,  0,  0,  0,  0, 59,
+    0, 60,  0,  0,  0,  0, 61, 62,  0,  0, 63,  0,  0,  0, 64,  0,
+    0,  0, 65,  0,  0,  0, 66,  0,  0,  0, 67,  0,  0,  0, 68,  0,
+    0, 69, 70,  0, 71, 72, 73, 74, 75, 76,  0,  0,  0, 77,  0,  0,
+    0, 78, 79,  0,  0,  0,  0, 47,  0,  0,  0, 49,  0, 80,  0,  0,
+    0, 62,  0,  0, 63,  0,  0, 81,  0,  0, 82,  0,  0,  0, 83,  0,
+    0, 19, 84,  0, 62,  0,  0,  0,  0, 49,  1, 85,  1, 52, 15, 86,
+   36, 10, 21, 87,  0, 55,  0,  0,  0,  0, 19, 10,  1,  0,  0,  0,
+    0,  0, 88,  0,  0, 89,  0,  0, 88,  0,  0,  0,  0, 78,  0,  0,
+   87,  9, 12,  4, 90,  8, 91, 47,  0, 58, 50,  0, 21,  1, 21, 92,
+   93,  1,  1,  1,  1, 94, 95, 96, 97,  1, 98, 58, 81, 99,100,  4,
+   58,  0,  0,  0,  0,  0,  0, 19, 50,  0,  0,  0,  0,  0,  0, 61,
+    0,  0,101,102,  0,  0,103,  0,  0,  1,  1, 50,  0,  0,  0, 38,
+    0, 63,  0,  0,  0,  0,  0, 62,  0,  0,104, 68, 61,  0,  0,  0,
+   78,  0,  0,  0,105,106, 58, 38, 81,  0,  0,  0,  0,  0,  0,107,
+    1, 14,  4, 12, 84,  0,  0,  0,  0, 38, 87,  0,  0,  0,  0,108,
+    0,  0,109, 61,  0,110,  0,  0,  0,  1,  0,  0,  0,  0, 49, 50,
     0,  0, 19, 58,  0,  0,  0, 51,  0,111, 14, 52,112, 41,  0,  0,
    62,  0,  0, 61,  0,  0,113,  0, 87,  0,  0,  0, 61, 62,  0,  0,
    62,  0, 89,  0,  0,113,  0,  0,  0,  0,114,  0,  0,  0, 78, 55,
-    0, 38,  1, 58,  1, 58,  0,  0, 63, 89,  0,  0,115,  0,  0,  0,
-   55,  0,  0,  0,  0,115,  0,  0,  0,  0, 61,  0,  0,  0,  0, 79,
-    0, 61,  0,  0,  0,  0, 56,  0, 89, 80,  0,  0, 79,  0,  0,  0,
-    8, 91,  0,  0,  1, 87,  0,  0,116,  0,  0,  0,  0,  0,  0,117,
-    0,118,119,120,121,  0,104,  4,122, 49, 23,  0,  0,  0, 38, 50,
-   38, 58,  0,  0,  1, 87,  1,  1,  1,  1, 39,  1, 48,105, 87,  0,
-    0,  0,  0,  1,  0,  0,  0,123,  4,122,  0,  0,  0,  1,124,  0,
-    0,  0,  0,  0,230,230,230,230,230,232,220,220,220,220,232,216,
-  220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220,
-    1,  1,  1,  1,  1,220,220,220,220,230,230,230,230,240,230,220,
-  220,220,230,230,230,220,220,  0,230,230,230,220,220,220,220,230,
-  232,220,220,230,233,234,234,233,234,234,233,230,  0,  0,  0,230,
-    0,220,230,230,230,230,220,230,230,230,222,220,230,230,220,220,
-  230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20,
-   21, 22,  0, 23,  0, 24, 25,  0,230,220,  0, 18, 30, 31, 32,  0,
-    0,  0,  0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230,
-  220,230,230,220, 35,  0,  0,  0,  0,  0,230,230,230,  0,  0,230,
-  230,  0,220,230,230,220,  0,  0,  0, 36,  0,  0,230,220,230,230,
-  220,220,230,220,220,230,220,230,220,230,230,  0,  0,220,  0,  0,
-  230,230,  0,230,  0,230,230,230,230,230,  0,  0,  0,220,220,220,
-  230,220,220,220,230,230,  0,220, 27, 28, 29,230,  7,  0,  0,  0,
-    0,  9,  0,  0,  0,230,220,230,230,  0,  0,  0,  0,  0,230,  0,
-    0, 84, 91,  0,  0,  0,  0,  9,  9,  0,  0,  0,  0,  0,  9,  0,
-  103,103,  9,  0,107,107,107,107,118,118,  9,  0,122,122,122,122,
-  220,220,  0,  0,  0,220,  0,220,  0,216,  0,  0,  0,129,130,  0,
-  132,  0,  0,  0,  0,  0,130,130,130,130,  0,  0,130,  0,230,230,
-    9,  0,230,230,  0,  0,220,  0,  0,  0,  0,  7,  0,  9,  9,  0,
-    9,  9,  0,  0,  0,230,  0,  0,  0,228,  0,  0,  0,222,230,220,
-  220,  0,  0,  0,230,  0,  0,220,230,220,  0,220,230,230,230,  0,
-    0,  0,  9,  9,  0,  0,  7,  0,230,  0,  1,  1,  1,  0,  0,  0,
-  230,234,214,220,202,230,230,230,230,230,232,228,228,220,218,230,
-  233,220,230,220,230,230,  1,  1,  1,  1,  1,230,  0,  1,  1,230,
-  220,230,  1,  1,  0,  0,218,228,232,222,224,224,  0,  8,  8,  0,
-    0,  0,  0,220,230,  0,230,230,220,  0,  0,230,  0,  0, 26,  0,
-    0,220,  0,230,230,  1,220,  0,  0,230,220,  0,  0,  0,220,220,
-    0,  0,230,220,  0,  9,  7,  0,  0,  7,  9,  0,  0,  0,  9,  7,
-    6,  6,  0,  0,  0,  0,  1,  0,  0,216,216,  1,  1,  1,  0,  0,
-    0,226,216,216,216,216,216,  0,220,220,220,  0,232,232,220,230,
-  230,230,  7,  0, 16, 17, 17, 17, 17, 17, 17, 33, 17, 17, 17, 19,
-   17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27, 28, 17, 17, 17,
-   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+    0, 38,  1, 58,  1, 58,  0,  0,  0,  0,  0, 88, 63, 89,  0,  0,
+  115,  0,  0,  0, 55,  0,  0,  0,  0,115,  0,  0,  0,  0, 61,  0,
+    0,  0,  0, 79,  0, 61,  0,  0,  0,  0, 56,  0, 89, 80,  0,  0,
+   79,  0,  0,  0,  8, 91,  0,  0,  1, 87,  0,  0,116,  0,  0,  0,
+    0,  0,  0,117,  0,118,119,120,121,  0,104,  4,122, 49, 23,  0,
+    0,  0, 38, 50, 38, 58,  0,  0,  1, 87,  1,  1,  1,  1, 39,  1,
+   48,105, 87,  0,  0,  0,  0,  1,  0,  0,  0,123,  0,  0,  0,112,
+    4,122,  0,  0,  0,  1,124,  0,  0,  0,  0,  0,230,230,230,230,
+  230,232,220,220,220,220,232,216,220,220,220,220,220,202,202,220,
+  220,220,220,202,202,220,220,220,  1,  1,  1,  1,  1,220,220,220,
+  220,230,230,230,230,240,230,220,220,220,230,230,230,220,220,  0,
+  230,230,230,220,220,220,220,230,232,220,220,230,233,234,234,233,
+  234,234,233,230,  0,  0,  0,230,  0,220,230,230,230,230,220,230,
+  230,230,222,220,230,230,220,220,230,222,228,230, 10, 11, 12, 13,
+   14, 15, 16, 17, 18, 19, 19, 20, 21, 22,  0, 23,  0, 24, 25,  0,
+  230,220,  0, 18, 30, 31, 32,  0,  0,  0,  0, 27, 28, 29, 30, 31,
+   32, 33, 34,230,230,220,220,230,220,230,230,220, 35,  0,  0,  0,
+    0,  0,230,230,230,  0,  0,230,230,  0,220,230,230,220,  0,  0,
+    0, 36,  0,  0,230,220,230,230,220,220,230,220,220,230,220,230,
+  220,230,230,  0,  0,220,  0,  0,230,230,  0,230,  0,230,230,230,
+  230,230,  0,  0,  0,220,220,220,230,220,220,220,230,230,  0,220,
+   27, 28, 29,230,  7,  0,  0,  0,  0,  9,  0,  0,  0,230,220,230,
+  230,  0,  0,  0,  0,  0,230,  0,  0, 84, 91,  0,  0,  0,  0,  9,
+    9,  0,  0,  0,  0,  0,  9,  0,103,103,  9,  0,107,107,107,107,
+  118,118,  9,  0,122,122,122,122,220,220,  0,  0,  0,220,  0,220,
+    0,216,  0,  0,  0,129,130,  0,132,  0,  0,  0,  0,  0,130,130,
+  130,130,  0,  0,130,  0,230,230,  9,  0,230,230,  0,  0,220,  0,
+    0,  0,  0,  7,  0,  9,  9,  0,  9,  9,  0,  0,  0,230,  0,  0,
+    0,228,  0,  0,  0,222,230,220,220,  0,  0,  0,230,  0,  0,220,
+  230,220,  0,220,230,230,230,  0,  0,  0,  9,  9,  0,  0,  7,  0,
+  230,  0,  1,  1,  1,  0,  0,  0,230,234,214,220,202,230,230,230,
+  230,230,232,228,228,220,218,230,233,220,230,220,230,230,  1,  1,
+    1,  1,  1,230,  0,  1,  1,230,220,230,  1,  1,  0,  0,218,228,
+  232,222,224,224,  0,  8,  8,  0,  0,  0,  0,220,230,  0,230,230,
+  220,  0,  0,230,  0,  0, 26,  0,  0,220,  0,230,230,  1,220,  0,
+    0,230,220,  0,  0,  0,220,220,  0,  0,230,220,  0,  9,  7,  0,
+    0,  7,  9,  0,  0,  0,  9,  7,  6,  6,  0,  0,  0,  0,  1,  0,
+    0,216,216,  1,  1,  1,  0,  0,  0,226,216,216,216,216,216,  0,
+  220,220,220,  0,232,232,220,230,230,230,  7,  0, 16, 17, 17, 17,
+   17, 17, 17, 33, 17, 17, 17, 19, 17, 17, 17, 17, 20,101, 17,113,
+  129,169, 17, 27, 28, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-   17, 17, 17,237,  0,  1,  2,  2,  0,  3,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  4,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    5,  0,  0,  0,  0,  6,  7,  8,  9,  0,  0,  0, 10, 11, 12, 13,
-   14, 15, 16, 17, 18, 19,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,
-    0,  0, 21, 22,  0,  0,  0,  0, 23, 24, 25, 26,  0, 27,  0, 28,
-   29, 30, 31, 32,  0,  0,  0,  0,  0,  0,  0, 33, 34, 35, 36,  0,
-    0,  0,  0,  0, 37,  0,  0,  0,  0,  0,  0,  0,  0,  0, 38, 39,
-    0,  0,  0,  0,  1,  2, 40, 41,  0,  1,  2,  2,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  2,  0,  0,  0,  0,
-    0,  0,  3,  4,  0,  0,  5,  0,  0,  0,  6,  0,  0,  0,  0,  0,
-    0,  0,  7,  1,  0,  0,  0,  0,  0,  0,  8,  9,  0,  0,  0,  0,
-    0,  0, 10,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0, 10,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0, 11, 12,
-    0, 13,  0, 14, 15, 16,  0,  0,  0,  0,  0,  1, 17, 18,  0, 19,
-    7,  1,  0,  0,  0, 20, 20,  7, 20, 20, 20, 20, 20, 20, 20,  8,
-   21,  0, 22,  0,  7, 23, 24,  0, 20, 20, 25,  0,  0,  0, 26, 27,
-    1,  7, 20, 20, 20, 20, 20,  1, 28, 29, 30, 31,  0,  0, 20,  0,
-    0,  0,  0,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0, 20, 20,
-   20,  1,  0,  0,  8, 21, 32,  4,  0, 10,  0, 33,  7, 20, 20, 20,
-    0,  0,  0,  0,  8, 34, 34, 35, 36, 34, 37,  0, 38,  1, 20, 20,
-    0,  0, 39,  0,  1,  1,  0,  8, 21,  1, 20,  0,  0,  0,  1,  0,
-    0, 40,  1,  1,  0,  0,  8, 21,  0,  1,  0,  1,  0,  1,  0,  0,
-    0,  0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21,  7, 20, 41,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 21,  0, 42, 43, 44,  0, 45,
-    0,  8, 21,  0,  0,  0,  0,  0,  0,  0,  0, 46,  7,  1, 10,  1,
-    0,  0,  0,  1, 20, 20,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0, 26, 34,  9,  0,  0, 20, 20,  1, 20, 20,  0,  0,  0,  0,  0,
-    0,  0, 26, 21,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  3, 47, 48,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,
-    4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-    9, 10, 11, 11, 11, 11, 12, 13, 13, 13, 13, 14, 15, 16, 17, 18,
-   19, 20, 21, 13, 22, 13, 13, 13, 13, 23, 24, 24, 25, 26, 13, 13,
-   13, 27, 28, 29, 13, 30, 31, 32, 33, 34, 35, 36,  7,  7,  7,  7,
-    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-   37,  7, 38, 39,  7, 40,  7,  7,  7, 41, 13, 42,  7,  7, 43,  7,
-   44, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 45,  0,  0,  1,
-    2,  2,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
-   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-   32, 32, 33, 34, 35, 36, 37, 37, 37, 37, 37, 38, 39, 40, 41, 42,
-   43, 44, 45, 46, 47, 48, 49, 50, 51, 52,  2,  2, 53, 54, 55, 56,
-   57, 58, 59, 59, 59, 59, 60, 59, 59, 59, 59, 59, 59, 59, 61, 61,
-   59, 59, 59, 59, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
-   74, 75, 76, 77, 78, 59, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 79, 70, 70, 70, 70, 80, 80,
-   80, 80, 80, 80, 80, 80, 80, 81, 82, 82, 83, 84, 85, 86, 87, 88,
-   89, 90, 91, 92, 93, 94, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 95, 96, 96,
-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-   70, 70, 97, 98, 99,100,101,101,102,103,104,105,106,107,108,109,
-  110,111, 96,112,113,114,115,116,117,118,119,119,120,121,122,123,
-  124,125,126,127,128,129,130,131,132, 96,133,134,135,136,137,138,
-  139,140,141,142,143, 96,144,145, 96,146,147,148,149, 96,150,151,
-  152,153,154,155,156, 96,157,158,159,160, 96,161,162,163,164,164,
-  164,164,164,164,164,165,166,164,167, 96, 96, 96, 96, 96, 96, 96,
-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,168,169,169,
-  169,169,169,169,169,169,170, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-   96, 96, 96, 96, 96, 96,171,171,171,171,172, 96, 96, 96,173,173,
-  173,173,174,175,176,177, 96, 96, 96, 96,178,179,180,181,182,182,
-  182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
-  182,182,182,182,182,182,182,182,182,182,182,182,182,183,182,182,
-  182,182,182,182,184,184,184,185,186, 96, 96, 96, 96, 96, 96, 96,
-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,187,188,189,
-  190,191,191,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-   96, 96, 96, 96, 96, 96,193,194, 96, 96, 96, 96, 96, 96, 96, 96,
-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,195,196, 59,197,
-  198,199,200,201,202, 96,203,204,205, 59, 59,206, 59,207,208,208,
-  208,208,208,209, 96, 96, 96, 96, 96, 96, 96, 96,210, 96,211,212,
-  213, 96, 96,214, 96, 96, 96,215, 96, 96, 96, 96, 96,216,217,218,
-  219, 96, 96, 96, 96, 96,220,221,222, 96,223,224, 96, 96,225,226,
-   59,227,228, 96, 59, 59, 59, 59, 59, 59, 59,229,230,231,232,233,
-   59, 59,234,235, 59,236, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,237, 70, 70, 70, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,238, 70,239, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,240, 70, 70, 70, 70,
-   70, 70, 70, 70, 70,241, 70, 70, 70, 70,242, 96, 96, 96, 70, 70,
-   70, 70,243, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
-   70, 70, 70, 70,244, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-   70, 70, 70, 70, 70,245, 96, 96, 96, 96, 96, 96, 96, 96,246, 96,
-  247,248,  0,  1,  2,  2,  0,  1,  2,  2,  2,  3,  4,  5,  0,  0,
-    0,  0,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-   19, 19, 19, 19, 19, 19, 19, 19, 19,  0,  0,  0,  0,  0,  0,  0,
-   19,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19, 19, 19,  0, 19,  0,
-    0,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19,  0,  0,  0,  0,  0,
-   26, 26,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  9,  9,
-    9,  9,  0,  9,  9,  9,  2,  2,  9,  9,  9,  9,  0,  9,  2,  2,
-    2,  2,  9,  0,  9,  0,  9,  9,  9,  2,  9,  2,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  2,  9,  9,  9,  9,  9,  9,  9,
-   55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,  6,  6,
-    6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  1,  1,  6,  2,  4,
-    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
-    4,  4,  4,  4,  4,  2,  4,  4,  4,  2,  2,  4,  4,  4,  2, 14,
-   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,  2,  2,
-    2,  2,  2,  2,  2,  2, 14, 14, 14,  2,  2,  2,  2, 14, 14, 14,
-   14, 14, 14,  2,  2,  2,  3,  3,  3,  3,  3,  0,  3,  3,  3,  3,
-    3,  3,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-    3,  0,  3,  3,  3,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-    3,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  3,  3,  1,  3,
-    3,  3,  3,  3,  3,  3, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-   37, 37, 37, 37,  2, 37, 37, 37, 37,  2,  2, 37, 37, 37, 38, 38,
-   38, 38, 38, 38, 38, 38, 38, 38,  2,  2,  2,  2,  2,  2, 64, 64,
-   64, 64, 64, 64, 64, 64, 64, 64, 64,  2,  2, 64, 64, 64, 90, 90,
-   90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,  2,  2, 90, 90,
-   90, 90, 90, 90, 90,  2, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
-   95, 95,  2,  2, 95,  2, 37, 37, 37,  2,  2,  2,  2,  2,  3,  3,
-    3,  3,  3,  3,  3,  2,  3,  3,  2,  2,  2,  2,  2,  2,  3,  3,
-    0,  3,  3,  3,  3,  3,  7,  7,  7,  7,  7,  7,  7,  7,  7,  1,
-    1,  1,  1,  7,  7,  7,  7,  7,  7,  7,  0,  0,  7,  7,  5,  5,
-    5,  5,  2,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2,  5,  5,  2,
-    2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,
-    5,  5,  5,  5,  5,  5,  5,  2,  5,  2,  2,  2,  5,  5,  5,  5,
-    2,  2,  5,  5,  5,  5,  5,  2,  2,  5,  5,  5,  5,  2,  2,  2,
-    2,  2,  2,  2,  2,  5,  2,  2,  2,  2,  5,  5,  2,  5,  5,  5,
-    5,  5,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2, 11,
-   11, 11,  2, 11, 11, 11, 11, 11, 11,  2,  2,  2,  2, 11, 11,  2,
-    2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,  2,
-   11, 11, 11, 11, 11, 11, 11,  2, 11, 11,  2, 11, 11,  2, 11, 11,
-    2,  2, 11,  2, 11, 11, 11,  2,  2, 11, 11, 11,  2,  2,  2, 11,
-    2,  2,  2,  2,  2,  2,  2, 11, 11, 11, 11,  2, 11,  2,  2,  2,
-    2,  2,  2,  2, 11, 11, 11, 11, 11, 11, 11, 11, 11,  2,  2, 10,
-   10, 10,  2, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,
-    2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2,
-   10, 10, 10, 10, 10, 10, 10,  2, 10, 10,  2, 10, 10, 10, 10, 10,
-    2,  2, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,  2,  2, 10,  2,
-    2,  2,  2,  2,  2,  2, 10, 10, 10, 10,  2,  2, 10, 10, 10, 10,
-    2,  2,  2,  2,  2,  2,  2, 10, 10, 10, 10, 10, 10, 10,  2, 21,
-   21, 21,  2, 21, 21, 21, 21, 21, 21, 21, 21,  2,  2, 21, 21,  2,
-    2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,  2,
-   21, 21, 21, 21, 21, 21, 21,  2, 21, 21,  2, 21, 21, 21, 21, 21,
-    2,  2, 21, 21, 21, 21, 21,  2,  2, 21, 21, 21,  2,  2,  2,  2,
-    2,  2,  2, 21, 21, 21,  2,  2,  2,  2, 21, 21,  2, 21, 21, 21,
-   21, 21,  2,  2, 21, 21,  2,  2, 22, 22,  2, 22, 22, 22, 22, 22,
-   22,  2,  2,  2, 22, 22, 22,  2, 22, 22, 22, 22,  2,  2,  2, 22,
-   22,  2, 22,  2, 22, 22,  2,  2,  2, 22, 22,  2,  2,  2, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22,  2,  2,  2,  2, 22, 22, 22,  2,
-    2,  2,  2,  2,  2, 22,  2,  2,  2,  2,  2,  2, 22, 22, 22, 22,
-   22,  2,  2,  2,  2,  2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
-   23, 23, 23,  2, 23, 23, 23,  2, 23, 23, 23, 23, 23, 23, 23, 23,
-    2,  2, 23, 23, 23, 23, 23,  2, 23, 23, 23, 23,  2,  2,  2,  2,
-    2,  2,  2, 23, 23,  2, 23, 23, 23,  2,  2, 23,  2,  2, 23, 23,
-   23, 23,  2,  2, 23, 23,  2,  2,  2,  2,  2,  2,  2, 23, 16, 16,
-   16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16,  2,
-   16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16, 16, 16,
-    2,  2, 16, 16, 16, 16, 16,  2, 16, 16, 16, 16,  2,  2,  2,  2,
-    2,  2,  2, 16, 16,  2, 16, 16, 16, 16,  2,  2, 16, 16,  2, 16,
-   16, 16,  2,  2,  2,  2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
-   20, 20, 20,  2, 20, 20, 20,  2, 20, 20, 20, 20, 20, 20,  2,  2,
-    2,  2, 20, 20, 20, 20, 20, 20, 20, 20,  2,  2, 20, 20,  2, 36,
-   36, 36,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-   36, 36, 36, 36, 36,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36, 36,
-    2, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2,  2,  2,
-   36,  2,  2,  2,  2, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2,  2,
-    2,  2,  2,  2, 36, 36,  2,  2, 36, 36, 36,  2,  2,  2,  2, 24,
-   24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-   24,  2,  2,  2,  2,  0, 24, 24, 24, 24,  2,  2,  2,  2,  2, 18,
-   18,  2, 18,  2, 18, 18, 18, 18, 18,  2, 18, 18, 18, 18, 18, 18,
-   18, 18, 18, 18, 18, 18, 18, 18, 18, 18,  2, 18,  2, 18, 18, 18,
-   18, 18, 18, 18,  2,  2, 18, 18, 18, 18, 18,  2, 18,  2, 18, 18,
-   18, 18, 18, 18, 18,  2, 18, 18,  2,  2, 18, 18, 18, 18, 25, 25,
-   25, 25, 25, 25, 25, 25,  2, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-   25, 25, 25,  2,  2,  2, 25, 25, 25, 25, 25,  2, 25, 25, 25, 25,
-   25, 25, 25,  0,  0,  0,  0, 25, 25,  2,  2,  2,  2,  2, 33, 33,
-   33, 33, 33, 33, 33, 33,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-    8,  8,  8,  8,  2,  8,  2,  2,  2,  2,  2,  8,  2,  2,  8,  8,
-    8,  0,  8,  8,  8,  8, 12, 12, 12, 12, 12, 12, 12, 12, 30, 30,
-   30, 30, 30, 30, 30, 30, 30,  2, 30, 30, 30, 30,  2,  2, 30, 30,
-   30, 30, 30, 30, 30,  2, 30, 30, 30,  2,  2, 30, 30, 30, 30, 30,
-   30, 30, 30,  2,  2,  2, 30, 30,  2,  2,  2,  2,  2,  2, 29, 29,
-   29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,  2,  2, 28, 28,
-   28, 28, 28, 28, 28, 28, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34,  2,  2,  2, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-   35,  0,  0,  0, 35, 35, 35,  2,  2,  2,  2,  2,  2,  2, 45, 45,
-   45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,  2,  2,  2,  2,
-    2,  2,  2,  2,  2, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
-   44, 44, 44,  0,  0,  2, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
-   43, 43,  2,  2,  2,  2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
-   46, 46, 46,  2, 46, 46, 46,  2, 46, 46,  2,  2,  2,  2, 31, 31,
-   31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,  2,  2, 31, 31,
-    2,  2,  2,  2,  2,  2, 32, 32,  0,  0, 32,  0, 32, 32, 32, 32,
-   32, 32, 32, 32, 32, 32, 32, 32,  2,  2,  2,  2,  2,  2, 32,  2,
-    2,  2,  2,  2,  2,  2, 32, 32, 32,  2,  2,  2,  2,  2, 28, 28,
-   28, 28, 28, 28,  2,  2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
-   48, 48, 48, 48, 48,  2, 48, 48, 48, 48,  2,  2,  2,  2, 48,  2,
-    2,  2, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-   52, 52, 52, 52,  2,  2, 52, 52, 52, 52, 52,  2,  2,  2, 58, 58,
-   58, 58, 58, 58, 58, 58, 58, 58, 58, 58,  2,  2,  2,  2, 58, 58,
-    2,  2,  2,  2,  2,  2, 58, 58, 58,  2,  2,  2, 58, 58, 54, 54,
-   54, 54, 54, 54, 54, 54, 54, 54, 54, 54,  2,  2, 54, 54, 91, 91,
-   91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,  2, 91, 91,
-   91, 91, 91,  2,  2, 91, 91, 91,  2,  2,  2,  2,  2,  2, 91, 91,
-   91, 91, 91, 91,  2,  2,  1,  1,  1,  1,  1,  1,  1,  2, 62, 62,
-   62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,  2,  2,  2, 62, 62,
-   62, 62, 62, 62, 62,  2, 76, 76, 76, 76, 76, 76, 76, 76, 93, 93,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,237,  0,  1,  2,  2,
+    0,  3,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  4,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  5,  0,  0,  0,  0,  6,  7,  8,
+    9,  0,  0,  0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,  0,  0,
+    0,  0,  0,  0,  0,  0,  0, 20,  0,  0, 21, 22,  0,  0,  0,  0,
+   23, 24, 25, 26,  0, 27,  0, 28, 29, 30, 31, 32,  0,  0,  0,  0,
+    0,  0,  0, 33, 34, 35, 36,  0,  0,  0,  0,  0, 37,  0,  0,  0,
+    0,  0,  0,  0,  0,  0, 38, 39,  0,  0,  0,  0,  1,  2, 40, 41,
+    0,  1,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,
+    0,  0,  0,  2,  0,  0,  0,  0,  0,  0,  3,  4,  0,  0,  5,  0,
+    0,  0,  6,  0,  0,  0,  0,  0,  0,  0,  7,  1,  0,  0,  0,  0,
+    0,  0,  8,  9,  0,  0,  0,  0,  0,  0, 10,  0,  0, 10,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 10,  0,  0,  0, 10,
+    0,  0,  0,  0,  0,  0, 11, 12,  0, 13,  0, 14, 15, 16,  0,  0,
+    0,  0,  0,  1, 17, 18,  0, 19,  7,  1,  0,  0,  0, 20, 20,  7,
+   20, 20, 20, 20, 20, 20, 20,  8, 21,  0, 22,  0,  7, 23, 24,  0,
+   20, 20, 25,  0,  0,  0, 26, 27,  1,  7, 20, 20, 20, 20, 20,  1,
+   28, 29, 30, 31,  0,  0, 20,  0,  0,  0,  0,  0,  0,  0, 10,  0,
+    0,  0,  0,  0,  0,  0, 20, 20, 20,  1,  0,  0,  8, 21, 32,  4,
+    0, 10,  0, 33,  7, 20, 20, 20,  0,  0,  0,  0,  8, 34, 34, 35,
+   36, 34, 37,  0, 38,  1, 20, 20,  0,  0, 39,  0,  1,  1,  0,  8,
+   21,  1, 20,  0,  0,  0,  1,  0,  0, 40,  1,  1,  0,  0,  8, 21,
+    0,  1,  0,  1,  0,  1,  0,  0,  0,  0, 26, 34, 34, 34, 34, 34,
+   34, 34, 34, 34, 21,  7, 20, 41, 34, 34, 34, 34, 34, 34, 34, 34,
+   34, 21,  0, 42, 43, 44,  0, 45,  0,  8, 21,  0,  0,  0,  0,  0,
+    0,  0,  0, 46,  7,  1, 10,  1,  0,  0,  0,  1, 20, 20,  1,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0, 26, 34,  9,  0,  0, 20, 20,
+    1, 20, 20,  0,  0,  0,  0,  0,  0,  0, 26, 21,  0,  1,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3, 47, 48,  0,  0,  0,
+    0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
+   12, 13, 13, 13, 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 16, 17, 18,
+   18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 20, 20, 20, 20, 20, 20,
+   20, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 20, 33,
+   34, 35, 34, 34, 36, 37, 20, 20, 20, 20, 20, 20, 38, 20, 39, 40,
+   41, 41, 41, 41, 41, 42, 43, 44, 20, 20, 20, 20, 20, 20, 20, 45,
+   46, 20, 20, 47, 20, 20, 20, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+   57, 58, 59, 20, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 60, 13, 13,
+   13, 61, 62, 13, 13, 13, 13, 63, 13, 13, 13, 13, 13, 13, 64, 65,
+   20, 20, 66, 20, 13, 13, 13, 13, 67, 13, 13, 13, 68, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20, 20, 69,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19,
+   19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+   19,  0,  0,  0,  0,  0,  0,  0, 19,  0,  0,  0,  0,  0, 19, 19,
+   19, 19, 19, 19, 19,  0, 19,  0,  0,  0,  0,  0,  0,  0, 19, 19,
+   19, 19, 19,  0,  0,  0,  0,  0, 26, 26,  0,  0,  0,  0,  1,  1,
+    1,  1,  1,  1,  1,  1,  9,  9,  9,  9,  0,  9,  9,  9,  2,  2,
+    9,  9,  9,  9,  0,  9,  2,  2,  2,  2,  9,  0,  9,  0,  9,  9,
+    9,  2,  9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    2,  9,  9,  9,  9,  9,  9,  9, 55, 55, 55, 55, 55, 55, 55, 55,
+   55, 55, 55, 55, 55, 55,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+    6,  6,  6,  1,  1,  6,  2,  4,  4,  4,  4,  4,  4,  4,  4,  4,
+    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  4,  4,
+    4,  2,  2,  4,  4,  4,  2, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+   14, 14, 14, 14, 14, 14,  2,  2,  2,  2,  2,  2,  2,  2, 14, 14,
+   14,  2,  2,  2,  2, 14, 14, 14, 14, 14, 14,  2,  2,  2,  3,  3,
+    3,  3,  3,  0,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,  0,  0,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  1,  1,  1,  1,  1,  1,  1,
+    1,  1,  1,  1,  3,  3,  1,  3,  3,  3,  3,  3,  3,  3, 37, 37,
+   37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,  2, 37, 37, 37,
+   37,  2,  2, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
+    2,  2,  2,  2,  2,  2, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+   64,  2,  2, 64, 64, 64, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
+   90, 90, 90, 90,  2,  2, 90, 90, 90, 90, 90, 90, 90,  2, 95, 95,
+   95, 95, 95, 95, 95, 95, 95, 95, 95, 95,  2,  2, 95,  2, 37, 37,
+   37,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,  2,  3,  3,
+    2,  2,  2,  2,  2,  3,  3,  3,  0,  3,  3,  3,  3,  3,  7,  7,
+    7,  7,  7,  7,  7,  7,  7,  1,  1,  1,  1,  7,  7,  7,  7,  7,
+    7,  7,  0,  0,  7,  7,  5,  5,  5,  5,  2,  5,  5,  5,  5,  5,
+    5,  5,  5,  2,  2,  5,  5,  2,  2,  5,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5,  5,  2,  5,  5,  5,  5,  5,  5,  5,  2,
+    5,  2,  2,  2,  5,  5,  5,  5,  2,  2,  5,  5,  5,  5,  5,  2,
+    2,  5,  5,  5,  5,  2,  2,  2,  2,  2,  2,  2,  2,  5,  2,  2,
+    2,  2,  5,  5,  2,  5,  5,  5,  5,  5,  2,  2,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  2,  2, 11, 11, 11,  2, 11, 11, 11, 11, 11,
+   11,  2,  2,  2,  2, 11, 11,  2,  2, 11, 11, 11, 11, 11, 11, 11,
+   11, 11, 11, 11, 11, 11, 11,  2, 11, 11, 11, 11, 11, 11, 11,  2,
+   11, 11,  2, 11, 11,  2, 11, 11,  2,  2, 11,  2, 11, 11, 11,  2,
+    2, 11, 11, 11,  2,  2,  2, 11,  2,  2,  2,  2,  2,  2,  2, 11,
+   11, 11, 11,  2, 11,  2,  2,  2,  2,  2,  2,  2, 11, 11, 11, 11,
+   11, 11, 11, 11, 11,  2,  2, 10, 10, 10,  2, 10, 10, 10, 10, 10,
+   10, 10, 10, 10,  2, 10, 10, 10,  2, 10, 10, 10, 10, 10, 10, 10,
+   10, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10, 10, 10, 10, 10,  2,
+   10, 10,  2, 10, 10, 10, 10, 10,  2,  2, 10, 10, 10, 10, 10, 10,
+    2, 10, 10, 10,  2,  2, 10,  2,  2,  2,  2,  2,  2,  2, 10, 10,
+   10, 10,  2,  2, 10, 10, 10, 10,  2,  2,  2,  2,  2,  2,  2, 10,
+   10, 10, 10, 10, 10, 10,  2, 21, 21, 21,  2, 21, 21, 21, 21, 21,
+   21, 21, 21,  2,  2, 21, 21,  2,  2, 21, 21, 21, 21, 21, 21, 21,
+   21, 21, 21, 21, 21, 21, 21,  2, 21, 21, 21, 21, 21, 21, 21,  2,
+   21, 21,  2, 21, 21, 21, 21, 21,  2,  2, 21, 21, 21, 21, 21,  2,
+    2, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2, 21, 21, 21,  2,  2,
+    2,  2, 21, 21,  2, 21, 21, 21, 21, 21,  2,  2, 21, 21,  2,  2,
+   22, 22,  2, 22, 22, 22, 22, 22, 22,  2,  2,  2, 22, 22, 22,  2,
+   22, 22, 22, 22,  2,  2,  2, 22, 22,  2, 22,  2, 22, 22,  2,  2,
+    2, 22, 22,  2,  2,  2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+    2,  2,  2,  2, 22, 22, 22,  2,  2,  2,  2,  2,  2, 22,  2,  2,
+    2,  2,  2,  2, 22, 22, 22, 22, 22,  2,  2,  2,  2,  2, 23, 23,
+   23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,  2, 23, 23, 23,  2,
+   23, 23, 23, 23, 23, 23, 23, 23,  2,  2, 23, 23, 23, 23, 23,  2,
+   23, 23, 23, 23,  2,  2,  2,  2,  2,  2,  2, 23, 23,  2, 23, 23,
+   23,  2,  2, 23,  2,  2, 23, 23, 23, 23,  2,  2, 23, 23,  2,  2,
+    2,  2,  2,  2,  2, 23, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+   16, 16, 16,  2, 16, 16, 16,  2, 16, 16, 16, 16, 16, 16, 16, 16,
+   16, 16,  2, 16, 16, 16, 16, 16,  2,  2, 16, 16, 16, 16, 16,  2,
+   16, 16, 16, 16,  2,  2,  2,  2,  2,  2,  2, 16, 16,  2, 16, 16,
+   16, 16,  2,  2, 16, 16,  2, 16, 16, 16,  2,  2,  2,  2, 20, 20,
+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  2, 20, 20, 20,  2,
+   20, 20, 20, 20, 20, 20,  2,  2,  2,  2, 20, 20, 20, 20, 20, 20,
+   20, 20,  2,  2, 20, 20,  2, 36, 36, 36,  2, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2,  2,  2,
+   36, 36, 36, 36, 36, 36, 36, 36,  2, 36, 36, 36, 36, 36, 36, 36,
+   36, 36,  2, 36,  2,  2,  2,  2, 36,  2,  2,  2,  2, 36, 36, 36,
+   36, 36, 36,  2, 36,  2,  2,  2,  2,  2,  2,  2, 36, 36,  2,  2,
+   36, 36, 36,  2,  2,  2,  2, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+   24, 24, 24, 24, 24, 24, 24, 24, 24,  2,  2,  2,  2,  0, 24, 24,
+   24, 24,  2,  2,  2,  2,  2, 18, 18,  2, 18,  2, 18, 18, 18, 18,
+   18,  2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+   18, 18,  2, 18,  2, 18, 18, 18, 18, 18, 18, 18,  2,  2, 18, 18,
+   18, 18, 18,  2, 18,  2, 18, 18, 18, 18, 18, 18, 18,  2, 18, 18,
+    2,  2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25,  2, 25,
+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,  2,  2,  2, 25, 25,
+   25, 25, 25,  2, 25, 25, 25, 25, 25, 25, 25,  0,  0,  0,  0, 25,
+   25,  2,  2,  2,  2,  2, 33, 33, 33, 33, 33, 33, 33, 33,  8,  8,
+    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  2,  8,  2,  2,
+    2,  2,  2,  8,  2,  2,  8,  8,  8,  0,  8,  8,  8,  8, 12, 12,
+   12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30,  2,
+   30, 30, 30, 30,  2,  2, 30, 30, 30, 30, 30, 30, 30,  2, 30, 30,
+   30,  2,  2, 30, 30, 30, 30, 30, 30, 30, 30,  2,  2,  2, 30, 30,
+    2,  2,  2,  2,  2,  2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+   29, 29, 29, 29,  2,  2, 28, 28, 28, 28, 28, 28, 28, 28, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,  2,  2,  2, 35, 35,
+   35, 35, 35, 35, 35, 35, 35, 35, 35,  0,  0,  0, 35, 35, 35,  2,
+    2,  2,  2,  2,  2,  2, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+   45, 45, 45, 45,  2,  2,  2,  2,  2,  2,  2,  2,  2, 45, 44, 44,
+   44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,  0,  0,  2, 43, 43,
+   43, 43, 43, 43, 43, 43, 43, 43, 43, 43,  2,  2,  2,  2, 46, 46,
+   46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,  2, 46, 46, 46,  2,
+   46, 46,  2,  2,  2,  2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+   31, 31, 31, 31,  2,  2, 31, 31,  2,  2,  2,  2,  2,  2, 32, 32,
+    0,  0, 32,  0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+    2,  2,  2,  2,  2,  2, 32,  2,  2,  2,  2,  2,  2,  2, 32, 32,
+   32,  2,  2,  2,  2,  2, 28, 28, 28, 28, 28, 28,  2,  2, 48, 48,
+   48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,  2, 48, 48,
+   48, 48,  2,  2,  2,  2, 48,  2,  2,  2, 48, 48, 48, 48, 52, 52,
+   52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,  2,  2, 52, 52,
+   52, 52, 52,  2,  2,  2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+   58, 58,  2,  2,  2,  2, 58, 58,  2,  2,  2,  2,  2,  2, 58, 58,
+   58,  2,  2,  2, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+   54, 54,  2,  2, 54, 54, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+   91, 91, 91, 91, 91,  2, 91, 91, 91, 91, 91,  2,  2, 91, 91, 91,
+    2,  2,  2,  2,  2,  2, 91, 91, 91, 91, 91, 91,  2,  2,  1,  1,
+    1,  1,  1,  1,  1,  2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+   62, 62, 62,  2, 62, 62, 76, 76, 76, 76, 76, 76, 76, 76, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93,  2,  2,  2,  2,  2,  2,
     2,  2, 93, 93, 93, 93, 70, 70, 70, 70, 70, 70, 70, 70,  2,  2,
     2, 70, 70, 70, 70, 70, 70, 70,  2,  2,  2, 70, 70, 70, 73, 73,
-   73, 73, 73, 73, 73, 73,  6,  2,  2,  2,  2,  2,  2,  2,  8,  8,
+   73, 73, 73, 73, 73, 73,  6,  6,  6,  2,  2,  2,  2,  2,  8,  8,
     8,  2,  2,  8,  8,  8,  1,  1,  1,  0,  1,  1,  1,  1,  1,  0,
     1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  1,  0,  0,  0,  0,
     0,  0,  1,  0,  0,  0,  1,  1,  0,  2,  2,  2,  2,  2, 19, 19,
@@ -1896,31 +1872,30 @@ _hb_ucd_u8[17884] =
     2,  2,  2,  2,  2,  2,  1,  2,  2,  2,  2,  2,  2,  2,  0,  0,
     0,  0,  0,  0,  9,  0,  0,  0, 19, 19,  0,  0,  0,  0,  0,  0,
     0,  0,  0,  0, 19,  0, 19,  0,  0,  0,  2,  2,  2,  2,  0,  0,
-    0,  2,  2,  2,  2,  2, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,
-    0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0, 56, 56,
-   56, 56, 56, 56, 56, 56, 55, 55, 55, 55,  2,  2,  2,  2,  2, 55,
-   55, 55, 55, 55, 55, 55, 61, 61, 61, 61, 61, 61, 61, 61,  2,  2,
-    2,  2,  2,  2,  2, 61, 61,  2,  2,  2,  2,  2,  2,  2,  0,  0,
-    0,  0,  0,  0,  2,  2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-    2, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  2, 13, 13,
-   13, 13, 13, 13,  2,  2,  0,  0,  0,  0,  0, 13,  0, 13,  0, 13,
-   13, 13, 13, 13, 13, 13, 13, 13,  1,  1,  1,  1, 12, 12, 13, 13,
-   13, 13,  0,  0,  0,  0,  2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,  1,
-    1,  0,  0, 15, 15, 15,  0, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-   17, 17, 17, 17, 17, 17, 17, 17, 17,  0,  0, 17, 17, 17,  2,  2,
-    2,  2,  2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2, 12,
-   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  2,  0,  0,
-    0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0, 12, 12,
+    2,  2,  2,  2,  2,  2,  0,  0,  0,  2,  2,  2,  2,  2, 27, 27,
+   27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  2,  2,  0,  0,  0,  0,
+    0,  0,  0,  0,  2,  0, 56, 56, 56, 56, 56, 56, 56, 56, 55, 55,
+   55, 55,  2,  2,  2,  2,  2, 55, 55, 55, 55, 55, 55, 55, 61, 61,
+   61, 61, 61, 61, 61, 61,  2,  2,  2,  2,  2,  2,  2, 61, 61,  2,
+    2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  2,  2, 13, 13,
+   13, 13, 13, 13, 13, 13, 13, 13,  2, 13, 13, 13, 13, 13, 13, 13,
+   13, 13,  2,  2,  2,  2, 13, 13, 13, 13, 13, 13,  2,  2,  0,  0,
+    0,  0,  0, 13,  0, 13,  0, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    1,  1,  1,  1, 12, 12, 13, 13, 13, 13,  0,  0,  0,  0,  2, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15,  2,  2,  1,  1,  0,  0, 15, 15, 15,  0, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17,  0,  0, 17, 17, 17,  2,  2,  2,  2,  2, 26, 26, 26, 26, 26,
+   26, 26, 26, 26, 26, 26,  2, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+   12, 12, 12, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  0, 12, 12,
    12, 12, 12, 12, 12,  0, 17, 17, 17, 17, 17, 17, 17,  0, 39, 39,
    39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,  2,  2,  2, 39, 39,
    39, 39, 39, 39, 39,  2, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77,
    77, 77, 77, 77, 77, 77, 77, 77, 77, 77,  2,  2,  2,  2, 79, 79,
    79, 79, 79, 79, 79, 79,  0,  0, 19, 19, 19, 19, 19, 19,  0,  0,
-    0, 19, 19, 19, 19, 19, 19, 19, 19,  2,  2,  2,  2,  2, 19, 19,
-    2, 19,  2, 19, 19, 19, 19, 19,  2,  2,  2,  2,  2,  2,  2,  2,
-   19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
-   60, 60, 60,  2,  2,  2,  0,  0,  2,  2,  2,  2,  2,  2, 65, 65,
+    0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,  2,  2, 19, 19,
+    2, 19,  2, 19, 19, 19,  2,  2, 19, 19, 19, 19, 19, 19, 60, 60,
+   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,  2,  2,  2, 65, 65,
    65, 65, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
    75, 75, 75, 75,  2,  2,  2,  2,  2,  2,  2,  2, 75, 75, 75, 75,
     2,  2,  2,  2,  2,  2, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
@@ -1943,36 +1918,38 @@ _hb_ucd_u8[17884] =
     2, 14, 14,  2, 14, 14,  3,  3,  3,  2,  2,  2,  2,  2,  2,  2,
     2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  0,  2,  2,
     3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  3,  1,  1,
-    1,  1,  1,  1,  6,  6,  0,  0,  0,  2,  0,  0,  0,  0,  3,  3,
-    3,  3,  3,  2,  3,  3,  3,  3,  3,  3,  3,  2,  2,  0,  2,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17, 17, 17, 17,
-   17, 17, 17, 17,  0,  0,  2,  2, 12, 12, 12, 12, 12, 12,  2,  2,
-   12, 12, 12,  2,  2,  2,  2,  0,  0,  0,  0,  0,  2,  2, 49, 49,
-   49, 49, 49, 49, 49, 49, 49, 49, 49, 49,  2, 49, 49, 49, 49, 49,
-   49, 49, 49, 49, 49,  2, 49, 49, 49,  2, 49, 49,  2, 49, 49, 49,
-   49, 49, 49, 49,  2,  2, 49, 49, 49,  2,  2,  2,  2,  2,  0,  0,
-    0,  2,  2,  2,  2,  0,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,
-    0,  0,  0,  2,  2,  2,  9,  2,  2,  2,  2,  2,  2,  2,  0,  0,
-    0,  0,  0,  1,  2,  2, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
-   71, 71, 71,  2,  2,  2, 67, 67, 67, 67, 67, 67, 67, 67, 67,  2,
-    2,  2,  2,  2,  2,  2,  1,  0,  0,  0,  0,  0,  0,  0, 42, 42,
-   42, 42, 42, 42, 42, 42, 42, 42, 42, 42,  2,  2,  2,  2,  2,  2,
-    2,  2,  2, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
-   41,  2,  2,  2,  2,  2,118,118,118,118,118,118,118,118,118,118,
-  118,  2,  2,  2,  2,  2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-   53, 53, 53, 53,  2, 53, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-   59, 59,  2,  2,  2,  2, 59, 59, 59, 59, 59, 59,  2,  2, 40, 40,
-   40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50,
-   50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,  2,  2, 50, 50,
-    2,  2,  2,  2,  2,  2,135,135,135,135,135,135,135,135,135,135,
-  135,135,  2,  2,  2,  2,106,106,106,106,106,106,106,106,104,104,
-  104,104,104,104,104,104,104,104,104,104,  2,  2,  2,  2,  2,  2,
-    2,  2,  2,  2,  2,104,161,161,161,161,161,161,161,161,161,161,
-  161,  2,161,161,161,161,161,161,161,  2,161,161,  2,161,161,161,
-    2,161,161,161,161,161,161,161,  2,161,161,  2,  2,  2,110,110,
-  110,110,110,110,110,110,110,110,110,110,110,110,110,  2,110,110,
-  110,110,110,110,  2,  2, 19, 19, 19, 19, 19, 19,  2, 19, 19,  2,
-   19, 19, 19, 19, 19, 19, 47, 47, 47, 47, 47, 47,  2,  2, 47,  2,
+    1,  1,  1,  1,  6,  6,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,
+    0,  0,  2,  2,  2,  2,  3,  3,  3,  3,  3,  2,  3,  3,  3,  3,
+    3,  3,  3,  2,  2,  0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0, 17, 17, 17, 17, 17, 17, 17, 17,  0,  0,  2,  2,
+   12, 12, 12, 12, 12, 12,  2,  2, 12, 12, 12,  2,  2,  2,  2,  0,
+    0,  0,  0,  0,  2,  2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+   49, 49,  2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,  2, 49, 49,
+   49,  2, 49, 49,  2, 49, 49, 49, 49, 49, 49, 49,  2,  2, 49, 49,
+   49,  2,  2,  2,  2,  2,  0,  0,  0,  2,  2,  2,  2,  0,  0,  0,
+    0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  2,  2,  2,  9,  2,
+    2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  1,  2,  2, 71, 71,
+   71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,  2,  2,  2, 67, 67,
+   67, 67, 67, 67, 67, 67, 67,  2,  2,  2,  2,  2,  2,  2,  1,  0,
+    0,  0,  0,  0,  0,  0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+   42, 42,  2,  2,  2,  2,  2,  2,  2,  2,  2, 42, 42, 42, 41, 41,
+   41, 41, 41, 41, 41, 41, 41, 41, 41,  2,  2,  2,  2,  2,118,118,
+  118,118,118,118,118,118,118,118,118,  2,  2,  2,  2,  2, 53, 53,
+   53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,  2, 53, 59, 59,
+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59,  2,  2,  2,  2, 59, 59,
+   59, 59, 59, 59,  2,  2, 40, 40, 40, 40, 40, 40, 40, 40, 51, 51,
+   51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+   50, 50, 50, 50,  2,  2, 50, 50,  2,  2,  2,  2,  2,  2,135,135,
+  135,135,135,135,135,135,135,135,135,135,  2,  2,  2,  2,106,106,
+  106,106,106,106,106,106,104,104,104,104,104,104,104,104,104,104,
+  104,104,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,104,161,161,
+  161,161,161,161,161,161,161,161,161,  2,161,161,161,161,161,161,
+  161,  2,161,161,  2,161,161,161,  2,161,161,161,161,161,161,161,
+    2,161,161,  2,  2,  2,170,170,170,170,170,170,170,170,170,170,
+  170,170,  2,  2,  2,  2,110,110,110,110,110,110,110,110,110,110,
+  110,110,110,110,110,  2,110,110,110,110,110,110,  2,  2, 19, 19,
+   19, 19, 19, 19,  2, 19, 19,  2, 19, 19, 19, 19, 19, 19, 19, 19,
+   19,  2,  2,  2,  2,  2, 47, 47, 47, 47, 47, 47,  2,  2, 47,  2,
    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
    47, 47, 47, 47,  2, 47, 47,  2,  2,  2, 47,  2,  2, 47, 81, 81,
    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,  2, 81,120,120,
@@ -1998,122 +1975,135 @@ _hb_ucd_u8[17884] =
   122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89,  2,
     2,  2,  2,  2,  2,  2,130,130,130,130,130,130,130,130,130,130,
   130,  2,  2,  2,  2,  2,  2,  2,130,130,130,130,130,130,144,144,
-  144,144,144,144,144,144,144,144,  2,  2,  2,  2,  2,  2,156,156,
+  144,144,144,144,144,144,144,144,  2,  2,  2,  2,  2,  2,165,165,
+  165,165,165,165,165,165,165,165,165,165,165,165,  2,  2,  2,165,
+  165,165,165,165,165,165,  2,  2,  2,  2,  2,  2,165,165,156,156,
   156,156,156,156,156,156,156,156,  2,156,156,156,  2,  2,156,156,
-    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,147,147,
-  147,147,147,147,147,147,148,148,148,148,148,148,148,148,148,148,
-    2,  2,  2,  2,  2,  2,158,158,158,158,158,158,158,158,158,158,
-    2,  2,  2,  2,  2,  2,153,153,153,153,153,153,153,153,153,153,
-  153,153,  2,  2,  2,  2,149,149,149,149,149,149,149,149,149,149,
-  149,149,149,149,149,  2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
-   94, 94, 94, 94,  2,  2,  2,  2, 94, 94, 94, 94, 94, 94,  2,  2,
-    2,  2,  2,  2,  2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
-   85,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 85,  2,  2,101,101,
-  101,101,101,101,101,101,101,  2,  2,  2,  2,  2,  2,  2,101,101,
-    2,  2,  2,  2,  2,  2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-   96, 96, 96,  2, 96, 96,111,111,111,111,111,111,111,111,111,111,
-  111,111,111,111,111,  2,100,100,100,100,100,100,100,100,  2, 36,
-   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2,  2,  2,108,108,
-  108,108,108,108,108,108,108,108,  2,108,108,108,108,108,108,108,
-    2,  2,  2,  2,  2,  2,129,129,129,129,129,129,129,  2,129,  2,
-  129,129,129,129,  2,129,129,129,129,129,129,129,129,129,129,129,
-  129,129,129,129,  2,129,129,129,  2,  2,  2,  2,  2,  2,109,109,
-  109,109,109,109,109,109,109,109,109,  2,  2,  2,  2,  2,109,109,
-    2,  2,  2,  2,  2,  2,107,107,107,107,  2,107,107,107,107,107,
-  107,107,107,  2,  2,107,107,  2,  2,107,107,107,107,107,107,107,
-  107,107,107,107,107,107,107,  2,107,107,107,107,107,107,107,  2,
-  107,107,  2,107,107,107,107,107,  2,  1,107,107,107,107,107,  2,
-    2,107,107,107,  2,  2,107,  2,  2,  2,  2,  2,  2,107,  2,  2,
-    2,  2,  2,107,107,107,107,107,107,107,  2,  2,107,107,107,107,
-  107,107,107,  2,  2,  2,137,137,137,137,137,137,137,137,137,137,
+    2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  2,  2,  2,  2,  2,
+    2,  2,  3,  3,  3,  3,147,147,147,147,147,147,147,147,148,148,
+  148,148,148,148,148,148,148,148,  2,  2,  2,  2,  2,  2,158,158,
+  158,158,158,158,158,158,158,158,  2,  2,  2,  2,  2,  2,153,153,
+  153,153,153,153,153,153,153,153,153,153,  2,  2,  2,  2,149,149,
+  149,149,149,149,149,149,149,149,149,149,149,149,149,  2, 94, 94,
+   94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,  2,  2,  2,  2,
+   94, 94, 94, 94, 94, 94,  2,  2,  2,  2,  2,  2,  2, 94, 85, 85,
+   85, 85, 85, 85, 85, 85, 85, 85, 85,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2, 85,  2,  2,101,101,101,101,101,101,101,101,101,  2,
+    2,  2,  2,  2,  2,  2,101,101,  2,  2,  2,  2,  2,  2, 96, 96,
+   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,  2, 96, 96,111,111,
+  111,111,111,111,111,111,111,111,111,111,111,111,111,  2,100,100,
+  100,100,100,100,100,100,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36,  2,  2,  2,108,108,108,108,108,108,108,108,108,108,
+    2,108,108,108,108,108,108,108,  2,  2,  2,  2,  2,  2,129,129,
+  129,129,129,129,129,  2,129,  2,129,129,129,129,  2,129,129,129,
+  129,129,129,129,129,129,129,129,129,129,129,129,  2,129,129,129,
+    2,  2,  2,  2,  2,  2,109,109,109,109,109,109,109,109,109,109,
+  109,  2,  2,  2,  2,  2,109,109,  2,  2,  2,  2,  2,  2,107,107,
+  107,107,  2,107,107,107,107,107,107,107,107,  2,  2,107,107,  2,
+    2,107,107,107,107,107,107,107,107,107,107,107,107,107,107,  2,
+  107,107,107,107,107,107,107,  2,107,107,  2,107,107,107,107,107,
+    2,  1,107,107,107,107,107,  2,  2,107,107,107,  2,  2,107,  2,
+    2,  2,  2,  2,  2,107,  2,  2,  2,  2,  2,107,107,107,107,107,
+  107,107,  2,  2,107,107,107,107,107,107,107,  2,  2,  2,171,171,
+  171,171,171,171,171,171,171,171,  2,171,  2,  2,171,  2,171,171,
+  171,171,171,171,  2,171,171,  2,171,  2,  2,171,  2,171,171,171,
+  171,  2,171,171,171,171,171,  2,  2,  2,  2,  2,  2,  2,  2,171,
+  171,  2,  2,  2,  2,  2,137,137,137,137,137,137,137,137,137,137,
   137,137,  2,137,137,137,137,137,  2,  2,  2,  2,  2,  2,124,124,
   124,124,124,124,124,124,124,124,  2,  2,  2,  2,  2,  2,123,123,
   123,123,123,123,123,123,123,123,123,123,123,123,  2,  2,114,114,
   114,114,114,114,114,114,114,114,114,114,114,  2,  2,  2,114,114,
     2,  2,  2,  2,  2,  2, 32, 32, 32, 32, 32,  2,  2,  2,102,102,
-  102,102,102,102,102,102,102,102,  2,  2,  2,  2,  2,  2,126,126,
-  126,126,126,126,126,126,126,126,126,  2,  2,126,126,126,126,126,
-  126,126,  2,  2,  2,  2,126,126,126,126,126,126,126,  2,142,142,
-  142,142,142,142,142,142,142,142,142,142,  2,  2,  2,  2,125,125,
-  125,125,125,125,125,125,125,125,125,  2,  2,  2,  2,  2,  2,  2,
-    2,  2,  2,  2,  2,125,154,154,154,154,154,154,154,  2,  2,154,
-    2,  2,154,154,154,154,154,154,154,154,  2,154,154,  2,154,154,
-  154,154,154,154,154,154,154,154,154,154,154,154,  2,154,154,  2,
-    2,154,154,154,154,154,154,154,  2,  2,  2,  2,  2,  2,150,150,
-  150,150,150,150,150,150,  2,  2,150,150,150,150,150,150,150,150,
-  150,150,150,  2,  2,  2,141,141,141,141,141,141,141,141,140,140,
-  140,140,140,140,140,140,140,140,140,  2,  2,  2,  2,  2,121,121,
-  121,121,121,121,121,121,121,  2,  2,  2,  2,  2,  2,  2,  7,  7,
-    2,  2,  2,  2,  2,  2,133,133,133,133,133,133,133,133,133,  2,
-  133,133,133,133,133,133,133,133,133,133,133,133,133,  2,133,133,
-  133,133,133,133,  2,  2,133,133,133,133,133,  2,  2,  2,134,134,
-  134,134,134,134,134,134,  2,  2,134,134,134,134,134,134,  2,134,
-  134,134,134,134,134,134,134,134,134,134,134,134,134,  2,138,138,
-  138,138,138,138,138,  2,138,138,  2,138,138,138,138,138,138,138,
-  138,138,138,138,138,138,  2,  2,138,  2,138,138,  2,138,138,138,
-    2,  2,  2,  2,  2,  2,143,143,143,143,143,143,  2,143,143,  2,
-  143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
-  143,143,143,143,143,  2,143,143,  2,143,143,143,143,143,143,  2,
-    2,  2,  2,  2,  2,  2,143,143,  2,  2,  2,  2,  2,  2,145,145,
-  145,145,145,145,145,145,145,  2,  2,  2,  2,  2,  2,  2,163,163,
-  163,163,163,163,163,163,163,  2,163,163,163,163,163,163,163,163,
-  163,  2,  2,  2,163,163,163,163,  2,  2,  2,  2,  2,  2, 86,  2,
-    2,  2,  2,  2,  2,  2, 22, 22,  2,  2,  2,  2,  2,  2,  2,  2,
-    2,  2,  2,  2,  2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
-    2,  2,  2,  2,  2,  2, 63, 63, 63, 63, 63, 63, 63,  2, 63, 63,
-   63, 63, 63,  2,  2,  2, 63, 63, 63, 63,  2,  2,  2,  2,157,157,
-  157,157,157,157,157,157,157,157,157,  2,  2,  2,  2,  2, 80, 80,
-   80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,  2,  2,127,127,
-  127,127,127,127,127,127,127,127,127,127,127,127,127,  2, 79,  2,
+  102,102,102,102,102,102,102,102,  2,  2,  2,  2,  2,  2, 33, 33,
+   33, 33,  2,  2,  2,  2,126,126,126,126,126,126,126,126,126,126,
+  126,  2,  2,126,126,126,126,126,126,126,  2,  2,  2,  2,126,126,
+  126,126,126,126,126,  2,142,142,142,142,142,142,142,142,142,142,
+  142,142,  2,  2,  2,  2,125,125,125,125,125,125,125,125,125,125,
+  125,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,125,154,154,
+  154,154,154,154,154,  2,  2,154,  2,  2,154,154,154,154,154,154,
+  154,154,  2,154,154,  2,154,154,154,154,154,154,154,154,154,154,
+  154,154,154,154,  2,154,154,  2,  2,154,154,154,154,154,154,154,
+    2,  2,  2,  2,  2,  2,150,150,150,150,150,150,150,150,  2,  2,
+  150,150,150,150,150,150,150,150,150,150,150,  2,  2,  2,141,141,
+  141,141,141,141,141,141,140,140,140,140,140,140,140,140,140,140,
+  140,  2,  2,  2,  2,  2,121,121,121,121,121,121,121,121,121,  2,
+    2,  2,  2,  2,  2,  2,  7,  7,  2,  2,  2,  2,  2,  2,169,169,
+  169,169,169,169,169,169,169,169,  2,  2,  2,  2,  2,  2,133,133,
+  133,133,133,133,133,133,133,  2,133,133,133,133,133,133,133,133,
+  133,133,133,133,133,  2,133,133,133,133,133,133,  2,  2,133,133,
+  133,133,133,  2,  2,  2,134,134,134,134,134,134,134,134,  2,  2,
+  134,134,134,134,134,134,  2,134,134,134,134,134,134,134,134,134,
+  134,134,134,134,134,  2,138,138,138,138,138,138,138,  2,138,138,
+    2,138,138,138,138,138,138,138,138,138,138,138,138,138,  2,  2,
+  138,  2,138,138,  2,138,138,138,  2,  2,  2,  2,  2,  2,143,143,
+  143,143,143,143,  2,143,143,  2,143,143,143,143,143,143,143,143,
+  143,143,143,143,143,143,143,143,143,143,143,143,143,  2,143,143,
+    2,143,143,143,143,143,143,  2,  2,  2,  2,  2,  2,  2,143,143,
+    2,  2,  2,  2,  2,  2,145,145,145,145,145,145,145,145,145,  2,
+    2,  2,  2,  2,  2,  2,163,163,163,163,163,163,163,163,163,  2,
+  163,163,163,163,163,163,163,163,163,  2,  2,  2,163,163,163,163,
+  163,  2,  2,  2,  2,  2, 86,  2,  2,  2,  2,  2,  2,  2, 22, 22,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 22, 63, 63,
+   63, 63, 63, 63, 63, 63, 63, 63,  2,  2,  2,  2,  2,  2, 63, 63,
+   63, 63, 63, 63, 63,  2, 63, 63, 63, 63, 63,  2,  2,  2, 63, 63,
+   63, 63,  2,  2,  2,  2,157,157,157,157,157,157,157,157,157,157,
+  157,  2,  2,  2,  2,  2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+   80, 80, 80, 80,  2,  2, 80, 80, 80,  2,  2,  2,  2,  2,127,127,
+  127,127,127,127,127,127,127,127,127,127,127,127,127,  2,166,166,
+  166,166,166,166,166,166,166,166,  2,  2,  2,  2,  2,  2, 79,  2,
     2,  2,  2,  2,  2,  2,115,115,115,115,115,115,115,115,115,115,
   115,115,115,115,115,  2,115,115,  2,  2,  2,  2,115,115,159,159,
   159,159,159,159,159,159,159,159,159,159,159,159,159,  2,159,159,
     2,  2,  2,  2,  2,  2,103,103,103,103,103,103,103,103,103,103,
   103,103,103,103,  2,  2,119,119,119,119,119,119,119,119,119,119,
   119,119,119,119,  2,  2,119,119,  2,119,119,119,119,119,  2,  2,
-    2,  2,  2,119,119,119,146,146,146,146,146,146,146,146,146,146,
+    2,  2,  2,119,119,119,167,167,167,167,167,167,167,167,167,167,
+    2,  2,  2,  2,  2,  2,146,146,146,146,146,146,146,146,146,146,
   146,  2,  2,  2,  2,  2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
    99,  2,  2,  2,  2, 99,  2,  2,  2,  2,  2,  2,  2, 99,136,139,
    13, 13,155,  2,  2,  2,136,136,136,136,136,136,136,136,155,155,
-  155,155,155,155,155,155,155,155,155,155,155,155,  2,  2,136,  2,
-    2,  2,  2,  2,  2,  2, 17, 17, 17, 17,  2, 17, 17, 17, 17, 17,
-   17, 17,  2, 17, 17,  2, 17, 15, 15, 15, 15, 15, 15, 15, 17, 17,
-   17,  2,  2,  2,  2,  2,  2,  2, 15,  2,  2,  2,  2,  2, 15, 15,
-   15,  2,  2, 17,  2,  2,  2,  2,  2,  2, 17, 17, 17, 17,139,139,
-  139,139,139,139,139,139,139,139,139,139,  2,  2,  2,  2,105,105,
-  105,105,105,105,105,105,105,105,105,  2,  2,  2,  2,  2,105,105,
-  105,105,105,  2,  2,  2,105,  2,  2,  2,  2,  2,  2,  2,105,105,
-    2,  2,105,105,105,105,  1,  1,  1,  1,  1,  1,  2,  2,  0,  0,
-    0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,
-    1,  1,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0,  0,  2,  2,
-    0,  2,  2,  0,  0,  2,  2,  0,  0,  0,  0,  2,  0,  0,  0,  0,
-    2,  0,  2,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,
-    0,  2,  2,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  2,  0,  0,
-    0,  0,  0,  2,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  2,
-    0,  0,  0,  0,  0,  0,131,131,131,131,131,131,131,131,131,131,
-  131,131,  2,  2,  2,  2,  2,  2,  2,131,131,131,131,131,  2,131,
-  131,131,131,131,131,131,  2,  2,  2,  2,  2, 19, 19, 19, 56, 56,
-   56, 56, 56, 56, 56,  2, 56,  2,  2, 56, 56, 56, 56, 56, 56, 56,
-    2, 56, 56,  2, 56, 56, 56, 56, 56,  2,  2,  2,  2,  2,  6,  6,
-    6,  6,  6,  6,  2,  2,  2,  2,  2,  2,  2,  2,  2,  6,151,151,
-  151,151,151,151,151,151,151,151,151,151,151,  2,  2,  2,151,151,
-  151,151,151,151,  2,  2,151,151,  2,  2,  2,  2,151,151,160,160,
-  160,160,160,160,160,160,160,160,160,160,160,160,160,  2,152,152,
-  152,152,152,152,152,152,152,152,  2,  2,  2,  2,  2,152,164,164,
-  164,164,164,164,164,164,164,164,  2,  2,  2,  2,  2,  2, 30, 30,
-   30, 30,  2, 30, 30,  2,113,113,113,113,113,113,113,113,113,113,
-  113,113,113,  2,  2,113,113,113,113,113,113,113,113,  2,132,132,
-  132,132,132,132,132,132,132,132,132,132,  2,  2,  2,  2,132,132,
-    2,  2,  2,  2,132,132,  3,  3,  3,  3,  2,  3,  3,  3,  2,  3,
-    3,  2,  3,  2,  2,  3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-    3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  2,  2,  2,  2,  2,  2,
-    3,  2,  2,  2,  2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  2,  3,
-    2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  3,
-    2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  3,
-    3,  3,  2,  3,  3,  3,  2,  2,  2,  2,  2,  2,  0,  0, 15,  0,
+  155,155,155,155,155,155,155,155,155,155,155,155,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,155,136,  2,  2,  2,  2,  2,  2,  2, 17, 17,
+   17, 17,  2, 17, 17, 17, 17, 17, 17, 17,  2, 17, 17,  2, 17, 15,
+   15, 15, 15, 15, 15, 15, 17, 17, 17,  2,  2,  2,  2,  2,  2,  2,
+   15,  2,  2,  2,  2,  2, 15, 15, 15,  2,  2, 17,  2,  2,  2,  2,
+    2,  2, 17, 17, 17, 17,139,139,139,139,139,139,139,139,139,139,
+  139,139,  2,  2,  2,  2,105,105,105,105,105,105,105,105,105,105,
+  105,  2,  2,  2,  2,  2,105,105,105,105,105,  2,  2,  2,105,  2,
+    2,  2,  2,  2,  2,  2,105,105,  2,  2,105,105,105,105,  1,  1,
+    1,  1,  1,  1,  2,  2,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,
+    1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,
+    1,  1,  1,  1,  0,  0,  2,  2,  0,  2,  2,  0,  0,  2,  2,  0,
+    0,  0,  0,  2,  0,  0,  0,  0,  2,  0,  2,  0,  0,  0,  0,  0,
+    0,  0,  2,  0,  0,  0,  0,  0,  0,  2,  2,  0,  0,  0,  0,  0,
+    2,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  2,  0,  2,  2,  2,
+    0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,131,131,
+  131,131,131,131,131,131,131,131,131,131,  2,  2,  2,  2,  2,  2,
+    2,131,131,131,131,131,  2,131,131,131,131,131,131,131,  2,  2,
+    2,  2,  2, 19, 19, 19, 56, 56, 56, 56, 56, 56, 56,  2, 56,  2,
+    2, 56, 56, 56, 56, 56, 56, 56,  2, 56, 56,  2, 56, 56, 56, 56,
+   56,  2,  2,  2,  2,  2,  6,  6,  6,  6,  6,  6,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,  6,151,151,151,151,151,151,151,151,151,151,
+  151,151,151,  2,  2,  2,151,151,151,151,151,151,  2,  2,151,151,
+    2,  2,  2,  2,151,151,160,160,160,160,160,160,160,160,160,160,
+  160,160,160,160,160,  2,152,152,152,152,152,152,152,152,152,152,
+    2,  2,  2,  2,  2,152,164,164,164,164,164,164,164,164,164,164,
+    2,  2,  2,  2,  2,  2,168,168,168,168,168,168,168,168,168,168,
+  168,  2,  2,  2,  2,168, 30, 30, 30, 30,  2, 30, 30,  2,113,113,
+  113,113,113,113,113,113,113,113,113,113,113,  2,  2,113,113,113,
+  113,113,113,113,113,  2,132,132,132,132,132,132,132,132,132,132,
+  132,132,  2,  2,  2,  2,132,132,  2,  2,  2,  2,132,132,  3,  3,
+    3,  3,  2,  3,  3,  3,  2,  3,  3,  2,  3,  2,  2,  3,  2,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  3,  3,  3,  3,  2,  3,
+    2,  3,  2,  2,  2,  2,  2,  2,  3,  2,  2,  2,  2,  3,  2,  3,
+    2,  3,  2,  3,  3,  3,  2,  3,  2,  3,  2,  3,  2,  3,  2,  3,
+    3,  3,  3,  2,  3,  2,  3,  3,  2,  3,  3,  3,  3,  3,  3,  3,
+    3,  3,  2,  2,  2,  2,  2,  3,  3,  3,  2,  3,  3,  3,  3,  3,
+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0, 15,  0,
     0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  2,  2,
-    2,  0,  0,  0,  0,  0, 13,  2,  2,  2,  2,  2,  2,  2, 13, 13,
+    2,  0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  2,  0,  0,  0,
+    0,  0,  0,  2,  2,  0, 13,  2,  2,  2,  2,  2,  2,  2, 13, 13,
    13,  2,  2,  2,  2,  2,  2,  0,  2,  2,  2,  2,  2,  2,  0,  1,
     2,  3,  4,  5,  6,  7,  8,  9,  9,  9,  9, 10,  9, 11, 12, 13,
     9,  9,  9, 14,  9,  9, 15,  9,  9,  9,  9,  9,  9,  9,  9,  9,
@@ -2123,13 +2113,14 @@ _hb_ucd_u8[17884] =
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 16, 17,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9, 18, 19, 20,  9, 21,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+   18,  9,  9,  9,  9,  9, 19, 20, 21,  9, 22,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 23,  9,
+    9,  9,  9,  9, 24,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9, 25,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9, 22,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
@@ -2137,8 +2128,7 @@ _hb_ucd_u8[17884] =
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 23, 24,  0,  0,  0,  0,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 26, 27,  0,  0,  0,  0,
     0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,
     9, 10, 11, 12,  0,  0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
@@ -2175,23 +2165,29 @@ _hb_ucd_u8[17884] =
   132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,
   148,149,150,151,152,153,154,155,156,157,  0,  0,  0,158,159,160,
   161,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,162,163,  0,  0,  0,  0,  0,  0,  0,164,  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,162,  0,163,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,164,165,  0,  0,  0,  0,  0,  0,  0,166,  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,
+  167,  0,  0,  0,168,169,  0,  0,170,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,171,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,172,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,173,
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-  165,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,166,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,167,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,168,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,174,  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,169,170,  0,  0,  0,  0,171,172,  0,  0,  0,173,174,175,176,
-  177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,
-  193,194,195,196,197,198,199,200,201,202,203,204,205,206,  0,  0,
+    0,  0,175,  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,176,177,  0,  0,  0,  0,178,179,  0,  0,  0,180,181,182,183,
+  184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,
+  200,201,202,203,204,205,206,207,208,209,210,211,212,213,  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,  1,  2,  3,  4,
 };
 static const uint16_t
-_hb_ucd_u16[9344] =
+_hb_ucd_u16[10400] =
 {
      0,   0,   1,   2,   3,   4,   5,   6,   0,   0,   7,   8,   9,  10,  11,  12,
     13,  13,  13,  14,  15,  13,  13,  16,  17,  18,  19,  20,  21,  22,  13,  23,
@@ -2210,9 +2206,10 @@ _hb_ucd_u16[9344] =
    136,  48,  48, 137, 138, 139, 140, 140, 141,  48, 142, 143, 144, 145, 140, 140,
    146, 147, 148, 149, 150,  48, 151, 152, 153, 154,  32, 155, 156, 157, 140, 140,
     48,  48, 158, 159, 160, 161, 162, 163, 164, 165,   9,   9, 166,  11,  11, 167,
-    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 168, 169,  48,  48,
-   168,  48,  48, 170, 171, 172,  48,  48,  48, 171,  48,  48,  48, 173, 174, 175,
-    48, 176,   9,   9,   9,   9,   9, 177, 178,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48, 168, 169,  48,  48, 168,  48,  48, 170, 171, 172,  48,  48,
+    48, 171,  48,  48,  48, 173, 174, 175,  48, 176,   9,   9,   9,   9,   9, 177,
+   178,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
     48,  48,  48,  48,  48,  48, 179,  48, 180, 181,  48,  48,  48,  48, 182, 183,
     48, 184,  48, 185,  48, 186, 187, 188,  48,  48,  48, 189, 190, 191, 192, 193,
    194, 192,  48,  48, 195,  48,  48, 196, 197,  48, 198,  48,  48,  48,  48, 199,
@@ -2225,28 +2222,34 @@ _hb_ucd_u16[9344] =
    241, 242, 241, 241, 242, 243, 241, 244, 245, 245, 245, 246, 247, 248, 249, 250,
    251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261, 262, 263, 264, 265,
    266, 267, 268, 269, 270, 271, 272, 272, 273, 274, 275, 209, 276, 277, 209, 278,
-   279, 279, 279, 279, 279, 279, 279, 279, 280, 209, 281, 209, 209, 209, 209, 282,
-   209, 283, 279, 284, 209, 285, 286, 209, 209, 209, 287, 140, 288, 140, 271, 271,
-   271, 289, 209, 209, 209, 209, 290, 271, 209, 209, 209, 209, 209, 209, 209, 209,
-   209, 209, 209, 291, 292, 209, 209, 293, 209, 209, 209, 209, 209, 209, 294, 209,
-   209, 209, 209, 209, 209, 209, 295, 296, 271, 297, 209, 209, 298, 279, 299, 279,
-   300, 301, 279, 279, 279, 302, 279, 303, 209, 209, 209, 279, 304, 209, 209, 305,
-   209, 306, 209, 209, 209, 209, 209, 209,   9,   9,   9,  11,  11,  11, 307, 308,
-    13,  13,  13,  13,  13,  13, 309, 310,  11,  11, 311,  48,  48,  48, 312, 313,
-    48, 314, 315, 315, 315, 315,  32,  32, 316, 317, 318, 319, 320, 321, 140, 140,
-   209, 322, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 324, 140, 209,
-   325, 326, 327, 328, 136,  48,  48,  48,  48, 329, 178,  48,  48,  48,  48, 330,
-   331,  48,  48, 136,  48,  48,  48,  48, 200, 332,  48,  48, 209, 209, 333,  48,
-   209, 334, 335, 209, 336, 337, 209, 209, 335, 209, 209, 337, 209, 209, 209, 209,
-    48,  48,  48,  48, 209, 209, 209, 209,  48, 338,  48,  48,  48,  48,  48,  48,
-   151, 209, 209, 209, 287,  48,  48, 229, 339,  48, 340, 140,  13,  13, 341, 342,
-    13, 343,  48,  48,  48,  48, 344, 345,  31, 346, 347, 348,  13,  13,  13, 349,
-   350, 351, 352, 353, 354, 355, 140, 356, 357,  48, 358, 359,  48,  48,  48, 360,
-   361,  48,  48, 362, 363, 192,  32, 364,  64,  48, 365,  48, 366, 367,  48, 151,
-    76,  48,  48, 368, 369, 370, 371, 372,  48,  48, 373, 374, 375, 376,  48, 377,
-    48,  48,  48, 378, 379, 380, 381, 382, 383, 384, 315,  11,  11, 385, 386,  11,
-    11,  11,  11,  11,  48,  48, 387, 192,  48,  48, 388,  48, 389,  48,  48, 206,
-   390, 390, 390, 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, 391, 391,
+   279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
+   280, 209, 281, 209, 209, 209, 209, 282, 209, 283, 279, 284, 209, 285, 286, 209,
+   209, 209, 176, 140, 287, 140, 271, 271, 271, 288, 209, 209, 209, 209, 289, 271,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 290, 291, 209, 209, 292,
+   209, 209, 209, 209, 209, 209, 293, 209, 209, 209, 209, 209, 209, 209, 209, 209,
+   209, 209, 209, 209, 209, 209, 294, 295, 271, 296, 209, 209, 297, 279, 298, 279,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
+   279, 279, 279, 279, 279, 279, 279, 279, 299, 300, 279, 279, 279, 301, 279, 302,
+   209, 209, 209, 279, 303, 209, 209, 304, 209, 305, 209, 209, 209, 209, 209, 209,
+     9,   9,   9,  11,  11,  11, 306, 307,  13,  13,  13,  13,  13,  13, 308, 309,
+    11,  11, 310,  48,  48,  48, 311, 312,  48, 313, 314, 314, 314, 314,  32,  32,
+   315, 316, 317, 318, 319, 320, 140, 140, 209, 321, 209, 209, 209, 209, 209, 322,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 323, 140, 209,
+   324, 325, 326, 327, 136,  48,  48,  48,  48, 328, 178,  48,  48,  48,  48, 329,
+   330,  48,  48, 136,  48,  48,  48,  48, 200, 331,  48,  48, 209, 209, 332,  48,
+   209, 333, 334, 209, 335, 336, 209, 209, 334, 209, 209, 336, 209, 209, 209, 209,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 209, 209, 209, 209,
+    48, 337,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48, 151, 209, 209, 209, 338,  48,  48, 229,
+   339,  48, 340, 140,  13,  13, 341, 342,  13, 343,  48,  48,  48,  48, 344, 345,
+    31, 346, 347, 348,  13,  13,  13, 349, 350, 351, 352, 353, 354, 355, 140, 356,
+   357,  48, 358, 359,  48,  48,  48, 360, 361,  48,  48, 362, 363, 192,  32, 364,
+    64,  48, 365,  48, 366, 367,  48, 151,  76,  48,  48, 368, 369, 370, 371, 372,
+    48,  48, 373, 374, 375, 376,  48, 377,  48,  48,  48, 378, 379, 380, 381, 382,
+   383, 384, 314,  11,  11, 385, 386,  11,  11,  11,  11,  11,  48,  48, 387, 192,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 388,  48, 389,  48,  48, 206,
+   390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
+   391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
     48,  48,  48,  48,  48,  48, 204,  48,  48,  48,  48,  48,  48, 207, 140, 140,
    392, 393, 394, 395, 396,  48,  48,  48,  48,  48,  48, 397, 398, 399,  48,  48,
     48,  48,  48, 400, 209,  48,  48,  48,  48, 401,  48,  48, 402, 140, 140, 403,
@@ -2257,108 +2260,204 @@ _hb_ucd_u16[9344] =
    140, 140, 140, 140, 140, 140, 140, 140,  48, 151,  48,  48,  48, 100, 429, 430,
     48,  48, 431,  48, 432,  48,  48, 433,  48, 434,  48,  48, 435, 436, 140, 140,
      9,   9, 437,  11,  11,  48,  48,  48,  48, 204, 192,   9,   9, 438,  11, 439,
-    48,  48, 440,  48,  48,  48, 441, 442, 442, 443, 444, 445, 140, 140, 140, 140,
-    48,  48,  48, 314,  48, 199, 440, 140, 446,  27,  27, 447, 140, 140, 140, 140,
+    48,  48, 440,  48,  48,  48, 441, 442, 442, 443, 444, 445,  48,  48,  48, 388,
+    48,  48,  48, 313,  48, 199, 440, 140, 446,  27,  27, 447, 140, 140, 140, 140,
    448,  48,  48, 449,  48, 450,  48, 451,  48, 200, 452, 140, 140, 140,  48, 453,
     48, 454,  48, 455, 140, 140, 140, 140,  48,  48,  48, 456, 271, 457, 271, 271,
    458, 459,  48, 460, 461, 462,  48, 463,  48, 464, 140, 140, 465,  48, 466, 467,
     48,  48,  48, 468,  48, 469,  48, 470,  48, 471, 472, 140, 140, 140, 140, 140,
     48,  48,  48,  48, 196, 140, 140, 140,   9,   9,   9, 473,  11,  11,  11, 474,
-    48,  48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 476,
-    48,  48, 477, 478, 140, 140, 140, 479,  48, 464, 480,  48,  62, 481, 140,  48,
-   482, 140, 140,  48, 483, 140,  48, 314, 484,  48,  48, 485, 486, 457, 487, 488,
-   222,  48,  48, 489, 490,  48, 196, 192, 491,  48, 492, 493, 494,  48,  48, 495,
-   222,  48,  48, 496, 497, 498, 499, 500,  48,  97, 501, 502, 503, 140, 140, 140,
-   504, 505, 506,  48,  48, 507, 508, 192, 509,  83,  84, 510, 511, 512, 513, 514,
-    48,  48,  48, 515, 516, 517, 478, 140,  48,  48,  48, 518, 519, 192, 140, 140,
-    48,  48, 520, 521, 522, 523, 140, 140,  48,  48,  48, 524, 525, 192, 526, 140,
-    48,  48, 527, 528, 192, 140, 140, 140,  48, 173, 529, 530, 314, 140, 140, 140,
-    48,  48, 501, 531, 140, 140, 140, 140, 140, 140,   9,   9,  11,  11, 148, 532,
-   533, 534,  48, 535, 536, 192, 140, 140, 140, 140, 537,  48,  48, 538, 539, 140,
-   540,  48,  48, 541, 542, 543,  48,  48, 544, 545, 546,  48,  48,  48,  48, 196,
-   547, 140, 140, 140, 140, 140, 140, 140,  84,  48, 520, 548, 549, 148, 175, 550,
-    48, 551, 552, 553, 140, 140, 140, 140, 554,  48,  48, 555, 556, 192, 557,  48,
-   558, 559, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 560,
-   561, 115,  48, 562, 563, 192, 140, 140, 140, 140, 140, 100, 271, 564, 565, 566,
-    48, 207, 140, 140, 140, 140, 140, 140, 272, 272, 272, 272, 272, 272, 567, 568,
-    48,  48,  48,  48, 388, 140, 140, 140, 140,  48,  48,  48,  48,  48,  48, 569,
-    48,  48,  48, 570, 571, 572, 140, 140,  48,  48,  48,  48, 314, 140, 140, 140,
-    48,  48,  48, 196,  48, 200, 370,  48,  48,  48,  48, 200, 192,  48, 204, 573,
-    48,  48,  48, 574, 575, 576, 577, 578,  48, 140, 140, 140, 140, 140, 140, 140,
-   140, 140, 140, 140,   9,   9,  11,  11, 271, 579, 140, 140, 140, 140, 140, 140,
-    48,  48,  48,  48, 580, 581, 582, 582, 583, 584, 140, 140, 140, 140, 585, 586,
-    48,  48,  48,  48,  48,  48,  48, 440,  48,  48,  48,  48,  48, 199, 140, 140,
-   196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 587,
-    48,  48, 588, 589, 140, 590, 591,  48,  48,  48,  48,  48,  48,  48,  48, 206,
-    48,  48,  48,  48,  48,  48,  71, 151, 196, 592, 593, 140, 140, 140, 140, 140,
-    32,  32, 594,  32, 595, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140,
-   209, 209, 209, 209, 209, 209, 209, 324, 209, 209, 596, 209, 209, 209, 597, 598,
-   599, 209, 600, 209, 209, 209, 288, 140, 209, 209, 209, 209, 601, 140, 140, 140,
-   140, 140, 140, 140, 271, 602, 271, 602, 209, 209, 209, 209, 209, 287, 271, 461,
-     9, 603,  11, 604, 605, 606, 241,   9, 607, 608, 609, 610, 611,   9, 603,  11,
-   612, 613,  11, 614, 615, 616, 617,   9, 618,  11,   9, 603,  11, 604, 605,  11,
-   241,   9, 607, 617,   9, 618,  11,   9, 603,  11, 619,   9, 620, 621, 622, 623,
-    11, 624,   9, 625, 626, 627, 628,  11, 629,   9, 630,  11, 631, 632, 632, 632,
-    32,  32,  32, 633,  32,  32, 634, 635, 636, 637,  45, 140, 140, 140, 140, 140,
-   638, 639, 640, 140, 140, 140, 140, 140, 641, 642, 643,  27,  27,  27, 644, 140,
-   645, 140, 140, 140, 140, 140, 140, 140,  48,  48, 151, 646, 647, 140, 140, 140,
-   140,  48, 648, 140,  48,  48, 649, 650, 140, 140, 140, 140, 140,  48, 651, 192,
-   140, 140, 140, 140, 140, 140, 652, 200,  48,  48,  48,  48, 653, 595, 140, 140,
-     9,   9, 607,  11, 654, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 499,
-   271, 271, 655, 656, 140, 140, 140, 140, 499, 271, 657, 658, 140, 140, 140, 140,
-   659,  48, 660, 661, 662, 663, 664, 665, 666, 206, 667, 206, 140, 140, 140, 668,
-   209, 209, 669, 209, 209, 209, 209, 209, 209, 323, 334, 670, 670, 670, 209, 324,
-   671, 209, 209, 209, 209, 209, 209, 209, 209, 209, 672, 140, 140, 140, 673, 209,
-   674, 209, 209, 669, 675, 676, 324, 140, 209, 209, 209, 209, 209, 209, 209, 677,
-   209, 209, 209, 209, 209, 678, 426, 426, 209, 209, 209, 209, 209, 209, 209, 679,
-   209, 209, 209, 209, 209, 176, 669, 427, 669, 209, 209, 209, 680, 176, 209, 209,
-   680, 209, 672, 676, 140, 140, 140, 140, 209, 209, 209, 209, 209, 323, 672, 426,
-   675, 209, 209, 681, 682, 669, 675, 675, 209, 683, 209, 209, 288, 140, 140, 192,
-    48,  48,  48,  48,  48,  48, 140, 140,  48,  48,  48, 207,  48,  48,  48,  48,
-    48, 204,  48,  48,  48,  48,  48,  48,  48,  48, 478,  48,  48,  48,  48,  48,
-    48,  48,  48,  48,  48,  48, 100,  48,  48,  48,  48,  48,  48, 204, 140, 140,
-    48, 204, 140, 140, 140, 140, 140, 140,  48,  48,  48,  48,  71,  48,  48,  48,
-    48,  48,  48, 140, 140, 140, 140, 140, 684, 140, 570, 570, 570, 570, 570, 570,
+    48,  48, 475, 192, 476,   9, 477,  11, 478, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 140, 140, 271, 479,  48,  48, 480, 481, 482, 140, 140, 483,
+    48, 464, 484,  48,  62, 485, 140,  48, 486, 140, 140,  48, 487, 140,  48, 313,
+   488,  48,  48, 489, 490, 457, 491, 492, 222,  48,  48, 493, 494,  48, 196, 192,
+   495,  48, 496, 497, 498,  48,  48, 499, 222,  48,  48, 500, 501, 502, 503, 504,
+    48,  97, 505, 506, 507, 140, 140, 140, 508, 509, 510,  48,  48, 511, 512, 192,
+   513,  83,  84, 514, 515, 516, 517, 518, 519,  48,  48, 520, 521, 522, 523, 140,
+    48,  48,  48, 524, 525, 526, 481, 140,  48,  48,  48, 527, 528, 192, 140, 140,
+   140, 140, 140, 140, 140, 140, 140, 140,  48,  48, 529, 530, 531, 532, 140, 140,
+    48,  48,  48, 533, 534, 192, 535, 140,  48,  48, 536, 537, 192, 538, 539, 140,
+    48, 540, 541, 542, 313, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+    48,  48, 505, 543, 140, 140, 140, 140, 140, 140,   9,   9,  11,  11, 148, 544,
+   545, 546,  48, 547, 548, 192, 140, 140, 140, 140, 549,  48,  48, 550, 551, 140,
+   552,  48,  48, 553, 554, 555,  48,  48, 556, 557, 558,  48,  48,  48,  48, 196,
+   559, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48,  48, 560, 192,
+    84,  48, 529, 561, 562, 148, 175, 563,  48, 564, 565, 566, 140, 140, 140, 140,
+   567,  48,  48, 568, 569, 192, 570,  48, 571, 572, 192, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 573,
+   574, 115,  48, 575, 576, 577, 140, 140, 140, 140, 140, 100, 271, 578, 579, 580,
+    48,  48,  48,  48,  48,  48,  48,  48,  48, 207, 140, 140, 140, 140, 140, 140,
+   272, 272, 272, 272, 272, 272, 581, 582,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48, 388, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 140, 140, 140, 140, 140,  48,  48,  48,  48,  48,  48, 583,
+    48,  48,  48, 584, 585, 586,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  71,
+    48,  48,  48,  48, 313, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+    48, 587, 588, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+    48,  48,  48, 196,  48, 200, 370,  48,  48,  48,  48, 200, 192,  48, 204, 589,
+    48,  48,  48, 590, 591, 592, 593, 594,  48, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 595,  48, 596, 192, 140, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140,   9,   9,  11,  11, 271, 597, 140, 140, 140, 140, 140, 140,
+    48,  48,  48,  48, 598, 599, 600, 600, 601, 602, 140, 140, 140, 140, 603, 604,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 440,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 199, 140, 605,
+   196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 606,
+    48,  48, 607, 608, 140, 609, 610,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 206,
+    48,  48,  48,  48,  48,  48,  71, 151, 196, 611, 612, 140, 140, 140, 140, 140,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 192,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 322, 140, 140, 140, 140,
+    32,  32, 613,  32, 614, 209, 209, 209, 209, 209, 209, 209, 322, 140, 140, 140,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 323,
+   209, 209, 615, 209, 209, 209, 616, 617, 618, 209, 619, 209, 209, 209, 287, 140,
+   209, 209, 209, 209, 620, 140, 140, 140, 140, 140, 140, 140, 271, 621, 271, 621,
+   209, 209, 209, 209, 209, 338, 271, 461, 140, 140, 140, 140, 140, 140, 140, 140,
+     9, 622,  11, 623, 624, 625, 241,   9, 626, 627, 628, 629, 630,   9, 622,  11,
+   631, 632,  11, 633, 634, 635, 636,   9, 637,  11,   9, 622,  11, 623, 624,  11,
+   241,   9, 626, 636,   9, 637,  11,   9, 622,  11, 638,   9, 639, 640, 641, 642,
+    11, 643,   9, 644, 645, 646, 647,  11, 648,   9, 649,  11, 650, 538, 538, 538,
+    32,  32,  32, 651,  32,  32, 652, 653, 654, 655,  45, 140, 140, 140, 140, 140,
+   656, 657, 658, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   659, 660, 661,  27,  27,  27, 662, 140, 663, 140, 140, 140, 140, 140, 140, 140,
+    48,  48, 151, 664, 665, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 666, 140,  48,  48, 667, 668,
+   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 669, 192,
+   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 587, 670,
+   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 671, 200,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 672, 614, 140, 140,
+     9,   9, 626,  11, 673, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 140, 140, 140, 503, 271, 271, 674, 675, 140, 140, 140, 140,
+   503, 271, 676, 677, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   678,  48, 679, 680, 681, 682, 683, 684, 685, 206, 686, 206, 140, 140, 140, 687,
+   209, 209, 688, 209, 209, 209, 209, 209, 209, 322, 333, 689, 689, 689, 209, 323,
+   690, 209, 209, 209, 209, 209, 209, 209, 209, 209, 691, 140, 140, 140, 692, 209,
+   693, 209, 209, 688, 694, 695, 323, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 696,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 697, 426, 426,
+   209, 209, 209, 209, 209, 209, 209, 698, 209, 209, 209, 209, 209, 176, 688, 427,
+   688, 209, 209, 209, 699, 176, 209, 209, 699, 209, 691, 688, 695, 140, 140, 140,
+   209, 209, 209, 209, 209, 322, 691, 426, 700, 209, 209, 209, 701, 702, 176, 694,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 703, 209, 209, 209, 209, 209, 192,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 140, 140,
+    48,  48,  48, 207,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48, 204,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 481,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 100,  48,
+    48,  48,  48,  48,  48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+    48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+    48,  48,  48,  48,  71,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 140, 140, 140, 140, 140,
+   704, 140, 584, 584, 584, 584, 584, 584, 140, 140, 140, 140, 140, 140, 140, 140,
     32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32, 140,
-   391, 391, 391, 391, 391, 391, 391, 685, 391, 391, 391, 391, 391, 391, 391, 686,
+   391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 705,
+   391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 706,
+     0,   1,   2,   3,   4,   4,   4,   4,   4,   4,   5,   6,   7,   8,   9,  10,
+    11,  11,  12,  11,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
+    25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,
+    41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
+    57,  57,  58,  59,  60,  60,  60,  60,  61,  62,  63,  64,  65,  66,  67,  68,
+    69,  69,  69,  69,  69,  69,  69,  69,  69,  69,  70,  71,  72,  73,  74,  75,
+    76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,
+    92,  93,  94,  95,  96,  97,  98,   7,   4,   4,   4,   4,  99, 100, 101, 102,
+   103, 104, 105, 106, 107, 108, 109,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   110, 111,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   112, 112, 112, 112,   0,   0,   0,   0,   0,   0,   0,   0,   0, 113, 114,   0,
+   115, 116, 117, 118, 119, 120, 121, 122,   0, 123, 124, 125, 126, 126, 126, 127,
+   128, 129, 130, 131, 132,  60, 133, 134, 135, 136,   0, 137, 138, 139,   0,   0,
+   126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
+   126, 126, 126, 126, 126, 126, 126,   0, 126, 126, 126, 126, 126, 126, 126, 126,
+   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 141, 142, 143, 143, 143, 143, 144,  11, 145, 146, 147,   4, 148, 149,
+   150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
+    60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,
+    60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60, 166, 167,
+   168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
+   168, 168, 168, 168, 126, 126, 126, 126, 126, 169, 126, 170, 171, 172,  19, 173,
+    19,  19,  19,  19, 174,  19, 175, 176, 177, 178,  19, 179, 180, 181, 182, 183,
+   184, 185, 186, 187, 188, 189, 190, 191, 168, 168, 192, 193, 194, 195, 196, 197,
+   198, 199, 200, 201, 202, 203, 204, 205, 206, 206, 206, 206, 207, 208, 209, 168,
+   210, 211, 212, 213, 214, 168, 215, 216, 217, 218, 219, 220, 221, 222, 223, 168,
+   224, 225, 226, 227, 228, 229, 230, 168, 168, 231, 232, 233, 234, 235, 236, 237,
+   238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
+   254, 255, 256, 257, 168, 168, 258, 259, 260, 261, 262, 263, 264, 265, 168, 168,
+   266, 168, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 168, 168, 278,
+   279, 280, 281, 168, 282, 283, 284, 168, 168, 168, 168, 285, 286, 287, 288, 289,
+   290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 291, 168,
+   290, 292, 290, 290, 290, 293, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
+   168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 294, 295,
+   296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
+   296, 297, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
+   296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 298,
+   299, 299, 299, 299, 299, 299, 299, 299, 299, 300, 168, 168, 168, 168, 168, 168,
+   168, 168, 168, 168, 301, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
+   302, 302, 302, 302, 302, 302, 302, 302, 303, 304, 305, 306, 307, 308, 309, 168,
+   168, 168, 168, 168, 168, 310, 168, 168, 168, 311, 312, 168, 313, 314, 315, 316,
+   317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
+   317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 318,
+   317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 319, 319, 319, 319,
+   319, 319, 319, 320, 321, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
+   168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 322,
+   323, 324, 324, 324, 325, 326, 327, 327, 327, 327, 327, 328, 168, 168, 168, 168,
+   329, 330, 331, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
+     0,   0,   0, 332,   0,   0,   0,   0,   0,   0, 333, 168, 334, 335,   0, 336,
+     0,   0,   0, 337, 338, 339, 340, 341, 189, 342, 168, 343,   0, 344, 168, 168,
+     0, 345, 346, 347, 348, 349,   0,   0,   0,   0, 350,   0,   0,   0,   0, 351,
+   352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 353, 168, 168, 168, 168, 168,
+   168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 354, 168, 168, 168,
+   355, 356, 357, 168, 358, 359, 168, 168, 168, 168, 360, 361, 168, 168, 168, 168,
+   168, 168, 168, 362, 168, 168, 168, 363, 168, 168, 168, 168, 168, 168, 168, 364,
+   365, 365, 365, 366, 367, 368, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
+   168, 369, 370, 168, 371, 168, 168, 168, 372, 373, 374, 375, 168, 168, 168, 168,
+   376,   0, 377, 378,   0,   0, 379, 380, 381, 382, 168, 168,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 383,   0, 384,   0, 385,
+   386, 387, 388, 389,   0,   0,   0,   0,   0, 390, 391, 392,   0,   0, 393, 332,
+   126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 394, 126, 126, 126, 126,
+   126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 395, 126, 126, 126,
+   396, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
+   126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 397, 126, 126, 126, 126, 126,
+   126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 398,
+   126, 126, 126, 126, 126, 126, 126, 126, 126, 399, 168, 168, 168, 168, 168, 168,
+   126, 126, 126, 126, 126, 126, 126, 126, 399, 168, 168, 168, 168, 168, 168, 168,
+   126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 400, 126, 126,
+   126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 401, 168,
+   402,   0, 168, 168,   7,   7,   7, 403,   0,   1,   2,   3,   4,   4,   4,   4,
      0,   0,   0,   0,   0,   0,   0,   0,   1,   2,   2,   3,   1,   2,   2,   3,
      0,   0,   0,   0,   0,   4,   0,   4,   2,   2,   5,   2,   2,   2,   5,   2,
-     2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
-     2,   2,   2,   2,   2,   2,   2,   6,   0,   0,   0,   0,   7,   8,   0,   0,
-     9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,  10,  11,
-    12,  13,  14,  14,  15,  14,  14,  14,  14,  14,  14,  14,  16,  17,  14,  14,
-    18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,
-    19,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,
-    18,  18,  18,  18,  18,  18,  20,  21,  21,  21,  22,  20,  21,  21,  21,  21,
-    21,  23,  24,  25,  25,  25,  25,  25,  25,  26,  25,  25,  25,  27,  28,  26,
-    29,  30,  31,  32,  31,  31,  31,  31,  33,  34,  35,  31,  31,  31,  36,  31,
-    31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  29,  31,  31,  31,  31,
-    37,  38,  37,  37,  37,  37,  37,  37,  37,  39,  31,  31,  31,  31,  31,  31,
-    40,  40,  40,  40,  40,  40,  41,  26,  42,  42,  42,  42,  42,  42,  42,  43,
-    44,  44,  44,  44,  44,  45,  44,  46,  47,  47,  47,  48,  37,  49,  31,  31,
-    31,  50,  51,  31,  31,  31,  31,  31,  31,  31,  31,  31,  52,  31,  31,  31,
-    53,  53,  53,  53,  53,  53,  53,  53,  53,  53,  54,  53,  55,  53,  53,  53,
-    56,  57,  58,  59,  59,  60,  61,  62,  57,  63,  64,  65,  66,  59,  59,  67,
-    68,  69,  70,  71,  71,  72,  73,  74,  69,  75,  76,  77,  78,  71,  79,  26,
-    80,  81,  82,  83,  83,  84,  85,  86,  81,  87,  88,  26,  89,  83,  90,  91,
-    92,  93,  94,  95,  95,  96,  97,  98,  93,  99, 100, 101, 102,  95,  95,  26,
-   103, 104, 105, 106, 107, 104, 108, 109, 104, 105, 110,  26, 111, 108, 108, 112,
-   113, 114, 115, 113, 113, 115, 113, 116, 114, 117, 118, 119, 120, 113, 121, 113,
-   122, 123, 124, 122, 122, 124, 125, 126, 123, 127, 128, 128, 129, 122, 130,  26,
-   131, 132, 133, 131, 131, 131, 131, 131, 132, 133, 134, 131, 135, 131, 131, 131,
-   136, 137, 138, 139, 137, 137, 140, 141, 138, 142, 143, 137, 144, 137, 145,  26,
-   146, 147, 147, 147, 147, 147, 147, 148, 147, 147, 147, 149,  26,  26,  26,  26,
-   150, 151, 152, 152, 153, 152, 152, 154, 155, 156, 152, 157,  26,  26,  26,  26,
-   158, 158, 158, 158, 158, 158, 158, 158, 158, 159, 158, 158, 158, 160, 159, 158,
-   158, 158, 158, 159, 158, 158, 158, 161, 158, 161, 162, 163,  26,  26,  26,  26,
-   164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
+     2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   6,
+     0,   0,   0,   0,   7,   8,   0,   0,   9,   9,   9,   9,   9,   9,   9,   9,
+     9,   9,   9,   9,   9,   9,  10,  11,  12,  13,  14,  14,  15,  14,  14,  14,
+    14,  14,  14,  14,  16,  17,  14,  14,  18,  18,  18,  18,  18,  18,  18,  18,
+    19,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  20,  21,
+    21,  21,  22,  20,  21,  21,  21,  21,  21,  23,  24,  25,  25,  25,  25,  25,
+    25,  26,  25,  25,  25,  27,  28,  26,  29,  30,  31,  32,  31,  31,  31,  31,
+    33,  34,  35,  31,  31,  31,  36,  31,  31,  31,  31,  31,  31,  31,  31,  31,
+    31,  31,  31,  29,  31,  31,  31,  31,  37,  38,  37,  37,  37,  37,  37,  37,
+    37,  39,  31,  31,  31,  31,  31,  31,  40,  40,  40,  40,  40,  40,  41,  26,
+    42,  42,  42,  42,  42,  42,  42,  43,  44,  44,  44,  44,  44,  45,  44,  46,
+    47,  47,  47,  48,  37,  49,  31,  31,  31,  50,  51,  31,  31,  31,  31,  31,
+    31,  31,  31,  31,  52,  31,  31,  31,  53,  53,  53,  53,  53,  53,  53,  53,
+    53,  53,  54,  53,  55,  53,  53,  53,  56,  57,  58,  59,  59,  60,  61,  62,
+    57,  63,  64,  65,  66,  59,  59,  67,  68,  69,  70,  71,  71,  72,  73,  74,
+    69,  75,  76,  77,  78,  71,  79,  26,  80,  81,  82,  83,  83,  84,  85,  86,
+    81,  87,  88,  26,  89,  83,  90,  91,  92,  93,  94,  95,  95,  96,  97,  98,
+    93,  99, 100, 101, 102,  95,  95,  26, 103, 104, 105, 106, 107, 104, 108, 109,
+   104, 105, 110,  26, 111, 108, 108, 112, 113, 114, 115, 113, 113, 115, 113, 116,
+   114, 117, 118, 119, 120, 113, 121, 113, 122, 123, 124, 122, 122, 124, 125, 126,
+   123, 127, 128, 128, 129, 122, 130,  26, 131, 132, 133, 131, 131, 131, 131, 131,
+   132, 133, 134, 131, 135, 131, 131, 131, 136, 137, 138, 139, 137, 137, 140, 141,
+   138, 142, 143, 137, 144, 137, 145,  26, 146, 147, 147, 147, 147, 147, 147, 148,
+   147, 147, 147, 149,  26,  26,  26,  26, 150, 151, 152, 152, 153, 152, 152, 154,
+   155, 156, 152, 157,  26,  26,  26,  26, 158, 158, 158, 158, 158, 158, 158, 158,
+   158, 159, 158, 158, 158, 160, 159, 158, 158, 158, 158, 159, 158, 158, 158, 161,
+   158, 161, 162, 163,  26,  26,  26,  26, 164, 164, 164, 164, 164, 164, 164, 164,
    164, 164, 164, 164, 165, 165, 165, 165, 166, 167, 165, 165, 165, 165, 165, 168,
-   169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169,
-   170, 170, 170, 170, 170, 170, 170, 170, 170, 171, 172, 171, 170, 170, 170, 170,
-   170, 171, 170, 170, 170, 170, 171, 172, 171, 170, 172, 170, 170, 170, 170, 170,
-   170, 170, 171, 170, 170, 170, 170, 170, 170, 170, 170, 173, 170, 170, 170, 174,
-   170, 170, 170, 175, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 177, 177,
-   178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
+   169, 169, 169, 169, 169, 169, 169, 169, 170, 170, 170, 170, 170, 170, 170, 170,
+   170, 171, 172, 171, 170, 170, 170, 170, 170, 171, 170, 170, 170, 170, 171, 172,
+   171, 170, 172, 170, 170, 170, 170, 170, 170, 170, 171, 170, 170, 170, 170, 170,
+   170, 170, 170, 173, 170, 170, 170, 174, 170, 170, 170, 175, 176, 176, 176, 176,
+   176, 176, 176, 176, 176, 176, 177, 177, 178, 178, 178, 178, 178, 178, 178, 178,
    179, 179, 179, 180, 181, 181, 181, 181, 181, 181, 181, 181, 181, 182, 181, 183,
    184, 184, 185, 186, 187, 187, 188,  26, 189, 189, 190,  26, 191, 192, 193,  26,
    194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 195, 194, 196, 194, 196,
@@ -2368,208 +2467,164 @@ _hb_ucd_u16[9344] =
    210, 210, 210, 210, 210, 211, 210, 210, 210, 212, 210, 213, 194, 194, 194, 194,
    214, 214, 214, 215, 216, 216, 216, 216, 216, 216, 216, 217, 216, 216, 216, 218,
    216, 219, 216, 219, 216, 220,   9,   9,   9, 221,  26,  26,  26,  26,  26,  26,
-   222, 222, 222, 222, 222, 222, 222, 222, 222, 223, 222, 222, 222, 222, 222, 224,
-   225, 225, 225, 225, 225, 225, 225, 225, 226, 226, 226, 226, 226, 226, 227, 228,
-   229, 229, 229, 229, 229, 229, 229, 230, 229, 231, 232, 232, 232, 232, 232, 232,
-    18, 233, 165, 165, 165, 165, 165, 234, 225,  26, 235,   9, 236, 237, 238, 239,
-     2,   2,   2,   2, 240, 241,   2,   2,   2,   2,   2, 242, 243, 244,   2, 245,
-     2,   2,   2,   2,   2,   2,   2, 246,   9,   9,   9,   9,   9,   9,   9,   9,
-    14,  14, 247, 247,  14,  14,  14,  14, 247, 247,  14, 248,  14,  14,  14, 247,
-    14,  14,  14,  14,  14,  14, 249,  14, 249,  14, 250, 251,  14,  14, 252, 253,
-     0, 254,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 255,   0, 256, 257,
-     0, 258,   2, 259,   0,   0,   0,   0, 260,  26,   9,   9,   9,   9, 261,  26,
-     0,   0,   0,   0, 262, 263,   4,   0,   0, 264,   0,   0,   2,   2,   2,   2,
-     2, 265,   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, 258,  26,  26,  26,   0, 266,  26,  26,   0,   0,   0,   0,
-   267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 268,   0,
-     0,   0, 269,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270,   2,   2,   2,   2,
-    17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17, 271, 272,
-   165, 165, 165, 165, 166, 167, 273, 273, 273, 273, 273, 273, 273, 274, 275, 274,
-   170, 170, 172,  26, 172, 172, 172, 172, 172, 172, 172, 172,  18,  18,  18,  18,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 276,  26,  26,  26,  26,
+   222, 222, 222, 222, 222, 222, 222, 222, 222, 223, 222, 222, 222, 222, 222, 222,
+   224, 224, 224, 224, 224, 224, 224, 224, 225, 225, 225, 225, 225, 225, 226, 227,
+   228, 228, 228, 228, 228, 228, 228, 229, 228, 230, 231, 231, 231, 231, 231, 231,
+    18, 232, 165, 165, 165, 165, 165, 233, 224,  26, 234,   9, 235, 236, 237, 238,
+     2,   2,   2,   2, 239, 240,   2,   2,   2,   2,   2, 241, 242, 243,   2, 244,
+     2,   2,   2,   2,   2,   2,   2, 245,  14,  14, 246, 246,  14,  14,  14,  14,
+   246, 246,  14, 247,  14,  14,  14, 246,  14,  14,  14,  14,  14,  14, 248,  14,
+   248,  14, 249, 250,  14,  14, 251, 252,   0, 253,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0, 254,   0, 255, 256,   0, 257,   2, 258,   0,   0,   0,   0,
+   259,  26,   9,   9,   9,   9, 260,  26,   0,   0,   0,   0, 261, 262,   4,   0,
+     0, 263,   0,   0,   2,   2,   2,   2,   2, 264,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0, 265,  26,  26,   0, 266,  26,  26,   0,   0,   0,   0,
+   267, 267, 267, 267, 267, 267, 267, 267,   0,   0,   0,   0,   0,   0, 268,   0,
+     0,   0, 269,   0,   0,   0,   0,   0, 270, 270, 270, 270, 270, 270, 270, 270,
+   270, 270, 270, 270,   2,   2,   2,   2,  17,  17,  17,  17,  17,  17,  17,  17,
+    17,  17,  17,  17,  17,  17, 271, 272, 165, 165, 165, 165, 166, 167, 273, 273,
+   273, 273, 273, 273, 273, 274, 275, 274, 170, 170, 172,  26, 172, 172, 172, 172,
+   172, 172, 172, 172,  18,  18,  18,  18,   0,   0,   0, 276,  26,  26,  26,  26,
    277, 277, 277, 278, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 279,  26,
-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
    277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 280,  26,  26,  26,   0,   0,
    281,   0,   0,   0, 282, 283,   0, 284, 285, 286, 286, 286, 286, 286, 286, 286,
    286, 286, 287, 288, 289, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 291,
-   292, 293, 293, 293, 293, 293, 294, 169, 169, 169, 169, 169, 169, 169, 169, 169,
-   169, 295,   0,   0, 293, 293, 293, 293,   0,   0,   0,   0, 296, 297, 290, 290,
-   169, 169, 169, 295,   0,   0,   0,   0,   0,   0,   0,   0, 169, 169, 169, 298,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 290, 290, 290, 290, 290, 299,
+   292, 293, 293, 293, 293, 293, 294, 169, 169, 295,   0,   0, 293, 293, 293, 293,
+     0,   0,   0,   0, 276, 296, 290, 290, 169, 169, 169, 295,   0,   0,   0,   0,
+     0,   0,   0,   0, 169, 169, 169, 297,   0,   0, 290, 290, 290, 290, 290, 298,
    290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290,   0,   0,   0,   0,   0,
-   277, 277, 277, 277, 277, 277, 277, 277,   0,   0,   0,   0,   0,   0,   0,   0,
-   300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
-   300, 301, 300, 300, 300, 300, 300, 300, 302,  26, 303, 303, 303, 303, 303, 303,
-   304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304,
-   304, 304, 304, 304, 304, 305,  26,  26,  18,  18,  18,  18,  18,  18,  18,  18,
-    18,  18,  18,  18, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306,  26,
-     0,   0,   0,   0, 307,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
-     2, 308,   2,   2,   2,   2,   2,   2,   2, 309, 310, 311,  26,  26, 312,   2,
-   313, 313, 313, 313, 313, 314,   0, 315, 316, 316, 316, 316, 316, 316, 316,  26,
-   317, 317, 317, 317, 317, 317, 317, 317, 318, 319, 317, 320,  53,  53,  53,  53,
-   321, 321, 321, 321, 321, 322, 323, 323, 323, 323, 324, 325, 169, 169, 169, 326,
-   327, 327, 327, 327, 327, 327, 327, 327, 327, 328, 327, 329, 164, 164, 164, 330,
-   331, 331, 331, 331, 331, 331, 332,  26, 331, 333, 331, 334, 164, 164, 164, 164,
-   335, 335, 335, 335, 335, 335, 335, 335, 336,  26,  26, 337, 338, 338, 339,  26,
-   340, 340, 340,  26, 172, 172,   2,   2,   2,   2,   2, 341, 342, 343, 176, 176,
-   176, 176, 176, 176, 176, 176, 176, 176, 338, 338, 338, 338, 338, 344, 338, 345,
-   169, 169, 169, 169, 346,  26, 169, 169, 295, 347, 169, 169, 169, 169, 169, 346,
-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 280, 277, 277,
-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 348,  26,  26,  26,  26,
-   349,  26, 350, 351,  25,  25, 352, 353, 354,  25,  31,  31,  31,  31,  31,  31,
-    31,  31,  31,  31,  31,  31,  31,  31, 355,  26, 356,  31,  31,  31,  31,  31,
-    31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,
-    31,  31,  31,  31,  31,  31,  31, 357,  31,  31,  31,  31,  31,  31,  31,  31,
-    31,  31, 358,  31,  31,  31,  31,  31,  31, 359,  26,  26,  26,  26,  31,  31,
-     9,   9,   0, 315,   9, 360,   0,   0,   0,   0, 361,   0, 258, 296, 362,  31,
-    31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31, 363,
-   364,   0,   0,   0,   1,   2,   2,   3,   1,   2,   2,   3, 365, 290, 289, 290,
-   290, 290, 290, 366, 169, 169, 169, 295, 367, 367, 367, 368, 258, 258,  26, 369,
-   370, 371, 370, 370, 372, 370, 370, 373, 370, 374, 370, 374,  26,  26,  26,  26,
-   370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 375,
-   376,   0,   0,   0,   0,   0, 377,   0,  14,  14,  14,  14,  14,  14,  14,  14,
-    14, 253,   0, 378, 379,  26,  26,  26,  26,  26,   0,   0,   0,   0,   0, 380,
-   381, 381, 381, 382, 383, 383, 383, 383, 383, 383, 384,  26, 385,   0,   0, 296,
-   386, 386, 386, 386, 387, 388, 389, 389, 389, 390, 391, 391, 391, 391, 391, 392,
-   393, 393, 393, 394, 395, 395, 395, 395, 396, 395, 397,  26,  26,  26,  26,  26,
-   398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 399, 399, 399, 399, 399, 399,
-   400, 400, 400, 401, 400, 402, 403, 403, 403, 403, 404, 403, 403, 403, 403, 404,
-   405, 405, 405, 405, 405,  26, 406, 406, 406, 406, 406, 406, 407, 408, 409, 410,
-   409, 410, 411, 409, 412, 409, 412, 413,  26,  26,  26,  26,  26,  26,  26,  26,
-   414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414,
-   414, 414, 414, 414, 414, 414, 415,  26, 414, 414, 416,  26, 414,  26,  26,  26,
-   417,   2,   2,   2,   2,   2, 418, 309,  26,  26,  26,  26,  26,  26,  26,  26,
-   419, 420, 421, 421, 421, 421, 422, 423, 424, 424, 425, 424, 426, 426, 426, 426,
-   427, 427, 427, 428, 429, 427,  26,  26,  26,  26,  26,  26, 430, 430, 431, 432,
-   433, 433, 433, 434, 435, 435, 435, 436,  26,  26,  26,  26,  26,  26,  26,  26,
-   437, 437, 437, 437, 438, 438, 438, 439, 438, 438, 440, 438, 438, 438, 438, 438,
-   441, 442, 443, 444, 445, 445, 446, 447, 445, 448, 445, 448, 449, 449, 449, 449,
-   450, 450, 450, 450,  26,  26,  26,  26, 451, 451, 451, 451, 452, 453, 452,  26,
-   454, 454, 454, 454, 454, 454, 455, 456, 457, 457, 458, 457, 459, 459, 460, 459,
-   461, 461, 462, 463,  26, 464,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-   465, 465, 465, 465, 465, 465, 465, 465, 465, 466,  26,  26,  26,  26,  26,  26,
-   467, 467, 467, 467, 467, 467, 468,  26, 467, 467, 467, 467, 467, 467, 468, 469,
-   470, 470, 470, 470, 470,  26, 470, 471,  26,  26,  26,  26,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  31,  31,  31,  50,
-   472, 472, 472, 472, 472, 473, 474,  26,  26,  26,  26,  26,  26,  26,  26, 475,
-   476, 476, 476, 476, 476,  26, 477, 477, 477, 477, 477, 478,  26,  26, 479, 479,
-   479, 480,  26,  26,  26,  26, 481, 481, 481, 482,  26,  26, 483, 483, 484,  26,
-   485, 485, 485, 485, 485, 485, 485, 485, 485, 486, 487, 485, 485, 485, 486, 488,
-   489, 489, 489, 489, 489, 489, 489, 489, 490, 491, 492, 492, 492, 493, 492, 494,
-   495, 495, 495, 495, 495, 495, 496, 495, 495,  26, 497, 497, 497, 497, 498,  26,
-   499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 500, 137, 501,  26,
-   502, 502, 503, 502, 502, 502, 502, 502, 504,  26,  26,  26,  26,  26,  26,  26,
-   505, 506, 507, 508, 507, 509, 510, 510, 510, 510, 510, 510, 510, 511, 510, 512,
-   513, 514, 515, 516, 516, 517, 518, 519, 514, 520, 521, 522, 523, 524, 524,  26,
-   525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 526, 527,  26,  26,  26,
-   528, 528, 528, 528, 528, 528, 528, 528, 528,  26, 528, 529,  26,  26,  26,  26,
-   530, 530, 530, 530, 530, 530, 531, 530, 530, 530, 530, 531,  26,  26,  26,  26,
-   532, 532, 532, 532, 532, 532, 532, 532, 533,  26, 532, 534, 198, 535,  26,  26,
-   536, 536, 536, 536, 536, 536, 536, 537, 536, 537,  26,  26,  26,  26,  26,  26,
-   538, 538, 538, 539, 538, 540, 538, 538, 541,  26,  26,  26,  26,  26,  26,  26,
-   542, 542, 542, 542, 542, 542, 542, 543,  26,  26,  26,  26,  26,  26,  26,  26,
-    26,  26,  26,  26, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 545, 546,
-   547, 548, 549, 550, 550, 550, 551, 552, 547,  26, 550, 553,  26,  26,  26,  26,
-    26,  26,  26,  26, 554, 555, 554, 554, 554, 554, 554, 555, 556,  26,  26,  26,
-   557, 557, 557, 557, 557, 557, 557, 557, 557,  26, 558, 558, 558, 558, 558, 558,
-   558, 558, 558, 558, 559,  26, 178, 178, 560, 560, 560, 560, 560, 560, 560, 561,
-    53, 562,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-   563, 564, 563, 563, 563, 563, 565, 563, 566,  26, 563, 563, 563, 567, 568, 568,
-   568, 568, 569, 568, 568, 570, 571,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-   572, 573, 574, 574, 574, 574, 572, 575, 574,  26, 574, 576, 577, 578, 579, 579,
-   579, 580, 581, 582, 579, 583,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 584, 584, 584, 585,
-   586, 586, 587, 586, 586, 586, 586, 588, 586, 586, 586, 589,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26, 590,  26, 108, 108, 108, 108, 108, 108, 591, 592,
-   593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593,
-   593, 593, 593, 594,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-   593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 595, 596,  26,
-   593, 593, 593, 593, 593, 593, 593, 593, 597,  26,  26,  26,  26,  26,  26,  26,
-    26,  26, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 599,  26,
-   600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600,
-   600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 601,  26,  26,  26,  26,  26,
-   602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602,
-   602, 602, 602, 602, 602, 602, 602, 602, 603,  26,  26,  26,  26,  26,  26,  26,
-   306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306,
-   306, 306, 306, 306, 306, 306, 306, 604, 605, 605, 605, 606, 605, 607, 608, 608,
-   608, 608, 608, 608, 608, 608, 608, 609, 608, 610, 611, 611, 611, 612, 612,  26,
-   613, 613, 613, 613, 613, 613, 613, 613, 614,  26, 613, 615, 615, 613, 613, 616,
-   613, 613,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26, 617, 617, 617, 617, 617, 617, 617, 617,
-   617, 617, 617, 618,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-   619, 619, 619, 619, 619, 619, 619, 619, 619, 620, 619, 619, 619, 619, 619, 619,
-   619, 621, 619, 619,  26,  26,  26,  26,  26,  26,  26,  26, 622,  26, 348,  26,
-   623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623,
-   623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623,  26,
-   624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624,
-   624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 625,  26,  26,  26,  26,  26,
-   623, 626,  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, 627, 628,
-   629, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
-   286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
-   286, 286, 286, 286, 630,  26, 631,  26,  26,  26, 632,  26, 633,  26, 634, 634,
-   634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634,
-   634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 635,
-   636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 637, 636, 638,
-   636, 639, 636, 640, 296,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-     9,   9,   9,   9,   9, 641,   9,   9, 221,  26,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0, 296,  26,  26,  26,  26,  26,  26,  26,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 276,  26,
-     0,   0,   0,   0, 258, 364,   0,   0,   0,   0,   0,   0, 642, 643,   0, 644,
-   645, 646,   0,   0,   0, 647,   0,   0,   0,   0,   0,   0,   0, 266,  26,  26,
-    14,  14,  14,  14,  14,  14,  14,  14, 247,  26,  26,  26,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26,   0,   0, 296,  26,   0,   0, 296,  26,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 258,  26,   0,   0,   0, 260,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 255,   0,   0,   0,   0,   0,
-     0,   0,   0, 255, 648, 649,   0, 650, 651,   0,   0,   0,   0,   0,   0,   0,
-   269, 652, 255, 255,   0,   0,   0, 653, 654, 655, 656,   0,   0,   0,   0,   0,
-     0,   0,   0,   0, 276,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0, 268,   0,   0,   0,   0,   0,   0,
-   657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657,
-   657, 658,  26, 659, 660, 657,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-     2,   2,   2, 349, 661, 309,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-   662, 270, 270, 663, 664, 665,  18,  18,  18,  18,  18,  18,  18, 666,  26,  26,
-    26, 667,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-   668, 668, 668, 668, 668, 669, 668, 670, 668, 671,  26,  26,  26,  26,  26,  26,
-    26,  26, 672, 672, 672, 673,  26,  26, 674, 674, 674, 674, 674, 674, 674, 675,
-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 676, 676, 676, 676, 676, 677,
-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 172, 678, 170, 172,
-   679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679,
-   679, 679, 679, 679, 679, 679, 679, 679, 680, 679, 681,  26,  26,  26,  26,  26,
-   682, 682, 682, 682, 682, 682, 682, 682, 682, 683, 682, 684,  26,  26,  26,  26,
-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 364,   0,
-     0,   0,   0,   0,   0,   0, 378,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-   364,   0,   0,   0,   0,   0,   0, 276,  26,  26,  26,  26,  26,  26,  26,  26,
-   685,  31,  31,  31, 686, 687, 688, 689, 690, 691, 686, 692, 686, 688, 688, 693,
-    31, 694,  31, 695, 696, 694,  31, 695,  26,  26,  26,  26,  26,  26,  51,  26,
-     0,   0,   0,   0,   0, 296,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0, 296,  26,   0, 258, 364,   0, 364,   0, 364,   0,   0,   0, 276,  26,
-     0,   0,   0,   0,   0, 276,  26,  26,  26,  26,  26,  26, 697,   0,   0,   0,
-   698,  26,   0,   0,   0,   0,   0, 296,   0, 260, 315,  26, 276,  26,  26,  26,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 699,   0, 378,   0, 378,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 258, 700,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 315,   0, 296, 260,  26,
-     0, 296,   0,   0,   0,   0,   0,   0,   0,  26,   0, 315,   0,   0,   0,   0,
-     0,  26,   0,   0,   0, 276, 315,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 296,  26,   0, 276,   0, 378,
-     0, 260,   0,   0,   0,   0,   0, 269, 276, 697,   0, 296,   0, 260,   0, 260,
-     0,   0, 361,   0,   0,   0,   0,   0,   0, 266,  26,  26,  26,  26,   0, 315,
-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,  26,  26,  26,  26,
-   277, 277, 277, 277, 277, 277, 277, 348, 277, 277, 277, 277, 277, 277, 277, 277,
-   277, 277, 277, 280, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
-   277, 277, 277, 277, 348,  26, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 701,  26, 277, 277,
-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 280,  26,  26,  26,  26,
-   277, 277, 277, 280,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-   277, 277, 277, 277, 277, 277, 277, 277, 277, 702, 277, 277, 277, 277, 277, 277,
-   277, 277, 277, 277, 277, 277,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-   703,  26,  26,  26,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,
-     9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   0,   0,
+   299, 299, 299, 299, 299, 299, 299, 299, 299, 300, 299, 299, 299, 299, 299, 299,
+   301,  26, 302, 302, 302, 302, 302, 302, 303, 303, 303, 303, 303, 303, 303, 303,
+   303, 303, 303, 303, 303, 304,  26,  26,  18,  18,  18,  18, 305, 305, 305, 305,
+   305, 305, 305, 305, 305, 305, 305,  26,   0,   0,   0,   0, 306,   2,   2,   2,
+     2, 307,   2,   2,   2,   2,   2,   2,   2, 308, 309, 258,  26,  26, 310,   2,
+   311, 311, 311, 311, 311, 312,   0, 265, 313, 313, 313, 313, 313, 313, 313,  26,
+   314, 314, 314, 314, 314, 314, 314, 314, 315, 316, 314, 317,  53,  53,  53,  53,
+   318, 318, 318, 318, 318, 319, 320, 320, 320, 320, 321, 322, 169, 169, 169, 323,
+   324, 324, 324, 324, 324, 324, 324, 324, 324, 325, 324, 326, 164, 164, 164, 327,
+   328, 328, 328, 328, 328, 328, 329,  26, 328, 330, 328, 331, 164, 164, 164, 164,
+   332, 332, 332, 332, 332, 332, 332, 332, 333,  26,  26, 334, 335, 335, 336,  26,
+   337, 337, 337,  26, 172, 172,   2,   2,   2,   2,   2, 338, 339, 340, 176, 176,
+   176, 176, 176, 176, 176, 176, 176, 176, 335, 335, 335, 335, 335, 341, 335, 342,
+   169, 169, 169, 169, 343,  26, 169, 169, 295, 344, 169, 169, 169, 169, 169, 343,
+    26,  26,  26,  26,  26,  26,  26,  26, 277, 277, 277, 277, 277, 280, 277, 277,
+   277, 277, 277, 345,  26,  26,  26,  26, 346,  26, 347, 348,  25,  25, 349, 350,
+   351,  25,  31,  31,  31,  31,  31,  31, 352,  26, 353,  31,  31,  31,  31,  31,
+    31,  31,  31,  31,  31,  31,  31, 354,  31,  31, 355,  31,  31,  31,  31,  31,
+    31, 356,  26,  26,  26,  26,  31,  31,   9,   9,   0, 265,   9, 357,   0,   0,
+     0,   0, 358,   0, 257, 359, 360,  31,  31,  31,  31,  31,  31,  31,  31, 361,
+   362,   0,   0,   0,   1,   2,   2,   3,   1,   2,   2,   3, 363, 290, 289, 290,
+   290, 290, 290, 364, 169, 169, 169, 295, 365, 365, 365, 366, 257, 257,  26, 367,
+   368, 369, 368, 368, 370, 368, 368, 371, 368, 372, 368, 372,  26,  26,  26,  26,
+   368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 373,
+   374,   0,   0,   0,   0,   0, 375,   0,  14,  14,  14,  14,  14,  14,  14,  14,
+    14, 252,   0, 376, 377,  26,  26,  26,  26,  26,   0,   0,   0,   0,   0, 378,
+   379, 379, 379, 380, 381, 381, 381, 381, 381, 381, 382,  26, 383,   0,   0, 359,
+   384, 384, 384, 384, 385, 386, 387, 387, 387, 388, 389, 389, 389, 389, 389, 390,
+   391, 391, 391, 392, 393, 393, 393, 393, 394, 393, 395,  26,  26,  26,  26,  26,
+   396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 397, 397, 397, 397, 397, 397,
+   398, 398, 398, 399, 398, 400, 401, 401, 401, 401, 402, 401, 401, 401, 401, 402,
+   403, 403, 403, 403, 403,  26, 404, 404, 404, 404, 404, 404, 405, 406, 407, 408,
+   407, 408, 409, 407, 410, 407, 410, 411, 412, 412, 412, 412, 412, 412, 413,  26,
+   414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 415,  26,
+   414, 414, 416,  26, 414,  26,  26,  26, 417,   2,   2,   2,   2,   2, 418, 419,
+   420, 421, 422, 422, 422, 422, 423, 424, 425, 425, 426, 425, 427, 427, 427, 427,
+   428, 428, 428, 429, 430, 428,  26,  26,  26,  26,  26,  26, 431, 431, 432, 433,
+   434, 434, 434, 435, 436, 436, 436, 437, 438, 438, 438, 438, 439, 439, 439, 440,
+   439, 439, 441, 439, 439, 439, 439, 439, 442, 443, 444, 445, 446, 446, 447, 448,
+   446, 449, 446, 449, 450, 450, 450, 450, 451, 451, 451, 451,  26,  26,  26,  26,
+   452, 452, 452, 452, 453, 454, 453,  26, 455, 455, 455, 455, 455, 455, 456, 457,
+   458, 458, 459, 458, 460, 460, 461, 460, 462, 462, 463, 464,  26, 465,  26,  26,
+   466, 466, 466, 466, 466, 466, 466, 466, 466, 467,  26,  26,  26,  26,  26,  26,
+   468, 468, 468, 468, 468, 468, 469,  26, 468, 468, 468, 468, 468, 468, 469, 470,
+   471, 471, 471, 471, 471,  26, 471, 472, 473, 473, 473, 473, 474, 475, 473, 473,
+   474, 476,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  31,  31,  31,  50,
+   477, 477, 477, 477, 477, 478, 479,  26, 480,  26,  26,  26,  26,  26,  26, 481,
+   482, 482, 482, 482, 482,  26, 483, 483, 483, 483, 483, 484,  26,  26, 485, 485,
+   485, 486,  26,  26,  26,  26, 487, 487, 487, 488,  26,  26, 489, 489, 490,  26,
+   491, 491, 491, 491, 491, 491, 491, 491, 491, 492, 493, 491, 491, 491, 492, 494,
+   495, 495, 495, 495, 495, 495, 495, 495, 496, 497, 498, 498, 498, 499, 498, 500,
+   501, 501, 501, 501, 501, 501, 502, 501, 501,  26, 503, 503, 503, 503, 504,  26,
+   505, 505, 505, 505, 505, 505, 505, 505, 505, 505, 505, 505, 506, 137, 507,  26,
+   508, 508, 509, 508, 508, 508, 508, 508, 510,  26,  26,  26,  26,  26,  26,  26,
+   511, 512, 513, 514, 513, 515, 516, 516, 516, 516, 516, 516, 516, 517, 516, 518,
+   519, 520, 521, 522, 522, 523, 524, 525, 520, 526, 527, 528, 529, 530, 530,  26,
+   531, 532, 531, 531, 531, 531, 533, 531, 534, 535, 533, 536, 537,  26,  26,  26,
+   538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 539, 540,  26,  26,  26,
+   541, 541, 541, 541, 541, 541, 541, 541, 541,  26, 541, 542,  26,  26,  26,  26,
+   543, 543, 543, 543, 543, 543, 544, 543, 543, 543, 543, 544,  26,  26,  26,  26,
+   545, 545, 545, 545, 545, 545, 545, 545, 546,  26, 545, 547, 198, 548,  26,  26,
+   549, 549, 549, 549, 549, 549, 549, 550, 549, 550, 164, 164, 551,  26,  26,  26,
+   552, 552, 552, 553, 552, 554, 552, 552, 555,  26,  26,  26,  26,  26,  26,  26,
+   556, 556, 556, 556, 556, 556, 556, 557,  26,  26,  26,  26, 558, 558, 558, 558,
+   558, 558, 558, 558, 558, 558, 559, 560, 561, 562, 563, 564, 564, 564, 565, 566,
+   561,  26, 564, 567,  26,  26,  26,  26,  26,  26,  26,  26, 568, 569, 568, 568,
+   568, 568, 568, 569, 570,  26,  26,  26, 571, 571, 571, 571, 571, 571, 571, 571,
+   571,  26, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 573,  26, 178, 178,
+   574, 574, 574, 574, 574, 574, 574, 575,  53, 576,  26,  26,  26,  26,  26,  26,
+   577, 577, 577, 577, 578,  26, 577, 578, 579, 580, 579, 579, 579, 579, 581, 579,
+   582,  26, 579, 579, 579, 583, 584, 584, 584, 584, 585, 584, 584, 586, 587,  26,
+   588, 589, 590, 590, 590, 590, 588, 591, 590,  26, 590, 592, 593, 594, 595, 595,
+   595, 596, 597, 598, 595, 599,  26,  26,  26,  26,  26,  26, 600, 600, 600, 601,
+   602, 602, 603, 602, 602, 602, 602, 604, 602, 602, 602, 605,  26,  26,  26,  26,
+    26,  26,  26,  26,  26,  26, 606,  26, 108, 108, 108, 108, 108, 108, 607, 608,
+   609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 610,  26,  26,  26,  26,
+   609, 609, 609, 609, 609, 611, 612,  26, 613,  26,  26,  26,  26,  26,  26,  26,
+    26,  26, 614, 614, 614, 614, 614, 614, 614, 614, 614, 614, 614, 614, 615,  26,
+   616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 617,  26, 616, 616, 616, 616,
+   616, 616, 616, 616, 616, 616, 616, 618, 619, 619, 619, 619, 619, 619, 619, 619,
+   620,  26,  26,  26,  26,  26,  26,  26, 621, 621, 621, 621, 621, 621, 621, 622,
+   305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 623,
+   624, 624, 624, 625, 624, 626, 627, 627, 627, 627, 627, 627, 627, 627, 627, 628,
+   627, 629, 630, 630, 630, 631, 631,  26, 632, 632, 632, 632, 632, 632, 632, 632,
+   633,  26, 632, 634, 634, 632, 632, 635, 632, 632,  26,  26,  26,  26,  26,  26,
+   636, 636, 636, 636, 636, 636, 636, 637, 638, 638, 638, 638, 638, 638, 638, 638,
+   638, 638, 638, 639,  26,  26,  26,  26, 640, 640, 640, 640, 640, 640, 640, 640,
+   640, 641, 640, 640, 640, 640, 640, 640, 640, 642, 640, 640,  26,  26,  26,  26,
+    26,  26,  26,  26, 643,  26, 345,  26, 644, 644, 644, 644, 644, 644, 644, 644,
+   644, 644, 644, 644, 644, 644, 644,  26, 645, 645, 645, 645, 645, 645, 645, 645,
+   645, 645, 646,  26,  26,  26,  26, 647, 644, 648,  26,  26,  26,  26,  26,  26,
+    26,  26,  26,  26,  26,  26, 649, 650, 651, 286, 286, 286, 286, 286, 286, 286,
+   286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 652,  26, 653,  26,
+    26,  26, 654,  26, 655,  26, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656,
+   656, 656, 656, 656, 656, 656, 656, 657, 658, 658, 658, 658, 658, 658, 658, 658,
+   658, 658, 658, 658, 658, 659, 658, 660, 658, 661, 658, 662, 359,  26,  26,  26,
+     0,   0,   0,   0,   0,   0,   0, 265,   0,   0,   0,   0,   0,   0, 359,  26,
+     9,   9,   9,   9,   9, 663,   9,   9, 221,  26,   0,   0,   0,   0,   0,   0,
+   359,  26,  26,  26,  26,  26,  26,  26,   0,   0,   0,   0,   0,   0, 276,  26,
+     0,   0,   0,   0, 257, 362,   0,   0,   0,   0,   0,   0, 664, 665,   0, 666,
+   667, 668,   0,   0,   0, 669,   0,   0,   0,   0,   0,   0,   0, 266,  26,  26,
+   246,  26,  26,  26,  26,  26,  26,  26,   0,   0, 359,  26,   0,   0, 359,  26,
+     0,   0, 257,  26,   0,   0,   0, 259,   0,   0, 254,   0,   0,   0,   0,   0,
+     0,   0,   0, 254, 670, 671,   0, 672, 673,   0,   0,   0,   0,   0,   0,   0,
+   269, 674, 254, 254,   0,   0,   0, 675, 676, 677, 678,   0,   0,   0,   0,   0,
+     0,   0,   0,   0, 276,   0,   0,   0,   0, 268,   0,   0,   0,   0,   0,   0,
+   679, 679, 679, 679, 679, 679, 679, 679, 679, 680,  26, 681, 682, 679,  26,  26,
+     2,   2,   2, 346, 683, 419,  26,  26, 684, 270, 270, 685, 686, 687,  18,  18,
+    18,  18,  18,  18,  18, 688,  26,  26,  26, 689,  26,  26,  26,  26,  26,  26,
+   690, 690, 690, 690, 690, 691, 690, 692, 690, 693,  26,  26,  26,  26,  26,  26,
+    26,  26, 694, 694, 694, 695,  26,  26, 696, 696, 696, 696, 696, 696, 696, 697,
+    26,  26, 698, 698, 698, 698, 698, 699,  26,  26, 700, 700, 700, 700, 700, 701,
+    26,  26,  26,  26, 172, 702, 170, 172, 703, 703, 703, 703, 703, 703, 703, 703,
+   704, 703, 705,  26,  26,  26,  26,  26, 706, 706, 706, 706, 706, 706, 706, 706,
+   706, 707, 706, 708,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 362,   0,
+     0,   0,   0,   0,   0,   0, 376,  26, 362,   0,   0,   0,   0,   0,   0, 276,
+   709,  31,  31,  31, 710, 711, 712, 713, 714, 715, 710, 716, 710, 712, 712, 717,
+    31, 718,  31, 719, 720, 718,  31, 719,  26,  26,  26,  26,  26,  26, 721,  26,
+     0,   0,   0,   0,   0, 359,   0,   0,   0,   0, 359,  26,   0, 257, 362,   0,
+   362,   0, 362,   0,   0,   0, 276,  26,   0,   0,   0,   0,   0, 276,  26,  26,
+    26,  26,  26,  26, 722,   0,   0,   0, 723,  26,   0,   0,   0,   0,   0, 359,
+     0, 259, 265,  26, 276,  26,  26,  26,   0,   0,   0, 724,   0, 376,   0, 376,
+     0,   0,   0,   0,   0,   0, 257, 725,   0,   0,   0, 265,   0, 359, 259,  26,
+     0, 359,   0,   0,   0,   0,   0,   0,   0,  26,   0, 265,   0,   0,   0,   0,
+     0,  26,   0,   0,   0, 276,   0, 359, 265,  26,  26,  26,  26,  26,  26,  26,
+     0,   0, 359,  26,   0, 276,   0, 376,   0, 726,   0,   0,   0,   0,   0,   0,
+   257, 722,   0, 727,   0, 265,   0, 259,   0,   0, 358,   0,   0,   0,   0,   0,
+   277, 277, 277, 277,  26,  26,  26,  26, 277, 277, 277, 277, 277, 277, 277, 345,
+   277, 277, 277, 280, 277, 277, 277, 277, 277, 277, 277, 277, 345,  26, 277, 277,
+   277, 277, 277, 277, 728,  26, 277, 277, 277, 277, 277, 280,  26,  26,  26,  26,
+   277, 729, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,  26,  26,
+   730,  26,  26,  26,   0,   0,   0,   0,   9,   9,   9,   9,   9,   9,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    939, 940, 941, 942, 946, 948,   0, 962, 969, 970, 971, 976,1001,1002,1003,1008,
      0,1033,1040,1041,1042,1043,1047,   0,   0,1080,1081,1082,1086,1110,   0,   0,
@@ -2732,17 +2787,24 @@ _hb_ucd_u16[9344] =
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1602,1603,1934,1935,1574,1575,
   1576,1577,1579,1580,1581,1583,1584,   0,1585,1587,1588,1589,1591,   0,1592,   0,
   1593,1594,   0,1595,1596,   0,1598,1599,1600,1601,1604,1582,1578,1590,1597,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1936,   0,1937,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1938,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1939,1940,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1941,1942,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1944,1943,   0,1945,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1946,1947,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,1948,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1949,1950,
-  1951,1952,1953,1954,1955,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1956,1957,1958,1960,1959,
-  1961,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1936,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,1937,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1938,   0,1939,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1940,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1941,1942,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1943,1944,   0,   0,   0,
+     0,   0,   0,1945,   0,1946,   0,   0,   0,   0,   0,   0,   0,   0,1947,   0,
+     0,1948,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,1950,   0,1949,1951,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1953,1952,   0,1954,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1955,1956,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,1957,   0,   0,   0,   0,   0,   0,   0,
+     0,1958,1961,1959,1965,1960,1962,1964,1963,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,1967,1966,1968,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1969,1970,
+  1971,1972,1973,1974,1975,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1976,1977,1978,1980,1979,
+  1981,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125,  34, 830, 130, 131,
    132, 137, 827,  35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152,  37,
    157, 158, 159, 160,  38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179,
@@ -2799,12 +2861,12 @@ _hb_ucd_i16[196] =
 static inline uint_fast8_t
 _hb_ucd_gc (unsigned u)
 {
-  return u<1114110u?_hb_ucd_u8[6808+(((_hb_ucd_u8[1312+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
+  return u<1114110u?_hb_ucd_u8[6472+(((_hb_ucd_u8[816+(((_hb_ucd_u16[((_hb_ucd_u8[272+(((_hb_ucd_u8[u>>1>>3>>4>>4])<<4)+((u>>1>>3>>4)&15u))])<<4)+((u>>1>>3)&15u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
 }
 static inline uint_fast8_t
 _hb_ucd_ccc (unsigned u)
 {
-  return u<125259u?_hb_ucd_u8[8800+(((_hb_ucd_u8[8244+(((_hb_ucd_u8[7784+(((_hb_ucd_u8[7432+(((_hb_ucd_u8[7186+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
+  return u<125259u?_hb_ucd_u8[8504+(((_hb_ucd_u8[7936+(((_hb_ucd_u8[7460+(((_hb_ucd_u8[7100+(((_hb_ucd_u8[6854+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
 }
 static inline unsigned
 _hb_ucd_b4 (const uint8_t* a, unsigned i)
@@ -2814,107 +2876,76 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i
 static inline int_fast16_t
 _hb_ucd_bmg (unsigned u)
 {
-  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9548+(((_hb_ucd_u8[9428+(((_hb_ucd_b4(9300+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0;
+  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9252+(((_hb_ucd_u8[9132+(((_hb_ucd_b4(9004+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0;
 }
 static inline uint_fast8_t
 _hb_ucd_sc (unsigned u)
 {
-  return u<918000u?_hb_ucd_u8[11070+(((_hb_ucd_u16[2048+(((_hb_ucd_u8[10334+(((_hb_ucd_u8[9884+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2;
+  return u<918000u?_hb_ucd_u8[10486+(((_hb_ucd_u16[3744+(((_hb_ucd_u16[2624+(((_hb_ucd_u8[9588+(u>>3>>3>>4)])<<4)+((u>>3>>3)&15u))])<<3)+((u>>3)&7u))])<<3)+((u)&7u))]:2;
 }
 static inline uint_fast16_t
 _hb_ucd_dm (unsigned u)
 {
-  return u<195102u?_hb_ucd_u16[6032+(((_hb_ucd_u8[17084+(((_hb_ucd_u8[16702+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
+  return u<195102u?_hb_ucd_u16[6976+(((_hb_ucd_u8[16716+(((_hb_ucd_u8[16334+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
 }
 
 
 #elif !defined(HB_NO_UCD_UNASSIGNED)
 
 static const uint8_t
-_hb_ucd_u8[14752] =
+_hb_ucd_u8[17524] =
 {
-    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,
-    7,  7,  7,  7,  9, 10,  7,  7,  7,  7, 11, 12, 13, 13, 13, 14,
-   15, 16, 17, 18, 19, 20, 21, 22, 23, 22, 22, 22, 22, 24,  7,  7,
-   25, 26, 22, 22, 22, 27, 28, 29, 22, 30, 31, 32, 33, 34, 35, 36,
-    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-    7,  7,  7,  7, 37,  7, 38, 39,  7, 40,  7,  7,  7, 41, 22, 42,
-    7,  7, 43,  7, 44, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   45, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 46,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 47,
+    0,  1,  2,  3,  4,  5,  5,  5,  5,  5,  6,  5,  5,  7,  8,  9,
+   10, 11, 12, 13, 14, 15, 16,  5, 17, 15, 18, 19, 20, 21, 22, 23,
+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 24, 25, 26,  5, 27, 28,
+    5, 29, 30, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   31, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8, 32,
+    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8, 33,
     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
-   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-   32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43,
-   44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
-   60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 69, 72, 73,
-   69, 69, 64, 74, 64, 64, 75, 76, 77, 78, 79, 80, 81, 82, 69, 83,
-   84, 85, 86, 87, 88, 89, 69, 69, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34,
-   91, 34, 34, 34, 34, 34, 34, 34, 34, 92, 34, 34, 93, 94, 95, 96,
-   97, 98, 99,100,101,102,103,104, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,105,
-  106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
-  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
-  107,107, 34, 34,108,109,110,111, 34, 34,112,113,114,115,116,117,
-  118,119,120,121,122,123,124,125,126,127,128,129, 34, 34,130,131,
-  132,133,134,135,136,137,138,139,140,141,142,122,143,144,145,146,
-  147,148,149,150,151,152,153,122,154,155,122,156,157,158,159,122,
-  160,161,162,163,164,165,166,122,167,168,169,170,122,171,172,173,
-   34, 34, 34, 34, 34, 34, 34,174,175, 34,176,122,122,122,122,122,
-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,177,
-   34, 34, 34, 34, 34, 34, 34, 34,178,122,122,122,122,122,122,122,
-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,
-  122,122,122,122,122,122,122,122, 34, 34, 34, 34,179,122,122,122,
-   34, 34, 34, 34,180,181,182,183,122,122,122,122,184,185,186,187,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,188,
-   34, 34, 34, 34, 34, 34, 34, 34, 34,189,190,122,122,122,122,122,
-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,191,
-   34, 34,192, 34, 34,193,122,122,122,122,122,122,122,122,122,122,
-  122,122,122,122,122,122,122,122,194,195,122,122,122,122,122,122,
-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,196,197,
-   69,198,199,200,201,202,203,122,204,205,206,207,208,209,210,211,
-   69, 69, 69, 69,212,213,122,122,122,122,122,122,122,122,214,122,
-  215,216,217,122,122,218,122,122,122,219,122,122,122,122,122,220,
-   34,221,222,122,122,122,122,122,223,224,225,122,226,227,122,122,
-  228,229,230,231,232,122, 69,233, 69, 69, 69, 69, 69,234,235,236,
-  237,238, 69, 69,239,240, 69,241,122,122,122,122,122,122,122,122,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,242, 34, 34,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,243, 34,
-  244, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,245, 34, 34,
-   34, 34, 34, 34, 34, 34, 34,246, 34, 34, 34, 34,247,122,122,122,
-   34, 34, 34, 34,248,122,122,122,122,122,122,122,122,122,122,122,
-   34, 34, 34, 34, 34, 34,249, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-   34, 34, 34, 34, 34, 34, 34,250,122,122,122,122,122,122,122,122,
-  251,122,252,253,122,122,122,122,122,122,122,122,122,122,122,122,
-  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,254,
-  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,255,
+   16, 17, 18, 19, 20, 17, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+   31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 33, 41, 42, 43, 44, 45,
+   46, 47, 48, 39, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   50, 17, 17, 17, 51, 17, 52, 53, 54, 55, 56, 57, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 58, 59, 59, 59, 59, 59, 59, 59, 59,
+   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+   60, 60, 60, 60, 60, 60, 60, 60, 60, 17, 61, 62, 17, 63, 64, 65,
+   66, 67, 68, 69, 70, 71, 17, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+   81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+   17, 17, 17, 97, 98, 99,100,100,100,100,100,100,100,100,100,101,
+   17, 17, 17, 17,102, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17,103, 17, 17,104,100,100,100,100,100,100,100,100,100,
+  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
+  100,105,100,100,100,100,100,100, 17, 17,106,107,100,108,109,110,
+   17, 17, 17, 17, 17, 17, 17,111, 17, 17, 17, 17,112,113,100,100,
+  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,114,
+   17,115,116,100,100,100,100,100,100,100,100,100,117,100,100,100,
+  100,100,100,100,100,100,100,100,100,100,100,100,118, 39,119,120,
+  121,122,123,124,125,126,127,128, 39, 39,129,100,100,100,100,130,
+  131,132,133,100,134,135,100,136,137,138,100,100,139,140,141,100,
+  142,143,144,145, 39, 39,146,147,148, 39,149,150,100,100,100,100,
+   17, 17, 17, 17, 17, 17,151, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17,152,153, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,154, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,155, 17, 17,156,100,
+  100,100,100,100,100,100,100,100, 17, 17,157,100,100,100,100,100,
+   17, 17, 17,158, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17,159,100,100,100,100,100,100,100,100,100,100,100,100,
+  160,161,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
+   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,162,
+   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,163,
     0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  2,  4,  5,  6,  2,
     7,  7,  7,  7,  7,  2,  8,  9, 10, 11, 11, 11, 11, 11, 11, 11,
    11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
@@ -2951,7 +2982,7 @@ _hb_ucd_u8[14752] =
    43, 43, 40, 21,  2, 81, 57, 20, 36, 36, 36, 43, 43, 75, 43, 43,
    43, 43, 75, 43, 75, 43, 43, 44,  2,  2,  2,  2,  2,  2,  2, 64,
    36, 36, 36, 36, 70, 43, 44, 64, 36, 36, 36, 36, 36, 61, 44, 44,
-   36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 44, 43, 43, 43, 43,
+   36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 57, 43, 43, 43, 43,
    36, 36, 36, 36, 83, 43, 43, 43, 43, 84, 43, 43, 43, 43, 43, 43,
    43, 85, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 85, 71, 86,
    87, 43, 43, 43, 85, 86, 87, 86, 70, 43, 43, 43, 36, 36, 36, 36,
@@ -3024,13 +3055,13 @@ _hb_ucd_u8[14752] =
    85, 85, 87, 43, 43, 43, 85, 86, 86, 87, 43, 43, 43, 43, 80, 57,
     2,  2,  2, 88,  2,  2,  2, 44, 43, 43, 43, 43, 43, 43, 43,109,
    43, 43, 43, 43, 43, 43, 43, 80, 43, 43, 98, 36, 36, 36, 36, 36,
-   36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61, 44,
-   97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21, 64,
+   36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61,  2,
+   97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21,  2,
    43, 98, 36, 36, 36, 36, 36, 36, 94, 43, 43, 86, 43, 87, 43, 36,
    36, 36, 36, 85, 43, 86, 87, 87, 43, 86, 44, 44, 44, 44,  2,  2,
    36, 36, 86, 86, 86, 86, 43, 43, 43, 43, 86, 43, 44, 93,  2,  2,
     7,  7,  7,  7,  7, 44, 62, 36, 36, 36, 36, 36, 40, 40, 40,  2,
-   16, 16, 16, 16,110, 44, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11,
+   16, 16, 16, 16, 34,110, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11,
     2,  2,  2,  2, 44, 44, 44, 44, 43, 60, 43, 43, 43, 43, 43, 43,
    85, 43, 43, 43, 71, 36, 70, 36, 36, 36, 71, 94, 43, 61, 44, 44,
    16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 45, 16, 16,
@@ -3058,33 +3089,33 @@ _hb_ucd_u8[14752] =
    67, 67, 67, 67,  4,  4, 67, 67,  8, 67, 67, 67,145,146, 67, 67,
    67, 67, 67, 67, 67, 67,144, 67, 67, 67, 67, 67, 67, 26,  8,  8,
     8,  8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,
-    8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44,
-   67, 67, 67, 67, 67, 92, 44, 44, 27, 27, 27, 27, 27, 27, 67, 67,
-   67, 67, 67, 67, 67, 27, 27, 27, 67, 67, 67, 26, 67, 67, 67, 67,
-   26, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,  8,  8,
-   67, 67, 67, 67, 67, 67, 67, 26, 67, 67, 67, 67,  4,  4,  4,  4,
-    4,  4,  4, 27, 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67,
-    8,  8,129,147,  8,  8,  8,  8,  8,  8,  8,  4,  4,  4,  4,  4,
-    8,129,148,148,148,148,148,148,148,148,148,148,147,  8,  8,  8,
-    8,  8,  8,  8,  4,  4,  8,  8,  8,  8,  8,  8,  8,  8,  4,  8,
-    8,  8,144, 26,  8,  8,144, 67, 67, 67, 44, 67, 67, 67, 67, 67,
-   67, 67, 67, 55, 67, 67, 67, 67, 32, 11, 32, 34, 34, 34, 34, 11,
-   32, 32, 34, 16, 16, 16, 40, 11, 32, 32,140, 67, 67,138, 34,149,
-   43, 32, 44, 44, 93,  2, 99,  2, 16, 16, 16,150, 44, 44,150, 44,
-   36, 36, 36, 36, 44, 44, 44, 52, 64, 44, 44, 44, 44, 44, 44, 57,
-   36, 36, 36, 61, 44, 44, 44, 44, 36, 36, 36, 61, 36, 36, 36, 61,
-    2,121,121,  2,125,126,121,  2,  2,  2,  2,  6,  2,108,121,  2,
-  121,  4,  4,  4,  4,  2,  2, 88,  2,  2,  2,  2,  2,120,  2,  2,
-  108,151,  2,  2,  2,  2,  2,  2, 67,  2,152,148,148,148,153, 44,
-   67, 67, 67, 67, 67, 55, 67, 67, 67, 67, 44, 44, 44, 44, 44, 44,
-   67, 67, 67, 44, 44, 44, 44, 44,  1,  2,154,155,  4,  4,  4,  4,
-    4, 67,  4,  4,  4,  4,156,157,158,105,105,105,105, 43, 43, 86,
-  159, 40, 40, 67,105,160, 63, 67, 36, 36, 36, 61, 57,161,162, 69,
-   36, 36, 36, 36, 36, 63, 40, 69, 44, 44, 62, 36, 36, 36, 36, 36,
-   67, 27, 27, 67, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, 44, 55,
-   67, 67, 67, 67, 67, 67, 67, 92, 27, 27, 27, 27, 27, 67, 67, 67,
-   67, 67, 67, 67, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27,
-   36, 36, 83, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,164,  2,
+    8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44,
+   27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27,
+   67, 67, 67, 26, 67, 67, 67, 67, 26, 67, 67, 67, 67, 67, 67, 67,
+   67, 67, 67, 67,  8,  8,  8,  8, 67, 67, 67, 67, 67, 67, 67, 26,
+   67, 67, 67, 67,  4,  4,  4,  4,  4,  4,  4, 27, 27, 27, 27, 27,
+   27, 27, 67, 67, 67, 67, 67, 67,  8,  8,129,147,  8,  8,  8,  8,
+    8,  8,  8,  4,  4,  4,  4,  4,  8,129,148,148,148,148,148,148,
+  148,148,148,148,147,  8,  8,  8,  8,  8,  8,  8,  4,  4,  8,  8,
+    8,  8,  8,  8,  8,  8,  4,  8,  8,  8,144, 26,  8,  8,144, 67,
+   67, 67, 44, 67, 67, 67, 67, 67, 67, 67, 67, 55, 67, 67, 67, 67,
+   32, 11, 32, 34, 34, 34, 34, 11, 32, 32, 34, 16, 16, 16, 40, 11,
+   32, 32,140, 67, 67,138, 34,149, 43, 32, 44, 44, 93,  2, 99,  2,
+   16, 16, 16,150, 44, 44,150, 44, 36, 36, 36, 36, 44, 44, 44, 52,
+   64, 44, 44, 44, 44, 44, 44, 57, 36, 36, 36, 61, 44, 44, 44, 44,
+   36, 36, 36, 61, 36, 36, 36, 61,  2,121,121,  2,125,126,121,  2,
+    2,  2,  2,  6,  2,108,121,  2,121,  4,  4,  4,  4,  2,  2, 88,
+    2,  2,  2,  2,  2,120,  2,  2,108,151,  2,  2,  2,  2,  2,  2,
+   67,  2,152,148,148,148,153, 44, 67, 67, 67, 67, 67, 55, 67, 67,
+   67, 67, 44, 44, 44, 44, 44, 44, 67, 67, 67, 44, 44, 44, 44, 44,
+    1,  2,154,155,  4,  4,  4,  4,  4, 67,  4,  4,  4,  4,156,157,
+  158,105,105,105,105, 43, 43, 86,159, 40, 40, 67,105,160, 63, 67,
+   36, 36, 36, 61, 57,161,162, 69, 36, 36, 36, 36, 36, 63, 40, 69,
+   44, 44, 62, 36, 36, 36, 36, 36, 67, 27, 27, 67, 67, 67, 67, 67,
+   67, 67, 67, 44, 44, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67, 92,
+   27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, 27,
+  163, 27, 27, 27, 27, 27, 27, 27, 36, 36, 83, 36, 36, 36, 36, 36,
+   67, 67, 67, 92, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36,164,  2,
     7,  7,  7,  7,  7, 36, 44, 44, 32, 32, 32, 32, 32, 32, 32, 70,
    51,165, 43, 43, 43, 43, 43, 88, 32, 32, 32, 32, 32, 32, 40, 43,
    36, 36, 36,105,105,105,105,105, 43,  2,  2,  2, 44, 44, 44, 44,
@@ -3092,7 +3123,7 @@ _hb_ucd_u8[14752] =
    16, 32, 32, 32, 32, 32, 32, 32, 45, 16, 16, 16, 34, 34, 34, 32,
    32, 32, 32, 32, 42,166, 34, 35, 32, 32, 16, 32, 32, 32, 32, 32,
    32, 32, 32, 32, 32, 11, 11, 32, 11, 11, 32, 32, 32, 32, 32, 32,
-   32, 32, 11, 11, 34,110, 44, 44, 32,150,150, 32, 32, 44, 44, 44,
+   32, 32, 11, 11, 34, 34, 32, 44, 32,150,150, 32, 32, 32, 47, 44,
    44, 40,167, 35, 40, 35, 36, 36, 36, 71, 36, 71, 36, 70, 36, 36,
    36, 94, 87, 85, 67, 67, 80, 44, 27, 27, 27, 67,168, 44, 44, 44,
    36, 36,  2,  2, 44, 44, 44, 44, 86, 36, 36, 36, 36, 36, 36, 36,
@@ -3153,8 +3184,10 @@ _hb_ucd_u8[14752] =
    36, 61, 44, 44, 27, 27, 27, 27, 36, 44, 44, 44, 93,  2, 64, 44,
    44, 44, 44, 44,179, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44,
    16,110, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44,
-   27, 27, 27, 27, 27, 27, 27,100, 36, 36, 36, 36, 36, 57,184, 44,
-   36, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 57, 43,
+    7,  7,  7,  7,  7, 36, 36, 69, 11, 11, 11, 44, 57, 43, 43,159,
+   16, 16, 16, 44, 44, 44, 44,  8, 27, 27, 27, 27, 27, 27, 27,100,
+   36, 36, 36, 36, 36, 57,184, 44, 36, 44, 44, 44, 44, 44, 44, 44,
+   44, 36, 61, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43,
    27, 27, 27, 95, 44, 44, 44, 44,180, 27, 30,  2,  2, 44, 44, 44,
    36, 43, 43,  2,  2, 44, 44, 44, 36, 36,183, 27, 27, 27, 44, 44,
    87, 98, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43,
@@ -3172,14 +3205,18 @@ _hb_ucd_u8[14752] =
    86, 87, 43, 43, 43, 80, 44, 44, 43, 86, 62, 36, 36, 36, 61, 62,
    61, 36, 62, 36, 36, 57, 71, 86, 85, 86, 90, 89, 90, 89, 86, 44,
    61, 44, 44, 89, 44, 44, 62, 36, 36, 86, 44, 43, 43, 43, 80, 44,
-   43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 94, 86, 43, 43, 43, 43,
-   86, 43, 85, 71, 36, 63,  2,  2,  7,  7,  7,  7,  7,  2, 93, 71,
-   86, 87, 43, 43, 85, 85, 86, 87, 85, 43, 36, 72, 44, 44, 44, 44,
-   36, 36, 36, 36, 36, 36, 36, 94, 86, 43, 43, 44, 86, 86, 43, 87,
-   60,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 43, 44,
-   86, 87, 43, 43, 43, 85, 87, 87, 60,  2, 61, 44, 44, 44, 44, 44,
-    2,  2,  2,  2,  2,  2, 64, 44, 36, 36, 36, 36, 36, 70, 87, 86,
-   43, 43, 43, 87, 63, 44, 44, 44, 86, 43, 43, 87, 43, 43, 44, 44,
+   43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 62, 44, 61,
+   36, 36, 36, 62, 86, 87, 43, 43, 80, 90, 89, 89, 86, 90, 86, 85,
+   71, 71,  2, 93, 64, 44, 44, 44, 57, 80, 44, 44, 44, 44, 44, 44,
+   36, 36, 94, 86, 43, 43, 43, 43, 86, 43, 85, 71, 36, 63,  2,  2,
+    7,  7,  7,  7,  7,  2, 93, 71, 86, 87, 43, 43, 85, 85, 86, 87,
+   85, 43, 36, 72, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 94,
+   86, 43, 43, 44, 86, 86, 43, 87, 60,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2, 36, 36, 43, 44, 86, 87, 43, 43, 43, 85, 87, 87,
+   60,  2, 61, 44, 44, 44, 44, 44,  2,  2,  2,  2,  2,  2, 64, 44,
+   36, 36, 36, 36, 36, 70, 87, 86, 43, 43, 43, 87, 63, 44, 44, 44,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 44, 44, 44, 44, 44, 44,
+   36, 36, 36, 36, 36, 61, 57, 87, 86, 43, 43, 87, 43, 43, 44, 44,
     7,  7,  7,  7,  7, 27,  2, 97, 43, 43, 43, 43, 87, 60, 44, 44,
    27,100, 44, 44, 44, 44, 44, 62, 36, 36, 36, 61, 62, 44, 36, 36,
    36, 36, 62, 61, 36, 36, 36, 36, 86, 86, 86, 89, 90, 57, 85, 71,
@@ -3189,49 +3226,52 @@ _hb_ucd_u8[14752] =
     2,  2,  2, 59, 44, 44, 44, 44, 70, 43, 43, 85, 87, 43, 36, 36,
    36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 85, 43,  2, 72,  2,
     2, 64, 44, 44, 44, 44, 44, 44,  2,  2,  2,  2,  2, 44, 44, 44,
-   43, 43, 43, 80, 43, 43, 43, 87, 63,  2,  2, 44, 44, 44, 44, 44,
-    2, 36, 36, 36, 36, 36, 36, 36, 44, 43, 43, 43, 43, 43, 43, 43,
-   43, 43, 43, 43, 89, 43, 43, 43, 85, 43, 87, 80, 44, 44, 44, 44,
-   36, 36, 36, 61, 36, 62, 36, 36, 70, 43, 43, 80, 44, 80, 43, 57,
-   43, 43, 43, 70, 44, 44, 44, 44, 36, 36, 36, 62, 61, 36, 36, 36,
-   36, 36, 36, 36, 36, 86, 86, 90, 43, 89, 87, 87, 61, 44, 44, 44,
-   36, 70, 85,107, 64, 44, 44, 44, 43, 94, 36, 36, 36, 36, 36, 36,
-   36, 36, 86, 43, 43, 80, 44, 86, 85, 60,  2,  2,  2,  2,  2,  2,
+   63, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 80, 43, 43, 43, 87,
+   63,  2,  2, 44, 44, 44, 44, 44,  2, 36, 36, 36, 36, 36, 36, 36,
+   44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 89, 43, 43, 43,
+   85, 43, 87, 80, 44, 44, 44, 44, 36, 36, 36, 61, 36, 62, 36, 36,
+   70, 43, 43, 80, 44, 80, 43, 57, 43, 43, 43, 70, 44, 44, 44, 44,
+   36, 36, 36, 62, 61, 36, 36, 36, 36, 36, 36, 36, 36, 86, 86, 90,
+   43, 89, 87, 87, 61, 44, 44, 44, 36, 70, 85,107, 64, 44, 44, 44,
+   43, 94, 36, 36, 36, 36, 36, 36, 36, 36, 86, 43, 43, 80, 44, 86,
+   85, 60,  2,  2,  2,  2,  2,  2,  7,  7,  7,  7,  7, 80, 44, 44,
    27, 27, 91, 67, 67, 67, 56, 20,168, 67, 67, 67, 67, 67, 67, 67,
    67, 44, 44, 44, 44, 44, 44, 93,105,105,105,105,105,105,105,181,
     2,  2, 64, 44, 44, 44, 44, 44, 63, 64, 44, 44, 44, 44, 44, 44,
    65, 65, 65, 65, 65, 65, 65, 65, 71, 36, 36, 70, 43, 43, 43, 43,
-   43, 43, 43, 44, 44, 44, 44, 44, 43, 43, 60, 44, 44, 44, 44, 44,
+   43, 43, 43, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 43,
+   43, 43, 43, 43, 43, 86, 87, 43, 43, 43, 60, 44, 44, 44, 44, 44,
    43, 43, 43, 60,  2,  2, 67, 67, 40, 40, 97, 44, 44, 44, 44, 44,
     7,  7,  7,  7,  7,179, 27, 27, 27, 62, 36, 36, 36, 36, 36, 36,
-   36, 36, 36, 36, 44, 44, 62, 36, 27, 27, 27, 30,  2, 64, 44, 44,
+   36, 36, 36, 36, 44, 44, 62, 36, 40, 69, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 83,164,  2, 27, 27, 27, 30,  2, 64, 44, 44,
    36, 36, 36, 36, 36, 61, 44, 57, 94, 86, 86, 86, 86, 86, 86, 86,
    86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 44, 44, 44, 57,
    43, 74, 40, 40, 40, 40, 40, 40, 40, 88, 80, 44, 44, 44, 44, 44,
-   86, 44, 44, 44, 44, 44, 44, 44, 40, 40, 52, 40, 40, 40, 52, 81,
-   36, 61, 44, 44, 44, 44, 44, 44, 44, 61, 44, 44, 44, 44, 44, 44,
-   36, 61, 62, 44, 44, 44, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44,
-   36, 36, 36, 36, 36, 44, 50, 60, 65, 65, 44, 44, 44, 44, 44, 44,
-   43, 43, 43, 43, 43, 43, 43, 44, 43, 43, 43, 80, 44, 44, 44, 44,
-   67, 67, 67, 92, 55, 67, 67, 67, 67, 67,186, 87, 43, 67,186, 86,
-   86,187, 65, 65, 65, 84, 43, 43, 43, 76, 50, 43, 43, 43, 67, 67,
-   67, 67, 67, 67, 67, 43, 43, 67, 67, 43, 76, 44, 44, 44, 44, 44,
-   27, 27, 44, 44, 44, 44, 44, 44, 11, 11, 11, 11, 11, 16, 16, 16,
-   16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16,
-   16, 16,110, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
-   16, 16, 16, 16, 16, 16, 47, 11, 44, 47, 48, 47, 48, 11, 47, 11,
-   11, 11, 11, 16, 16,150,150, 16, 16, 16,150, 16, 16, 16, 16, 16,
-   16, 16, 11, 48, 11, 47, 48, 11, 11, 11, 47, 11, 11, 11, 47, 16,
-   16, 16, 16, 16, 11, 48, 11, 47, 11, 11, 47, 47, 44, 11, 11, 11,
-   47, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11,
-   11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 44, 11, 11, 11, 11,
-   31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16,
-   16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16,
-   16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16,
-   16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11,
-   11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16,
-   11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 44,  7,
-    7,  7,  7,  7,  7,  7,  7,  7, 43, 43, 43, 76, 67, 50, 43, 43,
+   86, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 62,
+   40, 40, 52, 40, 40, 40, 52, 81, 36, 61, 44, 44, 44, 44, 44, 44,
+   44, 61, 44, 44, 44, 44, 44, 44, 36, 61, 62, 44, 44, 44, 44, 44,
+   44, 44, 36, 36, 44, 44, 44, 44, 36, 36, 36, 36, 36, 44, 50, 60,
+   65, 65, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 44,
+   43, 43, 43, 80, 44, 44, 44, 44, 67, 67, 67, 92, 55, 67, 67, 67,
+   67, 67,186, 87, 43, 67,186, 86, 86,187, 65, 65, 65, 84, 43, 43,
+   43, 76, 50, 43, 43, 43, 67, 67, 67, 67, 67, 67, 67, 43, 43, 67,
+   67, 43, 76, 44, 44, 44, 44, 44, 27, 27, 44, 44, 44, 44, 44, 44,
+   11, 11, 11, 11, 11, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 11,
+   11, 11, 11, 11, 11, 11, 11, 16, 16, 16,110, 16, 16, 16, 16, 16,
+   11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 47, 11,
+   44, 47, 48, 47, 48, 11, 47, 11, 11, 11, 11, 16, 16,150,150, 16,
+   16, 16,150, 16, 16, 16, 16, 16, 16, 16, 11, 48, 11, 47, 48, 11,
+   11, 11, 47, 11, 11, 11, 47, 16, 16, 16, 16, 16, 11, 48, 11, 47,
+   11, 11, 47, 47, 44, 11, 11, 11, 47, 16, 16, 16, 16, 16, 16, 16,
+   16, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 16, 16, 16, 16, 16,
+   16, 16, 16, 44, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16, 16, 16,
+   16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, 11, 11,
+   11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11,
+   11, 11, 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33,
+   16, 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31,
+   16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16,
+   16, 33, 16, 16, 16, 32, 44,  7, 43, 43, 43, 76, 67, 50, 43, 43,
    43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67,
    67, 67, 76, 21,  2,  2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43,
    16, 16, 16, 16, 16, 39, 16, 16, 16, 16, 16, 16, 16, 16, 16,110,
@@ -3241,22 +3281,23 @@ _hb_ucd_u8[14752] =
    43, 43, 43, 74, 40, 40, 40, 44,  7,  7,  7,  7,  7, 44, 44, 77,
    36, 36, 36, 36, 36, 36, 36, 80, 36, 36, 36, 36, 36, 36, 43, 43,
     7,  7,  7,  7,  7, 44, 44, 96, 36, 36, 36, 36, 36, 83, 43, 43,
-   36, 36, 36, 61, 36, 36, 62, 61, 36, 36, 61,179, 27, 27, 27, 27,
-   16, 16, 43, 43, 43, 74, 44, 44, 27, 27, 27, 27, 27, 27,163, 27,
-  188, 27,100, 44, 44, 44, 44, 44, 27, 27, 27, 27, 27, 27, 27,163,
-   27, 27, 27, 27, 27, 27, 27, 44, 36, 36, 62, 36, 36, 36, 36, 36,
-   62, 61, 61, 62, 62, 36, 36, 36, 36, 61, 36, 36, 62, 62, 44, 44,
-   44, 61, 44, 62, 62, 62, 62, 36, 62, 61, 61, 62, 62, 62, 62, 62,
-   62, 61, 61, 62, 36, 61, 36, 36, 36, 61, 36, 36, 62, 36, 61, 61,
-   36, 36, 36, 36, 36, 62, 36, 36, 62, 36, 62, 36, 36, 62, 36, 36,
-    8, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 44, 44,
-   55, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, 27, 27, 27, 91, 67,
-   67, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 67, 67, 67,
-   67, 92, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 92, 44, 44, 44,
-   67, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 25, 41, 41,
-   67, 67, 67, 67, 44, 44, 67, 67, 67, 67, 67, 92, 44, 55, 67, 67,
-   67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 67, 55,
-   67, 67, 67, 44, 44, 44, 44, 67, 67, 92, 67, 67, 67, 67, 67, 67,
+  188,  7,  7,  7,  7,189, 44, 93, 36, 36, 36, 61, 36, 36, 62, 61,
+   36, 36, 61,179, 27, 27, 27, 27, 16, 16, 43, 43, 43, 74, 44, 44,
+   27, 27, 27, 27, 27, 27,163, 27,190, 27,100, 44, 44, 44, 44, 44,
+   27, 27, 27, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27, 44,
+   36, 36, 62, 36, 36, 36, 36, 36, 62, 61, 61, 62, 62, 36, 36, 36,
+   36, 61, 36, 36, 62, 62, 44, 44, 44, 61, 44, 62, 62, 62, 62, 36,
+   62, 61, 61, 62, 62, 62, 62, 62, 62, 61, 61, 62, 36, 61, 36, 36,
+   36, 61, 36, 36, 62, 36, 61, 61, 36, 36, 36, 36, 36, 62, 36, 36,
+   62, 36, 62, 36, 36, 62, 36, 36,  8, 44, 44, 44, 44, 44, 44, 44,
+   67, 67, 67, 67, 67, 67, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67,
+   27, 27, 27, 27, 27, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 44,
+   44, 44, 44, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, 44, 44,
+   67, 67, 67, 67, 92, 44, 44, 44, 67, 44, 44, 44, 44, 44, 44, 44,
+   67, 67, 67, 67, 67, 25, 41, 41, 67, 67, 67, 67, 44, 44, 67, 67,
+   67, 67, 67, 92, 44, 55, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44,
+   67, 67, 67, 67, 67, 44, 44, 55, 67, 67, 67, 92, 44, 44, 44, 67,
+   67, 67, 67, 67, 67, 67, 92, 55, 67, 92, 67, 67, 67, 67, 67, 67,
    79, 44, 44, 44, 44, 44, 44, 44,171,171,171,171,171,171,171, 44,
   171,171,171,171,171,171,171,  0,  0,  0, 29, 21, 21, 21, 23, 21,
    22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21,  9,  9,  9,
@@ -3282,420 +3323,609 @@ _hb_ucd_u8[14752] =
     6, 21, 11, 21, 24,  9,  6,  9, 23, 26,  6, 10,  4,  4,  3,  3,
     7, 25, 17, 16, 16, 22, 16, 16, 25, 17, 25,  2, 25, 24,  2, 15,
    12, 15, 14,  2, 21, 14,  7, 15, 12, 17, 21,  1, 26, 10, 10,  1,
-   23, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0, 10, 11, 12,
-   13,  0, 14,  0,  0,  0,  0,  0, 15,  0, 16,  0,  0,  0,  0,  0,
+    7, 13, 13,  2, 23, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+    0, 10, 11, 12, 13,  0, 14,  0,  0,  0,  0,  0, 15,  0, 16,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0, 17, 18, 19,  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, 17, 18, 19,  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, 20,
-    0, 21, 22, 23,  0,  0,  0, 24, 25, 26, 27, 28, 29, 30, 31, 32,
-   33, 34,  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, 35,  0, 36,  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,
-   37,  0,  0,  0,  0,  0,  0,  0,  0,  0, 38, 39,  0,  0,  0,  0,
-    0,  0, 40, 41, 42,  0, 43,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  1,  2,  0,  0,  0,  0,  3,  0,  0,  0,  4,  5,
-    6,  7,  0,  8,  9, 10,  0, 11, 12, 13, 14, 15, 16, 17, 16, 18,
-   16, 19, 16, 19, 16, 19,  0, 19, 16, 20, 16, 19, 21, 19,  0, 22,
-   23, 24, 25, 26, 27, 28, 29, 30, 31,  0, 32,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0, 33,  0,  0,  0,  0,  0,  0, 34,  0,  0, 35,
-    0,  0, 36,  0, 37,  0,  0,  0, 38, 39, 40, 41, 42, 43, 44, 45,
-   46,  0,  0, 47,  0,  0,  0, 48,  0,  0,  0, 49,  0,  0,  0,  0,
-    0,  0,  0, 50,  0, 51,  0, 52, 53,  0, 54,  0,  0,  0,  0,  0,
-    0, 55, 56, 57,  0,  0,  0,  0, 58,  0,  0, 59, 60, 61, 62, 63,
-    0,  0, 64, 65,  0,  0,  0, 66,  0,  0,  0,  0, 67,  0,  0,  0,
-   68,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 69,
-    0,  0,  0, 70,  0, 71,  0,  0, 72,  0,  0, 73,  0,  0,  0,  0,
-    0,  0,  0,  0, 74,  0,  0,  0,  0,  0, 75, 76,  0, 77, 78,  0,
-    0, 79, 80,  0, 81, 62,  0, 82, 83,  0,  0, 84, 85, 86,  0,  0,
-    0, 87,  0, 88,  0,  0, 51, 89, 51,  0, 90,  0, 91,  0,  0,  0,
-   80,  0,  0,  0, 92, 93,  0, 94, 95, 96, 97,  0,  0,  0,  0,  0,
-   51,  0,  0,  0,  0, 98, 99,  0,  0,  0,  0,  0,  0,100,  0,  0,
-    0,  0,  0,101,102,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,103,
-    0,  0,104,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,106,  0,
-    0,107,  0,  0,  0,  0,  0,  0,108,  0,109,  0,102,  0,  0,  0,
-    0,  0,110,111,  0,  0,  0,  0,  0,  0,  0,112,  0,  0,  0,  0,
-    0,  0,  0,113,  0,114,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,
-    5,  6,  7,  0,  8,  0,  0,  0,  0,  9, 10, 11, 12,  0,  0,  0,
-    0, 13,  0,  0, 14, 15,  0, 16,  0, 17, 18,  0,  0, 19,  0, 20,
-   21,  0,  0,  0,  0,  0, 22, 23,  0, 24, 25,  0,  0, 26,  0,  0,
-    0, 27,  0,  0, 28, 29, 30, 31,  0,  0,  0, 32, 33, 34,  0,  0,
-   33,  0,  0, 35, 33,  0,  0,  0, 33, 36,  0,  0,  0,  0,  0, 37,
-   38,  0,  0,  0,  0,  0,  0, 39, 40,  0,  0,  0,  0,  0,  0, 41,
-   42,  0,  0,  0,  0, 43,  0, 44,  0,  0,  0, 45, 46,  0,  0,  0,
-   47,  0,  0,  0,  0,  0,  0, 48, 49,  0,  0,  0,  0, 50,  0,  0,
-    0, 51,  0, 52,  0, 53,  0,  0,  0,  0, 54,  0,  0,  0,  0, 55,
-    0, 56,  0,  0,  0,  0, 57, 58,  0,  0,  0, 59, 60,  0,  0,  0,
-    0,  0,  0, 61, 52,  0, 62, 63,  0,  0, 64,  0,  0,  0, 65, 66,
-    0,  0,  0, 67,  0, 68, 69, 70, 71, 72,  1, 73,  0, 74, 75, 76,
-    0,  0, 77, 78,  0,  0,  0, 79,  0,  0,  1,  1,  0,  0, 80,  0,
-    0, 81,  0,  0,  0,  0, 77, 82,  0, 83,  0,  0,  0,  0,  0, 78,
-   84,  0, 85,  0, 52,  0,  1, 78,  0,  0, 86,  0,  0, 87,  0,  0,
-    0,  0,  0, 88, 57,  0,  0,  0,  0,  0,  0, 89, 90,  0,  0, 84,
-    0,  0, 33,  0,  0, 91,  0,  0,  0,  0, 92,  0,  0,  0,  0, 49,
-    0,  0, 93,  0,  0,  0,  0, 94, 95,  0,  0, 96,  0,  0, 97,  0,
-    0,  0, 98,  0,  0,  0, 99,  0,  0,  0,  0,100,101, 93,  0,  0,
-  102,  0,  0,  0, 84,  0,  0,103,  0,  0,  0,104,105,  0,  0,106,
-  107,  0,  0,  0,  0,  0,  0,108,  0,  0,109,  0,  0,  0,  0,110,
-   33,  0,111,112,113, 35,  0,  0,114,  0,  0,  0,115,  0,  0,  0,
-    0,  0,  0,116,  0,  0,117,  0,  0,  0,  0,118, 88,  0,  0,  0,
-    0,  0, 57,  0,  0,  0,  0, 52,119,  0,  0,  0,  0,120,  0,  0,
-  121,  0,  0,  0,  0,119,  0,  0,122,  0,  0,  0,  0,  0,  0,123,
-    0,  0,  0,124,  0,  0,  0,125,  0,126,  0,  0,  0,  0,127,128,
-  129,  0,130,  0,131,  0,  0,  0,132,133,134,  0, 77,  0,  0,  0,
-    0,  0, 35,  0,  0,  0,135,  0,  0,  0,136,  0,  0,137,  0,  0,
-  138,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  3,  4,
-    5,  6,  7,  4,  4,  8,  9, 10,  1, 11, 12, 13, 14, 15, 16, 17,
-   18,  1,  1,  1, 19,  1,  0,  0, 20, 21, 22,  1, 23,  4, 21, 24,
-   25, 26, 27, 28, 29, 30,  0,  0,  1,  1, 31,  0,  0,  0, 32, 33,
-   34, 35,  1, 36, 37,  0,  0,  0,  0, 38,  1, 39, 14, 39, 40, 41,
-   42,  0,  0,  0, 43, 36, 44, 45, 21, 45, 46,  0,  0,  0, 19,  1,
-   21,  0,  0, 47,  0, 38, 48,  1,  1, 49, 49, 50,  0,  0, 51,  0,
-    0,  0, 52,  1,  0,  0, 38, 14,  4,  1,  1,  1, 53, 21, 43, 52,
-   54, 21, 35,  1,  0,  0,  0, 55,  0,  0,  0, 56, 57, 58,  0,  0,
-    0,  0,  0, 59,  0, 60,  0,  0,  0,  0, 61, 62,  0,  0, 63,  0,
-    0,  0, 64,  0,  0,  0, 65,  0,  0,  0, 66,  0,  0,  0, 67,  0,
-    0,  0, 68,  0,  0, 69, 70,  0, 71, 72, 73, 74, 75, 76,  0,  0,
-    0, 77,  0,  0,  0, 78, 79,  0,  0,  0,  0, 47,  0,  0,  0, 49,
-    0, 80,  0,  0,  0, 62,  0,  0, 63,  0,  0, 81,  0,  0, 82,  0,
-    0,  0, 83,  0,  0, 19, 84,  0, 62,  0,  0,  0,  0, 49,  1, 85,
-    1, 52, 15, 86, 36, 10, 21, 87,  0, 55,  0,  0,  0,  0, 19, 10,
-    1,  0,  0,  0,  0,  0, 88,  0,  0, 89,  0,  0, 88,  0,  0,  0,
-    0, 78,  0,  0, 87,  9, 12,  4, 90,  8, 91, 47,  0, 58, 50,  0,
-   21,  1, 21, 92, 93,  1,  1,  1,  1, 94, 95, 96, 97,  1, 98, 58,
-   81, 99,100,  4, 58,  0,  0,  0,  0,  0,  0, 19, 50,  0,  0,  0,
-    0,  0,  0, 61,  0,  0,101,102,  0,  0,103,  0,  0,  1,  1, 50,
-    0,  0,  0, 38,  0, 63,  0,  0,  0,  0,  0, 62,  0,  0,104, 68,
-   61,  0,  0,  0, 78,  0,  0,  0,105,106, 58, 38, 81,  0,  0,  0,
-    0,  0,  0,107,  1, 14,  4, 12, 84,  0,  0,  0,  0, 38, 87,  0,
-    0,  0,  0,108,  0,  0,109, 61,  0,110,  0,  0,  0,  1,  0,  0,
+    0,  0,  0, 20,  0, 21, 22, 23,  0,  0,  0, 24, 25, 26, 27, 28,
+   29, 30, 31, 32, 33, 34,  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, 35,  0,  0,  0,  0, 36,  0, 37,  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, 38,  0,  0,  0,  0,  0,  0,  0,  0,  0, 39, 40,
+    0,  0,  0,  0,  0,  0, 41, 42, 43,  0, 44,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  0,  0,  0,  0,  3,  0,
+    0,  0,  4,  5,  6,  7,  0,  8,  9, 10,  0, 11, 12, 13, 14, 15,
+   16, 17, 16, 18, 16, 19, 16, 19, 16, 19,  0, 19, 16, 20, 16, 19,
+   21, 19,  0, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,  0, 32,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0, 33,  0,  0,  0,  0,  0,  0,
+   34,  0,  0, 35,  0,  0, 36,  0, 37,  0,  0,  0, 38, 39, 40, 41,
+   42, 43, 44, 45, 46,  0,  0, 47,  0,  0,  0, 48,  0,  0,  0, 49,
+    0,  0,  0,  0,  0,  0,  0, 50,  0, 51,  0, 52, 53,  0, 54,  0,
+    0,  0,  0,  0,  0, 55, 56, 57,  0,  0,  0,  0, 58,  0,  0, 59,
+   60, 61, 62, 63,  0,  0, 64, 65,  0,  0,  0, 66,  0,  0,  0,  0,
+   67,  0,  0,  0, 68,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0, 69,  0,  0,  0, 70,  0, 71,  0,  0, 72,  0,  0, 73,
+    0,  0,  0,  0,  0,  0,  0,  0, 74, 75,  0,  0,  0,  0, 76, 77,
+    0, 78, 79,  0,  0, 80, 81,  0, 82, 62,  0, 83, 84,  0,  0, 85,
+   86, 87,  0, 88,  0, 89,  0, 90,  0,  0, 51, 91, 51,  0, 92,  0,
+   93,  0,  0,  0, 81,  0,  0,  0, 94, 95,  0, 96, 97, 98, 99,  0,
+    0,  0,  0,  0, 51,  0,  0,  0,  0,100,101,  0,  0,  0,  0,  0,
+    0,102,  0,  0,  0,  0,  0,  0,103,  0,  0,  0,  0,  0,  0,104,
+  105,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,106,  0,  0,107,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,108,109,  0,  0,110,  0,  0,
+    0,  0,  0,  0,111,  0,112,  0,105,  0,  0,  0,  0,  0,113,114,
+    0,  0,  0,  0,  0,  0,  0,115,  0,  0,  0,116,  0,  0,  0,117,
+    0,118,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  0,
+    8,  0,  0,  0,  0,  9, 10, 11, 12,  0,  0,  0,  0, 13,  0,  0,
+   14, 15,  0, 16,  0, 17, 18,  0,  0, 19,  0, 20, 21,  0,  0,  0,
+    0,  0, 22, 23,  0, 24, 25,  0,  0, 26,  0,  0,  0, 27,  0,  0,
+   28, 29, 30, 31,  0,  0,  0, 32, 33, 34,  0,  0, 33,  0,  0, 35,
+   33,  0,  0,  0, 33, 36,  0,  0,  0,  0,  0, 37, 38,  0,  0,  0,
+    0,  0,  0, 39, 40,  0,  0,  0,  0,  0,  0, 41, 42,  0,  0,  0,
+    0, 43,  0, 44,  0,  0,  0, 45, 46,  0,  0,  0, 47,  0,  0,  0,
+    0,  0,  0, 48, 49,  0,  0,  0,  0, 50,  0,  0,  0, 51,  0, 52,
+    0, 53,  0,  0,  0,  0, 54,  0,  0,  0,  0, 55,  0, 56,  0,  0,
+    0,  0, 57, 58,  0,  0,  0, 59, 60,  0,  0,  0,  0,  0,  0, 61,
+   52,  0, 62, 63,  0,  0, 64,  0,  0,  0, 65, 66,  0,  0,  0, 67,
+    0, 68, 69, 70, 71, 72,  1, 73,  0, 74, 75, 76,  0,  0, 77, 78,
+    0,  0,  0, 79,  0,  0,  1,  1,  0,  0, 80,  0,  0, 81,  0,  0,
+    0,  0, 77, 82,  0, 83,  0,  0,  0,  0,  0, 78, 84,  0, 85,  0,
+   52,  0,  1, 78,  0,  0, 86,  0,  0, 87,  0,  0,  0,  0,  0, 88,
+   57,  0,  0,  0,  0,  0,  0, 89, 90,  0,  0, 84,  0,  0, 33,  0,
+    0, 91,  0,  0,  0,  0, 92,  0,  0,  0,  0, 49,  0,  0, 93,  0,
+    0,  0,  0, 94, 95,  0,  0, 96,  0,  0, 97,  0,  0,  0, 98,  0,
+    0,  0, 99,  0,  0,  0,100,  0,  0,  0,  0,101,102, 93,  0,  0,
+  103,  0,  0,  0, 84,  0,  0,104,  0,  0,  0,105,106,  0,  0,107,
+  108,  0,  0,  0,  0,  0,  0,109,  0,  0,110,  0,  0,  0,  0,111,
+   33,  0,112,113,114, 57,  0,  0,115, 35,  0,  0,116,  0,  0,  0,
+  117,  0,  0,  0,  0,  0,  0,118,  0,  0,119,  0,  0,  0,  0,120,
+   88,  0,  0,  0,  0,  0, 57,  0,  0,  0,  0, 52,121,  0,  0,  0,
+    0,122,  0,  0,123,  0,  0,  0,  0,121,  0,  0,124,  0,  0,  0,
+    0,  0, 79,  0,  0,  0,  0,125,  0,  0,  0,126,  0,  0,  0,127,
+    0,128,  0,  0,  0,  0,129,130,131,  0,132,  0,133,  0,  0,  0,
+  134,135,136,  0, 77,  0,  0,  0,  0,  0, 35,  0,  0,  0,137,  0,
+    0,  0,138,  0,  0,  0,139,  0,  0,140,  0,  0,141,  0,  0,  0,
+    0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  3,  4,  5,  6,  7,  4,
+    4,  8,  9, 10,  1, 11, 12, 13, 14, 15, 16, 17, 18,  1,  1,  1,
+   19,  1,  0,  0, 20, 21, 22,  1, 23,  4, 21, 24, 25, 26, 27, 28,
+   29, 30,  0,  0,  1,  1, 31,  0,  0,  0, 32, 33, 34, 35,  1, 36,
+   37,  0,  0,  0,  0, 38,  1, 39, 14, 39, 40, 41, 42,  0,  0,  0,
+   43, 36, 44, 45, 21, 45, 46,  0,  0,  0, 19,  1, 21,  0,  0, 47,
+    0, 38, 48,  1,  1, 49, 49, 50,  0,  0, 51,  0,  0, 19, 52,  1,
+    0,  0, 38, 14,  4,  1,  1,  1, 53, 21, 43, 52, 54, 21, 35,  1,
+    0,  0,  0, 55,  0,  0,  0, 56, 57, 58,  0,  0,  0,  0,  0, 59,
+    0, 60,  0,  0,  0,  0, 61, 62,  0,  0, 63,  0,  0,  0, 64,  0,
+    0,  0, 65,  0,  0,  0, 66,  0,  0,  0, 67,  0,  0,  0, 68,  0,
+    0, 69, 70,  0, 71, 72, 73, 74, 75, 76,  0,  0,  0, 77,  0,  0,
+    0, 78, 79,  0,  0,  0,  0, 47,  0,  0,  0, 49,  0, 80,  0,  0,
+    0, 62,  0,  0, 63,  0,  0, 81,  0,  0, 82,  0,  0,  0, 83,  0,
+    0, 19, 84,  0, 62,  0,  0,  0,  0, 49,  1, 85,  1, 52, 15, 86,
+   36, 10, 21, 87,  0, 55,  0,  0,  0,  0, 19, 10,  1,  0,  0,  0,
+    0,  0, 88,  0,  0, 89,  0,  0, 88,  0,  0,  0,  0, 78,  0,  0,
+   87,  9, 12,  4, 90,  8, 91, 47,  0, 58, 50,  0, 21,  1, 21, 92,
+   93,  1,  1,  1,  1, 94, 95, 96, 97,  1, 98, 58, 81, 99,100,  4,
+   58,  0,  0,  0,  0,  0,  0, 19, 50,  0,  0,  0,  0,  0,  0, 61,
+    0,  0,101,102,  0,  0,103,  0,  0,  1,  1, 50,  0,  0,  0, 38,
+    0, 63,  0,  0,  0,  0,  0, 62,  0,  0,104, 68, 61,  0,  0,  0,
+   78,  0,  0,  0,105,106, 58, 38, 81,  0,  0,  0,  0,  0,  0,107,
+    1, 14,  4, 12, 84,  0,  0,  0,  0, 38, 87,  0,  0,  0,  0,108,
+    0,  0,109, 61,  0,110,  0,  0,  0,  1,  0,  0,  0,  0, 49, 50,
     0,  0, 19, 58,  0,  0,  0, 51,  0,111, 14, 52,112, 41,  0,  0,
    62,  0,  0, 61,  0,  0,113,  0, 87,  0,  0,  0, 61, 62,  0,  0,
    62,  0, 89,  0,  0,113,  0,  0,  0,  0,114,  0,  0,  0, 78, 55,
-    0, 38,  1, 58,  1, 58,  0,  0, 63, 89,  0,  0,115,  0,  0,  0,
-   55,  0,  0,  0,  0,115,  0,  0,  0,  0, 61,  0,  0,  0,  0, 79,
-    0, 61,  0,  0,  0,  0, 56,  0, 89, 80,  0,  0, 79,  0,  0,  0,
-    8, 91,  0,  0,  1, 87,  0,  0,116,  0,  0,  0,  0,  0,  0,117,
-    0,118,119,120,121,  0,104,  4,122, 49, 23,  0,  0,  0, 38, 50,
-   38, 58,  0,  0,  1, 87,  1,  1,  1,  1, 39,  1, 48,105, 87,  0,
-    0,  0,  0,  1,  0,  0,  0,123,  4,122,  0,  0,  0,  1,124,  0,
-    0,  0,  0,  0,230,230,230,230,230,232,220,220,220,220,232,216,
-  220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220,
-    1,  1,  1,  1,  1,220,220,220,220,230,230,230,230,240,230,220,
-  220,220,230,230,230,220,220,  0,230,230,230,220,220,220,220,230,
-  232,220,220,230,233,234,234,233,234,234,233,230,  0,  0,  0,230,
-    0,220,230,230,230,230,220,230,230,230,222,220,230,230,220,220,
-  230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20,
-   21, 22,  0, 23,  0, 24, 25,  0,230,220,  0, 18, 30, 31, 32,  0,
-    0,  0,  0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230,
-  220,230,230,220, 35,  0,  0,  0,  0,  0,230,230,230,  0,  0,230,
-  230,  0,220,230,230,220,  0,  0,  0, 36,  0,  0,230,220,230,230,
-  220,220,230,220,220,230,220,230,220,230,230,  0,  0,220,  0,  0,
-  230,230,  0,230,  0,230,230,230,230,230,  0,  0,  0,220,220,220,
-  230,220,220,220,230,230,  0,220, 27, 28, 29,230,  7,  0,  0,  0,
-    0,  9,  0,  0,  0,230,220,230,230,  0,  0,  0,  0,  0,230,  0,
-    0, 84, 91,  0,  0,  0,  0,  9,  9,  0,  0,  0,  0,  0,  9,  0,
-  103,103,  9,  0,107,107,107,107,118,118,  9,  0,122,122,122,122,
-  220,220,  0,  0,  0,220,  0,220,  0,216,  0,  0,  0,129,130,  0,
-  132,  0,  0,  0,  0,  0,130,130,130,130,  0,  0,130,  0,230,230,
-    9,  0,230,230,  0,  0,220,  0,  0,  0,  0,  7,  0,  9,  9,  0,
-    9,  9,  0,  0,  0,230,  0,  0,  0,228,  0,  0,  0,222,230,220,
-  220,  0,  0,  0,230,  0,  0,220,230,220,  0,220,230,230,230,  0,
-    0,  0,  9,  9,  0,  0,  7,  0,230,  0,  1,  1,  1,  0,  0,  0,
-  230,234,214,220,202,230,230,230,230,230,232,228,228,220,218,230,
-  233,220,230,220,230,230,  1,  1,  1,  1,  1,230,  0,  1,  1,230,
-  220,230,  1,  1,  0,  0,218,228,232,222,224,224,  0,  8,  8,  0,
-    0,  0,  0,220,230,  0,230,230,220,  0,  0,230,  0,  0, 26,  0,
-    0,220,  0,230,230,  1,220,  0,  0,230,220,  0,  0,  0,220,220,
-    0,  0,230,220,  0,  9,  7,  0,  0,  7,  9,  0,  0,  0,  9,  7,
-    6,  6,  0,  0,  0,  0,  1,  0,  0,216,216,  1,  1,  1,  0,  0,
-    0,226,216,216,216,216,216,  0,220,220,220,  0,232,232,220,230,
-  230,230,  7,  0, 16, 17, 17, 33, 17, 49, 17, 17, 84, 97,135,145,
-   26, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+    0, 38,  1, 58,  1, 58,  0,  0,  0,  0,  0, 88, 63, 89,  0,  0,
+  115,  0,  0,  0, 55,  0,  0,  0,  0,115,  0,  0,  0,  0, 61,  0,
+    0,  0,  0, 79,  0, 61,  0,  0,  0,  0, 56,  0, 89, 80,  0,  0,
+   79,  0,  0,  0,  8, 91,  0,  0,  1, 87,  0,  0,116,  0,  0,  0,
+    0,  0,  0,117,  0,118,119,120,121,  0,104,  4,122, 49, 23,  0,
+    0,  0, 38, 50, 38, 58,  0,  0,  1, 87,  1,  1,  1,  1, 39,  1,
+   48,105, 87,  0,  0,  0,  0,  1,  0,  0,  0,123,  0,  0,  0,112,
+    4,122,  0,  0,  0,  1,124,  0,  0,  0,  0,  0,230,230,230,230,
+  230,232,220,220,220,220,232,216,220,220,220,220,220,202,202,220,
+  220,220,220,202,202,220,220,220,  1,  1,  1,  1,  1,220,220,220,
+  220,230,230,230,230,240,230,220,220,220,230,230,230,220,220,  0,
+  230,230,230,220,220,220,220,230,232,220,220,230,233,234,234,233,
+  234,234,233,230,  0,  0,  0,230,  0,220,230,230,230,230,220,230,
+  230,230,222,220,230,230,220,220,230,222,228,230, 10, 11, 12, 13,
+   14, 15, 16, 17, 18, 19, 19, 20, 21, 22,  0, 23,  0, 24, 25,  0,
+  230,220,  0, 18, 30, 31, 32,  0,  0,  0,  0, 27, 28, 29, 30, 31,
+   32, 33, 34,230,230,220,220,230,220,230,230,220, 35,  0,  0,  0,
+    0,  0,230,230,230,  0,  0,230,230,  0,220,230,230,220,  0,  0,
+    0, 36,  0,  0,230,220,230,230,220,220,230,220,220,230,220,230,
+  220,230,230,  0,  0,220,  0,  0,230,230,  0,230,  0,230,230,230,
+  230,230,  0,  0,  0,220,220,220,230,220,220,220,230,230,  0,220,
+   27, 28, 29,230,  7,  0,  0,  0,  0,  9,  0,  0,  0,230,220,230,
+  230,  0,  0,  0,  0,  0,230,  0,  0, 84, 91,  0,  0,  0,  0,  9,
+    9,  0,  0,  0,  0,  0,  9,  0,103,103,  9,  0,107,107,107,107,
+  118,118,  9,  0,122,122,122,122,220,220,  0,  0,  0,220,  0,220,
+    0,216,  0,  0,  0,129,130,  0,132,  0,  0,  0,  0,  0,130,130,
+  130,130,  0,  0,130,  0,230,230,  9,  0,230,230,  0,  0,220,  0,
+    0,  0,  0,  7,  0,  9,  9,  0,  9,  9,  0,  0,  0,230,  0,  0,
+    0,228,  0,  0,  0,222,230,220,220,  0,  0,  0,230,  0,  0,220,
+  230,220,  0,220,230,230,230,  0,  0,  0,  9,  9,  0,  0,  7,  0,
+  230,  0,  1,  1,  1,  0,  0,  0,230,234,214,220,202,230,230,230,
+  230,230,232,228,228,220,218,230,233,220,230,220,230,230,  1,  1,
+    1,  1,  1,230,  0,  1,  1,230,220,230,  1,  1,  0,  0,218,228,
+  232,222,224,224,  0,  8,  8,  0,  0,  0,  0,220,230,  0,230,230,
+  220,  0,  0,230,  0,  0, 26,  0,  0,220,  0,230,230,  1,220,  0,
+    0,230,220,  0,  0,  0,220,220,  0,  0,230,220,  0,  9,  7,  0,
+    0,  7,  9,  0,  0,  0,  9,  7,  6,  6,  0,  0,  0,  0,  1,  0,
+    0,216,216,  1,  1,  1,  0,  0,  0,226,216,216,216,216,216,  0,
+  220,220,220,  0,232,232,220,230,230,230,  7,  0, 16, 17, 17, 33,
+   17, 49, 17, 17, 84, 97,135,145, 26, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-   17, 17, 17,177,  0,  1,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-    3,  3,  3,  3,  3,  3,  3,  3,  4,  3,  3,  3,  3,  3,  5,  3,
-    3,  3,  3,  3,  6,  7,  8,  3,  3,  3,  3,  3,  9, 10, 11, 12,
-   13,  3,  3,  3,  3,  3,  3,  3,  3, 14,  3, 15,  3,  3,  3,  3,
-    3,  3, 16, 17, 18, 19, 20, 21,  3,  3,  3, 22, 23, 24,  3,  3,
-    3,  3,  3,  3, 25,  3,  3,  3,  3,  3,  3,  3,  3, 26,  3,  3,
-   27, 28,  0,  1,  0,  0,  0,  0,  0,  1,  0,  2,  0,  0,  0,  3,
-    0,  0,  0,  3,  0,  0,  0,  0,  0,  4,  0,  5,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  6,  0,  0,  0,  7,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  8,  9,  0,  0,  0,
-    0,  0,  0,  9,  0,  9,  0,  0,  0,  0,  0,  0,  0, 10, 11, 12,
-   13,  0,  0, 14, 15, 16,  6,  0, 17, 18, 19, 19, 19, 20, 21, 22,
-   23, 24, 19, 25,  0, 26, 27, 19, 19, 28, 29, 30,  0, 31,  0,  0,
-    0,  8,  0,  0,  0,  0,  0,  0,  0, 19, 28,  0, 32, 33,  9, 34,
-   35, 19,  0,  0, 36, 37, 38, 39, 40, 19,  0, 41, 42, 43, 44, 31,
-    0,  1, 45, 42,  0,  0,  0,  0,  0, 32, 14, 14,  0,  0,  0,  0,
-   14,  0,  0, 46, 47, 47, 47, 47, 48, 49, 47, 47, 47, 47, 50, 51,
-   52, 53, 43, 21,  0,  0,  0,  0,  0,  0,  0, 54,  6, 55,  0, 14,
-   19,  1,  0,  0,  0,  0, 56, 57,  0,  0,  0,  0,  0, 19, 58, 31,
-    0,  0,  0,  0,  0,  0,  0, 59, 14,  0,  0,  0,  0,  1,  0,  2,
-    0,  0,  0,  3,  0,  0,  0, 60, 61,  0,  0,  0,  0,  0,  0,  0,
-    1,  0,  0,  0,  0,  0,  2,  3,  0,  4,  5,  0,  0,  6,  0,  0,
-    0,  7,  0,  0,  0,  1,  1,  0,  0,  8,  9,  0,  8,  9,  0,  0,
-    0,  0,  8,  9, 10, 11, 12,  0,  0,  0, 13,  0,  0,  0,  0, 14,
-   15, 16, 17,  0,  0,  0,  1,  0,  0, 18, 19,  0,  0,  0, 20,  0,
-    0,  0,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  0,  8,
-   21,  9,  0,  0, 22,  0,  0,  0,  0,  1,  0, 23, 24, 25,  0,  0,
-   26,  0,  0,  0,  8, 21, 27,  0,  1,  0,  0,  1,  1,  1,  1,  0,
-    1, 28, 29, 30,  0, 31, 32, 20,  1,  1,  0,  0,  0,  8, 21,  9,
-    1,  4,  5,  0,  0,  0, 33,  9,  0,  1,  1,  1,  0,  8, 21, 21,
-   21, 21, 34,  1, 35, 21, 21, 21,  9, 36,  0,  0, 37, 38,  1,  0,
-   39,  0,  0,  0,  1,  0,  1,  0,  0,  0,  0,  8, 21,  9,  1,  0,
-    0,  0, 40,  0,  8, 21, 21, 21, 21, 21, 21, 21, 21,  9,  0,  1,
-    1,  1,  1,  8, 21, 21, 21,  9,  0,  0,  0, 41,  0, 42, 43,  0,
-    0,  0,  1, 44,  0,  0,  0, 45,  8,  9,  1,  0,  0,  0,  8, 21,
-   21, 21,  9,  0,  1,  0,  1,  1,  8, 21, 21,  9,  0,  4,  5,  8,
-    9,  1,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,
-    7,  7,  7,  7,  7,  7,  7,  7,  9, 10, 11, 11, 11, 11, 12, 13,
-   13, 13, 13, 14, 15, 16, 17, 18, 19, 20, 21, 13, 22, 13, 13, 13,
-   13, 23, 24, 24, 25, 26, 13, 13, 13, 27, 28, 29, 13, 30, 31, 32,
-   33, 34, 35, 36,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-    7,  7,  7,  7,  7,  7,  7,  7, 37,  7, 38, 39,  7, 40,  7,  7,
-    7, 41, 13, 42,  7,  7, 43,  7, 44, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-   13, 13, 13, 13, 45,  0,  0,  1,  2,  2,  2,  3,  4,  5,  6,  7,
-    8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
-   24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 37,
-   37, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
-   51, 52,  2,  2, 53, 54, 55, 56, 57, 58, 59, 59, 59, 59, 60, 59,
-   59, 59, 59, 59, 59, 59, 61, 61, 59, 59, 59, 59, 62, 63, 64, 65,
-   66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 59, 70, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-   70, 79, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81,
-   82, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 32, 32,
-   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-   32, 32, 32, 32, 32, 95, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-   96, 96, 96, 96, 96, 96, 96, 96, 70, 70, 97, 98, 99,100,101,101,
-  102,103,104,105,106,107,108,109,110,111, 96,112,113,114,115,116,
-  117,118,119,119,120,121,122,123,124,125,126,127,128,129,130,131,
-  132, 96,133,134,135,136,137,138,139,140,141,142,143, 96,144,145,
-   96,146,147,148,149, 96,150,151,152,153,154,155,156, 96,157,158,
-  159,160, 96,161,162,163,164,164,164,164,164,164,164,165,166,164,
-  167, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-   96, 96, 96, 96, 96,168,169,169,169,169,169,169,169,169,170, 96,
-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,171,171,
-  171,171,172, 96, 96, 96,173,173,173,173,174,175,176,177, 96, 96,
-   96, 96,178,179,180,181,182,182,182,182,182,182,182,182,182,182,
-  182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
-  182,182,182,182,182,183,182,182,182,182,182,182,184,184,184,185,
-  186, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-   96, 96, 96, 96, 96,187,188,189,190,191,191,192, 96, 96, 96, 96,
-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,193,194,
-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-   96, 96, 96, 96,195,196, 59,197,198,199,200,201,202, 96,203,204,
-  205, 59, 59,206, 59,207,208,208,208,208,208,209, 96, 96, 96, 96,
-   96, 96, 96, 96,210, 96,211,212,213, 96, 96,214, 96, 96, 96,215,
-   96, 96, 96, 96, 96,216,217,218,219, 96, 96, 96, 96, 96,220,221,
-  222, 96,223,224, 96, 96,225,226, 59,227,228, 96, 59, 59, 59, 59,
-   59, 59, 59,229,230,231,232,233, 59, 59,234,235, 59,236, 96, 96,
-   96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-   70, 70, 70,237, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-   70, 70, 70, 70,238, 70,239, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-   70, 70, 70,240, 70, 70, 70, 70, 70, 70, 70, 70, 70,241, 70, 70,
-   70, 70,242, 96, 96, 96, 70, 70, 70, 70,243, 96, 96, 96, 96, 96,
-   96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70,244, 70, 70, 70,
-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,245, 96, 96,
-   96, 96, 96, 96, 96, 96,246, 96,247,248,  0,  1,  2,  2,  0,  1,
-    2,  2,  2,  3,  4,  5,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19,
-   19, 19, 19, 19, 19,  0,  0,  0, 19,  0, 19,  0,  0,  0,  0,  0,
-   26, 26,  1,  1,  1,  1,  9,  9,  9,  9,  0,  9,  9,  9,  2,  2,
-    9,  9,  9,  9,  0,  9,  2,  2,  2,  2,  9,  0,  9,  0,  9,  9,
-    9,  2,  9,  2,  9,  9,  9,  9,  2,  9,  9,  9, 55, 55, 55, 55,
-   55, 55,  6,  6,  6,  6,  6,  1,  1,  6,  2,  4,  4,  4,  4,  4,
-    4,  4,  4,  4,  4,  2,  2, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-   14,  2,  2,  2,  2, 14, 14,  2,  2,  2,  3,  3,  3,  3,  3,  0,
-    3,  3,  0,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,  1,  1,  1,
-    3,  3,  1,  3,  3,  3, 37, 37, 37, 37, 37, 37,  2, 37, 37, 37,
-   37,  2,  2, 37, 37, 37, 38, 38, 38, 38, 38, 38,  2,  2, 64, 64,
-   64, 64, 64, 64, 64,  2,  2, 64, 64, 64, 90, 90, 90, 90, 90, 90,
-    2,  2, 90, 90, 90,  2, 95, 95, 95, 95,  2,  2, 95,  2,  3,  3,
-    3,  2,  3,  3,  2,  2,  3,  3,  0,  3,  7,  7,  7,  7,  7,  1,
-    1,  1,  1,  7,  7,  7,  0,  0,  7,  7,  5,  5,  5,  5,  2,  5,
-    5,  5,  5,  2,  2,  5,  5,  2,  5,  5,  5,  2,  5,  2,  2,  2,
-    5,  5,  5,  5,  2,  2,  5,  5,  5,  2,  2,  2,  2,  5,  5,  5,
-    2,  5,  2, 11, 11, 11, 11, 11, 11,  2,  2,  2,  2, 11, 11,  2,
-    2, 11, 11, 11, 11, 11, 11,  2, 11, 11,  2, 11, 11,  2, 11, 11,
-    2,  2,  2, 11,  2,  2, 11,  2, 11,  2,  2,  2, 11, 11,  2, 10,
-   10, 10, 10, 10, 10, 10, 10, 10,  2, 10, 10,  2, 10, 10, 10, 10,
-    2,  2, 10,  2,  2,  2,  2,  2, 10, 10,  2, 21, 21, 21, 21, 21,
-   21, 21, 21,  2,  2, 21, 21,  2, 21, 21, 21, 21,  2,  2, 21, 21,
-    2, 21,  2,  2, 21, 21,  2,  2, 22, 22,  2, 22, 22, 22, 22, 22,
-   22,  2, 22,  2, 22, 22, 22, 22,  2,  2,  2, 22, 22,  2,  2,  2,
-    2, 22, 22,  2,  2,  2, 22, 22, 22, 22, 23, 23, 23, 23, 23,  2,
-   23, 23, 23, 23,  2,  2,  2, 23, 23,  2, 23, 23, 23,  2,  2, 23,
-    2,  2,  2,  2, 23, 23,  2,  2,  2, 23, 16, 16, 16, 16, 16,  2,
-   16, 16,  2, 16, 16, 16, 16, 16,  2,  2,  2, 16, 16,  2,  2,  2,
-   16, 16, 20, 20, 20, 20, 20,  2, 20, 20,  2,  2, 20, 20,  2, 36,
-   36, 36, 36, 36, 36, 36, 36, 36, 36,  2,  2,  2, 36, 36, 36, 36,
-    2, 36,  2, 36,  2,  2,  2,  2, 36,  2,  2,  2,  2, 36, 36,  2,
-   36,  2, 36,  2,  2,  2,  2, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-   24,  2,  2,  2,  2,  0,  2, 18, 18,  2, 18,  2, 18, 18, 18, 18,
-   18,  2, 18, 18, 18, 18,  2, 18,  2, 18, 18, 18,  2,  2, 18,  2,
-   18,  2, 25, 25, 25, 25,  2, 25, 25, 25, 25,  2,  2,  2, 25,  2,
-   25, 25, 25,  0,  0,  0,  0, 25, 25,  2, 33, 33, 33, 33,  8,  8,
-    8,  8,  8,  8,  2,  8,  2,  8,  2,  2,  8,  8,  8,  0, 12, 12,
-   12, 12, 30, 30, 30, 30, 30,  2, 30, 30, 30, 30,  2,  2, 30, 30,
-   30,  2,  2, 30, 30, 30, 30,  2,  2,  2, 29, 29, 29, 29, 29, 29,
-    2,  2, 28, 28, 28, 28, 34, 34, 34, 34, 34,  2,  2,  2, 35, 35,
-   35, 35, 35, 35, 35,  0,  0,  0, 35, 35, 35,  2,  2,  2, 45, 45,
-   45, 45, 45, 45,  2,  2,  2,  2,  2, 45, 44, 44, 44, 44, 44,  0,
-    0,  2, 43, 43, 43, 43, 46, 46, 46, 46, 46,  2, 46, 46, 31, 31,
-   31, 31, 31, 31,  2,  2, 32, 32,  0,  0, 32,  0, 32, 32, 32, 32,
-   32, 32, 32, 32,  2,  2, 32,  2,  2,  2, 32, 32, 32,  2, 28, 28,
-    2,  2, 48, 48, 48, 48, 48, 48, 48,  2, 48,  2,  2,  2, 52, 52,
-   52, 52, 52, 52,  2,  2, 52,  2,  2,  2, 58, 58, 58, 58, 58, 58,
-    2,  2, 58, 58, 58,  2,  2,  2, 58, 58, 54, 54, 54, 54,  2,  2,
-   54, 54, 91, 91, 91, 91, 91, 91, 91,  2, 91,  2,  2, 91, 91, 91,
-    2,  2,  1,  1,  1,  2, 62, 62, 62, 62, 62,  2,  2,  2, 62, 62,
-   62,  2, 76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70,  2,  2,
-    2, 70, 70, 70,  2,  2,  2, 70, 70, 70, 73, 73, 73, 73,  6,  2,
-    2,  2,  8,  8,  8,  2,  2,  8,  8,  8,  1,  1,  1,  0,  1,  0,
-    1,  1,  1,  0,  0,  0,  0,  1,  0,  0,  1,  1,  0,  2, 19, 19,
-    9,  9,  9,  9,  9,  6, 19,  9,  9,  9,  9,  9, 19, 19,  9,  9,
-    9, 19,  6, 19, 19, 19, 19, 19, 19,  9,  9,  9,  2,  2,  2,  9,
-    2,  9,  2,  9,  9,  9,  1,  1,  0,  0,  0,  2,  0,  0,  0, 19,
-    2,  2,  0,  0,  0, 19,  0,  0,  0,  2, 19,  2,  2,  2,  0,  2,
-    2,  2,  1,  2,  2,  2,  0,  0,  9,  0,  0,  0, 19, 19, 27, 27,
-   27, 27,  2,  2,  0,  0,  0,  0,  2,  0, 56, 56, 56, 56,  2, 55,
-   55, 55, 61, 61, 61, 61,  2,  2,  2, 61, 61,  2,  2,  2,  0,  0,
-    2,  2, 13, 13, 13, 13, 13, 13,  2, 13, 13, 13,  2,  2,  0, 13,
-    0, 13,  0, 13, 13, 13, 13, 13,  1,  1,  1,  1, 12, 12,  2, 15,
-   15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,  1,  1,  0,  0, 15,
-   15, 15,  0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,  0,  2, 26,
-   26, 26, 26, 26, 26, 26,  2, 12, 12, 12, 12, 12, 12,  2, 12, 12,
-   12,  0, 39, 39, 39, 39, 39,  2,  2,  2, 39, 39, 39,  2, 86, 86,
-   86, 86, 77, 77, 77, 77, 79, 79, 79, 79, 19, 19, 19,  2, 19, 19,
-    2, 19,  2, 19, 19, 19, 19, 19,  2,  2,  2,  2, 19, 19, 60, 60,
-   60, 60, 60,  2,  2,  2, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75,
-    2,  2,  2,  2, 75, 75, 69, 69, 69, 69, 69, 69,  0, 69, 74, 74,
-   74, 74,  2,  2,  2, 74, 12,  2,  2,  2, 84, 84, 84, 84, 84, 84,
-    2,  0, 84, 84,  2,  2,  2,  2, 84, 84, 33, 33, 33,  2, 68, 68,
-   68, 68, 68, 68, 68,  2, 68, 68,  2,  2, 92, 92, 92, 92, 92, 92,
-   92,  2,  2,  2,  2, 92, 87, 87, 87, 87, 87, 87, 87,  2, 19,  9,
-   19, 19, 19, 19,  0,  0, 87, 87,  2,  2,  2,  2,  2, 12,  2,  2,
-    2,  4, 14,  2, 14,  2, 14, 14,  2, 14, 14,  2, 14, 14,  2,  2,
-    2,  3,  3,  3,  0,  0,  2,  2,  3,  3,  1,  1,  6,  6,  3,  2,
-    3,  3,  3,  2,  2,  0,  2,  0,  0,  0,  0,  0, 17, 17, 17, 17,
-    0,  0,  2,  2, 12, 12, 49, 49, 49, 49,  2, 49, 49, 49, 49, 49,
-   49,  2, 49, 49,  2, 49, 49, 49,  2,  2,  9,  2,  2,  2,  0,  1,
-    2,  2, 71, 71, 71, 71, 71,  2,  2,  2, 67, 67, 67, 67, 67,  2,
-    2,  2, 42, 42, 42, 42,  2, 42, 42, 42, 41, 41, 41, 41, 41, 41,
-   41,  2,118,118,118,118,118,118,118,  2, 53, 53, 53, 53, 53, 53,
-    2, 53, 59, 59, 59, 59, 59, 59,  2,  2, 40, 40, 40, 40, 51, 51,
-   51, 51, 50, 50, 50, 50, 50, 50,  2,  2,135,135,135,135,106,106,
-  106,106,104,104,104,104,  2,  2,  2,104,161,161,161,161,161,161,
-  161,  2,161,161,  2,161,161,  2,  2,  2,110,110,110,110,110,110,
-  110,  2,110,110,  2,  2, 19,  2, 19, 19, 47, 47, 47, 47, 47, 47,
-    2,  2, 47,  2, 47, 47, 47, 47,  2, 47, 47,  2,  2,  2, 47,  2,
-    2, 47, 81, 81, 81, 81, 81, 81,  2, 81,120,120,120,120,116,116,
-  116,116,116,116,116,  2,  2,  2,  2,116,128,128,128,128,128,128,
-  128,  2,128,128,  2,  2,  2,  2,  2,128, 66, 66, 66, 66,  2,  2,
-    2, 66, 72, 72, 72, 72, 72, 72,  2,  2,  2,  2,  2, 72, 98, 98,
-   98, 98, 97, 97, 97, 97,  2,  2, 97, 97, 57, 57, 57, 57,  2, 57,
-   57,  2,  2, 57, 57, 57, 57, 57,  2,  2, 57, 57, 57,  2,  2,  2,
-    2, 57, 57,  2,  2,  2, 88, 88, 88, 88,117,117,117,117,112,112,
-  112,112,112,112,112,  2,  2,  2,  2,112, 78, 78, 78, 78, 78, 78,
-    2,  2,  2, 78, 78, 78, 83, 83, 83, 83, 83, 83,  2,  2, 82, 82,
-   82, 82, 82, 82, 82,  2,122,122,122,122,122,122,  2,  2,  2,122,
-  122,122,122,  2,  2,  2, 89, 89, 89, 89, 89,  2,  2,  2,130,130,
-  130,130,130,130,130,  2,  2,  2,130,130,144,144,144,144,144,144,
-    2,  2,156,156,156,156,156,156,  2,156,156,156,  2,  2,  2,  3,
-    3,  3,147,147,147,147,148,148,148,148,148,148,  2,  2,158,158,
-  158,158,158,158,  2,  2,153,153,153,153,149,149,149,149,149,149,
-  149,  2, 94, 94, 94, 94, 94, 94,  2,  2,  2,  2, 94, 94,  2,  2,
-    2, 94, 85, 85, 85, 85, 85, 85, 85,  2,  2, 85,  2,  2,101,101,
-  101,101,101,  2,  2,  2,101,101,  2,  2, 96, 96, 96, 96, 96,  2,
-   96, 96,111,111,111,111,111,111,111,  2,100,100,100,100,108,108,
-  108,108,108,108,  2,108,108,108,  2,  2,129,129,129,129,129,129,
-  129,  2,129,  2,129,129,129,129,  2,129,129,129,  2,  2,109,109,
-  109,109,109,109,109,  2,109,109,  2,  2,107,107,107,107,  2,107,
-  107,107,107,  2,  2,107,107,  2,107,107,107,107,  2,  1,107,107,
-    2,  2,107,  2,  2,  2,  2,  2,  2,107,  2,  2,107,107,137,137,
-  137,137,  2,137,137,137,137,137,  2,  2,124,124,124,124,124,124,
-    2,  2,123,123,123,123,123,123,  2,  2,114,114,114,114,114,  2,
-    2,  2,114,114,  2,  2,102,102,102,102,102,102,  2,  2,126,126,
-  126,126,126,126,126,  2,  2,126,126,126,142,142,142,142,125,125,
-  125,125,125,125,125,  2,  2,  2,  2,125,154,154,154,154,154,154,
-  154,  2,  2,154,  2,  2,  2,154,154,  2,154,154,  2,154,154,  2,
-    2,154,154,154,  2,  2,150,150,150,150,  2,  2,150,150,150,  2,
-    2,  2,141,141,141,141,140,140,140,140,140,140,140,  2,121,121,
-  121,121,121,  2,  2,  2,  7,  7,  2,  2,133,133,133,133,133,  2,
-  133,133,133,133,133,  2,133,133,  2,  2,133,  2,  2,  2,134,134,
-  134,134,  2,  2,134,134,  2,134,134,134,134,134,134,  2,138,138,
-  138,138,138,138,138,  2,138,138,  2,138,  2,  2,138,  2,138,138,
-    2,  2,143,143,143,143,143,143,  2,143,143,  2,143,143,143,143,
-  143,  2,143,  2,  2,  2,143,143,  2,  2,145,145,145,145,145,  2,
-    2,  2,163,163,163,163,163,  2,163,163,163,163,163,  2,  2,  2,
-  163,163,163,163,  2,  2, 86,  2,  2,  2, 63, 63, 63, 63, 63, 63,
-    2,  2, 63, 63, 63,  2, 63,  2,  2,  2,157,157,157,157,157,157,
-  157,  2, 80, 80, 80, 80, 80, 80,  2,  2,127,127,127,127,127,127,
-  127,  2, 79,  2,  2,  2,115,115,115,115,115,115,115,  2,115,115,
-    2,  2,  2,  2,115,115,159,159,159,159,159,159,159,  2,159,159,
-    2,  2,103,103,103,103,103,103,  2,  2,119,119,119,119,119,119,
-    2,  2,119,119,  2,119,  2,119,119,119,146,146,146,146,146,146,
-  146,  2, 99, 99, 99, 99, 99, 99, 99,  2,  2,  2,  2, 99,136,139,
-   13, 13,155,  2,  2,  2,136,136,136,136,155,155,155,155,155,155,
-    2,  2,136,  2,  2,  2,  2, 17, 17, 17,  2, 17, 17,  2, 17, 15,
-   15, 15, 17, 17, 17,  2,  2,  2, 15,  2,  2, 17,  2,  2,139,139,
-  139,139,105,105,105,105,105,105,105,  2,105,  2,  2,  2,105,105,
-    2,  2,  1,  1,  2,  2,  0,  0,  0,  1,  0,  1,  1,  1,  0,  0,
-    1,  1,  2,  2,  0,  2,  2,  0,  0,  2,  0,  2,  0,  2,131,131,
-  131,131,  2,  2,  2,131,  2,131,131,131, 56, 56, 56,  2, 56,  2,
-    2, 56, 56, 56,  2, 56, 56,  2, 56, 56,  6,  6,  2,  2,  2,  2,
-    2,  6,151,151,151,151,151,  2,  2,  2,151,151,  2,  2,  2,  2,
-  151,151,160,160,160,160,160,160,160,  2,152,152,152,152,152,152,
-    2,  2,  2,  2,  2,152,164,164,164,164,164,164,  2,  2,  2, 30,
-   30,  2,113,113,113,113,113,  2,  2,113,113,113,113,  2,132,132,
-  132,132,132,132,  2,  2,  2,  2,132,132,  2,  3,  3,  2,  3,  2,
-    2,  3,  2,  3,  2,  3,  2,  2,  3,  2,  3,  2,  3,  2,  3,  3,
-    2,  3, 15,  0,  0,  2, 13,  2,  2,  2, 13, 13, 13,  2,  2,  0,
-    2,  2,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  9,  9,  9, 10,
-    9, 11, 12, 13,  9,  9,  9, 14,  9,  9, 15,  9,  9,  9,  9,  9,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,177,  0,  1,  2,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+    4,  3,  3,  3,  3,  3,  5,  3,  3,  3,  3,  3,  6,  7,  8,  3,
+    3,  3,  3,  3,  9, 10, 11, 12, 13,  3,  3,  3,  3,  3,  3,  3,
+    3, 14,  3, 15,  3,  3,  3,  3,  3,  3, 16, 17, 18, 19, 20, 21,
+    3,  3,  3, 22, 23, 24,  3,  3,  3,  3,  3,  3, 25,  3,  3,  3,
+    3,  3,  3,  3,  3, 26,  3,  3, 27, 28,  0,  1,  0,  0,  0,  0,
+    0,  1,  0,  2,  0,  0,  0,  3,  0,  0,  0,  3,  0,  0,  0,  0,
+    0,  4,  0,  5,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  6,  0,  0,  0,  7,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  8,  9,  0,  0,  0,  0,  0,  0,  9,  0,  9,  0,  0,
+    0,  0,  0,  0,  0, 10, 11, 12, 13,  0,  0, 14, 15, 16,  6,  0,
+   17, 18, 19, 19, 19, 20, 21, 22, 23, 24, 19, 25,  0, 26, 27, 19,
+   19, 28, 29, 30,  0, 31,  0,  0,  0,  8,  0,  0,  0,  0,  0,  0,
+    0, 19, 28,  0, 32, 33,  9, 34, 35, 19,  0,  0, 36, 37, 38, 39,
+   40, 19,  0, 41, 42, 43, 44, 31,  0,  1, 45, 42,  0,  0,  0,  0,
+    0, 32, 14, 14,  0,  0,  0,  0, 14,  0,  0, 46, 47, 47, 47, 47,
+   48, 49, 47, 47, 47, 47, 50, 51, 52, 53, 43, 21,  0,  0,  0,  0,
+    0,  0,  0, 54,  6, 55,  0, 14, 19,  1,  0,  0,  0,  0, 56, 57,
+    0,  0,  0,  0,  0, 19, 58, 31,  0,  0,  0,  0,  0,  0,  0, 59,
+   14,  0,  0,  0,  0,  1,  0,  2,  0,  0,  0,  3,  0,  0,  0, 60,
+   61,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  2,  3,
+    0,  4,  5,  0,  0,  6,  0,  0,  0,  7,  0,  0,  0,  1,  1,  0,
+    0,  8,  9,  0,  8,  9,  0,  0,  0,  0,  8,  9, 10, 11, 12,  0,
+    0,  0, 13,  0,  0,  0,  0, 14, 15, 16, 17,  0,  0,  0,  1,  0,
+    0, 18, 19,  0,  0,  0, 20,  0,  0,  0,  1,  1,  1,  1,  0,  1,
+    1,  1,  1,  1,  1,  1,  0,  8, 21,  9,  0,  0, 22,  0,  0,  0,
+    0,  1,  0, 23, 24, 25,  0,  0, 26,  0,  0,  0,  8, 21, 27,  0,
+    1,  0,  0,  1,  1,  1,  1,  0,  1, 28, 29, 30,  0, 31, 32, 20,
+    1,  1,  0,  0,  0,  8, 21,  9,  1,  4,  5,  0,  0,  0, 33,  9,
+    0,  1,  1,  1,  0,  8, 21, 21, 21, 21, 34,  1, 35, 21, 21, 21,
+    9, 36,  0,  0, 37, 38,  1,  0, 39,  0,  0,  0,  1,  0,  1,  0,
+    0,  0,  0,  8, 21,  9,  1,  0,  0,  0, 40,  0,  8, 21, 21, 21,
+   21, 21, 21, 21, 21,  9,  0,  1,  1,  1,  1,  8, 21, 21, 21,  9,
+    0,  0,  0, 41,  0, 42, 43,  0,  0,  0,  1, 44,  0,  0,  0, 45,
+    8,  9,  1,  0,  0,  0,  8, 21, 21, 21,  9,  0,  1,  0,  1,  1,
+    8, 21, 21,  9,  0,  4,  5,  8,  9,  1,  0,  0,  0,  1,  2,  3,
+    4,  5,  5,  5,  5,  5,  6,  7,  7,  8,  9, 10, 11, 12, 13, 14,
+   15,  9, 16, 17, 18,  9, 19, 20, 21, 22, 23, 24,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5, 25, 26, 27,  5, 28, 29,  5, 30, 31,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 32,  0,  0,  1,
+    2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
+   18, 19, 20, 20, 21, 22, 23, 24, 25, 26, 27, 28,  1, 29, 30, 31,
+   32, 32, 33, 32, 32, 32, 34, 32, 32, 35, 36, 37, 38, 39, 40, 41,
+   42, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+   44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 44, 44, 44, 44,
+   44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 46, 46,
+   46, 46, 47, 48, 49, 50, 51, 52, 53, 54, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+   56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+   56, 56, 56, 56, 56, 56, 56, 44, 57, 58, 59, 60, 61, 62, 63, 64,
+   65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+   81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 95,
+   95, 96, 97, 98, 56, 56, 56, 56, 56, 56, 56, 56, 56, 99,100,100,
+  100,100,101,100,100,100,100,100,100,100,100,100,100,100,100,100,
+  100,102,103,103,104, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,105,
+   56, 56, 56, 56, 56, 56,106,106,107,108, 56,109,110,111,112,112,
+  112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
+  112,112,112,112,112,113,112,112,112,114,115,116, 56, 56, 56, 56,
+   56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,117,118,119,
+  120, 56, 56, 56, 56, 56, 56, 56, 56, 56,121, 56, 56, 56, 56, 56,
+   56, 56, 56, 56, 56, 56, 56, 56, 56, 56,122, 32,123,124,125,126,
+  127,128,129,130,131,132,133,133,134, 56, 56, 56, 56,135,136,137,
+  138, 56,139,140, 56,141,142,143, 56, 56,144,145,146, 56,147,148,
+  149, 32, 32, 32,150,151,152, 32,153,154, 56, 56, 56, 56, 44, 44,
+   44, 44, 44, 44,155, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+   44, 44, 44, 44, 44,156,157, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+   44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,158, 44, 44, 44,
+   44, 44, 44, 44, 44, 44, 44, 44, 44,159, 44, 44,160, 56, 56, 56,
+   56, 56, 56, 56, 56, 56, 44, 44,161, 56, 56, 56, 56, 56, 44, 44,
+   44,162, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+   44,163, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,164,165,
+    0,  1,  0,  1,  2,  3,  0,  1,  2,  3,  4,  5,  6,  7,  0,  0,
+    0,  0,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+   19, 19, 19, 19, 19, 19, 19, 19, 19,  0,  0,  0,  0,  0,  0,  0,
+   19,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19, 19, 19,  0, 19,  0,
+    0,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19,  0,  0,  0,  0,  0,
+   26, 26,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  9,  9,
+    9,  9,  0,  9,  9,  9,  2,  2,  9,  9,  9,  9,  0,  9,  2,  2,
+    2,  2,  9,  0,  9,  0,  9,  9,  9,  2,  9,  2,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  2,  9,  9,  9,  9,  9,  9,  9,
+   55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,  6,  6,
+    6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  1,  1,  6,  2,  4,
+    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
+    4,  4,  4,  4,  4,  2,  4,  4,  4,  2,  2,  4,  4,  4,  2, 14,
+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,  2,  2,
+    2,  2,  2,  2,  2,  2, 14, 14, 14,  2,  2,  2,  2, 14, 14, 14,
+   14, 14, 14,  2,  2,  2,  3,  3,  3,  3,  3,  0,  3,  3,  3,  3,
+    3,  3,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+    3,  0,  3,  3,  3,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+    3,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  3,  3,  1,  3,
+    3,  3,  3,  3,  3,  3, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
+   37, 37, 37, 37,  2, 37, 37, 37, 37,  2,  2, 37, 37, 37, 38, 38,
+   38, 38, 38, 38, 38, 38, 38, 38,  2,  2,  2,  2,  2,  2, 64, 64,
+   64, 64, 64, 64, 64, 64, 64, 64, 64,  2,  2, 64, 64, 64, 90, 90,
+   90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,  2,  2, 90, 90,
+   90, 90, 90, 90, 90,  2, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
+   95, 95,  2,  2, 95,  2, 37, 37, 37,  2,  2,  2,  2,  2,  3,  3,
+    3,  3,  3,  3,  3,  2,  3,  3,  2,  2,  2,  2,  2,  3,  3,  3,
+    0,  3,  3,  3,  3,  3,  7,  7,  7,  7,  7,  7,  7,  7,  7,  1,
+    1,  1,  1,  7,  7,  7,  7,  7,  7,  7,  0,  0,  7,  7,  5,  5,
+    5,  5,  2,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2,  5,  5,  2,
+    2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,
+    5,  5,  5,  5,  5,  5,  5,  2,  5,  2,  2,  2,  5,  5,  5,  5,
+    2,  2,  5,  5,  5,  5,  5,  2,  2,  5,  5,  5,  5,  2,  2,  2,
+    2,  2,  2,  2,  2,  5,  2,  2,  2,  2,  5,  5,  2,  5,  5,  5,
+    5,  5,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2, 11,
+   11, 11,  2, 11, 11, 11, 11, 11, 11,  2,  2,  2,  2, 11, 11,  2,
+    2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,  2,
+   11, 11, 11, 11, 11, 11, 11,  2, 11, 11,  2, 11, 11,  2, 11, 11,
+    2,  2, 11,  2, 11, 11, 11,  2,  2, 11, 11, 11,  2,  2,  2, 11,
+    2,  2,  2,  2,  2,  2,  2, 11, 11, 11, 11,  2, 11,  2,  2,  2,
+    2,  2,  2,  2, 11, 11, 11, 11, 11, 11, 11, 11, 11,  2,  2, 10,
+   10, 10,  2, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,
+    2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2,
+   10, 10, 10, 10, 10, 10, 10,  2, 10, 10,  2, 10, 10, 10, 10, 10,
+    2,  2, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,  2,  2, 10,  2,
+    2,  2,  2,  2,  2,  2, 10, 10, 10, 10,  2,  2, 10, 10, 10, 10,
+    2,  2,  2,  2,  2,  2,  2, 10, 10, 10, 10, 10, 10, 10,  2, 21,
+   21, 21,  2, 21, 21, 21, 21, 21, 21, 21, 21,  2,  2, 21, 21,  2,
+    2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,  2,
+   21, 21, 21, 21, 21, 21, 21,  2, 21, 21,  2, 21, 21, 21, 21, 21,
+    2,  2, 21, 21, 21, 21, 21,  2,  2, 21, 21, 21,  2,  2,  2,  2,
+    2,  2,  2, 21, 21, 21,  2,  2,  2,  2, 21, 21,  2, 21, 21, 21,
+   21, 21,  2,  2, 21, 21,  2,  2, 22, 22,  2, 22, 22, 22, 22, 22,
+   22,  2,  2,  2, 22, 22, 22,  2, 22, 22, 22, 22,  2,  2,  2, 22,
+   22,  2, 22,  2, 22, 22,  2,  2,  2, 22, 22,  2,  2,  2, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22,  2,  2,  2,  2, 22, 22, 22,  2,
+    2,  2,  2,  2,  2, 22,  2,  2,  2,  2,  2,  2, 22, 22, 22, 22,
+   22,  2,  2,  2,  2,  2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+   23, 23, 23,  2, 23, 23, 23,  2, 23, 23, 23, 23, 23, 23, 23, 23,
+    2,  2, 23, 23, 23, 23, 23,  2, 23, 23, 23, 23,  2,  2,  2,  2,
+    2,  2,  2, 23, 23,  2, 23, 23, 23,  2,  2, 23,  2,  2, 23, 23,
+   23, 23,  2,  2, 23, 23,  2,  2,  2,  2,  2,  2,  2, 23, 16, 16,
+   16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16,  2,
+   16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16, 16, 16,
+    2,  2, 16, 16, 16, 16, 16,  2, 16, 16, 16, 16,  2,  2,  2,  2,
+    2,  2,  2, 16, 16,  2, 16, 16, 16, 16,  2,  2, 16, 16,  2, 16,
+   16, 16,  2,  2,  2,  2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+   20, 20, 20,  2, 20, 20, 20,  2, 20, 20, 20, 20, 20, 20,  2,  2,
+    2,  2, 20, 20, 20, 20, 20, 20, 20, 20,  2,  2, 20, 20,  2, 36,
+   36, 36,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36, 36,
+    2, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2,  2,  2,
+   36,  2,  2,  2,  2, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2,  2,
+    2,  2,  2,  2, 36, 36,  2,  2, 36, 36, 36,  2,  2,  2,  2, 24,
+   24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+   24,  2,  2,  2,  2,  0, 24, 24, 24, 24,  2,  2,  2,  2,  2, 18,
+   18,  2, 18,  2, 18, 18, 18, 18, 18,  2, 18, 18, 18, 18, 18, 18,
+   18, 18, 18, 18, 18, 18, 18, 18, 18, 18,  2, 18,  2, 18, 18, 18,
+   18, 18, 18, 18,  2,  2, 18, 18, 18, 18, 18,  2, 18,  2, 18, 18,
+   18, 18, 18, 18, 18,  2, 18, 18,  2,  2, 18, 18, 18, 18, 25, 25,
+   25, 25, 25, 25, 25, 25,  2, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+   25, 25, 25,  2,  2,  2, 25, 25, 25, 25, 25,  2, 25, 25, 25, 25,
+   25, 25, 25,  0,  0,  0,  0, 25, 25,  2,  2,  2,  2,  2, 33, 33,
+   33, 33, 33, 33, 33, 33,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
+    8,  8,  8,  8,  2,  8,  2,  2,  2,  2,  2,  8,  2,  2,  8,  8,
+    8,  0,  8,  8,  8,  8, 12, 12, 12, 12, 12, 12, 12, 12, 30, 30,
+   30, 30, 30, 30, 30, 30, 30,  2, 30, 30, 30, 30,  2,  2, 30, 30,
+   30, 30, 30, 30, 30,  2, 30, 30, 30,  2,  2, 30, 30, 30, 30, 30,
+   30, 30, 30,  2,  2,  2, 30, 30,  2,  2,  2,  2,  2,  2, 29, 29,
+   29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,  2,  2, 28, 28,
+   28, 28, 28, 28, 28, 28, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+   34, 34, 34,  2,  2,  2, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+   35,  0,  0,  0, 35, 35, 35,  2,  2,  2,  2,  2,  2,  2, 45, 45,
+   45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,  2,  2,  2,  2,
+    2,  2,  2,  2,  2, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+   44, 44, 44,  0,  0,  2, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+   43, 43,  2,  2,  2,  2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
+   46, 46, 46,  2, 46, 46, 46,  2, 46, 46,  2,  2,  2,  2, 31, 31,
+   31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,  2,  2, 31, 31,
+    2,  2,  2,  2,  2,  2, 32, 32,  0,  0, 32,  0, 32, 32, 32, 32,
+   32, 32, 32, 32, 32, 32, 32, 32,  2,  2,  2,  2,  2,  2, 32,  2,
+    2,  2,  2,  2,  2,  2, 32, 32, 32,  2,  2,  2,  2,  2, 28, 28,
+   28, 28, 28, 28,  2,  2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+   48, 48, 48, 48, 48,  2, 48, 48, 48, 48,  2,  2,  2,  2, 48,  2,
+    2,  2, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+   52, 52, 52, 52,  2,  2, 52, 52, 52, 52, 52,  2,  2,  2, 58, 58,
+   58, 58, 58, 58, 58, 58, 58, 58, 58, 58,  2,  2,  2,  2, 58, 58,
+    2,  2,  2,  2,  2,  2, 58, 58, 58,  2,  2,  2, 58, 58, 54, 54,
+   54, 54, 54, 54, 54, 54, 54, 54, 54, 54,  2,  2, 54, 54, 91, 91,
+   91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,  2, 91, 91,
+   91, 91, 91,  2,  2, 91, 91, 91,  2,  2,  2,  2,  2,  2, 91, 91,
+   91, 91, 91, 91,  2,  2,  1,  1,  1,  1,  1,  1,  1,  2, 62, 62,
+   62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,  2, 62, 62, 76, 76,
+   76, 76, 76, 76, 76, 76, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+   93, 93,  2,  2,  2,  2,  2,  2,  2,  2, 93, 93, 93, 93, 70, 70,
+   70, 70, 70, 70, 70, 70,  2,  2,  2, 70, 70, 70, 70, 70, 70, 70,
+    2,  2,  2, 70, 70, 70, 73, 73, 73, 73, 73, 73, 73, 73,  6,  6,
+    6,  2,  2,  2,  2,  2,  8,  8,  8,  2,  2,  8,  8,  8,  1,  1,
+    1,  0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  0,
+    0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  1,  1,
+    0,  2,  2,  2,  2,  2, 19, 19, 19, 19, 19, 19,  9,  9,  9,  9,
+    9,  6, 19, 19, 19, 19, 19, 19, 19, 19, 19,  9,  9,  9,  9,  9,
+   19, 19, 19, 19,  9,  9,  9,  9,  9, 19, 19, 19, 19, 19,  6, 19,
+   19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,  9,  9,  9,
+    9,  9,  9,  9,  2,  2,  2,  9,  2,  9,  2,  9,  2,  9,  9,  9,
+    9,  9,  9,  2,  9,  9,  9,  9,  9,  9,  2,  2,  9,  9,  9,  9,
+    9,  9,  2,  9,  9,  9,  2,  2,  9,  9,  9,  2,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  2,  0,  0,  0,  0,  1,  1,  0,  0,  0,  0,
+    0,  0,  0,  2,  0,  0,  0, 19,  2,  2,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0, 19,  0,  0,  0,  0,  0,  0,  0,  2, 19, 19,
+   19, 19, 19,  2,  2,  2,  0,  2,  2,  2,  2,  2,  2,  2,  1,  2,
+    2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,
+   19, 19,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19,  0, 19,  0,
+    0,  0,  2,  2,  2,  2,  0,  0,  2,  2,  2,  2,  2,  2,  0,  0,
+    0,  2,  2,  2,  2,  2, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,
+    0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0, 56, 56,
+   56, 56, 56, 56, 56, 56, 55, 55, 55, 55,  2,  2,  2,  2,  2, 55,
+   55, 55, 55, 55, 55, 55, 61, 61, 61, 61, 61, 61, 61, 61,  2,  2,
+    2,  2,  2,  2,  2, 61, 61,  2,  2,  2,  2,  2,  2,  2,  0,  0,
+    0,  0,  0,  0,  2,  2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    2, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  2, 13, 13,
+   13, 13, 13, 13,  2,  2,  0,  0,  0,  0,  0, 13,  0, 13,  0, 13,
+   13, 13, 13, 13, 13, 13, 13, 13,  1,  1,  1,  1, 12, 12, 13, 13,
+   13, 13,  0,  0,  0,  0,  2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,  1,
+    1,  0,  0, 15, 15, 15,  0, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17,  0,  0, 17, 17, 17,  2,  2,
+    2,  2,  2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2, 12,
+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  2,  2,  2,
+    2,  2,  2,  2,  2,  0, 12, 12, 12, 12, 12, 12, 12,  0, 17, 17,
+   17, 17, 17, 17, 17,  0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
+   39, 39, 39,  2,  2,  2, 39, 39, 39, 39, 39, 39, 39,  2, 86, 86,
+   86, 86, 86, 86, 86, 86, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+   77, 77,  2,  2,  2,  2, 79, 79, 79, 79, 79, 79, 79, 79,  0,  0,
+   19, 19, 19, 19, 19, 19,  0,  0,  0, 19, 19, 19, 19, 19, 19, 19,
+   19, 19, 19, 19,  2,  2, 19, 19,  2, 19,  2, 19, 19, 19,  2,  2,
+   19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+   60, 60, 60,  2,  2,  2, 65, 65, 65, 65, 65, 65, 65, 65, 75, 75,
+   75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,  2,  2,  2,  2,
+    2,  2,  2,  2, 75, 75, 75, 75,  2,  2,  2,  2,  2,  2, 69, 69,
+   69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,  0, 69, 74, 74,
+   74, 74, 74, 74, 74, 74, 74, 74, 74, 74,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  2, 74, 12, 12, 12, 12, 12,  2,  2,  2, 84, 84,
+   84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,  2,  0, 84, 84,
+    2,  2,  2,  2, 84, 84, 33, 33, 33, 33, 33, 33, 33,  2, 68, 68,
+   68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,  2, 68, 68,
+   68, 68, 68, 68,  2,  2, 68, 68,  2,  2, 68, 68, 68, 68, 92, 92,
+   92, 92, 92, 92, 92, 92, 92, 92, 92,  2,  2,  2,  2,  2,  2,  2,
+    2, 92, 92, 92, 92, 92, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+   87, 87, 87, 87, 87,  2,  2, 30, 30, 30, 30, 30, 30,  2, 19, 19,
+   19,  0, 19, 19, 19, 19, 19, 19, 19, 19, 19,  9, 19, 19, 19, 19,
+    0,  0,  2,  2,  2,  2, 87, 87, 87, 87, 87, 87,  2,  2, 87, 87,
+    2,  2,  2,  2,  2,  2, 12, 12, 12, 12,  2,  2,  2,  2,  2,  2,
+    2, 12, 12, 12, 12, 12, 13, 13,  2,  2,  2,  2,  2,  2, 19, 19,
+   19, 19, 19, 19, 19,  2,  2,  2,  2,  4,  4,  4,  4,  4,  2,  2,
+    2,  2,  2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,  2, 14, 14,
+   14, 14, 14,  2, 14,  2, 14, 14,  2, 14, 14,  2, 14, 14,  3,  3,
+    3,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,
+    3,  3,  3,  3,  0,  0,  2,  2,  3,  3,  3,  3,  3,  3,  2,  2,
+    2,  2,  2,  2,  2,  3,  1,  1,  1,  1,  1,  1,  6,  6,  0,  0,
+    0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  3,  3,
+    3,  3,  3,  2,  3,  3,  3,  3,  3,  3,  3,  2,  2,  0,  2,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17, 17, 17, 17,
+   17, 17, 17, 17,  0,  0,  2,  2, 12, 12, 12, 12, 12, 12,  2,  2,
+   12, 12, 12,  2,  2,  2,  2,  0,  0,  0,  0,  0,  2,  2, 49, 49,
+   49, 49, 49, 49, 49, 49, 49, 49, 49, 49,  2, 49, 49, 49, 49, 49,
+   49, 49, 49, 49, 49,  2, 49, 49, 49,  2, 49, 49,  2, 49, 49, 49,
+   49, 49, 49, 49,  2,  2, 49, 49, 49,  2,  2,  2,  2,  2,  0,  0,
+    0,  2,  2,  2,  2,  0,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,
+    0,  0,  0,  2,  2,  2,  9,  2,  2,  2,  2,  2,  2,  2,  0,  0,
+    0,  0,  0,  1,  2,  2, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+   71, 71, 71,  2,  2,  2, 67, 67, 67, 67, 67, 67, 67, 67, 67,  2,
+    2,  2,  2,  2,  2,  2,  1,  0,  0,  0,  0,  0,  0,  0, 42, 42,
+   42, 42, 42, 42, 42, 42, 42, 42, 42, 42,  2,  2,  2,  2,  2,  2,
+    2,  2,  2, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
+   41,  2,  2,  2,  2,  2,118,118,118,118,118,118,118,118,118,118,
+  118,  2,  2,  2,  2,  2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+   53, 53, 53, 53,  2, 53, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+   59, 59,  2,  2,  2,  2, 59, 59, 59, 59, 59, 59,  2,  2, 40, 40,
+   40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50,
+   50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,  2,  2, 50, 50,
+    2,  2,  2,  2,  2,  2,135,135,135,135,135,135,135,135,135,135,
+  135,135,  2,  2,  2,  2,106,106,106,106,106,106,106,106,104,104,
+  104,104,104,104,104,104,104,104,104,104,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,104,161,161,161,161,161,161,161,161,161,161,
+  161,  2,161,161,161,161,161,161,161,  2,161,161,  2,161,161,161,
+    2,161,161,161,161,161,161,161,  2,161,161,  2,  2,  2,170,170,
+  170,170,170,170,170,170,170,170,170,170,  2,  2,  2,  2,110,110,
+  110,110,110,110,110,110,110,110,110,110,110,110,110,  2,110,110,
+  110,110,110,110,  2,  2, 19, 19, 19, 19, 19, 19,  2, 19, 19,  2,
+   19, 19, 19, 19, 19, 19, 19, 19, 19,  2,  2,  2,  2,  2, 47, 47,
+   47, 47, 47, 47,  2,  2, 47,  2, 47, 47, 47, 47, 47, 47, 47, 47,
+   47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,  2, 47, 47,  2,
+    2,  2, 47,  2,  2, 47, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+   81, 81, 81, 81,  2, 81,120,120,120,120,120,120,120,120,116,116,
+  116,116,116,116,116,116,116,116,116,116,116,116,116,  2,  2,  2,
+    2,  2,  2,  2,  2,116,128,128,128,128,128,128,128,128,128,128,
+  128,  2,128,128,  2,  2,  2,  2,  2,128,128,128,128,128, 66, 66,
+   66, 66, 66, 66, 66, 66, 66, 66, 66, 66,  2,  2,  2, 66, 72, 72,
+   72, 72, 72, 72, 72, 72, 72, 72,  2,  2,  2,  2,  2, 72, 98, 98,
+   98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97,  2,  2,
+    2,  2, 97, 97, 97, 97,  2,  2, 97, 97, 97, 97, 97, 97, 57, 57,
+   57, 57,  2, 57, 57,  2,  2,  2,  2,  2, 57, 57, 57, 57, 57, 57,
+   57, 57,  2, 57, 57, 57,  2, 57, 57, 57, 57, 57, 57, 57, 57, 57,
+   57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,  2,  2, 57, 57,
+   57,  2,  2,  2,  2, 57, 57,  2,  2,  2,  2,  2,  2,  2, 88, 88,
+   88, 88, 88, 88, 88, 88,117,117,117,117,117,117,117,117,112,112,
+  112,112,112,112,112,112,112,112,112,112,112,112,112,  2,  2,  2,
+    2,112,112,112,112,112, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+   78, 78, 78, 78,  2,  2,  2, 78, 78, 78, 78, 78, 78, 78, 83, 83,
+   83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,  2,  2, 82, 82,
+   82, 82, 82, 82, 82, 82, 82, 82, 82,  2,  2,  2,  2,  2,122,122,
+  122,122,122,122,122,122,122,122,  2,  2,  2,  2,  2,  2,  2,122,
+  122,122,122,  2,  2,  2,  2,122,122,122,122,122,122,122, 89, 89,
+   89, 89, 89, 89, 89, 89, 89,  2,  2,  2,  2,  2,  2,  2,130,130,
+  130,130,130,130,130,130,130,130,130,  2,  2,  2,  2,  2,  2,  2,
+  130,130,130,130,130,130,144,144,144,144,144,144,144,144,144,144,
+    2,  2,  2,  2,  2,  2,165,165,165,165,165,165,165,165,165,165,
+  165,165,165,165,  2,  2,  2,165,165,165,165,165,165,165,  2,  2,
+    2,  2,  2,  2,165,165,156,156,156,156,156,156,156,156,156,156,
+    2,156,156,156,  2,  2,156,156,  2,  2,  2,  2,  2,  2,  2,  2,
+    3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,147,147,
+  147,147,147,147,147,147,148,148,148,148,148,148,148,148,148,148,
+    2,  2,  2,  2,  2,  2,158,158,158,158,158,158,158,158,158,158,
+    2,  2,  2,  2,  2,  2,153,153,153,153,153,153,153,153,153,153,
+  153,153,  2,  2,  2,  2,149,149,149,149,149,149,149,149,149,149,
+  149,149,149,149,149,  2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+   94, 94, 94, 94,  2,  2,  2,  2, 94, 94, 94, 94, 94, 94,  2,  2,
+    2,  2,  2,  2,  2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+   85,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 85,  2,  2,101,101,
+  101,101,101,101,101,101,101,  2,  2,  2,  2,  2,  2,  2,101,101,
+    2,  2,  2,  2,  2,  2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+   96, 96, 96,  2, 96, 96,111,111,111,111,111,111,111,111,111,111,
+  111,111,111,111,111,  2,100,100,100,100,100,100,100,100,  2, 36,
+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2,  2,  2,108,108,
+  108,108,108,108,108,108,108,108,  2,108,108,108,108,108,108,108,
+    2,  2,  2,  2,  2,  2,129,129,129,129,129,129,129,  2,129,  2,
+  129,129,129,129,  2,129,129,129,129,129,129,129,129,129,129,129,
+  129,129,129,129,  2,129,129,129,  2,  2,  2,  2,  2,  2,109,109,
+  109,109,109,109,109,109,109,109,109,  2,  2,  2,  2,  2,109,109,
+    2,  2,  2,  2,  2,  2,107,107,107,107,  2,107,107,107,107,107,
+  107,107,107,  2,  2,107,107,  2,  2,107,107,107,107,107,107,107,
+  107,107,107,107,107,107,107,  2,107,107,107,107,107,107,107,  2,
+  107,107,  2,107,107,107,107,107,  2,  1,107,107,107,107,107,  2,
+    2,107,107,107,  2,  2,107,  2,  2,  2,  2,  2,  2,107,  2,  2,
+    2,  2,  2,107,107,107,107,107,107,107,  2,  2,107,107,107,107,
+  107,107,107,  2,  2,  2,171,171,171,171,171,171,171,171,171,171,
+    2,171,  2,  2,171,  2,171,171,171,171,171,171,  2,171,171,  2,
+  171,  2,  2,171,  2,171,171,171,171,  2,171,171,171,171,171,  2,
+    2,  2,  2,  2,  2,  2,  2,171,171,  2,  2,  2,  2,  2,137,137,
+  137,137,137,137,137,137,137,137,137,137,  2,137,137,137,137,137,
+    2,  2,  2,  2,  2,  2,124,124,124,124,124,124,124,124,124,124,
+    2,  2,  2,  2,  2,  2,123,123,123,123,123,123,123,123,123,123,
+  123,123,123,123,  2,  2,114,114,114,114,114,114,114,114,114,114,
+  114,114,114,  2,  2,  2,114,114,  2,  2,  2,  2,  2,  2, 32, 32,
+   32, 32, 32,  2,  2,  2,102,102,102,102,102,102,102,102,102,102,
+    2,  2,  2,  2,  2,  2, 33, 33, 33, 33,  2,  2,  2,  2,126,126,
+  126,126,126,126,126,126,126,126,126,  2,  2,126,126,126,126,126,
+  126,126,  2,  2,  2,  2,126,126,126,126,126,126,126,  2,142,142,
+  142,142,142,142,142,142,142,142,142,142,  2,  2,  2,  2,125,125,
+  125,125,125,125,125,125,125,125,125,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  2,125,154,154,154,154,154,154,154,  2,  2,154,
+    2,  2,154,154,154,154,154,154,154,154,  2,154,154,  2,154,154,
+  154,154,154,154,154,154,154,154,154,154,154,154,  2,154,154,  2,
+    2,154,154,154,154,154,154,154,  2,  2,  2,  2,  2,  2,150,150,
+  150,150,150,150,150,150,  2,  2,150,150,150,150,150,150,150,150,
+  150,150,150,  2,  2,  2,141,141,141,141,141,141,141,141,140,140,
+  140,140,140,140,140,140,140,140,140,  2,  2,  2,  2,  2,121,121,
+  121,121,121,121,121,121,121,  2,  2,  2,  2,  2,  2,  2,  7,  7,
+    2,  2,  2,  2,  2,  2,169,169,169,169,169,169,169,169,169,169,
+    2,  2,  2,  2,  2,  2,133,133,133,133,133,133,133,133,133,  2,
+  133,133,133,133,133,133,133,133,133,133,133,133,133,  2,133,133,
+  133,133,133,133,  2,  2,133,133,133,133,133,  2,  2,  2,134,134,
+  134,134,134,134,134,134,  2,  2,134,134,134,134,134,134,  2,134,
+  134,134,134,134,134,134,134,134,134,134,134,134,134,  2,138,138,
+  138,138,138,138,138,  2,138,138,  2,138,138,138,138,138,138,138,
+  138,138,138,138,138,138,  2,  2,138,  2,138,138,  2,138,138,138,
+    2,  2,  2,  2,  2,  2,143,143,143,143,143,143,  2,143,143,  2,
+  143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
+  143,143,143,143,143,  2,143,143,  2,143,143,143,143,143,143,  2,
+    2,  2,  2,  2,  2,  2,143,143,  2,  2,  2,  2,  2,  2,145,145,
+  145,145,145,145,145,145,145,  2,  2,  2,  2,  2,  2,  2,163,163,
+  163,163,163,163,163,163,163,  2,163,163,163,163,163,163,163,163,
+  163,  2,  2,  2,163,163,163,163,163,  2,  2,  2,  2,  2, 86,  2,
+    2,  2,  2,  2,  2,  2, 22, 22,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+    2,  2,  2,  2,  2,  2, 63, 63, 63, 63, 63, 63, 63,  2, 63, 63,
+   63, 63, 63,  2,  2,  2, 63, 63, 63, 63,  2,  2,  2,  2,157,157,
+  157,157,157,157,157,157,157,157,157,  2,  2,  2,  2,  2, 80, 80,
+   80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,  2,  2, 80, 80,
+   80,  2,  2,  2,  2,  2,127,127,127,127,127,127,127,127,127,127,
+  127,127,127,127,127,  2,166,166,166,166,166,166,166,166,166,166,
+    2,  2,  2,  2,  2,  2, 79,  2,  2,  2,  2,  2,  2,  2,115,115,
+  115,115,115,115,115,115,115,115,115,115,115,115,115,  2,115,115,
+    2,  2,  2,  2,115,115,159,159,159,159,159,159,159,159,159,159,
+  159,159,159,159,159,  2,159,159,  2,  2,  2,  2,  2,  2,103,103,
+  103,103,103,103,103,103,103,103,103,103,103,103,  2,  2,119,119,
+  119,119,119,119,119,119,119,119,119,119,119,119,  2,  2,119,119,
+    2,119,119,119,119,119,  2,  2,  2,  2,  2,119,119,119,167,167,
+  167,167,167,167,167,167,167,167,  2,  2,  2,  2,  2,  2,146,146,
+  146,146,146,146,146,146,146,146,146,  2,  2,  2,  2,  2, 99, 99,
+   99, 99, 99, 99, 99, 99, 99, 99, 99,  2,  2,  2,  2, 99,  2,  2,
+    2,  2,  2,  2,  2, 99,136,139, 13, 13,155,  2,  2,  2,136,136,
+  136,136,136,136,136,136,155,155,155,155,155,155,155,155,155,155,
+  155,155,155,155,  2,  2,  2,  2,  2,  2,  2,  2,  2,155,136,  2,
+    2,  2,  2,  2,  2,  2, 17, 17, 17, 17,  2, 17, 17, 17, 17, 17,
+   17, 17,  2, 17, 17,  2, 17, 15, 15, 15, 15, 15, 15, 15, 17, 17,
+   17,  2,  2,  2,  2,  2,  2,  2, 15,  2,  2,  2,  2,  2, 15, 15,
+   15,  2,  2, 17,  2,  2,  2,  2,  2,  2, 17, 17, 17, 17,139,139,
+  139,139,139,139,139,139,139,139,139,139,  2,  2,  2,  2,105,105,
+  105,105,105,105,105,105,105,105,105,  2,  2,  2,  2,  2,105,105,
+  105,105,105,  2,  2,  2,105,  2,  2,  2,  2,  2,  2,  2,105,105,
+    2,  2,105,105,105,105,  1,  1,  1,  1,  1,  1,  2,  2,  0,  0,
+    0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,
+    1,  1,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0,  0,  2,  2,
+    0,  2,  2,  0,  0,  2,  2,  0,  0,  0,  0,  2,  0,  0,  0,  0,
+    2,  0,  2,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,
+    0,  2,  2,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  2,  0,  0,
+    0,  0,  0,  2,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  2,
+    0,  0,  0,  0,  0,  0,131,131,131,131,131,131,131,131,131,131,
+  131,131,  2,  2,  2,  2,  2,  2,  2,131,131,131,131,131,  2,131,
+  131,131,131,131,131,131,  2,  2,  2,  2,  2, 19, 19, 19, 56, 56,
+   56, 56, 56, 56, 56,  2, 56,  2,  2, 56, 56, 56, 56, 56, 56, 56,
+    2, 56, 56,  2, 56, 56, 56, 56, 56,  2,  2,  2,  2,  2,  6,  6,
+    6,  6,  6,  6,  2,  2,  2,  2,  2,  2,  2,  2,  2,  6,151,151,
+  151,151,151,151,151,151,151,151,151,151,151,  2,  2,  2,151,151,
+  151,151,151,151,  2,  2,151,151,  2,  2,  2,  2,151,151,160,160,
+  160,160,160,160,160,160,160,160,160,160,160,160,160,  2,152,152,
+  152,152,152,152,152,152,152,152,  2,  2,  2,  2,  2,152,164,164,
+  164,164,164,164,164,164,164,164,  2,  2,  2,  2,  2,  2,168,168,
+  168,168,168,168,168,168,168,168,168,  2,  2,  2,  2,168, 30, 30,
+   30, 30,  2, 30, 30,  2,113,113,113,113,113,113,113,113,113,113,
+  113,113,113,  2,  2,113,113,113,113,113,113,113,113,  2,132,132,
+  132,132,132,132,132,132,132,132,132,132,  2,  2,  2,  2,132,132,
+    2,  2,  2,  2,132,132,  3,  3,  3,  3,  2,  3,  3,  3,  2,  3,
+    3,  2,  3,  2,  2,  3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+    3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  2,  2,  2,  2,  2,  2,
+    3,  2,  2,  2,  2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  2,  3,
+    2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  3,
+    2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  3,
+    3,  3,  2,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2,  0,  0, 15,  0,  0,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,
+    2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  2,  2,  0, 13,  2,
+    2,  2,  2,  2,  2,  2, 13, 13, 13,  2,  2,  2,  2,  2,  2,  0,
+    2,  2,  2,  2,  2,  2,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+    9,  9,  9, 10,  9, 11, 12, 13,  9,  9,  9, 14,  9,  9, 15,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 16, 17,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 18, 19, 20,  9, 21,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9, 16, 17,  9,  9,  9,  9, 18,  9,  9,  9,  9,  9, 19, 20,
+   21,  9, 22,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9, 23,  9,  9,  9,  9,  9, 24,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 25,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 22,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
@@ -3704,60 +3934,66 @@ _hb_ucd_u8[14752] =
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 23, 24,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,
-    5,  6,  7,  8,  9, 10, 11, 12,  0,  0, 13, 14, 15, 16, 17, 18,
-   19, 20, 21, 22,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0, 23,  0,  0, 24, 25, 26, 27, 28, 29, 30,  0,  0,
-   31, 32,  0, 33,  0, 34,  0, 35,  0,  0,  0,  0, 36, 37, 38, 39,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0, 40,  0,  0,  0,  0,  0,  0,  0,  0,  0, 41, 42,  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, 43, 44,  0, 45,  0,  0,  0,  0,  0,  0, 46, 47,  0,  0,
-    0,  0,  0, 48,  0, 49,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0, 50, 51,  0,  0,  0, 52,  0,  0, 53,  0,  0,  0,
-    0,  0,  0,  0, 54,  0,  0,  0,  0,  0,  0,  0, 55,  0,  0,  0,
-    0,  0,  0,  0, 56,  0,  0,  0,  0,  0,  0,  0,  0, 57,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0, 58, 59, 60, 61, 62, 63, 64, 65,  0,  0,  0,  0,
-    0,  0, 66,  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,  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,
-   67, 68,  0, 69, 70,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-   71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
-   87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,
-  103,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,104,  0,  0,  0,  0,  0,  0,105,106,  0,107,  0,  0,  0,
-  108,  0,109,  0,110,  0,111,112,113,  0,114,  0,  0,  0,115,  0,
-    0,  0,116,  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,117,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,118,119,120,121,  0,122,123,124,125,126,  0,127,
-    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,
-  128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
-  144,145,146,147,148,149,150,151,152,153,154,155,156,157,  0,  0,
-    0,158,159,160,161,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,162,163,  0,  0,  0,  0,  0,
-    0,  0,164,  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,165,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,166,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,167,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,168,  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,169,170,  0,  0,  0,  0,171,172,  0,  0,  0,
-  173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,
-  189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,
-  205,206,  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,  1,  2,  3,  4,
+    9,  9, 26, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12,  0,  0, 13, 14,
+   15, 16, 17, 18, 19, 20, 21, 22,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 23,  0,  0, 24, 25, 26, 27, 28,
+   29, 30,  0,  0, 31, 32,  0, 33,  0, 34,  0, 35,  0,  0,  0,  0,
+   36, 37, 38, 39,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0, 40,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+   41, 42,  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, 43, 44,  0, 45,  0,  0,  0,  0,  0,  0,
+   46, 47,  0,  0,  0,  0,  0, 48,  0, 49,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 50, 51,  0,  0,  0, 52,  0,  0,
+   53,  0,  0,  0,  0,  0,  0,  0, 54,  0,  0,  0,  0,  0,  0,  0,
+   55,  0,  0,  0,  0,  0,  0,  0, 56,  0,  0,  0,  0,  0,  0,  0,
+    0, 57,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0, 58, 59, 60, 61, 62, 63, 64, 65,
+    0,  0,  0,  0,  0,  0, 66,  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,  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, 67, 68,  0, 69, 70,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+   83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+   99,100,101,102,103,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,104,  0,  0,  0,  0,  0,  0,105,106,  0,
+  107,  0,  0,  0,108,  0,109,  0,110,  0,111,112,113,  0,114,  0,
+    0,  0,115,  0,  0,  0,116,  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,117,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,118,119,120,121,  0,122,123,124,
+  125,126,  0,127,  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,128,129,130,131,132,133,134,135,136,137,138,139,
+  140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,
+  156,157,  0,  0,  0,158,159,160,161,  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,
+  162,  0,163,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,164,165,  0,
+    0,  0,  0,  0,  0,  0,166,  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,167,  0,  0,  0,168,169,  0,  0,
+  170,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,171,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,172,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,173,  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,174,  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,175,  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,176,177,  0,  0,  0,  0,178,
+  179,  0,  0,  0,180,181,182,183,184,185,186,187,188,189,190,191,
+  192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+  208,209,210,211,212,213,  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,
+    1,  2,  3,  4,
 };
 static const uint16_t
-_hb_ucd_u16[10060] =
+_hb_ucd_u16[9668] =
 {
      0,   0,   1,   2,   3,   4,   5,   6,   0,   0,   7,   8,   9,  10,  11,  12,
     13,  13,  13,  14,  15,  13,  13,  16,  17,  18,  19,  20,  21,  22,  13,  23,
@@ -3776,9 +4012,10 @@ _hb_ucd_u16[10060] =
    136,  48,  48, 137, 138, 139, 140, 140, 141,  48, 142, 143, 144, 145, 140, 140,
    146, 147, 148, 149, 150,  48, 151, 152, 153, 154,  32, 155, 156, 157, 140, 140,
     48,  48, 158, 159, 160, 161, 162, 163, 164, 165,   9,   9, 166,  11,  11, 167,
-    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 168, 169,  48,  48,
-   168,  48,  48, 170, 171, 172,  48,  48,  48, 171,  48,  48,  48, 173, 174, 175,
-    48, 176,   9,   9,   9,   9,   9, 177, 178,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48, 168, 169,  48,  48, 168,  48,  48, 170, 171, 172,  48,  48,
+    48, 171,  48,  48,  48, 173, 174, 175,  48, 176,   9,   9,   9,   9,   9, 177,
+   178,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
     48,  48,  48,  48,  48,  48, 179,  48, 180, 181,  48,  48,  48,  48, 182, 183,
     48, 184,  48, 185,  48, 186, 187, 188,  48,  48,  48, 189, 190, 191, 192, 193,
    194, 192,  48,  48, 195,  48,  48, 196, 197,  48, 198,  48,  48,  48,  48, 199,
@@ -3791,28 +4028,34 @@ _hb_ucd_u16[10060] =
    241, 242, 241, 241, 242, 243, 241, 244, 245, 245, 245, 246, 247, 248, 249, 250,
    251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261, 262, 263, 264, 265,
    266, 267, 268, 269, 270, 271, 272, 272, 273, 274, 275, 209, 276, 277, 209, 278,
-   279, 279, 279, 279, 279, 279, 279, 279, 280, 209, 281, 209, 209, 209, 209, 282,
-   209, 283, 279, 284, 209, 285, 286, 209, 209, 209, 287, 140, 288, 140, 271, 271,
-   271, 289, 209, 209, 209, 209, 290, 271, 209, 209, 209, 209, 209, 209, 209, 209,
-   209, 209, 209, 291, 292, 209, 209, 293, 209, 209, 209, 209, 209, 209, 294, 209,
-   209, 209, 209, 209, 209, 209, 295, 296, 271, 297, 209, 209, 298, 279, 299, 279,
-   300, 301, 279, 279, 279, 302, 279, 303, 209, 209, 209, 279, 304, 209, 209, 305,
-   209, 306, 209, 209, 209, 209, 209, 209,   9,   9,   9,  11,  11,  11, 307, 308,
-    13,  13,  13,  13,  13,  13, 309, 310,  11,  11, 311,  48,  48,  48, 312, 313,
-    48, 314, 315, 315, 315, 315,  32,  32, 316, 317, 318, 319, 320, 321, 140, 140,
-   209, 322, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 324, 140, 209,
-   325, 326, 327, 328, 136,  48,  48,  48,  48, 329, 178,  48,  48,  48,  48, 330,
-   331,  48,  48, 136,  48,  48,  48,  48, 200, 332,  48,  48, 209, 209, 333,  48,
-   209, 334, 335, 209, 336, 337, 209, 209, 335, 209, 209, 337, 209, 209, 209, 209,
-    48,  48,  48,  48, 209, 209, 209, 209,  48, 338,  48,  48,  48,  48,  48,  48,
-   151, 209, 209, 209, 287,  48,  48, 229, 339,  48, 340, 140,  13,  13, 341, 342,
-    13, 343,  48,  48,  48,  48, 344, 345,  31, 346, 347, 348,  13,  13,  13, 349,
-   350, 351, 352, 353, 354, 355, 140, 356, 357,  48, 358, 359,  48,  48,  48, 360,
-   361,  48,  48, 362, 363, 192,  32, 364,  64,  48, 365,  48, 366, 367,  48, 151,
-    76,  48,  48, 368, 369, 370, 371, 372,  48,  48, 373, 374, 375, 376,  48, 377,
-    48,  48,  48, 378, 379, 380, 381, 382, 383, 384, 315,  11,  11, 385, 386,  11,
-    11,  11,  11,  11,  48,  48, 387, 192,  48,  48, 388,  48, 389,  48,  48, 206,
-   390, 390, 390, 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, 391, 391,
+   279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
+   280, 209, 281, 209, 209, 209, 209, 282, 209, 283, 279, 284, 209, 285, 286, 209,
+   209, 209, 176, 140, 287, 140, 271, 271, 271, 288, 209, 209, 209, 209, 289, 271,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 290, 291, 209, 209, 292,
+   209, 209, 209, 209, 209, 209, 293, 209, 209, 209, 209, 209, 209, 209, 209, 209,
+   209, 209, 209, 209, 209, 209, 294, 295, 271, 296, 209, 209, 297, 279, 298, 279,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
+   279, 279, 279, 279, 279, 279, 279, 279, 299, 300, 279, 279, 279, 301, 279, 302,
+   209, 209, 209, 279, 303, 209, 209, 304, 209, 305, 209, 209, 209, 209, 209, 209,
+     9,   9,   9,  11,  11,  11, 306, 307,  13,  13,  13,  13,  13,  13, 308, 309,
+    11,  11, 310,  48,  48,  48, 311, 312,  48, 313, 314, 314, 314, 314,  32,  32,
+   315, 316, 317, 318, 319, 320, 140, 140, 209, 321, 209, 209, 209, 209, 209, 322,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 323, 140, 209,
+   324, 325, 326, 327, 136,  48,  48,  48,  48, 328, 178,  48,  48,  48,  48, 329,
+   330,  48,  48, 136,  48,  48,  48,  48, 200, 331,  48,  48, 209, 209, 332,  48,
+   209, 333, 334, 209, 335, 336, 209, 209, 334, 209, 209, 336, 209, 209, 209, 209,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 209, 209, 209, 209,
+    48, 337,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48, 151, 209, 209, 209, 338,  48,  48, 229,
+   339,  48, 340, 140,  13,  13, 341, 342,  13, 343,  48,  48,  48,  48, 344, 345,
+    31, 346, 347, 348,  13,  13,  13, 349, 350, 351, 352, 353, 354, 355, 140, 356,
+   357,  48, 358, 359,  48,  48,  48, 360, 361,  48,  48, 362, 363, 192,  32, 364,
+    64,  48, 365,  48, 366, 367,  48, 151,  76,  48,  48, 368, 369, 370, 371, 372,
+    48,  48, 373, 374, 375, 376,  48, 377,  48,  48,  48, 378, 379, 380, 381, 382,
+   383, 384, 314,  11,  11, 385, 386,  11,  11,  11,  11,  11,  48,  48, 387, 192,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 388,  48, 389,  48,  48, 206,
+   390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
+   391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
     48,  48,  48,  48,  48,  48, 204,  48,  48,  48,  48,  48,  48, 207, 140, 140,
    392, 393, 394, 395, 396,  48,  48,  48,  48,  48,  48, 397, 398, 399,  48,  48,
     48,  48,  48, 400, 209,  48,  48,  48,  48, 401,  48,  48, 402, 140, 140, 403,
@@ -3823,571 +4066,540 @@ _hb_ucd_u16[10060] =
    140, 140, 140, 140, 140, 140, 140, 140,  48, 151,  48,  48,  48, 100, 429, 430,
     48,  48, 431,  48, 432,  48,  48, 433,  48, 434,  48,  48, 435, 436, 140, 140,
      9,   9, 437,  11,  11,  48,  48,  48,  48, 204, 192,   9,   9, 438,  11, 439,
-    48,  48, 440,  48,  48,  48, 441, 442, 442, 443, 444, 445, 140, 140, 140, 140,
-    48,  48,  48, 314,  48, 199, 440, 140, 446,  27,  27, 447, 140, 140, 140, 140,
+    48,  48, 440,  48,  48,  48, 441, 442, 442, 443, 444, 445,  48,  48,  48, 388,
+    48,  48,  48, 313,  48, 199, 440, 140, 446,  27,  27, 447, 140, 140, 140, 140,
    448,  48,  48, 449,  48, 450,  48, 451,  48, 200, 452, 140, 140, 140,  48, 453,
     48, 454,  48, 455, 140, 140, 140, 140,  48,  48,  48, 456, 271, 457, 271, 271,
    458, 459,  48, 460, 461, 462,  48, 463,  48, 464, 140, 140, 465,  48, 466, 467,
     48,  48,  48, 468,  48, 469,  48, 470,  48, 471, 472, 140, 140, 140, 140, 140,
     48,  48,  48,  48, 196, 140, 140, 140,   9,   9,   9, 473,  11,  11,  11, 474,
-    48,  48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 476,
-    48,  48, 477, 478, 140, 140, 140, 479,  48, 464, 480,  48,  62, 481, 140,  48,
-   482, 140, 140,  48, 483, 140,  48, 314, 484,  48,  48, 485, 486, 457, 487, 488,
-   222,  48,  48, 489, 490,  48, 196, 192, 491,  48, 492, 493, 494,  48,  48, 495,
-   222,  48,  48, 496, 497, 498, 499, 500,  48,  97, 501, 502, 503, 140, 140, 140,
-   504, 505, 506,  48,  48, 507, 508, 192, 509,  83,  84, 510, 511, 512, 513, 514,
-    48,  48,  48, 515, 516, 517, 478, 140,  48,  48,  48, 518, 519, 192, 140, 140,
-    48,  48, 520, 521, 522, 523, 140, 140,  48,  48,  48, 524, 525, 192, 526, 140,
-    48,  48, 527, 528, 192, 140, 140, 140,  48, 173, 529, 530, 314, 140, 140, 140,
-    48,  48, 501, 531, 140, 140, 140, 140, 140, 140,   9,   9,  11,  11, 148, 532,
-   533, 534,  48, 535, 536, 192, 140, 140, 140, 140, 537,  48,  48, 538, 539, 140,
-   540,  48,  48, 541, 542, 543,  48,  48, 544, 545, 546,  48,  48,  48,  48, 196,
-   547, 140, 140, 140, 140, 140, 140, 140,  84,  48, 520, 548, 549, 148, 175, 550,
-    48, 551, 552, 553, 140, 140, 140, 140, 554,  48,  48, 555, 556, 192, 557,  48,
-   558, 559, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 560,
-   561, 115,  48, 562, 563, 192, 140, 140, 140, 140, 140, 100, 271, 564, 565, 566,
-    48, 207, 140, 140, 140, 140, 140, 140, 272, 272, 272, 272, 272, 272, 567, 568,
-    48,  48,  48,  48, 388, 140, 140, 140, 140,  48,  48,  48,  48,  48,  48, 569,
-    48,  48,  48, 570, 571, 572, 140, 140,  48,  48,  48,  48, 314, 140, 140, 140,
-    48,  48,  48, 196,  48, 200, 370,  48,  48,  48,  48, 200, 192,  48, 204, 573,
-    48,  48,  48, 574, 575, 576, 577, 578,  48, 140, 140, 140, 140, 140, 140, 140,
-   140, 140, 140, 140,   9,   9,  11,  11, 271, 579, 140, 140, 140, 140, 140, 140,
-    48,  48,  48,  48, 580, 581, 582, 582, 583, 584, 140, 140, 140, 140, 585, 586,
-    48,  48,  48,  48,  48,  48,  48, 440,  48,  48,  48,  48,  48, 199, 140, 140,
-   196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 587,
-    48,  48, 588, 589, 140, 590, 591,  48,  48,  48,  48,  48,  48,  48,  48, 206,
-    48,  48,  48,  48,  48,  48,  71, 151, 196, 592, 593, 140, 140, 140, 140, 140,
-    32,  32, 594,  32, 595, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140,
-   209, 209, 209, 209, 209, 209, 209, 324, 209, 209, 596, 209, 209, 209, 597, 598,
-   599, 209, 600, 209, 209, 209, 288, 140, 209, 209, 209, 209, 601, 140, 140, 140,
-   140, 140, 140, 140, 271, 602, 271, 602, 209, 209, 209, 209, 209, 287, 271, 461,
-     9, 603,  11, 604, 605, 606, 241,   9, 607, 608, 609, 610, 611,   9, 603,  11,
-   612, 613,  11, 614, 615, 616, 617,   9, 618,  11,   9, 603,  11, 604, 605,  11,
-   241,   9, 607, 617,   9, 618,  11,   9, 603,  11, 619,   9, 620, 621, 622, 623,
-    11, 624,   9, 625, 626, 627, 628,  11, 629,   9, 630,  11, 631, 632, 632, 632,
-    32,  32,  32, 633,  32,  32, 634, 635, 636, 637,  45, 140, 140, 140, 140, 140,
-   638, 639, 640, 140, 140, 140, 140, 140, 641, 642, 643,  27,  27,  27, 644, 140,
-   645, 140, 140, 140, 140, 140, 140, 140,  48,  48, 151, 646, 647, 140, 140, 140,
-   140,  48, 648, 140,  48,  48, 649, 650, 140, 140, 140, 140, 140,  48, 651, 192,
-   140, 140, 140, 140, 140, 140, 652, 200,  48,  48,  48,  48, 653, 595, 140, 140,
-     9,   9, 607,  11, 654, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 499,
-   271, 271, 655, 656, 140, 140, 140, 140, 499, 271, 657, 658, 140, 140, 140, 140,
-   659,  48, 660, 661, 662, 663, 664, 665, 666, 206, 667, 206, 140, 140, 140, 668,
-   209, 209, 669, 209, 209, 209, 209, 209, 209, 323, 334, 670, 670, 670, 209, 324,
-   671, 209, 209, 209, 209, 209, 209, 209, 209, 209, 672, 140, 140, 140, 673, 209,
-   674, 209, 209, 669, 675, 676, 324, 140, 209, 209, 209, 209, 209, 209, 209, 677,
-   209, 209, 209, 209, 209, 678, 426, 426, 209, 209, 209, 209, 209, 209, 209, 679,
-   209, 209, 209, 209, 209, 176, 669, 427, 669, 209, 209, 209, 680, 176, 209, 209,
-   680, 209, 672, 676, 140, 140, 140, 140, 209, 209, 209, 209, 209, 323, 672, 426,
-   675, 209, 209, 681, 682, 669, 675, 675, 209, 683, 209, 209, 288, 140, 140, 192,
-    48,  48,  48,  48,  48,  48, 140, 140,  48,  48,  48, 207,  48,  48,  48,  48,
-    48, 204,  48,  48,  48,  48,  48,  48,  48,  48, 478,  48,  48,  48,  48,  48,
-    48,  48,  48,  48,  48,  48, 100,  48,  48,  48,  48,  48,  48, 204, 140, 140,
-    48, 204, 140, 140, 140, 140, 140, 140,  48,  48,  48,  48,  71,  48,  48,  48,
-    48,  48,  48, 140, 140, 140, 140, 140, 684, 140, 570, 570, 570, 570, 570, 570,
+    48,  48, 475, 192, 476,   9, 477,  11, 478, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 140, 140, 271, 479,  48,  48, 480, 481, 482, 140, 140, 483,
+    48, 464, 484,  48,  62, 485, 140,  48, 486, 140, 140,  48, 487, 140,  48, 313,
+   488,  48,  48, 489, 490, 457, 491, 492, 222,  48,  48, 493, 494,  48, 196, 192,
+   495,  48, 496, 497, 498,  48,  48, 499, 222,  48,  48, 500, 501, 502, 503, 504,
+    48,  97, 505, 506, 507, 140, 140, 140, 508, 509, 510,  48,  48, 511, 512, 192,
+   513,  83,  84, 514, 515, 516, 517, 518, 519,  48,  48, 520, 521, 522, 523, 140,
+    48,  48,  48, 524, 525, 526, 481, 140,  48,  48,  48, 527, 528, 192, 140, 140,
+   140, 140, 140, 140, 140, 140, 140, 140,  48,  48, 529, 530, 531, 532, 140, 140,
+    48,  48,  48, 533, 534, 192, 535, 140,  48,  48, 536, 537, 192, 538, 539, 140,
+    48, 540, 541, 542, 313, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+    48,  48, 505, 543, 140, 140, 140, 140, 140, 140,   9,   9,  11,  11, 148, 544,
+   545, 546,  48, 547, 548, 192, 140, 140, 140, 140, 549,  48,  48, 550, 551, 140,
+   552,  48,  48, 553, 554, 555,  48,  48, 556, 557, 558,  48,  48,  48,  48, 196,
+   559, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48,  48, 560, 192,
+    84,  48, 529, 561, 562, 148, 175, 563,  48, 564, 565, 566, 140, 140, 140, 140,
+   567,  48,  48, 568, 569, 192, 570,  48, 571, 572, 192, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 573,
+   574, 115,  48, 575, 576, 577, 140, 140, 140, 140, 140, 100, 271, 578, 579, 580,
+    48,  48,  48,  48,  48,  48,  48,  48,  48, 207, 140, 140, 140, 140, 140, 140,
+   272, 272, 272, 272, 272, 272, 581, 582,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48, 388, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 140, 140, 140, 140, 140,  48,  48,  48,  48,  48,  48, 583,
+    48,  48,  48, 584, 585, 586,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  71,
+    48,  48,  48,  48, 313, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+    48, 587, 588, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+    48,  48,  48, 196,  48, 200, 370,  48,  48,  48,  48, 200, 192,  48, 204, 589,
+    48,  48,  48, 590, 591, 592, 593, 594,  48, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 595,  48, 596, 192, 140, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140,   9,   9,  11,  11, 271, 597, 140, 140, 140, 140, 140, 140,
+    48,  48,  48,  48, 598, 599, 600, 600, 601, 602, 140, 140, 140, 140, 603, 604,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 440,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 199, 140, 605,
+   196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 606,
+    48,  48, 607, 608, 140, 609, 610,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 206,
+    48,  48,  48,  48,  48,  48,  71, 151, 196, 611, 612, 140, 140, 140, 140, 140,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 192,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 322, 140, 140, 140, 140,
+    32,  32, 613,  32, 614, 209, 209, 209, 209, 209, 209, 209, 322, 140, 140, 140,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 323,
+   209, 209, 615, 209, 209, 209, 616, 617, 618, 209, 619, 209, 209, 209, 287, 140,
+   209, 209, 209, 209, 620, 140, 140, 140, 140, 140, 140, 140, 271, 621, 271, 621,
+   209, 209, 209, 209, 209, 338, 271, 461, 140, 140, 140, 140, 140, 140, 140, 140,
+     9, 622,  11, 623, 624, 625, 241,   9, 626, 627, 628, 629, 630,   9, 622,  11,
+   631, 632,  11, 633, 634, 635, 636,   9, 637,  11,   9, 622,  11, 623, 624,  11,
+   241,   9, 626, 636,   9, 637,  11,   9, 622,  11, 638,   9, 639, 640, 641, 642,
+    11, 643,   9, 644, 645, 646, 647,  11, 648,   9, 649,  11, 650, 538, 538, 538,
+    32,  32,  32, 651,  32,  32, 652, 653, 654, 655,  45, 140, 140, 140, 140, 140,
+   656, 657, 658, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   659, 660, 661,  27,  27,  27, 662, 140, 663, 140, 140, 140, 140, 140, 140, 140,
+    48,  48, 151, 664, 665, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 666, 140,  48,  48, 667, 668,
+   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 669, 192,
+   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 587, 670,
+   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 671, 200,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 672, 614, 140, 140,
+     9,   9, 626,  11, 673, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   140, 140, 140, 140, 140, 140, 140, 503, 271, 271, 674, 675, 140, 140, 140, 140,
+   503, 271, 676, 677, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   678,  48, 679, 680, 681, 682, 683, 684, 685, 206, 686, 206, 140, 140, 140, 687,
+   209, 209, 688, 209, 209, 209, 209, 209, 209, 322, 333, 689, 689, 689, 209, 323,
+   690, 209, 209, 209, 209, 209, 209, 209, 209, 209, 691, 140, 140, 140, 692, 209,
+   693, 209, 209, 688, 694, 695, 323, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 696,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 697, 426, 426,
+   209, 209, 209, 209, 209, 209, 209, 698, 209, 209, 209, 209, 209, 176, 688, 427,
+   688, 209, 209, 209, 699, 176, 209, 209, 699, 209, 691, 688, 695, 140, 140, 140,
+   209, 209, 209, 209, 209, 322, 691, 426, 700, 209, 209, 209, 701, 702, 176, 694,
+   209, 209, 209, 209, 209, 209, 209, 209, 209, 703, 209, 209, 209, 209, 209, 192,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 140, 140,
+    48,  48,  48, 207,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48, 204,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 481,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 100,  48,
+    48,  48,  48,  48,  48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+    48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+    48,  48,  48,  48,  71,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 140, 140, 140, 140, 140,
+   704, 140, 584, 584, 584, 584, 584, 584, 140, 140, 140, 140, 140, 140, 140, 140,
     32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32, 140,
-   391, 391, 391, 391, 391, 391, 391, 685, 391, 391, 391, 391, 391, 391, 391, 686,
-     0,   0,   0,   0,   1,   2,   1,   2,   0,   0,   3,   3,   4,   5,   4,   5,
-     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   6,   0,   0,   7,   0,
-     8,   8,   8,   8,   8,   8,   8,   9,  10,  11,  12,  11,  11,  11,  13,  11,
-    14,  14,  14,  14,  14,  14,  14,  14,  15,  14,  14,  14,  14,  14,  14,  14,
-    14,  14,  14,  16,  17,  18,  17,  17,  19,  20,  21,  21,  22,  21,  23,  24,
-    25,  26,  27,  27,  28,  29,  27,  30,  27,  27,  27,  27,  27,  31,  27,  27,
-    32,  33,  33,  33,  34,  27,  27,  27,  35,  35,  35,  36,  37,  37,  37,  38,
-    39,  39,  40,  41,  42,  43,  44,  27,  45,  46,  27,  27,  27,  27,  47,  27,
-    48,  48,  48,  48,  48,  49,  50,  48,  51,  52,  53,  54,  55,  56,  57,  58,
-    59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,
-    75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
-    91,  92,  93,  94,  95,  96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106,
-   107, 108, 109, 109, 110, 111, 112, 109, 113, 114, 115, 116, 117, 118, 119, 120,
-   121, 122, 122, 123, 122, 124, 125, 125, 126, 127, 128, 129, 130, 131, 125, 125,
-   132, 132, 132, 132, 133, 132, 134, 135, 132, 133, 132, 136, 136, 137, 125, 125,
-   138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 140, 139, 139, 141,
-   142, 142, 142, 142, 142, 142, 142, 142, 143, 143, 143, 143, 144, 145, 143, 143,
-   144, 143, 143, 146, 147, 148, 143, 143, 143, 147, 143, 143, 143, 149, 143, 150,
-   143, 151, 152, 152, 152, 152, 152, 153, 154, 154, 154, 154, 154, 154, 154, 154,
-   155, 156, 157, 157, 157, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
-   168, 168, 168, 168, 168, 169, 170, 170, 171, 172, 173, 173, 173, 173, 173, 174,
-   173, 173, 175, 154, 154, 154, 154, 176, 177, 178, 179, 179, 180, 181, 182, 183,
-   184, 184, 185, 184, 186, 187, 168, 168, 188, 189, 190, 190, 190, 191, 190, 192,
-   193, 193, 194,   8, 195, 125, 125, 125, 196, 196, 196, 196, 197, 196, 196, 198,
-   199, 199, 199, 199, 200, 200, 200, 201, 202, 202, 202, 203, 204, 205, 205, 205,
-   206, 139, 139, 207, 208, 209, 210, 211,   4,   4, 212,   4,   4, 213, 214, 215,
-     4,   4,   4, 216,   8,   8,   8,   8,  11, 217,  11,  11, 217, 218,  11, 219,
-    11,  11,  11, 220, 220, 221,  11, 222, 223,   0,   0,   0,   0,   0, 224, 225,
-   226, 227,   0,   0, 228,   8,   8, 229,   0,   0, 230, 231, 232,   0,   4,   4,
-   233,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0, 234, 125, 235, 125,   0,   0, 236, 236, 236, 236, 236, 236, 236, 236,
-     0,   0,   0,   0,   0,   0,   0, 237,   0, 238,   0,   0,   0,   0,   0,   0,
-   239, 239, 239, 239, 239, 239,   4,   4, 240, 240, 240, 240, 240, 240, 240, 241,
-   139, 139, 140, 242, 242, 242, 243, 244, 143, 245, 246, 246, 246, 246,  14,  14,
-     0,   0,   0,   0,   0, 247, 125, 125, 248, 249, 248, 248, 248, 248, 248, 250,
-   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 125,   0,
-   252,   0, 253, 254, 255, 256, 256, 256, 256, 257, 258, 259, 259, 259, 259, 260,
-   261, 262, 262, 263, 142, 142, 142, 142, 264,   0, 262, 262,   0,   0, 265, 259,
-   142, 264,   0,   0,   0,   0, 142, 266,   0,   0,   0,   0,   0, 259, 259, 267,
-   259, 259, 259, 259, 259, 268,   0,   0, 248, 248, 248, 248,   0,   0,   0,   0,
-   269, 269, 269, 269, 269, 269, 269, 269, 270, 269, 269, 269, 271, 272, 272, 272,
-   273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 274, 125,  14,  14,  14,  14,
-    14,  14, 275, 275, 275, 275, 275, 276,   0,   0, 277,   4,   4,   4,   4,   4,
-   278,   4,   4,   4, 279, 280, 125, 281, 282, 282, 283, 284, 285, 285, 285, 286,
-   287, 287, 287, 287, 288, 289,  48,  48, 290, 290, 291, 292, 292, 293, 142, 294,
-   295, 295, 295, 295, 296, 297, 138, 298, 299, 299, 299, 300, 301, 302, 138, 138,
-   303, 303, 303, 303, 304, 305, 306, 307, 308, 309, 246,   4,   4, 310, 311, 152,
-   152, 152, 152, 152, 306, 306, 312, 313, 142, 142, 314, 142, 315, 142, 142, 316,
-   125, 125, 125, 125, 125, 125, 125, 125, 248, 248, 248, 248, 248, 248, 317, 248,
-   248, 248, 248, 248, 248, 318, 125, 125, 319, 320,  21, 321, 322,  27,  27,  27,
-    27,  27,  27,  27, 323, 324,  27,  27,  27,  27,  27,  27,  27,  27,  27,  27,
-    27,  27,  27, 325,  27,  27,  27,  27,  27, 326,  27,  27, 327, 125, 125,  27,
-     8, 284, 328,   0,   0, 329, 330, 331,  27,  27,  27,  27,  27,  27,  27, 332,
-   333,   0,   1,   2,   1,   2, 334, 258, 259, 335, 142, 264, 336, 337, 338, 339,
-   340, 341, 342, 343, 344, 344, 125, 125, 341, 341, 341, 341, 341, 341, 341, 345,
-   346,   0,   0, 347,  11,  11,  11,  11, 348, 349, 350, 125, 125,   0,   0, 351,
-   352, 353, 354, 354, 354, 355, 356, 357, 358, 358, 359, 360, 361, 362, 362, 363,
-   364, 365, 366, 366, 367, 368, 125, 125, 369, 369, 369, 369, 369, 370, 370, 370,
-   371, 372, 373, 374, 374, 375, 374, 376, 377, 377, 378, 379, 379, 379, 380, 381,
-   381, 382, 383, 384, 125, 125, 125, 125, 385, 385, 385, 385, 385, 385, 385, 385,
-   385, 385, 385, 386, 385, 387, 388, 125, 389,   4,   4, 390, 125, 125, 125, 125,
-   391, 392, 392, 393, 394, 395, 396, 396, 397, 398, 399, 125, 125, 125, 400, 401,
-   402, 403, 404, 405, 125, 125, 125, 125, 406, 406, 407, 408, 407, 409, 407, 407,
-   410, 411, 412, 413, 414, 414, 415, 415, 416, 416, 125, 125, 417, 417, 418, 419,
-   420, 420, 420, 421, 422, 423, 424, 425, 426, 427, 428, 125, 125, 125, 125, 125,
-   429, 429, 429, 429, 430, 125, 125, 125, 431, 431, 431, 432, 431, 431, 431, 433,
-   434, 434, 435, 436, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,  27,  45,
-   437, 437, 438, 439, 125, 125, 125, 440, 441, 441, 442, 443, 443, 444, 125, 445,
-   446, 125, 125, 447, 448, 125, 449, 450, 451, 451, 451, 451, 452, 453, 451, 454,
-   455, 455, 455, 455, 456, 457, 458, 459, 460, 460, 460, 461, 462, 463, 463, 464,
-   465, 465, 465, 465, 465, 465, 466, 467, 468, 469, 468, 468, 470, 125, 125, 125,
-   471, 472, 473, 474, 474, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484,
-   485, 485, 485, 485, 485, 486, 487, 125, 488, 488, 488, 488, 489, 490, 125, 125,
-   491, 491, 491, 492, 491, 493, 125, 125, 494, 494, 494, 494, 495, 496, 497, 125,
-   498, 498, 498, 499, 499, 125, 125, 125, 500, 501, 502, 500, 503, 125, 125, 125,
-   504, 504, 504, 505, 125, 125, 125, 125, 125, 125, 506, 506, 506, 506, 506, 507,
-   508, 509, 510, 511, 512, 513, 125, 125, 125, 125, 514, 515, 515, 514, 516, 125,
-   517, 517, 517, 517, 518, 519, 519, 519, 519, 519, 520, 154, 521, 521, 521, 522,
-   523, 125, 125, 125, 125, 125, 125, 125, 524, 525, 525, 526, 527, 525, 528, 529,
-   529, 530, 531, 532, 125, 125, 125, 125, 533, 534, 534, 535, 536, 537, 538, 539,
-   540, 541, 542, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 543, 544,
-   545, 546, 545, 547, 545, 548, 125, 125, 125, 125, 125, 549, 550, 550, 550, 551,
-   552, 552, 552, 552, 552, 552, 552, 552, 552, 553, 125, 125, 125, 125, 125, 125,
-   552, 552, 552, 552, 552, 552, 554, 555, 552, 552, 552, 552, 556, 125, 125, 125,
-   125, 557, 557, 557, 557, 557, 557, 558, 559, 559, 559, 559, 559, 559, 559, 559,
-   559, 559, 559, 559, 559, 560, 125, 125, 561, 561, 561, 561, 561, 561, 561, 561,
-   561, 561, 561, 561, 562, 125, 125, 125, 275, 275, 275, 275, 275, 275, 275, 275,
-   275, 275, 275, 563, 564, 565, 566, 567, 567, 567, 567, 568, 569, 570, 571, 572,
-   573, 573, 573, 573, 574, 575, 576, 577, 573, 125, 125, 125, 125, 125, 125, 125,
-   125, 125, 125, 125, 578, 578, 578, 578, 578, 579, 125, 125, 125, 125, 125, 125,
-   580, 580, 580, 580, 581, 580, 580, 580, 582, 580, 125, 125, 125, 125, 583, 584,
-   585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 586,
-   587, 587, 587, 587, 587, 587, 587, 587, 587, 587, 587, 587, 587, 588, 125, 125,
-   589, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 590,
-   591, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
-   256, 256, 592, 593, 125, 594, 595, 596, 596, 596, 596, 596, 596, 596, 596, 596,
-   596, 596, 596, 596, 596, 596, 596, 597, 598, 598, 598, 598, 598, 598, 599, 600,
-   601, 602, 603, 125, 125, 125, 125, 125,   8,   8, 604,   8, 605,   0,   0,   0,
-     0,   0,   0,   0, 603, 125, 125, 125,   0,   0,   0,   0,   0,   0,   0, 606,
-     0,   0, 607,   0,   0,   0, 608, 609, 610,   0, 611,   0,   0,   0, 235, 125,
-    11,  11,  11,  11, 612, 125, 125, 125, 125, 125, 125, 125,   0, 603,   0, 603,
-     0,   0,   0,   0,   0, 234,   0, 613,   0,   0,   0,   0,   0, 224,   0,   0,
-     0, 614, 615, 616, 617,   0,   0,   0, 618, 619,   0, 620, 621, 622,   0,   0,
-     0,   0, 623,   0,   0,   0,   0,   0,   0,   0,   0,   0, 624,   0,   0,   0,
-   625, 625, 625, 625, 625, 625, 625, 625, 626, 627, 628, 125, 125, 125, 125, 125,
-     4, 629, 630, 125, 125, 125, 125, 125, 631, 632, 633,  14,  14,  14, 634, 125,
-   635, 125, 125, 125, 125, 125, 125, 125, 636, 636, 637, 638, 639, 125, 125, 125,
-   125, 640, 641, 125, 642, 642, 642, 643, 125, 125, 125, 125, 125, 644, 644, 645,
-   125, 125, 125, 125, 125, 125, 646, 647, 648, 648, 648, 648, 648, 648, 648, 648,
-   648, 648, 648, 648, 649, 650, 125, 125, 651, 651, 651, 651, 652, 653, 125, 125,
-   125, 125, 125, 125, 125, 125, 125, 333,   0,   0,   0, 654, 125, 125, 125, 125,
-   333,   0,   0, 247, 125, 125, 125, 125, 655,  27, 656, 657, 658, 659, 660, 661,
-   662, 663, 664, 663, 125, 125, 125, 665,   0,   0, 357,   0,   0,   0,   0,   0,
-     0, 603, 226, 333, 333, 333,   0, 606,   0,   0, 247, 125, 125, 125, 666,   0,
-   667,   0,   0, 357, 613, 668, 606, 125,   0,   0,   0,   0,   0, 669, 349, 349,
-     0,   0,   0,   0,   0,   0,   0, 670,   0,   0,   0,   0,   0, 284, 357, 228,
-   357,   0,   0,   0, 671, 284,   0,   0, 671,   0, 247, 668, 125, 125, 125, 125,
-     0,   0,   0,   0,   0, 603, 247, 349, 613,   0,   0, 672, 673, 357, 613, 613,
-     0, 329,   0,   0, 235, 125, 125, 284, 248, 248, 248, 248, 248, 248, 125, 125,
-   248, 248, 248, 318, 248, 248, 248, 248, 248, 317, 248, 248, 248, 248, 248, 248,
-   248, 248, 584, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 674, 248,
-   248, 248, 248, 248, 248, 317, 125, 125, 248, 317, 125, 125, 125, 125, 125, 125,
-   248, 248, 248, 248, 675, 248, 248, 248, 248, 248, 248, 125, 125, 125, 125, 125,
-   676, 125,   0,   0,   0,   0,   0,   0,   8,   8,   8,   8,   8,   8,   8,   8,
-     8,   8,   8,   8,   8,   8,   8,   0,   0,   0,   0,   0,   1,   2,   2,   2,
-     2,   2,   3,   0,   0,   0,   4,   0,   2,   2,   2,   2,   2,   3,   2,   2,
-     2,   2,   5,   0,   2,   5,   6,   0,   7,   7,   7,   7,   8,   9,  10,  11,
-    12,  13,  14,  15,   8,   8,   8,   8,  16,   8,   8,   8,  17,  18,  18,  18,
-    19,  19,  19,  19,  19,  20,  19,  19,  21,  22,  22,  22,  22,  22,  22,  22,
-    22,  23,  21,  22,  22,  22,  23,  21,  24,  25,  25,  25,  25,  25,  25,  25,
-    25,  25,  12,  12,  25,  25,  26,  27,  25,  28,  12,  12,  29,  30,  29,  31,
-    29,  29,  32,  32,  29,  29,  29,  29,  31,  29,  33,   7,   7,  34,  29,  29,
-    35,  29,  29,  29,  29,  29,  29,  30,  36,  36,  36,  37,  36,  36,  36,  36,
-    36,  36,  38,  39,  40,  40,  40,  40,  41,  12,  12,  12,  42,  42,  42,  42,
-    42,  42,  43,  44,  45,  45,  45,  45,  45,  45,  45,  46,  45,  45,  45,  47,
-    48,  48,  48,  48,  48,  48,  48,  49,  36,  36,  38,  12,  29,  29,  29,  50,
-    51,  12,  29,  29,  52,  29,  29,  29,  53,  53,  53,  53,  54,  55,  53,  53,
-    53,  56,  53,  53,  57,  58,  57,  59,  59,  57,  57,  57,  57,  57,  60,  57,
-    61,  62,  63,  57,  57,  59,  59,  64,  12,  65,  12,  66,  57,  62,  57,  57,
-    57,  57,  57,  64,  67,  67,  68,  69,  70,  71,  71,  71,  71,  71,  72,  71,
-    72,  73,  74,  72,  68,  69,  70,  74,  75,  12,  67,  76,  12,  77,  71,  71,
-    71,  68,  12,  12,  78,  78,  79,  80,  80,  79,  79,  79,  79,  79,  81,  79,
-    81,  78,  82,  79,  79,  80,  80,  82,  83,  12,  12,  12,  79,  84,  79,  79,
-    82,  12,  78,  79,  85,  85,  86,  87,  87,  86,  86,  86,  86,  86,  88,  86,
-    88,  85,  89,  86,  86,  87,  87,  89,  12,  85,  12,  90,  86,  91,  86,  86,
-    86,  86,  12,  12,  92,  93,  94,  92,  95,  96,  97,  95,  98,  99,  94,  92,
-   100, 100,  96,  92,  94,  92,  95,  96,  99,  98,  12,  12,  12,  92, 100, 100,
-   100, 100,  94,  12, 101, 101, 101, 102, 102, 101, 101, 101, 101, 101, 102, 101,
-   101, 101, 103, 101, 101, 102, 102, 103,  12, 104, 105, 106, 101, 107, 101, 101,
-    12, 108, 101, 101, 109, 109, 109, 110, 110, 109, 109, 109, 109, 109, 110, 109,
-   109, 111, 112, 109, 109, 110, 110, 112,  12, 113,  12, 113, 109, 114, 109, 109,
-   111,  12,  12,  12, 115, 115, 115, 116, 116, 115, 115, 115, 115, 115, 115, 115,
-   115, 116, 116, 115,  12, 115, 115, 115, 115, 117, 115, 115, 118, 118, 119, 119,
-   119, 120, 121, 119, 119, 119, 119, 119, 122, 119, 119, 123, 119, 120, 124, 125,
-   119, 126, 119, 119,  12, 121, 119, 119, 121, 127,  12,  12, 128, 129, 129, 129,
-   129, 129, 129, 129, 129, 129, 130, 131, 129, 129, 129,  12,  12,  12,  12,  12,
-   132, 133, 134, 135, 135, 135, 135, 135, 135, 136, 135, 135, 135, 135, 135, 137,
-   135, 138, 135, 134, 135, 135, 137, 135, 139, 139, 139, 139, 139, 139, 140, 139,
-   139, 139, 139, 141, 140, 139, 139, 139, 139, 139, 139, 142, 139, 143, 144,  12,
-   145, 145, 145, 145, 146, 146, 146, 146, 146, 147,  12, 148, 146, 146, 149, 146,
-   150, 150, 150, 150, 151, 151, 151, 151, 151, 151, 152, 153, 151, 154, 152, 153,
-   152, 153, 151, 154, 152, 153, 151, 151, 151, 154, 151, 151, 151, 151, 154, 155,
-   151, 151, 151, 156, 151, 151, 153,  12, 157, 157, 157, 157, 157, 158, 157, 158,
-   159, 159, 159, 159, 160, 160, 160, 160, 160, 160, 160, 161, 162, 162, 162, 162,
-   162, 162, 163, 164, 162, 162, 165,  12, 166, 166, 166, 166, 166, 167,  12, 168,
-   169, 169, 169, 169, 169, 170,  12,  12, 171, 171, 171, 171, 171,  12,  12,  12,
-   172, 172, 172, 173, 173,  12,  12,  12, 174, 174, 174, 174, 174, 174, 174, 175,
-   174, 174, 175,  12, 176, 177, 178, 178, 178, 178, 179,  12, 178, 178, 178, 178,
-   178, 178, 180,  12, 178, 178, 181,  12, 159, 182,  12,  12, 183, 183, 183, 183,
-   183, 183, 183, 184, 183, 183, 183,  12, 185, 183, 183, 183, 186, 186, 186, 186,
-   186, 186, 186, 187, 186, 188,  12,  12, 189, 189, 189, 189, 189, 189, 189,  12,
-   189, 189, 190,  12, 189, 189, 191, 192, 193, 193, 193, 193, 193, 193, 193, 194,
-   195, 195, 195, 195, 195, 195, 195, 196, 195, 195, 195, 197, 195, 195, 198,  12,
-   195, 195, 195, 198,   7,   7,   7, 199, 200, 200, 200, 200, 200, 200, 200, 201,
-   200, 200, 200, 202, 203, 203, 203, 203, 204, 204, 204, 204, 204,  12,  12, 204,
-   205, 205, 205, 205, 205, 205, 206, 205, 205, 205, 207, 208, 209, 209, 209, 209,
-    19,  19, 210,  12, 146, 146, 211, 212, 203, 203,  12,  12, 213,   7,   7,   7,
-   214,   7, 215, 216,   0, 215, 217,  12,   2, 218, 219,   2,   2,   2,   2, 220,
-   221, 218, 222,   2,   2,   2, 223,   2,   2,   2,   2, 224,   8, 225,   8, 225,
-     8,   8, 226, 226,   8,   8,   8, 225,   8,  15,   8,   8,   8,  10,   8, 227,
-    10,  15,   8,  14,   0,   0,   0, 228,   0, 229,   0,   0, 230,   0,   0, 231,
-     0,   0,   0, 232,   2,   2,   2, 233, 234,  12,  12,  12, 235,  12,  12,  12,
-     0, 236, 237,   0,   4,   0,   0,   0,   0,   0,   0,   4,   2,   2,   5,  12,
-     0, 232,  12,  12,   0,   0, 232,  12, 238, 238, 238, 238,   0, 239,   0,   0,
-     0, 240,   0,   0, 241, 241, 241, 241,  18,  18,  18,  18,  18,  12, 242,  18,
-   243, 243, 243, 243, 243, 243,  12, 244, 245,  12,  12, 244, 151, 154,  12,  12,
-   151, 154, 151, 154,   0,   0,   0, 246, 247, 247, 247, 247, 247, 247, 248, 247,
-   247,  12,  12,  12, 247, 249,  12,  12,   0, 250,   0,   0, 251, 247, 252, 253,
-     0,   0, 247,   0, 254, 255, 255, 255, 255, 255, 255, 255, 255, 256, 257, 258,
-   259, 260, 260, 260, 260, 260, 260, 260, 260, 260, 261, 259,  12, 262, 263, 263,
-   263, 263, 263, 263, 264, 150, 150, 150, 150, 150, 150, 265,   0,  12,  12, 131,
-   150, 150, 150, 266, 260, 260, 260, 261, 260, 260,   0,   0, 267, 267, 267, 267,
-   267, 267, 267, 268, 267, 269,  12,  12, 270, 270, 270, 270, 271, 271, 271, 271,
-   271, 271, 271,  12, 272, 272, 272, 272, 272, 272,  12,  12, 237,   2,   2,   2,
-     2,   2, 231,   2,   2,   2, 273,  12, 274, 275, 276,  12, 277,   2,   2,   2,
-   278, 278, 278, 278, 278, 278, 278, 279,   0,   0, 246,  12, 280, 280, 280, 280,
-   280, 280,  12,  12, 281, 281, 281, 281, 281, 282,  12, 283, 281, 281, 282,  12,
-   284, 284, 284, 284, 284, 284, 284, 285, 286, 286, 286, 286, 286,  12,  12, 287,
-   150, 150, 150, 288, 289, 289, 289, 289, 289, 289, 289, 290, 289, 289, 291, 292,
-   145, 145, 145, 293, 294, 294, 294, 294, 294, 295,  12,  12, 294, 294, 294, 296,
-   294, 294, 296, 294, 297, 297, 297, 297, 298,  12,  12,  12,  12,  12, 299, 297,
-   300, 300, 300, 300, 300, 301,  12,  12, 155, 154, 155, 154, 155, 154,  12,  12,
-     2,   2,   3,   2,   2, 302, 303,  12, 300, 300, 300, 304, 300, 300, 304,  12,
-   150,  12,  12,  12, 150, 265, 305, 150, 150, 150, 150,  12, 247, 247, 247, 249,
-   247, 247, 249,  12,   2, 273,  12,  12, 306,  22,  12,  24,  25,  26,  25, 307,
-   308, 309,  25,  25,  50,  12,  12,  12, 310,  29,  29,  29,  29,  29,  29, 311,
-   312,  29,  29,  29,  29,  29,  12, 310,   7,   7,   7, 313, 232,   0,   0,   0,
-     0, 232,   0,  12,  29, 314,  29,  29,  29,  29,  29, 315, 316,   0,   0,   0,
-     0, 317, 260, 260, 260, 260, 260, 318, 319, 150, 319, 150, 319, 150, 319, 288,
-     0, 232,   0, 232,  12,  12, 316, 246, 320, 320, 320, 321, 320, 320, 320, 320,
-   320, 322, 320, 320, 320, 320, 322, 323, 320, 320, 320, 324, 320, 320, 322,  12,
-   232, 131,   0,   0,   0, 131,   0,   0,   8,   8,   8,  14,   0,   0,   0, 234,
-   325,  12,  12,  12,   0,   0,   0, 326, 327, 327, 327, 327, 327, 327, 327, 328,
-   329, 329, 329, 329, 330,  12,  12,  12, 215,   0,   0,   0,   0,   0,   0,  12,
-   331, 331, 331, 331, 331,  12,  12, 332, 333, 333, 333, 333, 333, 333, 334,  12,
-   335, 335, 335, 335, 335, 335, 336,  12, 337, 337, 337, 337, 337, 337, 337, 338,
-   339, 339, 339, 339, 339,  12, 339, 339, 339, 340,  12,  12, 341, 341, 341, 341,
-   342, 342, 342, 342, 343, 343, 343, 343, 343, 343, 343, 344, 343, 343, 344,  12,
-   345, 345, 345, 345, 345,  12, 345, 345, 345, 345, 345,  12, 346, 346, 346, 346,
-   346, 346,  12,  12, 347, 347, 347, 347, 347,  12,  12, 348, 349, 349, 350, 349,
-   350, 351, 349, 349, 351, 349, 349, 349, 351, 349, 351, 352, 353, 353, 353, 353,
-   353, 354,  12,  12, 353, 355,  12,  12, 353, 353,  12,  12,   2, 274,   2,   2,
-   356,   2, 273,  12, 357, 358, 359, 357, 357, 357, 357, 357, 357, 360, 361, 362,
-   363, 363, 363, 363, 363, 364, 363, 363, 365, 365, 365, 365, 366, 366, 366, 366,
-   366, 366, 366, 367,  12, 368, 366, 366, 369, 369, 369, 369, 370, 371, 372, 369,
-   373, 373, 373, 373, 373, 373, 373, 374, 375, 375, 375, 375, 375, 375, 376, 377,
-   378, 378, 378, 378, 379, 379, 379, 379, 379, 379,  12, 379, 380, 379, 379, 379,
-   381, 382,  12, 381, 381, 383, 383, 381, 381, 381, 381, 381, 381, 384, 385, 386,
-   381, 381, 387,  12, 388, 388, 388, 388, 389, 389, 389, 389, 390, 390, 390, 390,
-   390, 391, 392, 390, 390, 391,  12,  12, 393, 393, 393, 393, 393, 394, 395, 393,
-   396, 396, 396, 396, 396, 397, 396, 396, 398, 398, 398, 398, 399,  12, 398, 398,
-   400, 400, 400, 400, 401,  12, 402, 403,  12,  12, 402, 400, 404, 404, 404, 404,
-   404, 404, 405,  12, 406, 406, 406, 406, 407,  12,  12,  12, 407,  12, 408, 406,
-   409, 409, 409, 409, 409, 409,  12,  12, 409, 409, 410,  12, 411, 411, 411, 411,
-   411, 411, 412, 413, 413,  12,  12,  12,  12,  12,  12, 414, 415, 415, 415, 415,
-   415, 415,  12,  12, 416, 416, 416, 416, 416, 416, 417,  12, 418, 418, 418, 418,
-   418, 418, 419,  12, 420, 420, 420, 420, 420, 420, 420,  12, 421, 421, 421, 421,
-   421, 422,  12,  12, 423, 423, 423, 423, 423, 423, 423, 424, 425, 423, 423, 423,
-   423, 424,  12, 426, 427, 427, 427, 427, 428,  12,  12, 429, 430, 430, 430, 430,
-   430, 430, 431,  12, 430, 430, 432,  12, 433, 433, 433, 433, 433, 434, 433, 433,
-   433, 433,  12,  12, 435, 435, 435, 435, 435, 436,  12,  12, 437, 437, 437, 437,
-   118, 119, 119, 119, 119, 127,  12,  12, 438, 438, 438, 438, 439, 438, 438, 438,
-   440,  12,  12,  12, 441, 442, 443, 444, 441, 441, 441, 444, 441, 441, 445,  12,
-   446, 446, 446, 446, 446, 446, 447,  12, 446, 446, 448,  12, 449, 450, 449, 451,
-   451, 449, 449, 449, 449, 449, 452, 449, 452, 450, 453, 449, 449, 451, 451, 454,
-   455, 456,  12, 450, 449, 457, 449, 455, 449, 455,  12,  12, 458, 458, 458, 458,
-   458, 458, 458, 459, 460,  12,  12,  12, 461, 461, 461, 461, 461, 461,  12,  12,
-   461, 461, 462,  12, 463, 463, 463, 463, 463, 464, 463, 463, 463, 463, 463, 464,
-   465, 465, 465, 465, 465, 466,  12,  12, 465, 465, 467,  12, 178, 178, 178, 180,
-   468, 468, 468, 468, 468, 468, 469,  12, 470, 470, 470, 470, 470, 470, 471, 472,
-   470, 470, 470,  12, 470, 471,  12,  12, 473, 473, 473, 473, 473, 473, 473,  12,
-   474, 474, 474, 474, 475,  12,  12, 476, 477, 478, 479, 477, 477, 480, 477, 477,
-   477, 477, 477, 477, 477, 481, 482, 477, 477, 478,  12,  12, 477, 477, 483,  12,
-   484, 484, 485, 484, 484, 484, 484, 484, 484, 486,  12,  12, 487, 487, 487, 487,
-   487, 487,  12,  12, 488, 488, 488, 488, 489,  12,  12,  12, 490, 490, 490, 490,
-   490, 490, 491,  12,  53,  53, 492,  12, 493, 493, 494, 493, 493, 493, 493, 493,
-   493, 495, 493, 493, 493, 496,  12,  12, 493, 493, 493, 497, 498, 498, 498, 498,
-   499, 498, 498, 498, 498, 498, 500, 498, 498, 501,  12,  12, 502, 503, 504, 502,
-   502, 502, 502, 502, 502, 503, 505, 504, 502, 502,  12,  12, 502, 502, 506,  12,
-   507, 508, 509, 507, 507, 507, 507, 507, 507, 507, 507, 510, 508, 507, 511,  12,
-   507, 507, 512,  12, 513, 513, 513, 513, 513, 513, 514,  12, 515, 515, 515, 515,
-   516, 515, 515, 515, 515, 515, 517, 518, 515, 515, 519,  12, 520,  12,  12,  12,
-   100, 100, 100, 100,  96,  12,  12,  98, 521, 521, 521, 521, 521, 521, 522,  12,
-   521, 521, 521, 523, 521, 524,  12,  12, 521,  12,  12,  12, 525, 525, 525, 525,
-   526,  12,  12,  12, 527, 527, 527, 527, 527, 528,  12,  12, 529, 529, 529, 529,
-   529, 530,  12,  12, 272, 272, 531,  12, 532, 532, 532, 532, 532, 532, 532, 533,
-   532, 532, 534, 535, 536, 536, 536, 536, 536, 536, 536, 537, 536, 536, 538,  12,
-   539, 539, 539, 539, 539, 539, 539, 540, 539, 540,  12,  12, 541, 541, 541, 541,
-   541, 542,  12,  12, 541, 541, 543, 541, 543, 541, 541, 541, 541, 541,  12, 544,
-   545, 545, 545, 545, 545, 545, 546,  12, 547, 547, 547, 547, 547, 547, 548, 549,
-   547, 547,  12, 549, 550, 551,  12,  12, 249,  12,  12,  12, 552, 552, 552, 552,
-   552, 552,  12,  12, 553, 553, 553, 553, 553, 554,  12,  12, 552, 552, 555,  12,
-   260, 556, 260, 557, 558, 255, 255, 255, 559,  12,  12,  12, 560,  12,  12,  12,
-   256, 561,  12,  12,  12, 260,  12,  12, 562, 562, 562, 562, 562, 562, 562,  12,
-   563, 563, 563, 563, 563, 563, 564,  12, 563, 563, 563, 565, 563, 563, 565,  12,
-   563, 563, 566, 563,   0,  12,  12,  12,   7,   7,   7, 567,   7, 199,  12,  12,
-     0, 246,  12,  12,   0, 232, 316,   0,   0, 568, 228,   0,   0,   0, 568,   7,
-   213, 569,   7,   0,   0,   0, 570, 228,   8, 225,  12,  12,   0,   0, 234,  12,
-     0,   0,   0, 229, 571, 572, 316, 229,   0,   0, 240, 316,   0, 316,   0,   0,
-     0, 240, 232, 316,   0, 229,   0, 229,   0,   0, 240, 232,   0, 573, 239,   0,
-   229,   0,   0,   0,   0, 246,   0,   0,   0,   0,   0, 239, 574, 574, 574, 574,
-   574, 574, 574,  12,  12,  12, 575, 574, 576, 574, 574, 574,   2,   2,   2, 273,
-    12, 275, 273,  12, 241, 577, 241, 241, 241, 241, 578, 241, 579, 580, 577,  12,
-    19,  19,  19, 581,  12,  12,  12, 582, 583, 583, 583, 583, 583, 583, 583, 584,
-   583, 583, 583, 585, 583, 583, 585, 586, 587, 587, 587, 587, 587, 587, 587, 588,
-   589, 589, 589, 589, 589, 589, 590, 591, 592, 592, 592, 592, 592, 592, 593,  12,
-   151, 154, 151, 594, 151, 151, 151, 154, 595, 595, 595, 595, 595, 596, 595, 595,
-   595, 597,  12,  12, 598, 598, 598, 598, 598, 598, 598,  12, 598, 598, 599, 600,
-     0, 234,  12,  12,  29, 414,  29,  29, 601, 602, 414,  29,  50,  29, 603,  12,
-   604, 310, 603, 414, 601, 602, 603, 603, 601, 602,  50,  29,  50,  29, 414, 605,
-    29,  29, 606,  29,  29,  29,  29,  12, 414, 414, 606,  29,  51,  12,  12,  12,
-    12, 239,   0,   0, 607,  12,  12,  12, 246,  12,  12,  12,   0,   0,  12,   0,
-     0, 232, 131,   0,   0,   0,  12,  12,   0,   0,   0, 240,   0, 246,  12, 239,
-   608,  12,  12,  12, 247, 247, 609,  12, 610,  12,  12,  12,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 939, 940, 941, 942,
-   946, 948,   0, 962, 969, 970, 971, 976,1001,1002,1003,1008,   0,1033,1040,1041,
-  1042,1043,1047,   0,   0,1080,1081,1082,1086,1110,   0,   0,1124,1125,1126,1127,
-  1131,1133,   0,1147,1154,1155,1156,1161,1187,1188,1189,1193,   0,1219,1226,1227,
-  1228,1229,1233,   0,   0,1267,1268,1269,1273,1298,   0,1303, 943,1128, 944,1129,
-   954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149,   0,   0, 973,1158,
-   974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175, 991,1176, 993,1178,
-   994,1179,   0,   0,1004,1190,1005,1191,1006,1192,1014,1199,1007,   0,   0,   0,
-  1016,1201,1020,1206,   0,1022,1208,1025,1211,1023,1209,   0,   0,   0,   0,1032,
-  1218,1037,1223,1035,1221,   0,   0,   0,1044,1230,1045,1231,1049,1235,   0,   0,
-  1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258,1069,1255,1077,1264,
-  1074,1261,   0,   0,1083,1270,1084,1271,1085,1272,1088,1275,1089,1276,1096,1283,
-  1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310,   0,1053,1239,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1093,1280,   0,   0,   0,
+   391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 705,
+   391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 706,
+     0,   0,   1,   1,   0,   2,   3,   3,   4,   4,   4,   4,   4,   4,   4,   4,
+     4,   4,   4,   4,   4,   5,   0,   6,   7,   7,   7,   8,   9,  10,  11,  12,
+    13,  13,  13,  13,  14,  13,  13,  13,  13,  15,  16,  17,  18,  19,  20,  21,
+    22,  23,  24,  25,  23,  23,  26,  23,  27,  28,  29,  23,  30,  31,  32,  33,
+    34,  35,  36,  37,  38,  23,  23,  39,  40,  40,  41,  42,  43,  44,  45,  46,
+    47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,
+    63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,
+    79,  80,  81,  82,  83,  84,  85,  82,  86,  86,  87,  88,  89,  90,  91,  82,
+    92,  92,  92,  92,  92,  93,  94,  95,  96,  96,  96,  96,  96,  96,  96,  96,
+    97,  97,  98,  97,  99, 100, 101,  97, 102,  97, 103, 104, 105, 106, 106, 107,
+   108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, 110, 110, 111,
+   112, 113, 114, 115, 116, 116, 117, 118, 119, 120, 120, 121, 120, 122, 108, 123,
+   124, 125, 126, 127, 128, 129, 130, 116, 131, 132, 133, 134, 135, 136, 137,  82,
+   138, 138, 139, 138, 140, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150,
+     4, 151, 152, 153,   4, 154,   7,   7, 155,  11, 156, 157,  11, 158, 159, 160,
+   161,   0,   0, 162, 163,   0, 164, 165,   0, 166, 167,   4, 168,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0, 169, 170,   0,   0,   0,   0,   0,
+   171, 171, 171, 171, 171, 171, 171, 171,   0,   0,   0, 172, 173,   0,   0,   0,
+   174, 174, 174,   4, 175, 175, 175, 176,  93, 177, 178, 179, 180, 181, 181,  13,
+     0,   0, 182,  82, 183, 184, 184, 185, 184, 184, 184, 184, 184, 184, 186, 187,
+   188, 189, 190, 191, 192, 193, 194, 195, 196, 197,  96,  96, 198, 199,   0, 200,
+   201,   0,   0, 202,   0,   0, 203, 204, 194, 194, 205,   0,   0,   0,   0,   0,
+   184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184,   0,   0,
+   206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 207, 206, 208, 209,
+   210, 210, 210, 210, 210, 210, 210, 210, 210, 211,  13,  13,  13, 212, 212, 213,
+     0, 214,   4,   4, 215,   4, 216, 217, 218, 219, 220, 221, 222, 222, 223,  40,
+   224, 225, 226, 227, 228, 228, 229, 230, 231, 232, 233,  92, 234, 234, 235, 236,
+   237, 238, 239, 240, 106, 106, 241, 242,  96,  96,  96,  96,  96, 243, 244, 245,
+    82,  82,  82,  82,  82,  82,  82,  82, 184, 184, 184, 246, 184, 184, 247,  82,
+   248, 249, 250,  23,  23,  23, 251,  23,  23,  23,  23,  23,  23,  23,  23,  23,
+    23, 252,  23,  23, 253,  23, 254, 255, 256, 257, 258, 259,  23,  23,  23, 260,
+   261,   1,   1, 262, 263, 201, 264, 265, 266, 267, 268,  82, 269, 269, 269, 270,
+   271, 272,  11,  11, 273, 274, 187, 275,  82,  82,  82,  82, 276, 277, 278, 279,
+   280, 281, 282, 283, 284, 285, 286,  82, 287, 287, 288, 289, 290, 291, 292, 293,
+   294, 295, 296, 297, 298, 299, 300, 301, 302, 302, 302, 302, 302, 302, 302, 302,
+   302, 303, 304, 305, 306, 307,  82,  82, 308, 309, 310, 311, 312, 313,  82, 314,
+   315, 316,  82,  82, 317, 318, 319, 320, 321, 322, 323, 324, 325,  82, 326, 327,
+   328, 329, 330, 331, 332, 333,  82,  82, 334, 334, 335,  82, 336, 337, 336, 338,
+   339, 340, 341, 342, 343,  82,  82,  82,  82,  82,  82, 344, 345, 346, 347, 348,
+   349, 350, 351, 352, 353, 354, 355, 356, 357, 357, 358, 359, 360, 360, 361, 362,
+   363, 364, 365, 366, 367, 367, 367, 368, 369, 370, 371,  82, 372, 373, 374, 375,
+   376, 377, 378, 379, 380, 381, 382, 383, 384, 384, 385, 386, 387, 387, 388,  82,
+    82,  82,  82,  82, 389, 390, 391,  82, 392, 392, 393, 394, 395, 396, 397, 398,
+   399, 400, 401,  82,  82,  82,  82,  82, 402, 403,  82,  82,  82, 404, 404, 405,
+   406, 407, 408,  82,  82, 409, 410, 411, 412, 412, 413, 414, 414, 415, 416, 417,
+   418,  82,  82,  82,  82,  82, 419, 420, 421, 422, 423, 424, 425, 426,  82,  82,
+   427, 428, 429, 430, 431, 432,  82,  82,  82,  82,  82,  82,  82,  82,  82, 433,
+   434, 435, 436,  82,  82, 437, 438, 439, 440, 440, 440, 440, 440, 440, 440, 440,
+   440, 440, 440, 440, 441,  82,  82,  82, 440, 440, 440, 442, 440, 440, 440, 440,
+   440, 440, 443,  82,  82,  82,  82,  82,  82,  82,  82,  82, 444, 445, 445, 446,
+   447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 448, 447, 447, 447, 447, 447,
+   447, 447, 447, 447, 447, 447, 447, 449, 450, 450, 450, 450, 450, 450, 450, 450,
+   450, 450, 451,  82,  82,  82,  82,  82, 452, 453,  82,  82,  82,  82,  82,  82,
+   212, 212, 212, 212, 212, 212, 212, 212, 212, 454, 455, 456, 457, 458, 459, 460,
+   461, 461, 462, 463, 464,  82,  82,  82,  82,  82, 465, 466,  82,  82,  82,  82,
+    82,  82, 467, 467, 468,  82,  82,  82, 469, 469, 470, 469, 471,  82,  82, 472,
+   473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 474,
+   475, 475, 475, 475, 475, 475, 475, 475, 475, 475, 475, 475, 475, 475, 476, 477,
+   478,  82,  82,  82,  82,  82,  82,  82,  82,  82,  82,  82,  82,  82,  82, 479,
+   480, 191, 191, 191, 191, 191, 191, 191, 191, 481, 482, 483, 484, 484, 484, 484,
+   484, 484, 484, 484, 484, 484, 484, 485, 486, 486, 486, 487, 488, 489,  82,  82,
+     0,   0,   0,   0,   0,   0,   0, 490,   0,   0,   0,   0,   0, 491,  82,  82,
+     7, 492, 493,   0,   0,   0, 489,  82,   0,   0,   0,   0,   0,   0,   0, 494,
+     0, 495,   0, 496, 497, 498,   0, 170,  11,  11, 499,  82,  82,  82, 491, 491,
+     0,   0, 500, 501,  82,  82,  82,  82,   0,   0, 502,   0, 503, 504, 505,   0,
+   506, 507, 508,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 509,   0,   0,
+     0,   0,   0,   0,   0,   0, 510,   0, 511, 511, 511, 511, 511, 511, 511, 511,
+   511, 511, 511, 511, 512, 513,  82,  82, 514, 515,  82,  82,  82,  82,  82,  82,
+   516, 517,  13, 518, 519,  82,  82,  82, 520, 521, 522,  82,  82,  82,  82,  82,
+    82,  82,  82,  82, 523, 524, 525, 526,  82,  82,  82,  82,  82,  82, 527, 528,
+    82,  82,  82,  82,  82,  82, 529, 530,  82,  82,  82,  82,  82,  82,  82, 531,
+   532, 532, 532, 532, 532, 532, 533,  82, 534, 534, 535,  82,  82,  82,  82,  82,
+    82,  82,  82, 536,   0, 537,  82,  82, 261, 182,  82,  82,  82,  82,  82,  82,
+   538, 539, 540, 541, 542, 543,  82, 544,   0, 545,   0,   0, 491, 546, 547, 494,
+     0,   0,   0,   0,   0, 548,  82, 549, 550, 551, 552, 553,  82,  82,  82,  82,
+     0,   0,   0,   0,   0,   0, 554, 555,   0,   0,   0, 556,   0,   0, 490, 557,
+   545,   0, 558,   0, 559, 560, 561,  82,   0,   0, 491, 562, 563,   0, 564, 565,
+     0,   0,   0,   0, 258,   0,   0, 490, 184, 184, 184, 184, 184, 184, 184,  82,
+   184, 247, 184, 184, 184, 184, 184, 184, 566, 184, 184, 184, 184, 184, 184, 184,
+   184, 184, 184, 184, 184, 567, 184, 184, 184, 184, 184, 184, 184, 184, 184, 568,
+   184, 184, 566,  82,  82,  82,  82,  82, 566,  82,  82,  82,  82,  82,  82,  82,
+   184, 184, 569, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 570,  82,  82,
+   571,   0,   0,   0,  82,  82,  82,  82,   7,   7,   7,   7,   7,   7,   7, 572,
+     0,   0,   0,   0,   1,   2,   2,   3,   0,   4,   0,   4,   2,   2,   5,   2,
+     2,   2,   2,   2,   2,   2,   2,   6,   7,   8,   0,   0,   9,   9,   9,   9,
+     9,   9,  10,  11,  12,  13,  14,  14,  15,  14,  14,  14,  14,  14,  14,  14,
+    16,  17,  14,  14,  18,  18,  18,  18,  19,  18,  18,  18,  18,  18,  20,  21,
+    21,  21,  22,  20,  21,  21,  21,  21,  21,  23,  24,  25,  25,  25,  25,  25,
+    25,  26,  25,  25,  25,  27,  28,  26,  29,  30,  31,  32,  31,  31,  31,  31,
+    33,  34,  35,  31,  31,  31,  36,  31,  31,  31,  31,  29,  37,  38,  37,  37,
+    37,  37,  37,  37,  37,  39,  31,  31,  40,  40,  40,  40,  40,  40,  41,  26,
+    42,  42,  42,  42,  42,  42,  42,  43,  44,  44,  44,  44,  44,  45,  44,  46,
+    47,  47,  47,  48,  37,  49,  31,  31,  31,  50,  51,  31,  52,  31,  31,  31,
+    53,  53,  53,  53,  53,  53,  54,  53,  55,  53,  53,  53,  56,  57,  58,  59,
+    59,  60,  61,  62,  57,  63,  64,  65,  66,  59,  59,  67,  68,  69,  70,  71,
+    71,  72,  73,  74,  69,  75,  76,  77,  78,  71,  79,  26,  80,  81,  82,  83,
+    83,  84,  85,  86,  81,  87,  88,  26,  89,  83,  90,  91,  92,  93,  94,  95,
+    95,  96,  97,  98,  93,  99, 100, 101, 102,  95,  95,  26, 103, 104, 105, 106,
+   107, 104, 108, 109, 104, 105, 110,  26, 111, 108, 108, 112, 113, 114, 115, 113,
+   113, 115, 113, 116, 114, 117, 118, 119, 120, 113, 121, 113, 122, 123, 124, 122,
+   122, 124, 125, 126, 123, 127, 128, 128, 129, 122, 130,  26, 131, 132, 133, 131,
+   131, 131, 131, 131, 132, 133, 134, 131, 135, 131, 131, 131, 136, 137, 138, 139,
+   137, 137, 140, 141, 138, 142, 143, 137, 144, 137, 145,  26, 146, 147, 147, 147,
+   147, 147, 147, 148, 147, 147, 147, 149,  26,  26,  26,  26, 150, 151, 152, 152,
+   153, 152, 152, 154, 155, 156, 152, 157, 158, 158, 158, 158, 158, 159, 158, 158,
+   158, 160, 159, 158, 158, 158, 158, 159, 158, 158, 158, 161, 158, 161, 162, 163,
+   164, 164, 164, 164, 165, 165, 165, 165, 166, 167, 165, 165, 165, 165, 165, 168,
+   169, 169, 169, 169, 170, 170, 170, 170, 170, 171, 172, 171, 170, 171, 170, 170,
+   170, 170, 171, 172, 171, 170, 172, 170, 170, 170, 171, 170, 170, 170, 170, 173,
+   170, 170, 170, 174, 170, 170, 170, 175, 176, 176, 176, 176, 176, 176, 177, 177,
+   178, 178, 178, 178, 179, 179, 179, 180, 181, 181, 181, 181, 181, 182, 181, 183,
+   184, 184, 185, 186, 187, 187, 188,  26, 189, 189, 190,  26, 191, 192, 193,  26,
+   194, 194, 194, 194, 194, 194, 194, 195, 194, 196, 194, 196, 197, 198, 198, 199,
+   198, 198, 198, 198, 198, 198, 198, 200, 198, 201, 178, 178, 178, 178, 202,  26,
+   203, 203, 203, 204, 203, 205, 203, 205, 206, 203, 207, 207, 207, 208, 209,  26,
+   210, 210, 210, 210, 210, 211, 210, 210, 210, 212, 210, 213, 214, 214, 214, 215,
+   216, 216, 216, 216, 216, 216, 216, 217, 216, 216, 216, 218, 216, 219, 216, 219,
+   216, 220,   9,   9,   9, 221,  26,  26, 222, 222, 222, 222, 222, 223, 222, 222,
+   224, 224, 224, 224, 225, 225, 225, 225, 225, 225, 226, 227, 228, 228, 228, 228,
+   228, 228, 228, 229, 228, 230, 231, 231, 231, 231, 231, 231,  18, 232, 165, 165,
+   165, 165, 165, 233, 224,  26, 234,   9, 235, 236, 237, 238, 239, 240,   2,   2,
+     2,   2,   2, 241, 242, 243,   2, 244,   2,   2,   2, 245,  14,  14, 246, 246,
+   246, 246,  14, 247,  14,  14,  14, 246,  14,  14, 248,  14, 248,  14, 249, 250,
+    14,  14, 251, 252,   0, 253,   0,   0, 254,   0, 255, 256,   0, 257,   2, 258,
+   259,  26,   9,   9,   9,   9, 260,  26, 261, 262,   4,   0,   0, 263,   0,   0,
+     2, 264,   0,   0,   0, 265,  26,  26,   0, 266,  26,  26, 267, 267, 267, 267,
+     0,   0, 268,   0,   0,   0, 269,   0, 270, 270, 270, 270,  17,  17,  17,  17,
+    17,  17, 271, 272, 166, 167, 273, 273, 273, 273, 273, 273, 273, 274, 275, 274,
+   170, 170, 172,  26, 172, 172, 172, 172,   0,   0,   0, 276, 277, 277, 277, 278,
+   277, 277, 277, 277, 277, 277, 279,  26, 277, 277, 280,  26,  26,  26,   0,   0,
+   281,   0,   0,   0, 282, 283,   0, 284, 285, 286, 286, 286, 286, 286, 286, 286,
+   286, 286, 287, 288, 289, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 291,
+   292, 293, 293, 293, 293, 293, 294, 169, 169, 295,   0,   0, 293, 293, 293, 293,
+   276, 296, 290, 290, 169, 169, 169, 295, 169, 169, 169, 297,   0,   0, 290, 290,
+   290, 290, 290, 298, 290, 290, 290,   0, 299, 299, 299, 299, 299, 300, 299, 299,
+   301,  26, 302, 302, 302, 302, 302, 302, 303, 303, 303, 303, 303, 304,  26,  26,
+   305, 305, 305, 305, 305, 305, 305,  26, 306,   2,   2,   2,   2, 307,   2,   2,
+     2, 308, 309, 258,  26,  26, 310,   2, 311, 311, 311, 311, 311, 312,   0, 265,
+   313, 313, 313, 313, 313, 313, 313,  26, 314, 314, 314, 314, 315, 316, 314, 317,
+   318, 318, 318, 318, 318, 319, 320, 320, 320, 320, 321, 322, 169, 169, 169, 323,
+   324, 324, 324, 324, 324, 325, 324, 326, 164, 164, 164, 327, 328, 328, 328, 328,
+   328, 328, 329,  26, 328, 330, 328, 331, 332, 332, 332, 332, 333,  26,  26, 334,
+   335, 335, 336,  26, 337, 337, 337,  26, 172, 172,   2,   2,   2,   2,   2, 338,
+   339, 340, 176, 176, 335, 335, 335, 335, 335, 341, 335, 342, 343,  26, 169, 169,
+   295, 344, 169, 169, 169, 169, 169, 343, 277, 280, 277, 277, 277, 277, 277, 345,
+   346,  26, 347, 348,  25,  25, 349, 350, 351,  25,  31,  31, 352,  26, 353,  31,
+    31,  31,  31, 354,  31,  31, 355,  31,  31, 356,  26,  26,  26,  26,  31,  31,
+     9,   9,   0, 265,   9, 357,   0,   0,   0,   0, 358,   0, 257, 359, 360,  31,
+    31,  31,  31, 361, 362,   0,   0,   0, 363, 290, 289, 290, 290, 290, 290, 364,
+   365, 365, 365, 366, 257, 257,  26, 367, 368, 369, 368, 368, 370, 368, 368, 371,
+   368, 372, 368, 372, 368, 368, 368, 368, 368, 368, 368, 373, 374,   0,   0,   0,
+     0,   0, 375,   0,  14, 252,   0, 376, 377,  26,  26,  26,   0,   0,   0, 378,
+   379, 379, 379, 380, 381, 381, 381, 381, 381, 381, 382,  26, 383,   0,   0, 359,
+   384, 384, 384, 384, 385, 386, 387, 387, 387, 388, 389, 389, 389, 389, 389, 390,
+   391, 391, 391, 392, 393, 393, 393, 393, 394, 393, 395,  26, 396, 396, 396, 396,
+   396, 396, 397, 397, 397, 397, 397, 397, 398, 398, 398, 399, 398, 400, 401, 401,
+   401, 401, 402, 401, 401, 401, 401, 402, 403, 403, 403, 403, 403,  26, 404, 404,
+   404, 404, 404, 404, 405, 406, 407, 408, 407, 408, 409, 407, 410, 407, 410, 411,
+   412, 412, 412, 412, 412, 412, 413,  26, 414, 414, 414, 414, 414, 414, 415,  26,
+   414, 414, 416,  26, 414,  26,  26,  26, 417,   2,   2,   2,   2,   2, 418, 419,
+   420, 421, 422, 422, 422, 422, 423, 424, 425, 425, 426, 425, 427, 427, 427, 427,
+   428, 428, 428, 429, 430, 428,  26,  26, 431, 431, 432, 433, 434, 434, 434, 435,
+   436, 436, 436, 437, 438, 438, 438, 438, 439, 439, 439, 440, 439, 439, 441, 439,
+   439, 439, 439, 439, 442, 443, 444, 445, 446, 446, 447, 448, 446, 449, 446, 449,
+   450, 450, 450, 450, 451, 451, 451, 451, 452, 452, 452, 452, 453, 454, 453,  26,
+   455, 455, 455, 455, 455, 455, 456, 457, 458, 458, 459, 458, 460, 460, 461, 460,
+   462, 462, 463, 464,  26, 465,  26,  26, 466, 466, 466, 466, 466, 467,  26,  26,
+   468, 468, 468, 468, 468, 468, 469,  26, 468, 468, 469, 470, 471, 471, 471, 471,
+   471,  26, 471, 472, 473, 473, 473, 473, 474, 475, 473, 473, 474, 476,  26,  26,
+    31,  31,  31,  50, 477, 477, 477, 477, 477, 478, 479,  26, 480,  26,  26,  26,
+    26,  26,  26, 481, 482, 482, 482, 482, 482,  26, 483, 483, 483, 483, 483, 484,
+    26,  26, 485, 485, 485, 486,  26,  26,  26,  26, 487, 487, 487, 488,  26,  26,
+   489, 489, 490,  26, 491, 491, 491, 491, 491, 492, 493, 491, 491, 491, 492, 494,
+   495, 495, 495, 495, 496, 497, 498, 498, 498, 499, 498, 500, 501, 501, 501, 501,
+   501, 501, 502, 501, 501,  26, 503, 503, 503, 503, 504,  26, 505, 505, 505, 505,
+   506, 137, 507,  26, 508, 508, 509, 508, 508, 508, 508, 508, 510,  26,  26,  26,
+   511, 512, 513, 514, 513, 515, 516, 516, 516, 516, 516, 516, 516, 517, 516, 518,
+   519, 520, 521, 522, 522, 523, 524, 525, 520, 526, 527, 528, 529, 530, 530,  26,
+   531, 532, 531, 531, 531, 531, 533, 531, 534, 535, 533, 536, 537,  26,  26,  26,
+   538, 538, 538, 538, 538, 538, 538, 539, 540,  26,  26,  26, 541, 541, 541, 541,
+   541,  26, 541, 542, 543, 543, 543, 543, 543, 543, 544, 543, 543, 543, 543, 544,
+   545, 545, 545, 545, 546,  26, 545, 547, 198, 548,  26,  26, 549, 549, 549, 549,
+   549, 549, 549, 550, 549, 550, 164, 164, 551,  26,  26,  26, 552, 552, 552, 553,
+   552, 554, 552, 552, 555,  26,  26,  26, 556, 556, 556, 556, 556, 556, 556, 557,
+   558, 558, 558, 558, 558, 558, 559, 560, 561, 562, 563, 564, 564, 564, 565, 566,
+   561,  26, 564, 567, 568, 569, 568, 568, 568, 568, 568, 569, 570,  26,  26,  26,
+   571, 571, 571, 571, 571,  26, 572, 572, 572, 572, 572, 572, 573,  26, 178, 178,
+   574, 574, 574, 574, 574, 574, 574, 575,  53, 576,  26,  26, 577, 577, 577, 577,
+   578,  26, 577, 578, 579, 580, 579, 579, 579, 579, 581, 579, 582,  26, 579, 579,
+   579, 583, 584, 584, 584, 584, 585, 584, 584, 586, 587,  26, 588, 589, 590, 590,
+   590, 590, 588, 591, 590,  26, 590, 592, 593, 594, 595, 595, 595, 596, 597, 598,
+   595, 599,  26,  26, 600, 600, 600, 601, 602, 602, 603, 602, 602, 602, 602, 604,
+   602, 602, 602, 605,  26,  26, 606,  26, 108, 108, 108, 108, 108, 108, 607, 608,
+   609, 609, 609, 609, 609, 609, 609, 610, 609, 611, 612,  26, 613,  26,  26,  26,
+    26,  26, 614, 614, 614, 614, 614, 614, 614, 614, 615,  26, 616, 616, 616, 616,
+   616, 616, 617,  26, 616, 616, 616, 618, 619, 619, 619, 619, 620,  26,  26,  26,
+   621, 621, 621, 621, 621, 621, 621, 622, 305, 305, 305, 623, 624, 624, 624, 625,
+   624, 626, 627, 627, 627, 627, 627, 627, 627, 627, 627, 628, 627, 629, 630, 630,
+   630, 631, 631,  26, 632, 632, 632, 632, 633,  26, 632, 634, 634, 632, 632, 635,
+   632, 632,  26,  26, 636, 636, 636, 636, 636, 636, 636, 637, 638, 638, 638, 638,
+   638, 638, 638, 639, 640, 640, 640, 640, 640, 641, 640, 640, 640, 642, 640, 640,
+   643,  26, 345,  26, 644, 644, 644, 644, 644, 644, 644,  26, 645, 645, 645, 645,
+   645, 645, 646,  26,  26,  26,  26, 647, 644, 648,  26,  26,  26,  26, 649, 650,
+   651, 286, 286, 286, 652,  26, 653,  26,  26,  26, 654,  26, 655,  26, 656, 656,
+   656, 656, 656, 656, 656, 656, 656, 657, 658, 658, 658, 658, 658, 659, 658, 660,
+   658, 661, 658, 662, 359,  26,  26,  26,   0,   0,   0, 265,   0,   0, 359,  26,
+     9, 663,   9,   9, 221,  26,   0,   0,   0,   0, 276,  26, 257, 362,   0,   0,
+   664, 665,   0, 666, 667, 668,   0,   0,   0, 669,   0,   0, 246,  26,  26,  26,
+     0,   0, 257,  26,   0,   0,   0, 259,   0,   0, 254,   0,   0,   0,   0, 254,
+   670, 671,   0, 672, 673,   0,   0,   0, 269, 674, 254, 254,   0,   0,   0, 675,
+   676, 677, 678,   0, 276,   0,   0,   0,   0, 268,   0,   0, 679, 679, 679, 679,
+   679, 680,  26, 681, 682, 679,  26,  26,   2,   2,   2, 346, 683, 419,  26,  26,
+   684, 270, 270, 685, 686, 687,  18,  18,  18, 688,  26,  26,  26, 689,  26,  26,
+   690, 690, 690, 690, 690, 691, 690, 692, 690, 693,  26,  26,  26,  26, 694, 694,
+   694, 695,  26,  26, 696, 696, 696, 696, 696, 696, 696, 697,  26,  26, 698, 698,
+   698, 698, 698, 699,  26,  26, 700, 700, 700, 700, 700, 701, 172, 702, 170, 172,
+   703, 703, 703, 703, 704, 703, 705,  26, 706, 706, 706, 706, 706, 707, 706, 708,
+    26,  26, 362,   0,   0,   0, 376,  26, 709,  31,  31,  31, 710, 711, 712, 713,
+   714, 715, 710, 716, 710, 712, 712, 717,  31, 718,  31, 719, 720, 718,  31, 719,
+    26,  26, 721,  26,   0, 359,   0,   0,   0, 257, 362,   0, 362,   0, 362,   0,
+     0, 276,  26,  26, 722,   0,   0,   0, 723,  26,   0,   0,   0,   0,   0, 359,
+     0, 259, 265,  26, 276,  26,  26,  26,   0,   0,   0, 724,   0, 376,   0, 376,
+     0,   0, 257, 725,   0, 359, 259,  26,   0,  26,   0, 265,   0,  26,   0,   0,
+     0, 276,   0, 359, 265,  26,  26,  26,   0, 276,   0, 376,   0, 726,   0,   0,
+   257, 722,   0, 727,   0, 265,   0, 259, 277, 277, 277, 280, 345,  26, 277, 277,
+   728,  26, 277, 277, 277, 729, 277, 277, 277, 277,  26,  26, 730,  26,  26,  26,
+     9,   9,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0, 939, 940, 941, 942, 946, 948,   0, 962, 969, 970, 971, 976,
+  1001,1002,1003,1008,   0,1033,1040,1041,1042,1043,1047,   0,   0,1080,1081,1082,
+  1086,1110,   0,   0,1124,1125,1126,1127,1131,1133,   0,1147,1154,1155,1156,1161,
+  1187,1188,1189,1193,   0,1219,1226,1227,1228,1229,1233,   0,   0,1267,1268,1269,
+  1273,1298,   0,1303, 943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145,
+   961,1146, 964,1149,   0,   0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163,
+   988,1173, 990,1175, 991,1176, 993,1178, 994,1179,   0,   0,1004,1190,1005,1191,
+  1006,1192,1014,1199,1007,   0,   0,   0,1016,1201,1020,1206,   0,1022,1208,1025,
+  1211,1023,1209,   0,   0,   0,   0,1032,1218,1037,1223,1035,1221,   0,   0,   0,
+  1044,1230,1045,1231,1049,1235,   0,   0,1058,1244,1064,1250,1060,1246,1066,1252,
+  1067,1253,1072,1258,1069,1255,1077,1264,1074,1261,   0,   0,1083,1270,1084,1271,
+  1085,1272,1088,1275,1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,
+  1309,1121,1310,   0,1053,1239,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1093,1280,   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, 949,1134,1010,1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,
+  1366,   0,1320,1347,1418,1419,1323,1350,   0,   0, 992,1177,1018,1204,1055,1241,
+  1416,1417,1415,1424,1202,   0,   0,   0, 987,1172,   0,   0,1031,1217,1321,1348,
+  1322,1349,1338,1365, 950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,
+  1051,1237,1052,1238,1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263,
+     0,   0, 997,1182,   0,   0,   0,   0,   0,   0, 945,1130, 982,1167,1337,1364,
+  1335,1362,1046,1232,1422,1423,1113,1301,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   8,   9,   0,  10,1425,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   7,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   1,   0,   0,   0,   0,   0,   0,1314,1427,   5,1434,1438,1443,   0,
+  1450,   0,1455,1461,1514,   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,1446,1458,
+  1468,1476,1480,1486,1517,   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,1489,1503,
+  1494,1500,1508,   0,   0,   0,   0,1520,1521,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,1526,1528,   0,1525,   0,   0,   0,1522,   0,   0,   0,   0,
+  1536,1532,1539,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1534,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1556,   0,   0,
+     0,   0,   0,   0,1548,1550,   0,1547,   0,   0,   0,1567,   0,   0,   0,   0,
+  1558,1554,1561,   0,   0,   0,   0,   0,   0,   0,1568,1569,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,1529,1551,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,1523,1545,1524,1546,   0,   0,1527,1549,   0,   0,1570,1571,
+  1530,1552,1531,1553,   0,   0,1533,1555,1535,1557,1537,1559,   0,   0,1572,1573,
+  1544,1566,1538,1560,1540,1562,1541,1563,1542,1564,   0,   0,1543,1565,   0,   0,
+     0,   0,   0,   0,   0,   0,1606,1607,1609,1608,1610,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,1613,   0,1611,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,1612,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1620,   0,   0,
+     0,   0,   0,   0,   0,1623,   0,   0,1624,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1614,1615,1616,1617,
+  1618,1619,1621,1622,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1628,
+  1629,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1625,1626,   0,1627,   0,   0,   0,1634,   0,   0,1635,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1630,1631,1632,
+     0,   0,1633,   0,   0,   0,   0,   0,   0,   0,   0,   0,1639,   0,   0,1638,
+  1640,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1636,1637,   0,   0,   0,   0,   0,   0,1641,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1642,1644,
+  1643,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1645,   0,   0,   0,
+     0,   0,   0,   0,1646,   0,   0,   0,   0,   0,   0,1648,1649,   0,1647,1650,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1651,1653,
+  1652,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1654,   0,
+  1655,1657,1656,   0,   0,   0,   0,1659,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,1660,   0,   0,   0,   0,1661,   0,   0,   0,   0,1662,   0,   0,   0,   0,
+  1663,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1658,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,1664,   0,1665,1673,   0,1674,   0,   0,   0,
+     0,   0,   0,   0,   0,1666,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,1668,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,1669,   0,   0,   0,   0,1670,   0,   0,   0,   0,1671,   0,   0,   0,   0,
+  1672,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1667,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1675,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1676,   0,1677,   0,1678,   0,
+  1679,   0,1680,   0,   0,   0,1681,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1682,
+     0,1683,   0,   0,1684,1685,   0,1686,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0, 953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148,
+   965,1150, 968,1153, 966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,
+  1420,1421, 986,1171, 989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,
+  1015,1200,1329,1356,1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,
+  1026,1212,1028,1214,1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,
+  1334,1361,1336,1363,1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,
+  1689,1690,1065,1251,1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,
+  1075,1262,1079,1266,1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,
+  1099,1286,1100,1287,1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,
+  1108,1296,1114,1302,1119,1308,1122,1311,1123,1312,1186,1260,1293,1305,   0,1394,
+     0,   0,   0,   0, 952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,
+  1693,1695,1371,1375,1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162,
+   972,1157,1326,1353,1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,
+  1054,1240,1048,1234,1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,
+  1395,1400,1398,1403,1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,
+  1408,1413,1407,1412,1409,1414,1109,1297,1117,1306,1116,1304,1112,1300,   0,   0,
+     0,   0,   0,   0,1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,
+  1716,1720,1717,1721,1477,1478,1729,1731,1730,1732,   0,   0,1435,1436,1733,1735,
+  1734,1736,   0,   0,1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,
+  1752,1756,1753,1757,1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,
+  1772,1775,1773,1776,1495,1496,1777,1779,1778,1780,   0,   0,1451,1452,1781,1783,
+  1782,1784,   0,   0,1504,1505,1785,1788,1786,1789,1787,1790,   0,1459,   0,1791,
+     0,1792,   0,1793,1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,
+  1809,1813,1810,1814,1467,  21,1475,  22,1479,  23,1485,  24,1493,  27,1499,  28,
+  1507,  29,   0,   0,1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,
+  1725,1726,1727,1728,1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,
+  1761,1762,1763,1764,1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,
+  1818,1819,1820,1821,1470,1469,1822,1474,1465,   0,1473,1825,1429,1428,1426,  12,
+  1432,   0,  26,   0,   0,1315,1823,1484,1466,   0,1483,1829,1433,  13,1437,  14,
+  1441,1826,1827,1828,1488,1487,1513,  19,   0,   0,1492,1515,1445,1444,1442,  15,
+     0,1831,1832,1833,1502,1501,1516,  25,1497,1498,1506,1518,1457,1456,1454,  17,
+  1453,1313,  11,   3,   0,   0,1824,1512,1519,   0,1511,1830,1449,  16,1460,  18,
+  1464,   4,   0,   0,  30,  31,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  20,   0,   0,   0,   2,   6,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1834,1835,
      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, 949,1134,1010,1195,1050,1236,1090,
-  1277,1341,1368,1340,1367,1342,1369,1339,1366,   0,1320,1347,1418,1419,1323,1350,
-     0,   0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424,1202,   0,   0,   0,
-   987,1172,   0,   0,1031,1217,1321,1348,1322,1349,1338,1365, 950,1135, 951,1136,
-   979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238,1061,1247,1062,1248,
-  1091,1278,1092,1279,1071,1257,1076,1263,   0,   0, 997,1182,   0,   0,   0,   0,
-     0,   0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232,1422,1423,1113,1301,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   8,   9,   0,  10,
-  1425,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0,
-     0,1314,1427,   5,1434,1438,1443,   0,1450,   0,1455,1461,1514,   0,   0,   0,
+     0,   0,1836,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,1837,1839,1838,   0,   0,   0,   0,1840,   0,   0,   0,   0,1841,   0,   0,
+  1842,   0,   0,   0,   0,   0,   0,   0,1843,   0,1844,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,1845,   0,   0,1846,   0,   0,1847,   0,1848,   0,   0,
+     0,   0,   0,   0, 937,   0,1850,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,1849, 936, 938,1851,1852,   0,   0,1853,1854,   0,   0,1855,1856,   0,   0,
+     0,   0,   0,   0,1857,1858,   0,   0,1861,1862,   0,   0,1863,1864,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,1446,1458,1468,1476,1480,1486,1517,   0,   0,   0,
+  1867,1868,1869,1870,1859,1860,1865,1866,   0,   0,   0,   0,   0,   0,1871,1872,
+  1873,1874,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  32,  33,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,1489,1503,1494,1500,1508,   0,   0,   0,   0,1520,
-  1521,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1526,1528,   0,1525,
-     0,   0,   0,1522,   0,   0,   0,   0,1536,1532,1539,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,1534,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,1556,   0,   0,   0,   0,   0,   0,1548,1550,   0,1547,
-     0,   0,   0,1567,   0,   0,   0,   0,1558,1554,1561,   0,   0,   0,   0,   0,
-     0,   0,1568,1569,   0,   0,   0,   0,   0,   0,   0,   0,   0,1529,1551,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1523,1545,1524,1546,
-     0,   0,1527,1549,   0,   0,1570,1571,1530,1552,1531,1553,   0,   0,1533,1555,
-  1535,1557,1537,1559,   0,   0,1572,1573,1544,1566,1538,1560,1540,1562,1541,1563,
-  1542,1564,   0,   0,1543,1565,   0,   0,   0,   0,   0,   0,   0,   0,1606,1607,
-  1609,1608,1610,   0,   0,   0,   0,   0,   0,   0,   0,   0,1613,   0,1611,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1612,
+  1875,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1877,   0,1878,   0,1879,   0,1880,   0,1881,   0,1882,   0,1883,   0,1884,   0,
+  1885,   0,1886,   0,1887,   0,1888,   0,   0,1889,   0,1890,   0,1891,   0,   0,
+     0,   0,   0,   0,1892,1893,   0,1894,1895,   0,1896,1897,   0,1898,1899,   0,
+  1900,1901,   0,   0,   0,   0,   0,   0,1876,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,1902,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1904,   0,1905,   0,1906,   0,1907,   0,1908,   0,1909,   0,1910,   0,1911,   0,
+  1912,   0,1913,   0,1914,   0,1915,   0,   0,1916,   0,1917,   0,1918,   0,   0,
+     0,   0,   0,   0,1919,1920,   0,1921,1922,   0,1923,1924,   0,1925,1926,   0,
+  1927,1928,   0,   0,   0,   0,   0,   0,1903,   0,   0,1929,1930,1931,1932,   0,
+     0,   0,1933,   0, 710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205,
+   241, 336, 524, 601, 663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108,
+   180, 416, 482, 662, 810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492,
+   740, 116, 146, 168, 368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538,
+   553, 588, 642, 758, 811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267,
+   412, 445, 457, 585, 594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345,
+   411, 704, 105, 259, 313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183,
+   228, 529, 650, 697, 424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580,
+   624, 700, 750, 170, 193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384,
+   420, 730, 287, 330, 337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759,
+   154, 163, 198, 473, 683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280,
+   314, 499, 506, 603, 608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126,
+   260, 265, 373, 411, 479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451,
+   502, 516, 537, 583, 791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496,
+   771, 155, 190, 269, 377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175,
+   452, 191, 480, 510, 659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471,
+   707, 111, 636, 156, 153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295,
+   128, 210,   0,   0, 227,   0, 379,   0,   0, 150, 493, 525, 544, 551, 552, 556,
+   783, 576, 604,   0, 661,   0, 703,   0,   0, 735, 743,   0,   0,   0, 793, 794,
+   795, 808, 741, 773, 118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268,
+   270, 317, 327, 329, 335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539,
+   545, 547, 546, 548, 549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607,
+   620, 625, 625, 651, 690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315,
+   869, 623,   0,   0, 102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212,
+   227, 231, 240, 243, 250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335,
+   341, 357, 360, 362, 370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465,
+   477, 535, 485, 490, 493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541,
+   565, 569, 574, 586, 591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699,
+   705, 704, 702, 706, 709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787,
+   790, 802, 825, 848, 847, 857,  55,  65,  66, 883, 892, 916, 822, 824,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,1620,   0,   0,   0,   0,   0,   0,   0,1623,   0,   0,
-  1624,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,1614,1615,1616,1617,1618,1619,1621,1622,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,1628,1629,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,1625,1626,   0,1627,   0,   0,   0,1634,
-     0,   0,1635,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,1630,1631,1632,   0,   0,1633,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,1639,   0,   0,1638,1640,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,1636,1637,   0,   0,   0,   0,   0,   0,
-  1641,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,1642,1644,1643,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,1645,   0,   0,   0,   0,   0,   0,   0,1646,   0,   0,   0,
-     0,   0,   0,1648,1649,   0,1647,1650,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,1651,1653,1652,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,1654,   0,1655,1657,1656,   0,   0,   0,   0,1659,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,1660,   0,   0,   0,   0,1661,   0,
-     0,   0,   0,1662,   0,   0,   0,   0,1663,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,1658,   0,   0,   0,   0,   0,   0,   0,   0,   0,1664,
-     0,1665,1673,   0,1674,   0,   0,   0,   0,   0,   0,   0,   0,1666,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1668,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,1669,   0,   0,   0,   0,1670,   0,
-     0,   0,   0,1671,   0,   0,   0,   0,1672,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,1667,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,1675,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,1676,   0,1677,   0,1678,   0,1679,   0,1680,   0,   0,   0,1681,   0,
+     0,1586,   0,1605,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1602,1603,
+  1934,1935,1574,1575,1576,1577,1579,1580,1581,1583,1584,   0,1585,1587,1588,1589,
+  1591,   0,1592,   0,1593,1594,   0,1595,1596,   0,1598,1599,1600,1601,1604,1582,
+  1578,1590,1597,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1936,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,1937,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1938,   0,
+  1939,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1940,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,1682,   0,1683,   0,   0,1684,1685,   0,1686,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 953,1138, 955,1140,
-   956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153, 966,1151, 967,1152,
-  1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171, 989,1174, 995,1180,
-   998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356,1017,1203,1019,1205,
-  1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214,1029,1215,1030,1216,
-  1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363,1382,1384,1383,1385,
-  1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251,1068,1254,1070,1256,
-  1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266,1078,1265,1095,1282,
-  1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287,1101,1288,1102,1289,
-  1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302,1119,1308,1122,1311,
-  1123,1312,1186,1260,1293,1305,   0,1394,   0,   0,   0,   0, 952,1137, 947,1132,
-  1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375,1370,1374,1373,1377,
-  1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353,1325,1352,1328,1355,
-  1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234,1331,1358,1330,1357,
-  1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403,1397,1402,1399,1404,
-  1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412,1409,1414,1109,1297,
-  1117,1306,1116,1304,1112,1300,   0,   0,   0,   0,   0,   0,1471,1472,1701,1705,
-  1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721,1477,1478,1729,1731,
-  1730,1732,   0,   0,1435,1436,1733,1735,1734,1736,   0,   0,1481,1482,1737,1741,
-  1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757,1490,1491,1765,1768,
-  1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776,1495,1496,1777,1779,
-  1778,1780,   0,   0,1451,1452,1781,1783,1782,1784,   0,   0,1504,1505,1785,1788,
-  1786,1789,1787,1790,   0,1459,   0,1791,   0,1792,   0,1793,1509,1510,1794,1798,
-  1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814,1467,  21,1475,  22,
-  1479,  23,1485,  24,1493,  27,1499,  28,1507,  29,   0,   0,1704,1708,1709,1710,
-  1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728,1740,1744,1745,1746,
-  1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764,1797,1801,1802,1803,
-  1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821,1470,1469,1822,1474,
-  1465,   0,1473,1825,1429,1428,1426,  12,1432,   0,  26,   0,   0,1315,1823,1484,
-  1466,   0,1483,1829,1433,  13,1437,  14,1441,1826,1827,1828,1488,1487,1513,  19,
-     0,   0,1492,1515,1445,1444,1442,  15,   0,1831,1832,1833,1502,1501,1516,  25,
-  1497,1498,1506,1518,1457,1456,1454,  17,1453,1313,  11,   3,   0,   0,1824,1512,
-  1519,   0,1511,1830,1449,  16,1460,  18,1464,   4,   0,   0,  30,  31,   0,   0,
+     0,   0,1941,1942,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1943,
+  1944,   0,   0,   0,   0,   0,   0,1945,   0,1946,   0,   0,   0,   0,   0,   0,
+     0,   0,1947,   0,   0,1948,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,1950,   0,1949,1951,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1953,
+  1952,   0,1954,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1955,1956,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1957,   0,   0,   0,
+     0,   0,   0,   0,   0,1958,1961,1959,1965,1960,1962,1964,1963,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1967,1966,1968,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,  20,   0,   0,   0,   2,   6,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,1834,1835,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1836,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,1837,1839,1838,   0,   0,   0,   0,
-  1840,   0,   0,   0,   0,1841,   0,   0,1842,   0,   0,   0,   0,   0,   0,   0,
-  1843,   0,1844,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1845,   0,   0,
-  1846,   0,   0,1847,   0,1848,   0,   0,   0,   0,   0,   0, 937,   0,1850,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,1849, 936, 938,1851,1852,   0,   0,
-  1853,1854,   0,   0,1855,1856,   0,   0,   0,   0,   0,   0,1857,1858,   0,   0,
-  1861,1862,   0,   0,1863,1864,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,1867,1868,1869,1870,1859,1860,1865,1866,
-     0,   0,   0,   0,   0,   0,1871,1872,1873,1874,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,  32,  33,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,1875,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,1877,   0,1878,   0,1879,   0,1880,   0,
-  1881,   0,1882,   0,1883,   0,1884,   0,1885,   0,1886,   0,1887,   0,1888,   0,
-     0,1889,   0,1890,   0,1891,   0,   0,   0,   0,   0,   0,1892,1893,   0,1894,
-  1895,   0,1896,1897,   0,1898,1899,   0,1900,1901,   0,   0,   0,   0,   0,   0,
-  1876,   0,   0,   0,   0,   0,   0,   0,   0,   0,1902,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,1904,   0,1905,   0,1906,   0,1907,   0,
-  1908,   0,1909,   0,1910,   0,1911,   0,1912,   0,1913,   0,1914,   0,1915,   0,
-     0,1916,   0,1917,   0,1918,   0,   0,   0,   0,   0,   0,1919,1920,   0,1921,
-  1922,   0,1923,1924,   0,1925,1926,   0,1927,1928,   0,   0,   0,   0,   0,   0,
-  1903,   0,   0,1929,1930,1931,1932,   0,   0,   0,1933,   0, 710, 385, 724, 715,
-   455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601, 663, 676, 688, 738,
-   411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662, 810, 275, 462, 658,
-   692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168, 368, 414, 481, 527,
-   606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758, 811, 701, 233, 299,
-   573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585, 594, 766, 167, 613,
-   149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259, 313, 496, 518, 174,
-   542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697, 424, 732, 428, 349,
-   632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170, 193, 245, 297, 374,
-   463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330, 337, 366, 459, 476,
-   509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473, 683, 697, 292, 311,
-   353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603, 608, 752, 778, 782,
-   788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411, 479, 523, 655, 737,
-   823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583, 791, 136, 340, 769,
-   122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269, 377, 391, 406, 432,
-   501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510, 659, 772, 805, 813,
-   397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156, 153, 288, 346, 578,
-   256, 435, 383, 729, 680, 767, 694, 295, 128, 210,   0,   0, 227,   0, 379,   0,
-     0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604,   0, 661,   0, 703,   0,
-     0, 735, 743,   0,   0,   0, 793, 794, 795, 808, 741, 773, 118, 127, 130, 166,
-   169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329, 335, 369, 375, 381,
-   404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548, 549, 550, 554, 555,
-   561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651, 690, 695, 705, 706,
-   716, 717, 733, 735, 777, 786, 790, 315, 869, 623,   0,   0, 102, 145, 134, 115,
-   129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243, 250, 254, 294, 296,
-   303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362, 370, 379, 388, 389,
-   393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490, 493, 507, 512, 514,
-   521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586, 591, 597, 607, 637,
-   647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706, 709, 717, 728, 736,
-   747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848, 847, 857,  55,  65,
-    66, 883, 892, 916, 822, 824,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,1586,   0,1605,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,1602,1603,1934,1935,1574,1575,1576,1577,1579,1580,
-  1581,1583,1584,   0,1585,1587,1588,1589,1591,   0,1592,   0,1593,1594,   0,1595,
-  1596,   0,1598,1599,1600,1601,1604,1582,1578,1590,1597,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,1936,   0,1937,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,1938,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1939,1940,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,1941,1942,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,1944,1943,   0,1945,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,1946,1947,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,1948,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1949,1950,1951,1952,1953,1954,
-  1955,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,1956,1957,1958,1960,1959,1961,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 106, 104, 107, 826,
-   114, 118, 119, 121, 123, 124, 127, 125,  34, 830, 130, 131, 132, 137, 827,  35,
-   133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152,  37, 157, 158, 159, 160,
-    38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179, 181, 182, 182, 182,
-   833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195, 197, 199, 200, 201,
-   203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216, 153, 234, 221, 222,
-   223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244, 836, 837, 247, 248,
-   249, 246, 251,  39,  40, 253, 255, 255, 838, 257, 258, 259, 261, 839, 262, 263,
-   301, 264,  41, 266, 270, 272, 271, 841, 274, 842, 277, 276, 278, 281, 282,  42,
-   283, 284, 285, 286,  43, 843,  44, 289, 290, 291, 293, 934, 298, 845, 845, 621,
-   300, 300,  45, 852, 894, 302, 304,  46, 306, 309, 310, 312, 316,  48,  47, 317,
-   846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334, 335, 336, 338, 339,
-   342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361, 358, 356,  49, 363,
-   365, 367, 364,  50, 369, 371, 851, 376, 386, 378,  53, 381,  52,  51, 140, 141,
-   387, 382, 614,  78, 388, 389, 390, 394, 392, 856,  54, 399, 396, 402, 404, 858,
-   405, 401, 407,  55, 408, 409, 410, 413, 859, 415,  56, 417, 860, 418,  57, 419,
-   422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433, 437, 441, 438, 439,
-   442, 443, 864, 436, 449, 450,  58, 454, 453, 865, 447, 460, 866, 867, 461, 466,
-   465, 464,  59, 467, 470, 469, 472, 828, 475, 868, 478, 870, 483, 485, 486, 871,
-   488, 489, 872, 873, 495, 497,  60, 498,  61,  61, 504, 505, 507, 508, 511,  62,
-   513, 874, 515, 875, 518, 844, 520, 876, 877, 878,  63,  64, 528, 880, 879, 881,
-   882, 530, 531, 531, 533,  66, 534,  67,  68, 884, 536, 538, 541,  69, 885, 549,
-   886, 887, 556, 559,  70, 561, 562, 563, 888, 889, 889, 567,  71, 890, 570, 571,
-    72, 891, 577,  73, 581, 579, 582, 893, 587,  74, 590, 592, 596,  75, 895, 896,
-    76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611, 853,  77, 615, 616,
-    79, 617, 252, 902, 903, 854, 855, 621, 622, 731,  80, 627, 626, 628, 164, 629,
-   630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651, 638, 643, 644, 645,
-   905, 907, 906,  81, 653, 654, 656, 911, 657, 908,  82,  83, 909, 910,  84, 664,
-   665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675,  85, 677, 678,  86, 681,
-   682, 912, 685, 686,  87, 689,  36, 913, 914,  88,  89, 696, 702, 709, 711, 915,
-   712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728, 918, 919, 739, 742,
-   744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762,  90, 764, 922,  91, 775,
-   279, 780, 923, 925,  92,  93, 785, 926,  94, 927, 787, 787, 789, 928, 792,  95,
-   796, 797, 798, 800,  96, 929, 802, 804, 806,  97,  98, 807, 930,  99, 931, 932,
-   933, 814, 100, 816, 817, 818, 819, 820, 821, 935,   0,   0,
+     0,   0,1969,1970,1971,1972,1973,1974,1975,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1976,
+  1977,1978,1980,1979,1981,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0, 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125,
+    34, 830, 130, 131, 132, 137, 827,  35, 133, 139, 829, 142, 143, 112, 144, 145,
+   924, 151, 152,  37, 157, 158, 159, 160,  38, 165, 166, 169, 171, 172, 173, 174,
+   176, 177, 178, 179, 181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189,
+   196, 192, 194, 195, 197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218,
+   213, 219, 214, 216, 153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236,
+   237, 238, 239, 244, 836, 837, 247, 248, 249, 246, 251,  39,  40, 253, 255, 255,
+   838, 257, 258, 259, 261, 839, 262, 263, 301, 264,  41, 266, 270, 272, 271, 841,
+   274, 842, 277, 276, 278, 281, 282,  42, 283, 284, 285, 286,  43, 843,  44, 289,
+   290, 291, 293, 934, 298, 845, 845, 621, 300, 300,  45, 852, 894, 302, 304,  46,
+   306, 309, 310, 312, 316,  48,  47, 317, 846, 318, 323, 324, 325, 324, 328, 329,
+   333, 331, 332, 334, 335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352,
+   354, 359, 850, 361, 358, 356,  49, 363, 365, 367, 364,  50, 369, 371, 851, 376,
+   386, 378,  53, 381,  52,  51, 140, 141, 387, 382, 614,  78, 388, 389, 390, 394,
+   392, 856,  54, 399, 396, 402, 404, 858, 405, 401, 407,  55, 408, 409, 410, 413,
+   859, 415,  56, 417, 860, 418,  57, 419, 422, 424, 425, 861, 840, 862, 426, 863,
+   429, 431, 427, 433, 437, 441, 438, 439, 442, 443, 864, 436, 449, 450,  58, 454,
+   453, 865, 447, 460, 866, 867, 461, 466, 465, 464,  59, 467, 470, 469, 472, 828,
+   475, 868, 478, 870, 483, 485, 486, 871, 488, 489, 872, 873, 495, 497,  60, 498,
+    61,  61, 504, 505, 507, 508, 511,  62, 513, 874, 515, 875, 518, 844, 520, 876,
+   877, 878,  63,  64, 528, 880, 879, 881, 882, 530, 531, 531, 533,  66, 534,  67,
+    68, 884, 536, 538, 541,  69, 885, 549, 886, 887, 556, 559,  70, 561, 562, 563,
+   888, 889, 889, 567,  71, 890, 570, 571,  72, 891, 577,  73, 581, 579, 582, 893,
+   587,  74, 590, 592, 596,  75, 895, 896,  76, 897, 600, 898, 602, 605, 607, 899,
+   900, 609, 901, 611, 853,  77, 615, 616,  79, 617, 252, 902, 903, 854, 855, 621,
+   622, 731,  80, 627, 626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640,
+   635, 641, 646, 651, 638, 643, 644, 645, 905, 907, 906,  81, 653, 654, 656, 911,
+   657, 908,  82,  83, 909, 910,  84, 664, 665, 666, 667, 669, 668, 671, 670, 674,
+   672, 673, 675,  85, 677, 678,  86, 681, 682, 912, 685, 686,  87, 689,  36, 913,
+   914,  88,  89, 696, 702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720,
+   723, 832, 725, 728, 918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760,
+   761, 921, 762,  90, 764, 922,  91, 775, 279, 780, 923, 925,  92,  93, 785, 926,
+    94, 927, 787, 787, 789, 928, 792,  95, 796, 797, 798, 800,  96, 929, 802, 804,
+   806,  97,  98, 807, 930,  99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820,
+   821, 935,   0,   0,
 };
 static const int16_t
 _hb_ucd_i16[92] =
@@ -4403,12 +4615,12 @@ _hb_ucd_i16[92] =
 static inline uint_fast8_t
 _hb_ucd_gc (unsigned u)
 {
-  return u<1114110u?_hb_ucd_u8[6808+(((_hb_ucd_u8[1312+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
+  return u<1114110u?_hb_ucd_u8[6472+(((_hb_ucd_u8[816+(((_hb_ucd_u16[((_hb_ucd_u8[272+(((_hb_ucd_u8[u>>1>>3>>4>>4])<<4)+((u>>1>>3>>4)&15u))])<<4)+((u>>1>>3)&15u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
 }
 static inline uint_fast8_t
 _hb_ucd_ccc (unsigned u)
 {
-  return u<125259u?_hb_ucd_u8[8800+(((_hb_ucd_u8[8244+(((_hb_ucd_u8[7784+(((_hb_ucd_u8[7432+(((_hb_ucd_u8[7186+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
+  return u<125259u?_hb_ucd_u8[8504+(((_hb_ucd_u8[7936+(((_hb_ucd_u8[7460+(((_hb_ucd_u8[7100+(((_hb_ucd_u8[6854+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
 }
 static inline unsigned
 _hb_ucd_b4 (const uint8_t* a, unsigned i)
@@ -4418,55 +4630,55 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i
 static inline int_fast16_t
 _hb_ucd_bmg (unsigned u)
 {
-  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9692+(((_hb_ucd_u8[9460+(((_hb_ucd_u8[9364+(((_hb_ucd_b4(9300+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0;
+  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9396+(((_hb_ucd_u8[9164+(((_hb_ucd_u8[9068+(((_hb_ucd_b4(9004+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0;
 }
 static inline uint_fast8_t
 _hb_ucd_sc (unsigned u)
 {
-  return u<918000u?_hb_ucd_u8[11126+(((_hb_ucd_u16[4040+(((_hb_ucd_u16[2048+(((_hb_ucd_u8[10390+(((_hb_ucd_u8[9940+(u>>2>>2>>3>>4)])<<4)+((u>>2>>2>>3)&15u))])<<3)+((u>>2>>2)&7u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
+  return u<918000u?_hb_ucd_u8[10398+(((_hb_ucd_u16[3952+(((_hb_ucd_u16[2624+(((_hb_ucd_u8[9870+(((_hb_ucd_u8[9644+(u>>3>>2>>3>>4)])<<4)+((u>>3>>2>>3)&15u))])<<3)+((u>>3>>2)&7u))])<<2)+((u>>3)&3u))])<<3)+((u)&7u))]:2;
 }
 static inline uint_fast16_t
 _hb_ucd_dm (unsigned u)
 {
-  return u<195102u?_hb_ucd_u16[6748+(((_hb_ucd_u8[13952+(((_hb_ucd_u8[13570+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
+  return u<195102u?_hb_ucd_u16[6244+(((_hb_ucd_u8[16628+(((_hb_ucd_u8[16246+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
 }
 
 
 #else
 
 static const uint8_t
-_hb_ucd_u8[13386] =
+_hb_ucd_u8[13730] =
 {
     0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,
     7,  7,  7,  7,  9, 10,  7,  7,  7,  7,  7, 11, 12, 12, 12, 13,
-   14, 15, 16, 17, 18, 19, 20, 21, 22, 21, 21, 21, 21, 23,  7,  7,
-    7, 24, 21, 21, 21, 25, 26, 27, 21, 28, 29, 30, 31, 32, 33, 34,
+   14, 15, 16, 17, 18, 19, 20,  7, 21, 22, 22, 22, 23, 24,  7,  7,
+    7, 25, 22, 22, 22, 26, 27, 28, 22, 29, 30, 31, 32, 33, 34, 35,
     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 35, 21, 36,
-    7,  7,  7,  7, 37, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   38, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 21, 22, 36,
+    7,  7,  7,  7, 37, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   38, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
@@ -4486,30 +4698,30 @@ _hb_ucd_u8[13386] =
   100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
   100,100, 34, 34, 34, 34,101,102, 34, 34,103,104,105,106,107,108,
    34, 34,109,110,111,112,113,114,115,116,117,118, 34, 34, 34,119,
-  120,121,122,123,124,125,126,127, 34,128,129,111,130,131,132,133,
-  134,135,136,137,138,139,140,111,141,142,111,143,144,145,146,111,
-  147,148,149,150,151,152,153,111,154,155,156,157,111,158,159,160,
-   34, 34, 34, 34, 34, 34, 34, 34,161, 34, 34,111,111,111,111,111,
-  111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,162,
-   34, 34, 34, 34, 34, 34, 34, 34,163,111,111,111,111,111,111,111,
+  120,121,122,123,124,125,126,127, 34,128,129,130,131,132,133,134,
+  135,136,137,138,139,140,141,142,143,144,111,145,146,147,148,111,
+  149,150,151,152,153,154,155,156,157,158,159,160,111,161,162,163,
+   34, 34, 34, 34, 34, 34, 34, 34,164, 34, 34,111,111,111,111,111,
+  111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,165,
+   34, 34, 34, 34, 34, 34, 34, 34,166, 34, 34, 34, 34, 34, 34, 34,
+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,111,111,111,
   111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-  111,111,111,111,111,111,111,111, 34, 34, 34, 34, 34,111,111,111,
-   34, 34, 34, 34,164,165,166, 34,111,111,111,111,167,168,169,170,
+  111,111,167,111,111,111,111,111,111,111,111,111,111,111,111,111,
+   34, 34, 34, 34,168,169,170, 34,111,111,171,111,172,173,174,175,
    34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,111,111,111,111,111,
   111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,119,
    34, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,111,111,
-  111,111,111,111,111,111,111,111, 34,171,111,111,111,111,111,111,
-  111,111,111,111,111,111,111,111,111,111,111,111,111,111,172, 67,
-   67, 67,173,174,175,130, 65,111,176,177,178,179,180,181,182,183,
-   67, 67, 67, 67,184,185,111,111,111,111,111,111,111,111,186,111,
-  187,188,189,111,111,190,111,111,111,191,111,111,111,111,111, 34,
-   34,192,193,111,111,111,111,111,130,194,195,111, 34,196,111,111,
-   67, 67,197, 67, 67,111, 67,198, 67, 67, 67, 67, 67, 67, 67, 67,
-   67, 67, 67, 67, 67, 67, 67,199,111,111,111,111,111,111,111,111,
-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,111,111,111,
+  111,111,111,111,111,111,111,111, 34,176,111,111,111,111,111,111,
+  111,111,111,111,111,111,111,111, 67,177, 67, 67, 67, 67,178, 67,
+   67, 67,179,180,181,131, 65,111,182,183,184,185,186,187,188,189,
+   67, 67, 67, 67,190,191,111,111,111,111,111,111,111,111,192,111,
+  193,194,195,111,111,196,111,111,111,197,111,198,111,111,111, 34,
+   34,199,200,111,111,111,111,111,131,201,202,111, 34,203,111,111,
+   67, 67,204, 67, 67,111, 67,205, 67, 67, 67, 67, 67, 67, 67, 67,
+   67, 67, 67, 67, 67, 67, 67,177,111,111,111,111,111,111,111,111,
    34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,111,111,111,
    34, 34, 34, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,
-  200,111,188,188,111,111,111,111,111,111,111,111,111,111,111,111,
+  206,111,194,194,111,111,111,111,111,111,111,111,111,111,111,111,
     0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  2,  4,  5,  6,  2,
     7,  7,  7,  7,  7,  2,  8,  9, 10, 11, 11, 11, 11, 11, 11, 11,
    11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
@@ -4544,8 +4756,8 @@ _hb_ucd_u8[13386] =
    36, 36, 36, 36, 36, 64, 43, 43, 43, 43, 40, 21,  2, 40, 69, 20,
    36, 36, 36, 43, 43, 69, 43, 43, 43, 43, 69, 43, 69, 43, 43, 43,
     2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 36, 36, 64, 43, 43,  2,
-   36, 36, 36, 36, 74, 36, 36, 36, 59, 59, 59, 59, 43, 43, 43, 43,
-   36, 36, 36, 36, 75, 43, 43, 43, 43, 76, 43, 43, 43, 43, 43, 43,
+   36, 36, 36, 36, 74, 36, 36, 36, 59, 59, 59, 75, 43, 43, 43, 43,
+   36, 36, 36, 36, 76, 43, 43, 43, 43, 75, 43, 43, 43, 43, 43, 43,
    43, 77, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 77, 65, 78,
    79, 43, 43, 43, 77, 78, 79, 78, 64, 43, 43, 43, 36, 36, 36, 36,
    36, 43,  2,  7,  7,  7,  7,  7, 80, 36, 36, 36, 36, 36, 36, 36,
@@ -4590,130 +4802,135 @@ _hb_ucd_u8[13386] =
    36, 43, 77, 78, 78, 78, 78, 81, 36, 43, 97,  2,  2,  2,  2,  2,
    36, 43, 43, 43, 43, 43, 43, 43, 36, 36, 43, 79, 43, 43, 43, 78,
    78, 78, 78, 77, 79, 43, 43, 43, 43, 43,  2, 80,  2, 60, 64, 43,
-    7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2, 98,  2, 56, 43, 76,
-   36, 75, 36, 36, 36, 36, 36, 36, 36, 36, 64, 65, 36, 36, 36, 36,
+    7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2, 98,  2, 56, 43, 75,
+   36, 76, 36, 36, 36, 36, 36, 36, 36, 36, 64, 65, 36, 36, 36, 36,
    36, 36, 36, 36, 64, 36, 36, 36, 43, 77, 78, 79, 77, 78, 78, 78,
    78, 77, 78, 78, 79, 43, 43, 43, 61, 61,  2,  7,  7,  7,  7,  7,
     7,  7,  7,  7,  7, 27, 27, 61, 36, 36, 36, 64, 77, 79, 43,  2,
    36, 36, 82, 77, 43, 43, 43, 43, 77, 77, 79, 43, 43, 43, 77, 78,
    78, 79, 43, 43, 43, 43, 43, 43,  2,  2,  2, 80,  2,  2,  2,  2,
    43, 43, 43, 43, 43, 43, 43, 99, 43, 43, 81, 36, 36, 36, 36, 36,
-   36, 36, 77, 43, 43, 77, 77, 78, 78, 77, 81, 36, 36, 36, 36, 36,
+   36, 36, 77, 43, 43, 77, 77, 78, 78, 77, 81, 36, 36, 36, 36,  2,
    89, 61, 61, 61, 61, 47, 43, 43, 43, 43, 61, 61, 61, 61, 21,  2,
    43, 81, 36, 36, 36, 36, 36, 36, 82, 43, 43, 78, 43, 79, 43, 36,
    36, 36, 36, 77, 43, 78, 79, 79, 43, 78, 78, 78, 78, 78,  2,  2,
    36, 36, 78, 78, 78, 78, 43, 43, 43, 43, 78, 43, 43, 57,  2,  2,
     7,  7,  7,  7,  7,  7, 86, 36, 36, 36, 36, 36, 40, 40, 40,  2,
-   43, 57, 43, 43, 43, 43, 43, 43, 77, 43, 43, 43, 65, 36, 64, 36,
-   36, 36, 65, 82, 43, 36, 36, 36, 16, 16, 16, 16, 16, 16, 40, 40,
-   40, 40, 40, 40, 40, 44, 16, 16, 16, 16, 16, 16, 44, 16, 16, 16,
-   16, 16, 16, 16, 16,100, 40, 40, 32, 32, 32, 16, 16, 16, 16, 32,
-   16, 16, 16, 16, 11, 11, 11, 11, 16, 16, 16, 16, 34, 11, 11, 11,
-   16, 16, 16, 16,101,101,101,101, 16, 16, 16, 16, 11, 11,102,103,
-   41, 16, 16, 16, 11, 11,102, 41, 16, 16, 16, 16, 11, 11,104, 41,
-  105,105,105,105,105,106, 59, 59, 51, 51, 51,  2,107,108,107,108,
-    2,  2,  2,  2,109, 59, 59,110,  2,  2,  2,  2,111,112,  2,113,
-  114,  2,115,116,  2,  2,  2,  2,  2,  9,114,  2,  2,  2,  2,117,
-   59, 59, 59, 59, 59, 59, 59, 59,118, 40, 27, 27, 27,  8,115,119,
-   27, 27, 27, 27, 27,  8,115, 94, 20, 20, 20, 20, 20, 20, 20, 20,
-   43, 43, 43, 43, 43, 43,120, 48, 99, 48, 99, 43, 43, 43, 43, 43,
-   61,121, 61,122, 61, 34, 11, 16, 11, 32,122, 61, 46, 11, 11, 61,
-   61, 61,121,121,121, 11, 11,123, 11, 11, 35, 36, 39, 61, 16, 11,
-    8,  8, 46, 16, 16, 26, 61,124, 95, 95, 95, 95, 95, 95, 95, 95,
-   95,125,126, 95,127, 61, 61, 61,  8,  8,128, 61, 61,  8, 61, 61,
-  128, 26, 61,128, 61, 61, 61,128, 61, 61, 61, 61, 61, 61, 61,  8,
-   61,128,128, 61, 61, 61, 61, 61, 61, 61,  8,  8,  8,  8,  8,  8,
-    8,  8,  8,  8,  8,  8,  8,  8, 61, 61, 61, 61,  4,  4, 61, 61,
-    8, 61, 61, 61,129,130, 61, 61, 61, 61, 61, 61, 61, 61,128, 61,
-   61, 61, 61, 61, 61, 26,  8,  8,  8,  8, 61, 61, 61, 61, 61, 61,
-   61, 61, 61, 61, 61, 61,  8,  8,  8, 61, 61, 61, 61, 61, 61, 61,
-   27, 27, 27, 27, 27, 27, 61, 61, 61, 61, 61, 61, 61, 27, 27, 27,
-   61, 61, 61, 26, 61, 61, 61, 61, 26, 61, 61, 61, 61, 61, 61, 61,
-   61, 61, 61, 61,  8,  8,  8,  8, 61, 61, 61, 61, 61, 61, 61, 26,
-   61, 61, 61, 61,  4,  4,  4,  4,  4,  4,  4, 27, 27, 27, 27, 27,
-   27, 27, 61, 61, 61, 61, 61, 61,  8,  8,115,131,  8,  8,  8,  8,
-    8,  8,  8,  4,  4,  4,  4,  4,  8,115,132,132,132,132,132,132,
-  132,132,132,132,131,  8,  8,  8,  8,  8,  8,  8,  4,  4,  8,  8,
-    8,  8,  8,  8,  8,  8,  4,  8,  8,  8,128, 26,  8,  8,128, 61,
-   32, 11, 32, 34, 34, 34, 34, 11, 32, 32, 34, 16, 16, 16, 40, 11,
-   32, 32,124, 61, 61,122, 34,133, 43, 32, 16, 16, 50,  2, 90,  2,
-   36, 36, 36, 36, 36, 36, 36, 75,  2,  2,  2,  2,  2,  2,  2, 56,
-    2,107,107,  2,111,112,107,  2,  2,  2,  2,  6,  2, 98,107,  2,
-  107,  4,  4,  4,  4,  2,  2, 80,  2,  2,  2,  2,  2, 51,  2,  2,
-   98,134,  2,  2,  2,  2,  2,  2, 61,  2,135,132,132,132,136, 51,
-   51, 51, 51, 51, 51, 51, 51, 51,  1,  2,137,138,  4,  4,  4,  4,
-    4, 61,  4,  4,  4,  4,139, 94,140, 95, 95, 95, 95, 43, 43, 78,
-  141, 40, 40, 61, 95,142, 58, 61, 72, 36, 36, 36, 36, 36, 36, 36,
-   36, 36, 36, 36, 64,143,144, 63, 36, 36, 36, 36, 36, 58, 40, 63,
-   61, 27, 27, 61, 61, 61, 61, 61, 27, 27, 27, 27, 27, 61, 61, 61,
-   61, 61, 61, 61, 27, 27, 27, 27,145, 27, 27, 27, 27, 27, 27, 27,
-   36, 36, 75, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,146,  2,
-   32, 32, 32, 32, 32, 32, 32, 64, 48,147, 43, 43, 43, 43, 43, 80,
-   32, 32, 32, 32, 32, 32, 40, 43, 36, 36, 36, 95, 95, 95, 95, 95,
-   43,  2,  2,  2,  2,  2,  2,  2, 41, 41, 41,144, 40, 40, 40, 40,
-   41, 32, 32, 32, 32, 32, 32, 32, 16, 32, 32, 32, 32, 32, 32, 32,
-   44, 16, 16, 16, 34, 34, 34, 32, 32, 32, 32, 32, 42,148, 34, 35,
-   32, 32, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 11, 11, 32,
-   11, 11, 32, 32, 32, 32, 32, 32, 32, 32, 11, 11, 34, 16, 16, 16,
-   32, 16, 16, 32, 32, 16, 16, 16, 16, 40,149, 35, 40, 35, 36, 36,
-   36, 65, 36, 65, 36, 64, 36, 36, 36, 82, 79, 77, 61, 61, 43, 43,
-   27, 27, 27, 61,150, 61, 61, 61, 36, 36,  2,  2,  2,  2,  2,  2,
-   78, 36, 36, 36, 36, 36, 36, 36, 36, 36, 78, 78, 78, 78, 78, 78,
-   78, 78, 43, 43, 43, 43, 43,  2, 43, 36, 36, 36,  2, 66, 66, 64,
-   36, 36, 36, 43, 43, 43, 43,  2, 36, 36, 36, 64, 43, 43, 43, 43,
-   43, 78, 78, 78, 78, 78, 78, 97, 36, 64, 78, 43, 43, 78, 43, 78,
-   97,  2,  2,  2,  2,  2,  2, 80,  7,  7,  7,  7,  7,  7,  7,  2,
-   36, 36, 64, 63, 36, 36, 36, 36, 36, 36, 36, 36, 64, 43, 43, 77,
-   79, 77, 79, 43, 43, 43, 43, 43, 36, 64, 36, 36, 36, 36, 77, 78,
-    7,  7,  7,  7,  7,  7,  2,  2, 63, 36, 36, 71, 61, 82, 77, 36,
-   65, 43, 65, 64, 65, 36, 36, 43, 36, 36, 36, 36, 36, 36, 75,  2,
-   36, 36, 36, 36, 36, 82, 43, 78,  2, 75,151, 43, 43, 43, 43, 43,
-   16, 16, 16, 16, 16,103, 40, 40, 16, 16, 16, 16,100, 41, 41, 41,
-   36, 82, 79, 78, 77, 97, 79, 43,152,152,152,152,152,152,152,152,
-  153,153,153,153,153,153,153,153, 16, 16, 16, 16, 16, 16, 35, 65,
-   36, 36, 36, 36,154, 36, 36, 36, 36, 41, 41, 41, 41, 41, 41, 41,
-   41, 74, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,132,
-   36, 36, 36, 36, 36, 36, 36, 71, 36, 36, 36, 36, 36, 36,150, 61,
-    2,  2,  2,135,116,  2,  2,  2,  6,155,156,132,132,132,132,132,
-  132,132,116,135,116,  2,113,157,  2,  2,  2,  2,139,132,132,116,
-    2,158,  8,  8, 60,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36,159,
-    2,  2,  3,  2,  4,  5,  6,  2, 16, 16, 16, 16, 16, 17, 18,115,
-  116,  4,  2, 36, 36, 36, 36, 36, 63, 36, 36, 36, 36, 36, 36, 36,
-   36, 36, 36, 36, 36, 36, 36, 40, 20,160, 53, 20, 26,  8,128, 61,
-   61, 61, 61, 61,161, 59, 61, 61,  2,  2,  2, 90, 27, 27, 27, 27,
-   27, 27, 27, 84, 61, 61, 61, 61, 95, 95,127, 27, 84, 61, 61, 61,
-   61, 61, 61, 61, 61, 27, 61, 61, 61, 61, 61, 61, 61, 61, 47, 43,
-  162,162,162,162,162,162,162,162,163, 27, 27, 27, 27, 27, 27, 27,
-   27, 27, 27, 27, 27, 27, 87, 36,138, 36, 36, 36, 36, 95, 95, 95,
-   36, 36, 36, 36, 36, 36, 36, 58,164, 95, 95, 95, 95, 95, 95, 95,
-   11, 11, 11, 32, 16, 16, 16, 16, 36, 36, 36, 58, 27, 27, 27, 27,
-   36, 36, 36, 71,145, 27, 27, 27, 36, 36, 36,165, 27, 27, 27, 27,
-   36, 36, 36, 36, 36,165, 27, 27, 36, 36, 36, 27, 27, 27, 27, 30,
-   36, 36, 36, 36, 36, 36, 27, 36, 64, 43, 43, 43, 43, 43, 43, 43,
-   36, 36, 36, 36, 43, 43, 43, 43, 36, 36, 36, 36, 36, 36,165, 30,
-   36, 36, 36, 36, 36, 36,165, 27, 36, 36, 36, 36, 72, 36, 36, 36,
-   36, 36, 64, 43, 43,163, 27, 27, 36, 36, 36, 36, 58,  2,  2,  2,
-   36, 36, 36, 36, 27, 27, 27, 27, 16, 16, 16, 16, 16, 27, 27, 27,
-   36, 36, 43, 43, 43, 43, 43, 43, 36, 36, 36, 36, 36, 64,166, 51,
-   27, 27, 27, 87, 36, 36, 36, 36,163, 27, 30,  2,  2,  2,  2,  2,
-   36, 43, 43,  2,  2,  2,  2,  2, 36, 36,165, 27, 27, 27, 27, 27,
-   79, 81, 36, 36, 36, 36, 36, 36, 43, 43, 43, 57,  2,  2,  2,  2,
-    2, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  7,  7,  7,  7,  7,
-   65, 64, 65, 36, 36, 36, 36, 64, 78, 79, 43, 77, 79, 57, 73,  2,
-    2, 43, 43, 43, 43, 43, 67, 59, 36, 36, 36, 64, 43, 43, 79, 43,
-   43, 43, 43,  7,  7,  7,  7,  7,  2,  2, 82, 81, 36, 36, 36, 36,
-   36, 64,  2, 36, 36, 36, 36, 36, 36, 82, 78, 43, 43, 43, 43, 77,
-   81, 36, 58,  2, 56, 43, 57, 79,  7,  7,  7,  7,  7, 58, 58,  2,
-   90, 27, 27, 27, 27, 27, 27, 27, 36, 36, 36, 36, 36, 36, 78, 79,
-   43, 78, 77, 43,  2,  2,  2, 65, 36, 36, 36, 36, 36, 36, 36, 64,
-   77, 78, 78, 78, 78, 78, 78, 78, 36, 36, 36, 82, 78, 78, 81, 36,
-   36, 78, 78, 43, 43, 43, 43, 43, 36, 36, 82, 78, 43, 43, 43, 43,
-   78, 43, 77, 65, 36, 58,  2,  2,  7,  7,  7,  7,  7,  2,  2, 65,
-   78, 79, 43, 43, 77, 77, 78, 79, 77, 43, 36, 66, 36, 36, 36, 36,
-   36, 36, 36, 36, 36, 36, 36, 82, 78, 43, 43, 43, 78, 78, 43, 79,
-   57,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 43, 43,
-   78, 79, 43, 43, 43, 77, 79, 79, 57,  2, 36, 36, 36, 36, 36, 36,
-   36, 36, 36, 36, 36, 64, 79, 78, 43, 43, 43, 79, 58,  2,  2,  2,
+   16, 16, 16, 16, 34, 16, 16, 16, 43, 57, 43, 43, 43, 43, 43, 43,
+   77, 43, 43, 43, 65, 36, 64, 36, 36, 36, 65, 82, 43, 36, 36, 36,
+   16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 44, 16, 16,
+   16, 16, 16, 16, 44, 16, 16, 16, 16, 16, 16, 16, 16,100, 40, 40,
+   32, 32, 32, 16, 16, 16, 16, 32, 16, 16, 16, 16, 11, 11, 11, 11,
+   16, 16, 16, 16, 34, 11, 11, 11, 16, 16, 16, 16,101,101,101,101,
+   16, 16, 16, 16, 11, 11,102,103, 41, 16, 16, 16, 11, 11,102, 41,
+   16, 16, 16, 16, 11, 11,104, 41,105,105,105,105,105,106, 59, 59,
+   51, 51, 51,  2,107,108,107,108,  2,  2,  2,  2,109, 59, 59,110,
+    2,  2,  2,  2,111,112,  2,113,114,  2,115,116,  2,  2,  2,  2,
+    2,  9,114,  2,  2,  2,  2,117, 59, 59, 59, 59, 59, 59, 59, 59,
+  118, 40, 27, 27, 27,  8,115,119, 27, 27, 27, 27, 27,  8,115, 94,
+   20, 20, 20, 20, 20, 20, 20, 20, 43, 43, 43, 43, 43, 43,120, 48,
+   99, 48, 99, 43, 43, 43, 43, 43, 61,121, 61,122, 61, 34, 11, 16,
+   11, 32,122, 61, 46, 11, 11, 61, 61, 61,121,121,121, 11, 11,123,
+   11, 11, 35, 36, 39, 61, 16, 11,  8,  8, 46, 16, 16, 26, 61,124,
+   95, 95, 95, 95, 95, 95, 95, 95, 95,125,126, 95,127, 61, 61, 61,
+    8,  8,128, 61, 61,  8, 61, 61,128, 26, 61,128, 61, 61, 61,128,
+   61, 61, 61, 61, 61, 61, 61,  8, 61,128,128, 61, 61, 61, 61, 61,
+   61, 61,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
+   61, 61, 61, 61,  4,  4, 61, 61,  8, 61, 61, 61,129,130, 61, 61,
+   61, 61, 61, 61, 61, 61,128, 61, 61, 61, 61, 61, 61, 26,  8,  8,
+    8,  8, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,  8,  8,
+    8, 61, 61, 61, 61, 61, 61, 61, 27, 27, 27, 27, 27, 27, 61, 61,
+   61, 61, 61, 61, 61, 27, 27, 27, 61, 61, 61, 26, 61, 61, 61, 61,
+   26, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,  8,  8,  8,  8,
+   61, 61, 61, 61, 61, 61, 61, 26, 61, 61, 61, 61,  4,  4,  4,  4,
+    4,  4,  4, 27, 27, 27, 27, 27, 27, 27, 61, 61, 61, 61, 61, 61,
+    8,  8,115,131,  8,  8,  8,  8,  8,  8,  8,  4,  4,  4,  4,  4,
+    8,115,132,132,132,132,132,132,132,132,132,132,131,  8,  8,  8,
+    8,  8,  8,  8,  4,  4,  8,  8,  8,  8,  8,  8,  8,  8,  4,  8,
+    8,  8,128, 26,  8,  8,128, 61, 32, 11, 32, 34, 34, 34, 34, 11,
+   32, 32, 34, 16, 16, 16, 40, 11, 32, 32,124, 61, 61,122, 34,133,
+   43, 32, 16, 16, 50,  2, 90,  2, 36, 36, 36, 36, 36, 36, 36, 76,
+    2,  2,  2,  2,  2,  2,  2, 56,  2,107,107,  2,111,112,107,  2,
+    2,  2,  2,  6,  2, 98,107,  2,107,  4,  4,  4,  4,  2,  2, 80,
+    2,  2,  2,  2,  2, 51,  2,  2, 98,134,  2,  2,  2,  2,  2,  2,
+   61,  2,135,132,132,132,136, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+    1,  2,137,138,  4,  4,  4,  4,  4, 61,  4,  4,  4,  4,139, 94,
+  140, 95, 95, 95, 95, 43, 43, 78,141, 40, 40, 61, 95,142, 58, 61,
+   72, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 64,143,144, 63,
+   36, 36, 36, 36, 36, 58, 40, 63, 61, 27, 27, 61, 61, 61, 61, 61,
+   27, 27, 27, 27, 27, 61, 61, 61, 61, 61, 61, 61, 27, 27, 27, 27,
+  145, 27, 27, 27, 27, 27, 27, 27, 36, 36, 76, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36,146,  2, 32, 32, 32, 32, 32, 32, 32, 64,
+   48,147, 43, 43, 43, 43, 43, 80, 32, 32, 32, 32, 32, 32, 40, 43,
+   36, 36, 36, 95, 95, 95, 95, 95, 43,  2,  2,  2,  2,  2,  2,  2,
+   41, 41, 41,144, 40, 40, 40, 40, 41, 32, 32, 32, 32, 32, 32, 32,
+   16, 32, 32, 32, 32, 32, 32, 32, 44, 16, 16, 16, 34, 34, 34, 32,
+   32, 32, 32, 32, 42,148, 34, 35, 32, 32, 16, 32, 32, 32, 32, 32,
+   32, 32, 32, 32, 32, 11, 11, 32, 11, 11, 32, 32, 32, 32, 32, 32,
+   32, 32, 11, 11, 34, 34, 32, 16, 32, 16, 16, 32, 32, 32, 11, 11,
+   11, 40,149, 35, 40, 35, 36, 36, 36, 65, 36, 65, 36, 64, 36, 36,
+   36, 82, 79, 77, 61, 61, 43, 43, 27, 27, 27, 61,150, 61, 61, 61,
+   36, 36,  2,  2,  2,  2,  2,  2, 78, 36, 36, 36, 36, 36, 36, 36,
+   36, 36, 78, 78, 78, 78, 78, 78, 78, 78, 43, 43, 43, 43, 43,  2,
+   43, 36, 36, 36,  2, 66, 66, 64, 36, 36, 36, 43, 43, 43, 43,  2,
+   36, 36, 36, 64, 43, 43, 43, 43, 43, 78, 78, 78, 78, 78, 78, 97,
+   36, 64, 78, 43, 43, 78, 43, 78, 97,  2,  2,  2,  2,  2,  2, 80,
+    7,  7,  7,  7,  7,  7,  7,  2, 36, 36, 64, 63, 36, 36, 36, 36,
+   36, 36, 36, 36, 64, 43, 43, 77, 79, 77, 79, 43, 43, 43, 43, 43,
+   36, 64, 36, 36, 36, 36, 77, 78,  7,  7,  7,  7,  7,  7,  2,  2,
+   63, 36, 36, 71, 61, 82, 77, 36, 65, 43, 65, 64, 65, 36, 36, 43,
+   36, 36, 36, 36, 36, 36, 76,  2, 36, 36, 36, 36, 36, 82, 43, 78,
+    2, 76,151, 43, 43, 43, 43, 43, 16, 16, 16, 16, 16,103, 40, 40,
+   16, 16, 16, 16,100, 41, 41, 41, 36, 82, 79, 78, 77, 97, 79, 43,
+  152,152,152,152,152,152,152,152,153,153,153,153,153,153,153,153,
+   16, 16, 16, 16, 16, 16, 35, 65, 36, 36, 36, 36,154, 36, 36, 36,
+   36, 41, 41, 41, 41, 41, 41, 41, 41, 74, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 36, 36,132, 36, 36, 36, 36, 36, 36, 36, 71,
+   36, 36, 36, 36, 36, 36,150, 61,  2,  2,  2,135,116,  2,  2,  2,
+    6,155,156,132,132,132,132,132,132,132,116,135,116,  2,113,157,
+    2,  2,  2,  2,139,132,132,116,  2,158,  8,  8, 60,  2,  2,  2,
+   36, 36, 36, 36, 36, 36, 36,159,  2,  2,  3,  2,  4,  5,  6,  2,
+   16, 16, 16, 16, 16, 17, 18,115,116,  4,  2, 36, 36, 36, 36, 36,
+   63, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 40,
+   20,160, 53, 20, 26,  8,128, 61, 61, 61, 61, 61,161, 59, 61, 61,
+    2,  2,  2, 90, 27, 27, 27, 27, 27, 27, 27, 84, 61, 61, 61, 61,
+   95, 95,127, 27, 84, 61, 61, 61, 61, 61, 61, 61, 61, 27, 61, 61,
+   61, 61, 61, 61, 61, 61, 47, 43,162,162,162,162,162,162,162,162,
+  163, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 87, 36,
+  138, 36, 36, 36, 36, 95, 95, 95, 36, 36, 36, 36, 36, 36, 36, 58,
+  164, 95, 95, 95, 95, 95, 95, 95, 11, 11, 11, 32, 16, 16, 16, 16,
+   36, 36, 36, 58, 27, 27, 27, 27, 36, 36, 36, 71,145, 27, 27, 27,
+   36, 36, 36,165, 27, 27, 27, 27, 36, 36, 36, 36, 36,165, 27, 27,
+   36, 36, 36, 27, 27, 27, 27, 30, 36, 36, 36, 36, 36, 36, 27, 36,
+   64, 43, 43, 43, 43, 43, 43, 43, 36, 36, 36, 36, 43, 43, 43, 43,
+   36, 36, 36, 36, 36, 36,165, 30, 36, 36, 36, 36, 36, 36,165, 27,
+   36, 36, 36, 36, 72, 36, 36, 36, 36, 36, 64, 43, 43,163, 27, 27,
+   36, 36, 36, 36, 58,  2,  2,  2, 36, 36, 36, 36, 27, 27, 27, 27,
+   16, 16, 16, 16, 16, 27, 27, 27, 36, 36, 43, 43, 43, 43, 43, 43,
+    7,  7,  7,  7,  7, 36, 36, 63, 11, 11, 11, 11,166, 43, 43,141,
+   16, 16, 16, 16, 16, 16, 16,  8, 36, 36, 36, 36, 36, 64,167, 51,
+   36, 36, 36, 36, 36, 36, 43, 43, 27, 27, 27, 87, 36, 36, 36, 36,
+  163, 27, 30,  2,  2,  2,  2,  2, 36, 43, 43,  2,  2,  2,  2,  2,
+   36, 36,165, 27, 27, 27, 27, 27, 79, 81, 36, 36, 36, 36, 36, 36,
+   43, 43, 43, 57,  2,  2,  2,  2,  2, 27, 27, 27, 27, 27, 27, 27,
+   27, 27, 27,  7,  7,  7,  7,  7, 65, 64, 65, 36, 36, 36, 36, 64,
+   78, 79, 43, 77, 79, 57, 73,  2,  2, 43, 43, 43, 43, 43, 67, 59,
+   36, 36, 36, 64, 43, 43, 79, 43, 43, 43, 43,  7,  7,  7,  7,  7,
+    2,  2, 82, 81, 36, 36, 36, 36, 36, 64,  2, 36, 36, 36, 36, 36,
+   36, 82, 78, 43, 43, 43, 43, 77, 81, 36, 58,  2, 56, 43, 57, 79,
+    7,  7,  7,  7,  7, 58, 58,  2, 90, 27, 27, 27, 27, 27, 27, 27,
+   36, 36, 36, 36, 36, 36, 78, 79, 43, 78, 77, 43,  2,  2,  2, 65,
+   36, 36, 36, 36, 36, 36, 36, 64, 77, 78, 78, 78, 78, 78, 78, 78,
+   36, 36, 36, 82, 78, 78, 81, 36, 36, 78, 78, 43, 43, 43, 43, 43,
+   36, 36, 36, 36, 78, 79, 43, 43, 43, 78, 78, 78, 78, 78, 78, 77,
+   65, 65,  2,  2,  2,  2,  2,  2, 56, 43, 43, 43, 43, 43, 43, 43,
+   36, 36, 82, 78, 43, 43, 43, 43, 78, 43, 77, 65, 36, 58,  2,  2,
+    7,  7,  7,  7,  7,  2,  2, 65, 78, 79, 43, 43, 77, 77, 78, 79,
+   77, 43, 36, 66, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 82,
+   78, 43, 43, 43, 78, 78, 43, 79, 57,  2,  2,  2,  2,  2,  2,  2,
+    2,  2,  2,  2, 36, 36, 43, 43, 78, 79, 43, 43, 43, 77, 79, 79,
+   57,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 64, 79, 78,
+   43, 43, 43, 79, 58,  2,  2,  2, 36, 36, 36, 36, 36, 36, 64, 79,
    78, 43, 43, 79, 43, 43, 43, 43,  7,  7,  7,  7,  7, 27,  2, 89,
    43, 43, 43, 43, 79, 57,  2,  2, 27, 27, 27, 27, 27, 27, 27, 87,
    78, 78, 78, 78, 78, 79, 77, 65, 81, 79,  2,  2,  2,  2,  2,  2,
@@ -4721,39 +4938,41 @@ _hb_ucd_u8[13386] =
    78, 78, 78, 78, 78, 78, 78, 78, 64, 43, 43, 43, 43, 65, 36, 36,
    36, 64, 43, 43, 77, 64, 43, 57,  2,  2,  2, 56, 43, 43, 43, 43,
    64, 43, 43, 77, 79, 43, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43,
-   43, 43, 43, 77, 43,  2, 66,  2, 43, 43, 43, 43, 43, 43, 43, 79,
-   58,  2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36,
+   43, 43, 43, 77, 43,  2, 66,  2, 58,  2,  2,  2,  2,  2,  2,  2,
+   43, 43, 43, 43, 43, 43, 43, 79,  2, 36, 36, 36, 36, 36, 36, 36,
    43, 43, 43, 43, 77, 43, 43, 43, 77, 43, 79, 43, 43, 43, 43, 43,
    43, 43, 43, 64, 43, 43, 43, 43, 36, 36, 36, 36, 36, 78, 78, 78,
    43, 77, 79, 79, 36, 36, 36, 36, 36, 64, 77, 97,  2,  2,  2,  2,
    43, 82, 36, 36, 36, 36, 36, 36, 36, 36, 78, 43, 43, 43, 43, 78,
-   77, 57,  2,  2,  2,  2,  2,  2, 27, 27, 84, 61, 61, 61, 53, 20,
-  150, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 21,
-   65, 36, 36, 64, 43, 43, 43, 43, 43, 43, 57,  2,  2,  2,  2,  2,
-   43, 43, 43, 57,  2,  2, 61, 61, 40, 40, 89, 61, 61, 61, 61, 61,
-    7,  7,  7,  7,  7,167, 27, 27, 27, 87, 36, 36, 36, 36, 36, 36,
-   27, 27, 27, 30,  2,  2,  2,  2, 82, 78, 78, 78, 78, 78, 78, 78,
-   78, 78, 78, 78, 78, 78, 78, 79, 43, 68, 40, 40, 40, 40, 40, 40,
-   40, 80, 43, 43, 43, 43, 43, 43, 36, 36, 36, 36, 36, 36, 47, 57,
-   61, 61,168, 79, 43, 61,168, 78, 78,169, 59, 59, 59, 76, 43, 43,
-   43, 70, 47, 43, 43, 43, 61, 61, 61, 61, 61, 61, 61, 43, 43, 61,
-   61, 43, 70, 61, 61, 61, 61, 61, 11, 11, 11, 11, 11, 16, 16, 16,
-   16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16,
-   11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11,
-   11, 11, 11, 16, 16, 16, 16, 16, 31, 16, 16, 16, 16, 16, 16, 16,
-   16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, 11, 11,
-   11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11,
-   11, 11, 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33,
-   16, 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31,
-   16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16,
-   16, 33, 16, 16, 16, 32, 16,  7, 43, 43, 43, 70, 61, 47, 43, 43,
-   43, 43, 43, 43, 43, 43, 70, 61, 61, 61, 47, 61, 61, 61, 61, 61,
-   61, 61, 70, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2, 56, 43, 43,
-   16, 16, 16, 16, 16, 39, 16, 16, 43, 43, 43, 68, 40, 40, 40, 40,
-    7,  7,  7,  7,  7,  7,  7, 71, 36, 36, 36, 36, 36, 36, 36, 43,
-   36, 36, 36, 36, 36, 36, 43, 43,  7,  7,  7,  7,  7,  7,  7,170,
-   36, 36, 36, 36, 36, 75, 43, 43, 16, 16, 43, 43, 43, 68, 40, 40,
-   27, 27, 27, 27, 27, 27,145, 27,171, 27, 27, 27, 27, 27, 27, 27,
+   77, 57,  2,  2,  2,  2,  2,  2,  7,  7,  7,  7,  7, 43, 43, 43,
+   27, 27, 84, 61, 61, 61, 53, 20,150, 61, 61, 61, 61, 61, 61, 61,
+   61, 61, 61, 61, 61, 61, 61, 21, 65, 36, 36, 64, 43, 43, 43, 43,
+   36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 78, 79, 43,
+   43, 43, 57,  2,  2,  2,  2,  2, 43, 43, 43, 57,  2,  2, 61, 61,
+   40, 40, 89, 61, 61, 61, 61, 61,  7,  7,  7,  7,  7,168, 27, 27,
+   27, 87, 36, 36, 36, 36, 36, 36, 40, 63, 36, 36, 36, 36, 36, 36,
+   36, 36, 36, 36, 36, 76,146,  2, 27, 27, 27, 30,  2,  2,  2,  2,
+   82, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79,
+   43, 68, 40, 40, 40, 40, 40, 40, 40, 80, 43, 43, 43, 43, 43, 43,
+   36, 36, 36, 36, 36, 36, 47, 57, 61, 61,169, 79, 43, 61,169, 78,
+   78,170, 59, 59, 59, 75, 43, 43, 43, 70, 47, 43, 43, 43, 61, 61,
+   61, 61, 61, 61, 61, 43, 43, 61, 61, 43, 70, 61, 61, 61, 61, 61,
+   11, 11, 11, 11, 11, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 11,
+   11, 11, 11, 11, 11, 11, 11, 16, 11, 16, 16, 16, 16, 16, 16, 16,
+   16, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 16, 16, 16, 16, 16,
+   31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16,
+   16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16,
+   16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16,
+   16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11,
+   11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16,
+   11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 16,  7,
+   43, 43, 43, 70, 61, 47, 43, 43, 43, 43, 43, 43, 43, 43, 70, 61,
+   61, 61, 47, 61, 61, 61, 61, 61, 61, 61, 70, 21,  2,  2,  2,  2,
+    2,  2,  2,  2,  2, 56, 43, 43, 16, 16, 16, 16, 16, 39, 16, 16,
+   43, 43, 43, 68, 40, 40, 40, 40,  7,  7,  7,  7,  7,  7,  7, 71,
+    7,  7,  7,  7,  7,  7,  7,171, 36, 36, 36, 36, 36, 76, 43, 43,
+  172,  7,  7,  7,  7,  7,  7, 85, 16, 16, 43, 43, 43, 68, 40, 40,
+   27, 27, 27, 27, 27, 27,145, 27,173, 27, 27, 27, 27, 27, 27, 27,
    27, 27, 27, 27, 27, 27, 27,145, 27, 27, 27, 27, 27, 27, 84, 61,
    61, 61, 61, 61, 61, 25, 41, 41,  0,  0, 29, 21, 21, 21, 23, 21,
    22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21,  9,  9,  9,
@@ -4764,8 +4983,8 @@ _hb_ucd_u8[13386] =
     6,  5,  9, 21, 25,  9, 26, 12, 11, 11,  9,  6,  5, 21, 17, 17,
    17, 26, 26, 23, 23, 12, 17, 12, 21, 12, 12, 21,  7, 21,  1,  1,
    21, 23, 26, 26,  1, 21,  6,  7,  7, 12, 12,  7, 21,  7, 12,  1,
-   12,  6,  6, 12, 12, 26,  7, 26, 26,  7, 21,  1, 24,  7,  7,  6,
-    1, 12, 12, 10, 10, 10, 10, 12, 21,  6, 10,  7,  7, 10, 23,  7,
+   12,  6,  6, 12, 12, 26,  7, 26, 26,  7, 21,  1, 24,  7,  1, 12,
+    7,  6, 12, 10, 10, 10, 10, 12, 21,  6, 10,  7,  7, 10, 23,  7,
    15, 26, 13, 21, 13,  7, 15,  7, 12, 23, 21, 26, 21, 15, 17,  7,
    29,  7,  7, 22, 18, 18, 14, 14, 14,  7, 10, 21, 17, 21, 11, 12,
     5,  6,  8,  8,  8, 24,  5, 24,  9, 24, 29, 29, 29,  1, 20, 19,
@@ -4776,247 +4995,250 @@ _hb_ucd_u8[13386] =
    26, 14, 17,  6, 14,  6, 12, 24, 24,  6, 26, 15,  6, 21, 11, 21,
    24,  9,  6,  9, 23, 26,  6, 10,  4,  4,  3,  3,  7, 25, 17, 16,
    16, 22, 16, 16, 25, 17,  7,  1, 25, 24, 26,  1,  2,  2, 12, 15,
-   21, 14,  7, 15, 12, 17, 13, 15, 26, 10, 10,  1, 13, 23, 23, 15,
-    0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0, 10, 11, 12, 13,  0,
-   14,  0,  0,  0,  0,  0, 15,  0, 16,  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,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0, 17, 18, 19,  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, 20,  0, 21,
-   22, 23,  0,  0,  0, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
-    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, 35,  0, 36,  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, 37,  0,
-    0,  0,  0,  0,  0,  0,  0,  0, 38, 39,  0,  0,  0,  0,  0,  0,
-   40, 41, 42,  0, 43,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  1,  2,  0,  0,  0,  0,  3,  0,  0,  0,  4,  5,  6,  7,
-    0,  8,  9, 10,  0, 11, 12, 13, 14, 15, 16, 17, 16, 18, 16, 19,
-   16, 19, 16, 19,  0, 19, 16, 20, 16, 19, 21, 19,  0, 22, 23, 24,
-   25, 26, 27, 28, 29, 30, 31,  0, 32,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0, 33,  0,  0,  0,  0,  0,  0, 34,  0,  0, 35,  0,  0,
-   36,  0, 37,  0,  0,  0, 38, 39, 40, 41, 42, 43, 44, 45, 46,  0,
-    0, 47,  0,  0,  0, 48,  0,  0,  0, 49,  0,  0,  0,  0,  0,  0,
-    0, 50,  0, 51,  0, 52, 53,  0, 54,  0,  0,  0,  0,  0,  0, 55,
-   56, 57,  0,  0,  0,  0, 58,  0,  0, 59, 60, 61, 62, 63,  0,  0,
-   64, 65,  0,  0,  0, 66,  0,  0,  0,  0, 67,  0,  0,  0, 68,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 69,  0,  0,
-    0, 70,  0, 71,  0,  0, 72,  0,  0, 73,  0,  0,  0,  0,  0,  0,
-    0,  0, 74,  0,  0,  0,  0,  0, 75, 76,  0, 77, 78,  0,  0, 79,
-   80,  0, 81, 62,  0, 82, 83,  0,  0, 84, 85, 86,  0,  0,  0, 87,
-    0, 88,  0,  0, 51, 89, 51,  0, 90,  0, 91,  0,  0,  0, 80,  0,
-    0,  0, 92, 93,  0, 94, 95, 96, 97,  0,  0,  0,  0,  0, 51,  0,
-    0,  0,  0, 98, 99,  0,  0,  0,  0,  0,  0,100,  0,  0,  0,  0,
-    0,101,102,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,103,  0,  0,
-  104,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,106,  0,  0,107,
-    0,  0,  0,  0,  0,  0,108,  0,109,  0,102,  0,  0,  0,  0,  0,
-  110,111,  0,  0,  0,  0,  0,  0,  0,112,  0,  0,  0,  0,  0,  0,
-    0,113,  0,114,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,
-    7,  0,  8,  0,  0,  0,  0,  9, 10, 11, 12,  0,  0,  0,  0, 13,
-    0,  0, 14, 15,  0, 16,  0, 17, 18,  0,  0, 19,  0, 20, 21,  0,
-    0,  0,  0,  0, 22, 23,  0, 24, 25,  0,  0, 26,  0,  0,  0, 27,
-    0,  0, 28, 29, 30, 31,  0,  0,  0, 32, 33, 34,  0,  0, 33,  0,
-    0, 35, 33,  0,  0,  0, 33, 36,  0,  0,  0,  0,  0, 37, 38,  0,
-    0,  0,  0,  0,  0, 39, 40,  0,  0,  0,  0,  0,  0, 41, 42,  0,
-    0,  0,  0, 43,  0, 44,  0,  0,  0, 45, 46,  0,  0,  0, 47,  0,
-    0,  0,  0,  0,  0, 48, 49,  0,  0,  0,  0, 50,  0,  0,  0, 51,
-    0, 52,  0, 53,  0,  0,  0,  0, 54,  0,  0,  0,  0, 55,  0, 56,
-    0,  0,  0,  0, 57, 58,  0,  0,  0, 59, 60,  0,  0,  0,  0,  0,
-    0, 61, 52,  0, 62, 63,  0,  0, 64,  0,  0,  0, 65, 66,  0,  0,
-    0, 67,  0, 68, 69, 70, 71, 72,  1, 73,  0, 74, 75, 76,  0,  0,
-   77, 78,  0,  0,  0, 79,  0,  0,  1,  1,  0,  0, 80,  0,  0, 81,
-    0,  0,  0,  0, 77, 82,  0, 83,  0,  0,  0,  0,  0, 78, 84,  0,
-   85,  0, 52,  0,  1, 78,  0,  0, 86,  0,  0, 87,  0,  0,  0,  0,
-    0, 88, 57,  0,  0,  0,  0,  0,  0, 89, 90,  0,  0, 84,  0,  0,
-   33,  0,  0, 91,  0,  0,  0,  0, 92,  0,  0,  0,  0, 49,  0,  0,
-   93,  0,  0,  0,  0, 94, 95,  0,  0, 96,  0,  0, 97,  0,  0,  0,
-   98,  0,  0,  0, 99,  0,  0,  0,  0,100,101, 93,  0,  0,102,  0,
-    0,  0, 84,  0,  0,103,  0,  0,  0,104,105,  0,  0,106,107,  0,
-    0,  0,  0,  0,  0,108,  0,  0,109,  0,  0,  0,  0,110, 33,  0,
-  111,112,113, 35,  0,  0,114,  0,  0,  0,115,  0,  0,  0,  0,  0,
-    0,116,  0,  0,117,  0,  0,  0,  0,118, 88,  0,  0,  0,  0,  0,
-   57,  0,  0,  0,  0, 52,119,  0,  0,  0,  0,120,  0,  0,121,  0,
-    0,  0,  0,119,  0,  0,122,  0,  0,  0,  0,  0,  0,123,  0,  0,
-    0,124,  0,  0,  0,125,  0,126,  0,  0,  0,  0,127,128,129,  0,
-  130,  0,131,  0,  0,  0,132,133,134,  0, 77,  0,  0,  0,  0,  0,
-   35,  0,  0,  0,135,  0,  0,  0,136,  0,  0,137,  0,  0,138,  0,
-    0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  3,  4,  5,  6,
-    7,  4,  4,  8,  9, 10,  1, 11, 12, 13, 14, 15, 16, 17, 18,  1,
-    1,  1, 19,  1,  0,  0, 20, 21, 22,  1, 23,  4, 21, 24, 25, 26,
-   27, 28, 29, 30,  0,  0,  1,  1, 31,  0,  0,  0, 32, 33, 34, 35,
-    1, 36, 37,  0,  0,  0,  0, 38,  1, 39, 14, 39, 40, 41, 42,  0,
-    0,  0, 43, 36, 44, 45, 21, 45, 46,  0,  0,  0, 19,  1, 21,  0,
-    0, 47,  0, 38, 48,  1,  1, 49, 49, 50,  0,  0, 51,  0,  0,  0,
-   52,  1,  0,  0, 38, 14,  4,  1,  1,  1, 53, 21, 43, 52, 54, 21,
-   35,  1,  0,  0,  0, 55,  0,  0,  0, 56, 57, 58,  0,  0,  0,  0,
-    0, 59,  0, 60,  0,  0,  0,  0, 61, 62,  0,  0, 63,  0,  0,  0,
-   64,  0,  0,  0, 65,  0,  0,  0, 66,  0,  0,  0, 67,  0,  0,  0,
-   68,  0,  0, 69, 70,  0, 71, 72, 73, 74, 75, 76,  0,  0,  0, 77,
-    0,  0,  0, 78, 79,  0,  0,  0,  0, 47,  0,  0,  0, 49,  0, 80,
-    0,  0,  0, 62,  0,  0, 63,  0,  0, 81,  0,  0, 82,  0,  0,  0,
-   83,  0,  0, 19, 84,  0, 62,  0,  0,  0,  0, 49,  1, 85,  1, 52,
-   15, 86, 36, 10, 21, 87,  0, 55,  0,  0,  0,  0, 19, 10,  1,  0,
-    0,  0,  0,  0, 88,  0,  0, 89,  0,  0, 88,  0,  0,  0,  0, 78,
-    0,  0, 87,  9, 12,  4, 90,  8, 91, 47,  0, 58, 50,  0, 21,  1,
-   21, 92, 93,  1,  1,  1,  1, 94, 95, 96, 97,  1, 98, 58, 81, 99,
-  100,  4, 58,  0,  0,  0,  0,  0,  0, 19, 50,  0,  0,  0,  0,  0,
-    0, 61,  0,  0,101,102,  0,  0,103,  0,  0,  1,  1, 50,  0,  0,
-    0, 38,  0, 63,  0,  0,  0,  0,  0, 62,  0,  0,104, 68, 61,  0,
-    0,  0, 78,  0,  0,  0,105,106, 58, 38, 81,  0,  0,  0,  0,  0,
-    0,107,  1, 14,  4, 12, 84,  0,  0,  0,  0, 38, 87,  0,  0,  0,
-    0,108,  0,  0,109, 61,  0,110,  0,  0,  0,  1,  0,  0,  0,  0,
+   21, 14,  7, 15,  9, 12, 12, 17, 13, 15, 26, 10, 10,  1, 13, 23,
+    7, 13, 23, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0, 10,
+   11, 12, 13,  0, 14,  0,  0,  0,  0,  0, 15,  0, 16,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0, 17, 18, 19,  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, 20,  0, 21, 22, 23,  0,  0,  0, 24, 25, 26, 27, 28, 29, 30,
+   31, 32, 33, 34,  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, 35,  0,  0,  0,  0, 36,  0, 37,  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, 38,  0,  0,  0,  0,  0,  0,  0,  0,  0, 39, 40,  0,  0,
+    0,  0,  0,  0, 41, 42, 43,  0, 44,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  1,  2,  0,  0,  0,  0,  3,  0,  0,  0,
+    4,  5,  6,  7,  0,  8,  9, 10,  0, 11, 12, 13, 14, 15, 16, 17,
+   16, 18, 16, 19, 16, 19, 16, 19,  0, 19, 16, 20, 16, 19, 21, 19,
+    0, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,  0, 32,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0, 33,  0,  0,  0,  0,  0,  0, 34,  0,
+    0, 35,  0,  0, 36,  0, 37,  0,  0,  0, 38, 39, 40, 41, 42, 43,
+   44, 45, 46,  0,  0, 47,  0,  0,  0, 48,  0,  0,  0, 49,  0,  0,
+    0,  0,  0,  0,  0, 50,  0, 51,  0, 52, 53,  0, 54,  0,  0,  0,
+    0,  0,  0, 55, 56, 57,  0,  0,  0,  0, 58,  0,  0, 59, 60, 61,
+   62, 63,  0,  0, 64, 65,  0,  0,  0, 66,  0,  0,  0,  0, 67,  0,
+    0,  0, 68,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0, 69,  0,  0,  0, 70,  0, 71,  0,  0, 72,  0,  0, 73,  0,  0,
+    0,  0,  0,  0,  0,  0, 74, 75,  0,  0,  0,  0, 76, 77,  0, 78,
+   79,  0,  0, 80, 81,  0, 82, 62,  0, 83, 84,  0,  0, 85, 86, 87,
+    0, 88,  0, 89,  0, 90,  0,  0, 51, 91, 51,  0, 92,  0, 93,  0,
+    0,  0, 81,  0,  0,  0, 94, 95,  0, 96, 97, 98, 99,  0,  0,  0,
+    0,  0, 51,  0,  0,  0,  0,100,101,  0,  0,  0,  0,  0,  0,102,
+    0,  0,  0,  0,  0,  0,103,  0,  0,  0,  0,  0,  0,104,105,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,106,  0,  0,107,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,108,109,  0,  0,110,  0,  0,  0,  0,
+    0,  0,111,  0,112,  0,105,  0,  0,  0,  0,  0,113,114,  0,  0,
+    0,  0,  0,  0,  0,115,  0,  0,  0,116,  0,  0,  0,117,  0,118,
+    0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  0,  8,  0,
+    0,  0,  0,  9, 10, 11, 12,  0,  0,  0,  0, 13,  0,  0, 14, 15,
+    0, 16,  0, 17, 18,  0,  0, 19,  0, 20, 21,  0,  0,  0,  0,  0,
+   22, 23,  0, 24, 25,  0,  0, 26,  0,  0,  0, 27,  0,  0, 28, 29,
+   30, 31,  0,  0,  0, 32, 33, 34,  0,  0, 33,  0,  0, 35, 33,  0,
+    0,  0, 33, 36,  0,  0,  0,  0,  0, 37, 38,  0,  0,  0,  0,  0,
+    0, 39, 40,  0,  0,  0,  0,  0,  0, 41, 42,  0,  0,  0,  0, 43,
+    0, 44,  0,  0,  0, 45, 46,  0,  0,  0, 47,  0,  0,  0,  0,  0,
+    0, 48, 49,  0,  0,  0,  0, 50,  0,  0,  0, 51,  0, 52,  0, 53,
+    0,  0,  0,  0, 54,  0,  0,  0,  0, 55,  0, 56,  0,  0,  0,  0,
+   57, 58,  0,  0,  0, 59, 60,  0,  0,  0,  0,  0,  0, 61, 52,  0,
+   62, 63,  0,  0, 64,  0,  0,  0, 65, 66,  0,  0,  0, 67,  0, 68,
+   69, 70, 71, 72,  1, 73,  0, 74, 75, 76,  0,  0, 77, 78,  0,  0,
+    0, 79,  0,  0,  1,  1,  0,  0, 80,  0,  0, 81,  0,  0,  0,  0,
+   77, 82,  0, 83,  0,  0,  0,  0,  0, 78, 84,  0, 85,  0, 52,  0,
+    1, 78,  0,  0, 86,  0,  0, 87,  0,  0,  0,  0,  0, 88, 57,  0,
+    0,  0,  0,  0,  0, 89, 90,  0,  0, 84,  0,  0, 33,  0,  0, 91,
+    0,  0,  0,  0, 92,  0,  0,  0,  0, 49,  0,  0, 93,  0,  0,  0,
+    0, 94, 95,  0,  0, 96,  0,  0, 97,  0,  0,  0, 98,  0,  0,  0,
+   99,  0,  0,  0,100,  0,  0,  0,  0,101,102, 93,  0,  0,103,  0,
+    0,  0, 84,  0,  0,104,  0,  0,  0,105,106,  0,  0,107,108,  0,
+    0,  0,  0,  0,  0,109,  0,  0,110,  0,  0,  0,  0,111, 33,  0,
+  112,113,114, 57,  0,  0,115, 35,  0,  0,116,  0,  0,  0,117,  0,
+    0,  0,  0,  0,  0,118,  0,  0,119,  0,  0,  0,  0,120, 88,  0,
+    0,  0,  0,  0, 57,  0,  0,  0,  0, 52,121,  0,  0,  0,  0,122,
+    0,  0,123,  0,  0,  0,  0,121,  0,  0,124,  0,  0,  0,  0,  0,
+   79,  0,  0,  0,  0,125,  0,  0,  0,126,  0,  0,  0,127,  0,128,
+    0,  0,  0,  0,129,130,131,  0,132,  0,133,  0,  0,  0,134,135,
+  136,  0, 77,  0,  0,  0,  0,  0, 35,  0,  0,  0,137,  0,  0,  0,
+  138,  0,  0,  0,139,  0,  0,140,  0,  0,141,  0,  0,  0,  0,  0,
+    0,  0,  1,  1,  1,  1,  1,  2,  3,  4,  5,  6,  7,  4,  4,  8,
+    9, 10,  1, 11, 12, 13, 14, 15, 16, 17, 18,  1,  1,  1, 19,  1,
+    0,  0, 20, 21, 22,  1, 23,  4, 21, 24, 25, 26, 27, 28, 29, 30,
+    0,  0,  1,  1, 31,  0,  0,  0, 32, 33, 34, 35,  1, 36, 37,  0,
+    0,  0,  0, 38,  1, 39, 14, 39, 40, 41, 42,  0,  0,  0, 43, 36,
+   44, 45, 21, 45, 46,  0,  0,  0, 19,  1, 21,  0,  0, 47,  0, 38,
+   48,  1,  1, 49, 49, 50,  0,  0, 51,  0,  0, 19, 52,  1,  0,  0,
+   38, 14,  4,  1,  1,  1, 53, 21, 43, 52, 54, 21, 35,  1,  0,  0,
+    0, 55,  0,  0,  0, 56, 57, 58,  0,  0,  0,  0,  0, 59,  0, 60,
+    0,  0,  0,  0, 61, 62,  0,  0, 63,  0,  0,  0, 64,  0,  0,  0,
+   65,  0,  0,  0, 66,  0,  0,  0, 67,  0,  0,  0, 68,  0,  0, 69,
+   70,  0, 71, 72, 73, 74, 75, 76,  0,  0,  0, 77,  0,  0,  0, 78,
+   79,  0,  0,  0,  0, 47,  0,  0,  0, 49,  0, 80,  0,  0,  0, 62,
+    0,  0, 63,  0,  0, 81,  0,  0, 82,  0,  0,  0, 83,  0,  0, 19,
+   84,  0, 62,  0,  0,  0,  0, 49,  1, 85,  1, 52, 15, 86, 36, 10,
+   21, 87,  0, 55,  0,  0,  0,  0, 19, 10,  1,  0,  0,  0,  0,  0,
+   88,  0,  0, 89,  0,  0, 88,  0,  0,  0,  0, 78,  0,  0, 87,  9,
+   12,  4, 90,  8, 91, 47,  0, 58, 50,  0, 21,  1, 21, 92, 93,  1,
+    1,  1,  1, 94, 95, 96, 97,  1, 98, 58, 81, 99,100,  4, 58,  0,
+    0,  0,  0,  0,  0, 19, 50,  0,  0,  0,  0,  0,  0, 61,  0,  0,
+  101,102,  0,  0,103,  0,  0,  1,  1, 50,  0,  0,  0, 38,  0, 63,
+    0,  0,  0,  0,  0, 62,  0,  0,104, 68, 61,  0,  0,  0, 78,  0,
+    0,  0,105,106, 58, 38, 81,  0,  0,  0,  0,  0,  0,107,  1, 14,
+    4, 12, 84,  0,  0,  0,  0, 38, 87,  0,  0,  0,  0,108,  0,  0,
+  109, 61,  0,110,  0,  0,  0,  1,  0,  0,  0,  0, 49, 50,  0,  0,
    19, 58,  0,  0,  0, 51,  0,111, 14, 52,112, 41,  0,  0, 62,  0,
     0, 61,  0,  0,113,  0, 87,  0,  0,  0, 61, 62,  0,  0, 62,  0,
    89,  0,  0,113,  0,  0,  0,  0,114,  0,  0,  0, 78, 55,  0, 38,
-    1, 58,  1, 58,  0,  0, 63, 89,  0,  0,115,  0,  0,  0, 55,  0,
-    0,  0,  0,115,  0,  0,  0,  0, 61,  0,  0,  0,  0, 79,  0, 61,
-    0,  0,  0,  0, 56,  0, 89, 80,  0,  0, 79,  0,  0,  0,  8, 91,
-    0,  0,  1, 87,  0,  0,116,  0,  0,  0,  0,  0,  0,117,  0,118,
-  119,120,121,  0,104,  4,122, 49, 23,  0,  0,  0, 38, 50, 38, 58,
-    0,  0,  1, 87,  1,  1,  1,  1, 39,  1, 48,105, 87,  0,  0,  0,
-    0,  1,  0,  0,  0,123,  4,122,  0,  0,  0,  1,124,  0,  0,  0,
-    0,  0,230,230,230,230,230,232,220,220,220,220,232,216,220,220,
-  220,220,220,202,202,220,220,220,220,202,202,220,220,220,  1,  1,
-    1,  1,  1,220,220,220,220,230,230,230,230,240,230,220,220,220,
-  230,230,230,220,220,  0,230,230,230,220,220,220,220,230,232,220,
-  220,230,233,234,234,233,234,234,233,230,  0,  0,  0,230,  0,220,
-  230,230,230,230,220,230,230,230,222,220,230,230,220,220,230,222,
-  228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22,
-    0, 23,  0, 24, 25,  0,230,220,  0, 18, 30, 31, 32,  0,  0,  0,
-    0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230,220,230,
-  230,220, 35,  0,  0,  0,  0,  0,230,230,230,  0,  0,230,230,  0,
-  220,230,230,220,  0,  0,  0, 36,  0,  0,230,220,230,230,220,220,
-  230,220,220,230,220,230,220,230,230,  0,  0,220,  0,  0,230,230,
-    0,230,  0,230,230,230,230,230,  0,  0,  0,220,220,220,230,220,
-  220,220,230,230,  0,220, 27, 28, 29,230,  7,  0,  0,  0,  0,  9,
-    0,  0,  0,230,220,230,230,  0,  0,  0,  0,  0,230,  0,  0, 84,
-   91,  0,  0,  0,  0,  9,  9,  0,  0,  0,  0,  0,  9,  0,103,103,
-    9,  0,107,107,107,107,118,118,  9,  0,122,122,122,122,220,220,
-    0,  0,  0,220,  0,220,  0,216,  0,  0,  0,129,130,  0,132,  0,
-    0,  0,  0,  0,130,130,130,130,  0,  0,130,  0,230,230,  9,  0,
-  230,230,  0,  0,220,  0,  0,  0,  0,  7,  0,  9,  9,  0,  9,  9,
-    0,  0,  0,230,  0,  0,  0,228,  0,  0,  0,222,230,220,220,  0,
-    0,  0,230,  0,  0,220,230,220,  0,220,230,230,230,  0,  0,  0,
-    9,  9,  0,  0,  7,  0,230,  0,  1,  1,  1,  0,  0,  0,230,234,
-  214,220,202,230,230,230,230,230,232,228,228,220,218,230,233,220,
-  230,220,230,230,  1,  1,  1,  1,  1,230,  0,  1,  1,230,220,230,
-    1,  1,  0,  0,218,228,232,222,224,224,  0,  8,  8,  0,  0,  0,
-    0,220,230,  0,230,230,220,  0,  0,230,  0,  0, 26,  0,  0,220,
-    0,230,230,  1,220,  0,  0,230,220,  0,  0,  0,220,220,  0,  0,
-  230,220,  0,  9,  7,  0,  0,  7,  9,  0,  0,  0,  9,  7,  6,  6,
-    0,  0,  0,  0,  1,  0,  0,216,216,  1,  1,  1,  0,  0,  0,226,
-  216,216,216,216,216,  0,220,220,220,  0,232,232,220,230,230,230,
-    7,  0, 16, 17, 17, 33, 17, 49, 17, 17, 84, 97,135,145, 26, 17,
-   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+    1, 58,  1, 58,  0,  0,  0,  0,  0, 88, 63, 89,  0,  0,115,  0,
+    0,  0, 55,  0,  0,  0,  0,115,  0,  0,  0,  0, 61,  0,  0,  0,
+    0, 79,  0, 61,  0,  0,  0,  0, 56,  0, 89, 80,  0,  0, 79,  0,
+    0,  0,  8, 91,  0,  0,  1, 87,  0,  0,116,  0,  0,  0,  0,  0,
+    0,117,  0,118,119,120,121,  0,104,  4,122, 49, 23,  0,  0,  0,
+   38, 50, 38, 58,  0,  0,  1, 87,  1,  1,  1,  1, 39,  1, 48,105,
+   87,  0,  0,  0,  0,  1,  0,  0,  0,123,  0,  0,  0,112,  4,122,
+    0,  0,  0,  1,124,  0,  0,  0,  0,  0,230,230,230,230,230,232,
+  220,220,220,220,232,216,220,220,220,220,220,202,202,220,220,220,
+  220,202,202,220,220,220,  1,  1,  1,  1,  1,220,220,220,220,230,
+  230,230,230,240,230,220,220,220,230,230,230,220,220,  0,230,230,
+  230,220,220,220,220,230,232,220,220,230,233,234,234,233,234,234,
+  233,230,  0,  0,  0,230,  0,220,230,230,230,230,220,230,230,230,
+  222,220,230,230,220,220,230,222,228,230, 10, 11, 12, 13, 14, 15,
+   16, 17, 18, 19, 19, 20, 21, 22,  0, 23,  0, 24, 25,  0,230,220,
+    0, 18, 30, 31, 32,  0,  0,  0,  0, 27, 28, 29, 30, 31, 32, 33,
+   34,230,230,220,220,230,220,230,230,220, 35,  0,  0,  0,  0,  0,
+  230,230,230,  0,  0,230,230,  0,220,230,230,220,  0,  0,  0, 36,
+    0,  0,230,220,230,230,220,220,230,220,220,230,220,230,220,230,
+  230,  0,  0,220,  0,  0,230,230,  0,230,  0,230,230,230,230,230,
+    0,  0,  0,220,220,220,230,220,220,220,230,230,  0,220, 27, 28,
+   29,230,  7,  0,  0,  0,  0,  9,  0,  0,  0,230,220,230,230,  0,
+    0,  0,  0,  0,230,  0,  0, 84, 91,  0,  0,  0,  0,  9,  9,  0,
+    0,  0,  0,  0,  9,  0,103,103,  9,  0,107,107,107,107,118,118,
+    9,  0,122,122,122,122,220,220,  0,  0,  0,220,  0,220,  0,216,
+    0,  0,  0,129,130,  0,132,  0,  0,  0,  0,  0,130,130,130,130,
+    0,  0,130,  0,230,230,  9,  0,230,230,  0,  0,220,  0,  0,  0,
+    0,  7,  0,  9,  9,  0,  9,  9,  0,  0,  0,230,  0,  0,  0,228,
+    0,  0,  0,222,230,220,220,  0,  0,  0,230,  0,  0,220,230,220,
+    0,220,230,230,230,  0,  0,  0,  9,  9,  0,  0,  7,  0,230,  0,
+    1,  1,  1,  0,  0,  0,230,234,214,220,202,230,230,230,230,230,
+  232,228,228,220,218,230,233,220,230,220,230,230,  1,  1,  1,  1,
+    1,230,  0,  1,  1,230,220,230,  1,  1,  0,  0,218,228,232,222,
+  224,224,  0,  8,  8,  0,  0,  0,  0,220,230,  0,230,230,220,  0,
+    0,230,  0,  0, 26,  0,  0,220,  0,230,230,  1,220,  0,  0,230,
+  220,  0,  0,  0,220,220,  0,  0,230,220,  0,  9,  7,  0,  0,  7,
+    9,  0,  0,  0,  9,  7,  6,  6,  0,  0,  0,  0,  1,  0,  0,216,
+  216,  1,  1,  1,  0,  0,  0,226,216,216,216,216,216,  0,220,220,
+  220,  0,232,232,220,230,230,230,  7,  0, 16, 17, 17, 33, 17, 49,
+   17, 17, 84, 97,135,145, 26, 17, 17, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-   17,177,  0,  1,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-    3,  3,  3,  3,  3,  3,  4,  3,  3,  3,  3,  3,  5,  3,  3,  3,
-    3,  3,  6,  7,  8,  3,  3,  3,  3,  3,  9, 10, 11, 12, 13,  3,
-    3,  3,  3,  3,  3,  3,  3, 14,  3, 15,  3,  3,  3,  3,  3,  3,
-   16, 17, 18, 19, 20, 21,  3,  3,  3, 22, 23, 24,  3,  3,  3,  3,
-    3,  3, 25,  3,  3,  3,  3,  3,  3,  3,  3, 26,  3,  3, 27, 28,
-    0,  1,  0,  0,  0,  0,  0,  1,  0,  2,  0,  0,  0,  3,  0,  0,
-    0,  3,  0,  0,  0,  0,  0,  4,  0,  5,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  6,  0,  0,  0,  7,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  8,  9,  0,  0,  0,  0,  0,
-    0,  9,  0,  9,  0,  0,  0,  0,  0,  0,  0, 10, 11, 12, 13,  0,
-    0, 14, 15, 16,  6,  0, 17, 18, 19, 19, 19, 20, 21, 22, 23, 24,
-   19, 25,  0, 26, 27, 19, 19, 28, 29, 30,  0, 31,  0,  0,  0,  8,
-    0,  0,  0,  0,  0,  0,  0, 19, 28,  0, 32, 33,  9, 34, 35, 19,
-    0,  0, 36, 37, 38, 39, 40, 19,  0, 41, 42, 43, 44, 31,  0,  1,
-   45, 42,  0,  0,  0,  0,  0, 32, 14, 14,  0,  0,  0,  0, 14,  0,
-    0, 46, 47, 47, 47, 47, 48, 49, 47, 47, 47, 47, 50, 51, 52, 53,
-   43, 21,  0,  0,  0,  0,  0,  0,  0, 54,  6, 55,  0, 14, 19,  1,
-    0,  0,  0,  0, 56, 57,  0,  0,  0,  0,  0, 19, 58, 31,  0,  0,
-    0,  0,  0,  0,  0, 59, 14,  0,  0,  0,  0,  1,  0,  2,  0,  0,
-    0,  3,  0,  0,  0, 60, 61,  0,  0,  0,  0,  0,  0,  0,  1,  0,
-    0,  0,  0,  0,  2,  3,  0,  4,  5,  0,  0,  6,  0,  0,  0,  7,
-    0,  0,  0,  1,  1,  0,  0,  8,  9,  0,  8,  9,  0,  0,  0,  0,
-    8,  9, 10, 11, 12,  0,  0,  0, 13,  0,  0,  0,  0, 14, 15, 16,
-   17,  0,  0,  0,  1,  0,  0, 18, 19,  0,  0,  0, 20,  0,  0,  0,
-    1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  0,  8, 21,  9,
-    0,  0, 22,  0,  0,  0,  0,  1,  0, 23, 24, 25,  0,  0, 26,  0,
-    0,  0,  8, 21, 27,  0,  1,  0,  0,  1,  1,  1,  1,  0,  1, 28,
-   29, 30,  0, 31, 32, 20,  1,  1,  0,  0,  0,  8, 21,  9,  1,  4,
-    5,  0,  0,  0, 33,  9,  0,  1,  1,  1,  0,  8, 21, 21, 21, 21,
-   34,  1, 35, 21, 21, 21,  9, 36,  0,  0, 37, 38,  1,  0, 39,  0,
-    0,  0,  1,  0,  1,  0,  0,  0,  0,  8, 21,  9,  1,  0,  0,  0,
-   40,  0,  8, 21, 21, 21, 21, 21, 21, 21, 21,  9,  0,  1,  1,  1,
-    1,  8, 21, 21, 21,  9,  0,  0,  0, 41,  0, 42, 43,  0,  0,  0,
-    1, 44,  0,  0,  0, 45,  8,  9,  1,  0,  0,  0,  8, 21, 21, 21,
-    9,  0,  1,  0,  1,  1,  8, 21, 21,  9,  0,  4,  5,  8,  9,  1,
-    0,  0,  0,  1,  2,  3,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12,
-   13, 14,  3,  3,  3,  3,  3,  3,  3, 15,  3, 16, 17, 17, 17, 17,
+   17, 17, 17, 17, 17, 17, 17, 17, 17,177,  0,  1,  2,  3,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  4,  3,
+    3,  3,  3,  3,  5,  3,  3,  3,  3,  3,  6,  7,  8,  3,  3,  3,
+    3,  3,  9, 10, 11, 12, 13,  3,  3,  3,  3,  3,  3,  3,  3, 14,
+    3, 15,  3,  3,  3,  3,  3,  3, 16, 17, 18, 19, 20, 21,  3,  3,
+    3, 22, 23, 24,  3,  3,  3,  3,  3,  3, 25,  3,  3,  3,  3,  3,
+    3,  3,  3, 26,  3,  3, 27, 28,  0,  1,  0,  0,  0,  0,  0,  1,
+    0,  2,  0,  0,  0,  3,  0,  0,  0,  3,  0,  0,  0,  0,  0,  4,
+    0,  5,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  6,  0,  0,  0,  7,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  8,  9,  0,  0,  0,  0,  0,  0,  9,  0,  9,  0,  0,  0,  0,
+    0,  0,  0, 10, 11, 12, 13,  0,  0, 14, 15, 16,  6,  0, 17, 18,
+   19, 19, 19, 20, 21, 22, 23, 24, 19, 25,  0, 26, 27, 19, 19, 28,
+   29, 30,  0, 31,  0,  0,  0,  8,  0,  0,  0,  0,  0,  0,  0, 19,
+   28,  0, 32, 33,  9, 34, 35, 19,  0,  0, 36, 37, 38, 39, 40, 19,
+    0, 41, 42, 43, 44, 31,  0,  1, 45, 42,  0,  0,  0,  0,  0, 32,
+   14, 14,  0,  0,  0,  0, 14,  0,  0, 46, 47, 47, 47, 47, 48, 49,
+   47, 47, 47, 47, 50, 51, 52, 53, 43, 21,  0,  0,  0,  0,  0,  0,
+    0, 54,  6, 55,  0, 14, 19,  1,  0,  0,  0,  0, 56, 57,  0,  0,
+    0,  0,  0, 19, 58, 31,  0,  0,  0,  0,  0,  0,  0, 59, 14,  0,
+    0,  0,  0,  1,  0,  2,  0,  0,  0,  3,  0,  0,  0, 60, 61,  0,
+    0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  2,  3,  0,  4,
+    5,  0,  0,  6,  0,  0,  0,  7,  0,  0,  0,  1,  1,  0,  0,  8,
+    9,  0,  8,  9,  0,  0,  0,  0,  8,  9, 10, 11, 12,  0,  0,  0,
+   13,  0,  0,  0,  0, 14, 15, 16, 17,  0,  0,  0,  1,  0,  0, 18,
+   19,  0,  0,  0, 20,  0,  0,  0,  1,  1,  1,  1,  0,  1,  1,  1,
+    1,  1,  1,  1,  0,  8, 21,  9,  0,  0, 22,  0,  0,  0,  0,  1,
+    0, 23, 24, 25,  0,  0, 26,  0,  0,  0,  8, 21, 27,  0,  1,  0,
+    0,  1,  1,  1,  1,  0,  1, 28, 29, 30,  0, 31, 32, 20,  1,  1,
+    0,  0,  0,  8, 21,  9,  1,  4,  5,  0,  0,  0, 33,  9,  0,  1,
+    1,  1,  0,  8, 21, 21, 21, 21, 34,  1, 35, 21, 21, 21,  9, 36,
+    0,  0, 37, 38,  1,  0, 39,  0,  0,  0,  1,  0,  1,  0,  0,  0,
+    0,  8, 21,  9,  1,  0,  0,  0, 40,  0,  8, 21, 21, 21, 21, 21,
+   21, 21, 21,  9,  0,  1,  1,  1,  1,  8, 21, 21, 21,  9,  0,  0,
+    0, 41,  0, 42, 43,  0,  0,  0,  1, 44,  0,  0,  0, 45,  8,  9,
+    1,  0,  0,  0,  8, 21, 21, 21,  9,  0,  1,  0,  1,  1,  8, 21,
+   21,  9,  0,  4,  5,  8,  9,  1,  0,  0,  0,  1,  2,  3,  3,  4,
+    5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  3,  3,  3,  3,  3,  3,
+    3, 15,  3, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-   17, 17, 18,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
-   12, 13, 14, 15, 16, 17, 17, 17, 18, 17, 19, 20, 21, 22, 23, 23,
-   23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 23, 23, 23, 23, 23,
-   23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
-   23, 23, 23, 23, 25, 25, 26, 27, 28, 29, 30, 30, 30, 30, 30, 30,
-   30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
-   31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
-   32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-   48, 49, 50, 51, 52, 52, 53, 31, 31, 31, 31, 54, 55, 55, 56, 31,
-   31, 31, 31, 31, 31, 31, 57, 58, 31, 31, 31, 31, 31, 31, 31, 31,
-   31, 31, 31, 31, 31, 31, 31, 31, 59, 60, 31, 61, 62, 62, 62, 62,
-   62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 64, 31, 31, 31, 31, 31,
-   31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 65, 66, 67, 31, 31,
-   31, 31, 68, 31, 31, 31, 31, 31, 31, 31, 31, 69, 70, 71, 17, 17,
-   72, 73, 31, 74, 75, 76, 77, 78, 79, 31, 80, 81, 17, 82, 17, 17,
-   17, 17, 31, 31, 23, 23, 23, 23, 23, 23, 23, 83, 31, 31, 31, 31,
-   23, 83, 31, 31, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18,  0,  0,  1,  2,  3,
+    4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 17, 17,
+   18, 17, 19, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+   23, 23, 24, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+   23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 25, 25, 26, 27,
+   28, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
+   30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31,
+   31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+   40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 31,
+   31, 31, 31, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 57,
+   31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 58, 31, 31, 31,
+   59, 60, 61, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+   63, 64, 65, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+   31, 31, 31, 66, 67, 68, 31, 31, 31, 31, 69, 31, 31, 31, 31, 31,
+   31, 31, 17, 70, 71, 72, 17, 17, 73, 74, 31, 75, 76, 77, 78, 79,
+   80, 31, 81, 82, 17, 83, 17, 17, 17, 17, 31, 31, 23, 23, 23, 23,
+   23, 23, 23, 84, 31, 31, 31, 31, 23, 84, 31, 31, 23, 23, 31, 31,
    31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
-   31, 31, 31, 31, 84,  0,  0,  1,  0,  1,  2,  3,  0,  1,  2,  3,
-    4,  5,  6,  7,  0,  1,  2,  3,  4,  4,  4,  4,  4,  4,  5,  6,
-    7,  8,  9, 10, 11, 11, 12, 11, 13, 14, 15, 16, 17, 18, 19, 20,
-   21, 22, 23, 24, 25, 26, 19, 27, 28, 29, 30, 30, 31, 31, 32, 32,
-   33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 40, 41, 41,
-   42, 42, 42, 43, 44, 44, 45, 46, 47, 47, 47, 47, 48, 48, 48, 48,
-   48, 48, 49, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 53,
-   54, 55, 56, 56, 57, 58, 59, 51, 60, 61, 62, 63, 64, 65, 66,  7,
-   67, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,  7,  4,  4,  4,  4,
-   77, 77, 77, 77, 78, 79, 80, 81, 82, 83, 84,  0,  0,  0,  0,  0,
-    0,  0,  0,  0, 85, 85, 85, 85,  0,  0,  0,  0, 86, 87, 88, 88,
-   89, 90, 48, 91,  0,  0, 92, 92, 92, 92, 92, 93, 94, 95, 96, 97,
-   98, 47, 99,100,101,102,  0,103,104,105,  0,  0, 92, 92, 92, 92,
-   92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,  0,106,106,106,106,
-  106,106,106,106,106,106,106,107,108,108,108,108,108, 11,109,110,
-  111,  4,112,  4,113,114,115,116,117,118,119,120,121,122,123,124,
-  125,126, 50,127, 47, 47, 47, 47, 47, 47, 47, 47,128,128,128,128,
-  128,128,128,128,128,128,128,128, 92, 92, 92, 92, 92, 92, 92, 92,
-  129,130, 19, 19, 19, 19, 19, 19,131, 19, 19, 19,132,133, 19,134,
-  135,136,137,101,138,138,138,138,  0, 77,139,140,128,128,141,142,
-  143,144,145,146,147,148,149,150,151,152,153,153,154,154,154,154,
-  154,154,  4,  4,155,156,157,158,159,160,161,162,163,164,165,166,
-  167,168,169,169,170,170,171,171,172,172,128,128, 19, 19,173,174,
-  175,176,177,178,179,179,180,181,182,183,184,185,186,186,187,188,
-  189,190,128,128,191,191,192,192,128,128,193,193,194,195,196,196,
-  197,197,128,128,198,198,199,199,200,200,201,201,202,203,204,205,
-   28, 28,128,128,206,207,208,208,209,210,211,211,128,128,212,212,
-  213,213,214, 34,215,215,215,215,215,215,215,215,215,215,215,215,
-  215,215,128,128,128,128,128,128,128,128,216,216,217,217,217,217,
-  217,217,217,217,217,217,128,128,128,128,128,128,218,218,218,218,
-  218,218,218,218,218,218,128,128,128,128,128,128,110,110,110,110,
-  110,110,110,110,110,219,220,221,222,222,222,222,223,223,223,223,
-  224,224,224,225,226,226,226,226,226,226,226,226,226,226,226,226,
-  227,227,227,227,227,227,227,227,226,226,128,128,128,128,128,128,
-  128,128,104,104,228,229,229,229,230,231,232,232,232,232,232,232,
-  128,128,128,128,233,233,234,  0,128,128,128,128,128,128,128,128,
-    7,235,  0,  0,  0,  0,  0,  0,  0,236,237,  0, 77, 77,  0,  0,
-    0,  0,128,128,238,238,238,238,238,238,238,238,238,238,238,238,
-  128,128,128,128,128,128,128,128,  4,  4,128,128,239, 11, 11, 11,
-  240,240,128,128,128,128,241,242,128,128,128,128,128,128,243,243,
-  128,128,128,128,128,128,128,128,128,128, 48, 48,244,244,244,244,
-  245,245,128,128,  0,  0,  0,  0,  0,  0,128,128, 19, 19, 19, 19,
-  128,128,128,128,246,  0,128,128,  0,  0,  0,  0, 92, 92,128,128,
+   31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 85,  0,  0,  1,
+    0,  1,  2,  3,  0,  1,  2,  3,  4,  5,  6,  7,  0,  1,  2,  3,
+    4,  4,  4,  4,  4,  4,  5,  6,  7,  8,  9, 10, 11, 11, 12, 11,
+   13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 19, 27,
+   28, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36,
+   37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 42, 43, 44, 44, 45, 46,
+   47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 49, 50, 51, 51, 51, 51,
+   51, 51, 51, 51, 51, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 51,
+   60, 61, 62, 63, 64, 65, 66,  7, 67, 67, 68, 69, 70, 71, 72, 73,
+   74, 75, 76,  7,  4,  4,  4,  4, 77, 77, 77, 77, 78, 79, 80, 81,
+   82, 83, 84,  0,  0,  0,  0,  0,  0,  0,  0,  0, 85, 85, 85, 85,
+    0,  0,  0,  0, 86, 87, 88, 88, 89, 90, 48, 91,  0,  0, 92, 92,
+   92, 92, 92, 93, 94, 95, 96, 97, 98, 47, 99,100,101,102,  0,103,
+  104,105,  0,  0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+   92, 92, 92,  0,106,106,106,106,106,106,106,106,106,106,106,107,
+  108,108,108,108,108, 11,109,110,111,  4,112,  4,113,114,115,116,
+  117,118,119,120,121,122,123,124,125,126, 50,127, 47, 47, 47, 47,
+   47, 47, 47, 47,128,128,128,128,128,128,128,128,128,128,128,128,
+   92, 92, 92, 92, 92, 92, 92, 92,129,130, 19, 19, 19, 19, 19, 19,
+  131, 19, 19, 19,132,133, 19,134,135,136,137,101,138,138,138,138,
+    0, 77,139,140,128,128,141,142,143,144,145,146,147,148,149,150,
+  151,152,153,154,155,155,155,155,155,155,  4,  4,156,157,158,159,
+  160,161,162,163,164,165,166,167,168,169,170,170,171,171,172,172,
+  173,174,174,174, 19, 19,175,176,177,178,179,180,181,181,182,183,
+  184,185,186,187,188,188,189,190,191,192,193,193,194,194,195,195,
+  128,128,196,196,197,198,199,200,201,201,128,128,202,202,203,203,
+  204,204,205,205,206,207,208,209, 28, 28,210,210,211,212,213,213,
+  214,215,216,216,128,128,217,217,218,218,219, 34,220,220,220,220,
+  220,220,220,220,220,220,220,220,220,220,128,128,128,128,128,128,
+  128,128,221,221,222,222,222,222,222,222,222,222,223,223,223,223,
+  223,223,223,223,223,223,128,128,128,128,128,128,128,128,128,128,
+  224,224,128,128,110,110,110,110,110,110,110,110,110,225,226,227,
+  228,228,228,228,128,128,128,128,229,229,128,128,230,230,230,230,
+  231,231,231,232,233,233,233,233,233,233,233,233,233,233,233,233,
+  234,234,234,234,234,234,234,234,233,233,128,128,128,128,128,128,
+  128,128,104,104,235,236,236,236,237,238,239,239,239,239,239,239,
+  128,128,128,128,240,240,241,  0,128,128,128,128,  0,  0,  0,  0,
+    7,242,  0,  0,  0,  0,  0,  0,  0,243,244,  0, 77, 77,  0,  0,
+    0,  0,128,128,245,245,245,245,245,245,245,245,245,245,245,245,
+  128,128,128,128,128,128,128,128,  4,  4,128,128,246, 11, 11, 11,
+  247,247,128,128,128,128,248,249,128,128,128,128,128,128,250,250,
+  128,128,251,251,128,128,128,128,128,128, 48, 48,252,252,252,252,
+  253,253,128,128,  0,  0,  0,  0,  0,  0,128,128, 19, 19, 19, 19,
+  128,128,128,128,254,  0,128,128,  0,  0,  0,  0, 92, 92,128,128,
   128,128,128,128,  0,  0,128,128,  7,  7,  7,  7,  0,  0,  0,  0,
     1,  2,  1,  2,  0,  0,  3,  3,  4,  5,  4,  5,  4,  4,  4,  4,
     4,  4,  4,  6,  0,  0,  7,  0,  8,  8,  8,  8,  8,  8,  8,  9,
@@ -5056,30 +5278,32 @@ _hb_ucd_u8[13386] =
   137,137,138,138,138,138,139,  0,140,140,140,141,141,142,142,142,
   143,143,144,144,144,144,144,144,145,145,145,145,145,146,146,146,
   147,147,147,148,148,148,148,148,149,149,149,150,150,150,150,151,
-  151,151,151,151,152,152,152,152,153,153,153,153,154,154,155,155,
-  156,156,156,156,156,156,157,157,158,158,159,159,159,159,159,159,
-  160,160,161,161,161,161,161,161,162,162,162,162,162,162,163,163,
-  164,164,164,164,165,165,165,165,166,166,166,166,167,167,168,168,
-  169,169,169,169,170,170,170,170,171,171,171,171,172,172,172,172,
-  173,173,173,173,173,173,173,174,175,175,175,176,176,176,176,177,
-  177,177,177,178,178,178,179,179,180,180,180,180,181,181,181,181,
-  181,182,182,182,183,183,183,183,183,184,184,184,185,185,185,185,
-  185,185,186, 43,187,187,187,187,188,188,188,189,189,189,189,189,
-  190,190,190,191,190,190,190,190,192,192,192,192,193,193,193,193,
-  194,194,194,194,195,195,195,195,195,195, 66, 66,196,196,196,196,
-  197,197,197,197,198,198,198,198,199,199,199,199,200,200,200,200,
-  201,201,201,201,202,202,202,202,202,203,203,203,203,203,203, 55,
-  204,204,204,204,205,205,205,205,205,205,205,206,206,206,206,206,
-  207,207,207,207,207,207,208,208,208,208,208,208,209,209,209,209,
-  210,210,210,210,110,110,110,110,211,211,211,211,212,212,212,212,
-  213,213,213,213,214,214,214,214,215,215,215,216,216,216,216,216,
-  216,217,217,217,218,218,218,218,219,219,219,219,220,220,220,220,
-  220,220,221, 94,222,222,222,222,223,223,223,223,224, 99, 99, 99,
-   99, 99, 99, 99, 99, 99,102,225, 99,226,102,227,227,227,227,227,
-  228,228,228,228,228,228,  0,  0,  8,  0,  0,  0,  0,  0,229,230,
-  231,  0,232,  0,233,233,233,233, 91, 91, 91, 13,234,234,234,234,
-  235,235,235,235,236,236,236,236,237,237,237,237,238,238,238,238,
-  239,239,239,239,240,  0,  0,  0,  0,  0,  0,  0,  1,  2,  2,  2,
+  151,151,151,151,152,152,152,152,153,153,153,153,154,154,154,154,
+  155,155,156,156,157,157,157,157,157,157,158,158,159,159,160,160,
+  160,160,160,160,161,161,162,162,162,162,162,162,163,163,163,163,
+  163,163,164,164,165,165,165,165,166,166,166,166,167,167,167,167,
+  168,168,169,169,170,170,170,170,171,171,171,171,172,172,172,172,
+  173,173,173,173,174,174,174,174,175,175,175,175,176, 21, 21, 21,
+  177,177,177,178,178,178,178,179,179,179,179,180,180,180,181,181,
+  182,182,182,182,183,183,183,183,183,184,184,184,185,185,185,185,
+  185,186,186,186,187,187,187,187,187,187,188, 43,189,189,189,189,
+  190,190,190,191,191,191,191,191,192,192,192,193,192,192,192,192,
+  194,194,194,194,195,195,195,195,196,196,196,196,197,197,197,197,
+  198,198,198,198,198,198, 66, 66,199,199,199,199,199, 49, 49, 49,
+  200,200,200,200,201,201,201,201,202,202,202,202,203,203,203,203,
+  204,204,204,204,205,205,205,205,205,206,206,206,206,206,206, 55,
+  207,207,207,207,208,208,208,208,209,209,209,209,209,209,209,210,
+  210,210,210,210,211,211,211,211,211,211,212,212,212,212,212,212,
+  213,213,213,213,214,214,214,214,110,110,110,110,215,215,215,215,
+  216,216,216,216,217,217,217,217,218,218,218,218,219,219,219,219,
+  220,220,220,221,221,221,221,221,221,222,222,222,223,223,223,223,
+  224,224,224,224,225,225,225,225,226,226,226,226,226,226,227, 94,
+  228,228,228,228,229,229,229,229,230, 99, 99, 99, 99, 99, 99, 99,
+   99, 99,102,231, 99,232,102,233,233,233,233,233,234,234,234,234,
+  234,234,  0,  0,  8,  0,  0,  0,  0,  0,235,236,237,  0,238,  0,
+  239,239,239,239, 91, 91, 91, 13,240,240,240,240,241,241,241,241,
+  242,242,242,242,243,243,243,243,244,244,244,244,245,245,245,245,
+  246,246,246,246,247,  0,  0,  0,  0,  0,  0,  0,  1,  2,  2,  2,
     2,  2,  3,  0,  0,  0,  4,  0,  2,  2,  2,  2,  2,  3,  2,  2,
     2,  2,  5,  0,  2,  5,  6,  0,  7,  7,  7,  7,  8,  9,  8, 10,
     8, 11,  8,  8,  8,  8,  8,  8, 12, 13, 13, 13, 14, 14, 14, 14,
@@ -5123,98 +5347,102 @@ _hb_ucd_u8[13386] =
   163,163,163,163,164,164,164,164,165,165,165,165,166,166,166,166,
   167,167,167,167,168,168,168,168,169,169,169,169,170,170,170,170,
   171,171,171,171,172,172,172,172,173,173,173,173,174,174,174,174,
-  174,174,174,175,176,176,176,176,177,177,177,177,178,178,178,178,
+  175,175,175,175,176,176,176,176,177, 20, 20, 20,178,178,178,178,
   179,179,179,179,180,180,180,180,181,181,181,181,182,182,182,182,
   183,183,183,183,184,184,184,184,185,185,185,185,186,186,186,186,
-  187, 45, 45, 45,188,188,188,188,189,189,189,189,190,190,190,190,
-  191,191,191,191,191,191,192,191,193,193,193,193,194,194,194,194,
+  187,187,187,187,188,188,188,188,189, 45, 45, 45,190,190,190,190,
+  191,191,191,191,192,192,192,192,193,193,193,193,193,193,194,193,
   195,195,195,195,196,196,196,196,197,197,197,197,198,198,198,198,
   199,199,199,199,200,200,200,200,201,201,201,201,202,202,202,202,
   203,203,203,203,204,204,204,204,205,205,205,205,206,206,206,206,
   207,207,207,207,208,208,208,208,209,209,209,209,210,210,210,210,
   211,211,211,211,212,212,212,212,213,213,213,213,214,214,214,214,
   215,215,215,215,216,216,216,216,217,217,217,217,218,218,218,218,
-  219,219,219,219,220,220,220,220,221,221,221,221,222,223,223,223,
-  224,224,224,224,223,223,223,223,225,106,106,106,226,106,106,106,
-  106,227,109,109,228,228,228,228,229,229,229,229,  0,230, 86,  0,
-    0,  0,230,  7, 82,138,  7,  0,  0,  0,231, 86,232,232,232,232,
-  233,233,233,233,234,234,234,234,235,235,235,235,236,236,236,236,
-  237,237,237,237,238,238,238,238,239,  0,  0,  0,  0,  0,  0,  0,
-    0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,  0,  0,  0, 19,  0,
-   19,  0,  0,  0,  0,  0, 26, 26,  1,  1,  1,  1,  9,  9,  9,  9,
-    0,  9,  9,  9,  9,  9,  0,  9,  9,  0,  9,  0,  9,  9, 55, 55,
-   55, 55, 55, 55,  6,  6,  6,  6,  6,  1,  1,  6,  6,  4,  4,  4,
-    4,  4,  4,  4,  4, 14, 14, 14, 14, 14, 14, 14,  3,  3,  3,  3,
-    3,  0,  3,  3,  0,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,  1,
-    1,  1,  3,  3,  1,  3,  3,  3, 37, 37, 37, 37, 38, 38, 38, 38,
-   64, 64, 64, 64, 90, 90, 90, 90, 95, 95, 95, 95,  3,  3,  0,  3,
-    7,  7,  7,  7,  7,  1,  1,  1,  1,  7,  7,  7,  0,  0,  7,  7,
-    5,  5,  5,  5, 11, 11, 11, 11, 10, 10, 10, 10, 21, 21, 21, 21,
-   22, 22, 22, 22, 23, 23, 23, 23, 16, 16, 16, 16, 20, 20, 20, 20,
-   36, 36, 36, 36, 24, 24, 24, 24, 24, 24, 24,  0, 18, 18, 18, 18,
-   25, 25, 25, 25, 25,  0,  0,  0,  0, 25, 25, 25, 33, 33, 33, 33,
-    8,  8,  8,  8,  8,  8,  8,  0, 12, 12, 12, 12, 30, 30, 30, 30,
-   29, 29, 29, 29, 28, 28, 28, 28, 34, 34, 34, 34, 35, 35, 35, 35,
-   35, 35, 35,  0,  0,  0, 35, 35, 45, 45, 45, 45, 44, 44, 44, 44,
-   44,  0,  0,  0, 43, 43, 43, 43, 46, 46, 46, 46, 31, 31, 31, 31,
-   32, 32,  0,  0, 32,  0, 32, 32, 32, 32, 32, 32, 48, 48, 48, 48,
-   52, 52, 52, 52, 58, 58, 58, 58, 54, 54, 54, 54, 91, 91, 91, 91,
-   62, 62, 62, 62, 76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70,
-   73, 73, 73, 73,  1,  1,  1,  0,  1,  0,  1,  1,  1,  0,  0,  0,
-    0,  1,  0,  0,  1,  1,  0,  0, 19, 19,  9,  9,  9,  9,  9,  6,
-   19,  9,  9,  9,  9,  9, 19, 19,  9,  9,  9, 19,  6, 19, 19, 19,
-   19, 19, 19,  9,  0,  0,  0, 19,  0,  0,  9,  0,  0,  0, 19, 19,
-   27, 27, 27, 27, 56, 56, 56, 56, 61, 61, 61, 61, 13, 13, 13, 13,
-    0, 13,  0, 13,  0, 13, 13, 13, 13, 13,  1,  1,  1,  1, 12, 12,
-    0, 15, 15, 15, 15, 15, 15, 15, 15,  1,  1,  0,  0, 17, 17, 17,
-   17, 17, 17, 17, 17, 17, 17,  0, 26, 26, 26, 26, 26, 12, 12, 12,
-   12, 12, 12,  0, 39, 39, 39, 39, 86, 86, 86, 86, 77, 77, 77, 77,
-   79, 79, 79, 79, 60, 60, 60, 60, 65, 65, 65, 65, 75, 75, 75, 75,
-   69, 69, 69, 69, 69, 69,  0, 69, 74, 74, 74, 74, 84, 84, 84, 84,
-   84, 84, 84,  0, 68, 68, 68, 68, 92, 92, 92, 92, 87, 87, 87, 87,
-   19,  9, 19, 19, 19, 19,  0,  0,  2,  2,  2,  2, 19, 19, 19,  4,
-    3,  3,  0,  0,  1,  1,  6,  6,  0,  0, 17, 17, 17, 17,  0,  0,
-   49, 49, 49, 49,  0,  1,  1,  1, 71, 71, 71, 71, 67, 67, 67, 67,
-   42, 42, 42, 42, 41, 41, 41, 41,118,118,118,118, 53, 53, 53, 53,
-   59, 59, 59, 59, 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50,
-  135,135,135,135,106,106,106,106,104,104,104,104,161,161,161,161,
+  219,219,219,219,220,220,220,220,221,221,221,221,222,222,222,222,
+  223,223,223,223,224,224,224,224,225,225,225,225,226,226,226,226,
+  227,227,227,227,228,229,229,229,230,230,230,230,229,229,229,229,
+  231,106,106,106,232,106,106,106,106,233,109,109,234,234,234,234,
+  235,235,235,235,  0,236, 86,  0,  0,  0,236,  7, 82,138,  7,  0,
+    0,  0,237, 86,238,238,238,238,239,239,239,239,240,240,240,240,
+  241,241,241,241,242,242,242,242,243,243,243,243,244,244,244,244,
+  245,245,245,245,246,  0,  0,  0,  0,  0,  0,  0,  0, 19, 19, 19,
+   19, 19, 19, 19, 19, 19, 19,  0,  0,  0, 19,  0, 19,  0,  0,  0,
+    0,  0, 26, 26,  1,  1,  1,  1,  9,  9,  9,  9,  0,  9,  9,  9,
+    9,  9,  0,  9,  9,  0,  9,  0,  9,  9, 55, 55, 55, 55, 55, 55,
+    6,  6,  6,  6,  6,  1,  1,  6,  6,  4,  4,  4,  4,  4,  4,  4,
+    4, 14, 14, 14, 14, 14, 14, 14,  3,  3,  3,  3,  3,  0,  3,  3,
+    0,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,  1,  1,  1,  3,  3,
+    1,  3,  3,  3, 37, 37, 37, 37, 38, 38, 38, 38, 64, 64, 64, 64,
+   90, 90, 90, 90, 95, 95, 95, 95,  3,  3,  0,  3,  7,  7,  7,  7,
+    7,  1,  1,  1,  1,  7,  7,  7,  0,  0,  7,  7,  5,  5,  5,  5,
+   11, 11, 11, 11, 10, 10, 10, 10, 21, 21, 21, 21, 22, 22, 22, 22,
+   23, 23, 23, 23, 16, 16, 16, 16, 20, 20, 20, 20, 36, 36, 36, 36,
+   24, 24, 24, 24, 24, 24, 24,  0, 18, 18, 18, 18, 25, 25, 25, 25,
+   25,  0,  0,  0,  0, 25, 25, 25, 33, 33, 33, 33,  8,  8,  8,  8,
+    8,  8,  8,  0, 12, 12, 12, 12, 30, 30, 30, 30, 29, 29, 29, 29,
+   28, 28, 28, 28, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35,  0,
+    0,  0, 35, 35, 45, 45, 45, 45, 44, 44, 44, 44, 44,  0,  0,  0,
+   43, 43, 43, 43, 46, 46, 46, 46, 31, 31, 31, 31, 32, 32,  0,  0,
+   32,  0, 32, 32, 32, 32, 32, 32, 48, 48, 48, 48, 52, 52, 52, 52,
+   58, 58, 58, 58, 54, 54, 54, 54, 91, 91, 91, 91, 62, 62, 62, 62,
+   76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70, 73, 73, 73, 73,
+    1,  1,  1,  0,  1,  0,  1,  1,  1,  0,  0,  0,  0,  1,  0,  0,
+    1,  1,  0,  0, 19, 19,  9,  9,  9,  9,  9,  6, 19,  9,  9,  9,
+    9,  9, 19, 19,  9,  9,  9, 19,  6, 19, 19, 19, 19, 19, 19,  9,
+    0,  0,  0, 19,  0,  0,  9,  0,  0,  0, 19, 19, 27, 27, 27, 27,
+   56, 56, 56, 56, 61, 61, 61, 61, 13, 13, 13, 13,  0, 13,  0, 13,
+    0, 13, 13, 13, 13, 13,  1,  1,  1,  1, 12, 12,  0, 15, 15, 15,
+   15, 15, 15, 15, 15,  1,  1,  0,  0, 17, 17, 17, 17, 17, 17, 17,
+   17, 17, 17,  0, 26, 26, 26, 26, 26, 12, 12, 12, 12, 12, 12,  0,
+   39, 39, 39, 39, 86, 86, 86, 86, 77, 77, 77, 77, 79, 79, 79, 79,
+   60, 60, 60, 60, 65, 65, 65, 65, 75, 75, 75, 75, 69, 69, 69, 69,
+   69, 69,  0, 69, 74, 74, 74, 74, 84, 84, 84, 84, 84, 84, 84,  0,
+   68, 68, 68, 68, 92, 92, 92, 92, 87, 87, 87, 87, 19,  9, 19, 19,
+   19, 19,  0,  0,  2,  2,  2,  2, 19, 19, 19,  4,  3,  3,  0,  0,
+    1,  1,  6,  6,  0,  0, 17, 17, 17, 17,  0,  0, 49, 49, 49, 49,
+    0,  1,  1,  1, 71, 71, 71, 71, 67, 67, 67, 67, 42, 42, 42, 42,
+   41, 41, 41, 41,118,118,118,118, 53, 53, 53, 53, 59, 59, 59, 59,
+   40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50,135,135,135,135,
+  106,106,106,106,104,104,104,104,161,161,161,161,170,170,170,170,
   110,110,110,110, 47, 47, 47, 47, 81, 81, 81, 81,120,120,120,120,
   116,116,116,116,128,128,128,128, 66, 66, 66, 66, 72, 72, 72, 72,
    98, 98, 98, 98, 97, 97, 97, 97, 57, 57, 57, 57, 88, 88, 88, 88,
   117,117,117,117,112,112,112,112, 78, 78, 78, 78, 83, 83, 83, 83,
    82, 82, 82, 82,122,122,122,122, 89, 89, 89, 89,130,130,130,130,
-  144,144,144,144,156,156,156,156,156,  3,  3,  3,147,147,147,147,
-  148,148,148,148,158,158,158,158,153,153,153,153,149,149,149,149,
-   94, 94, 94, 94, 85, 85, 85, 85,101,101,101,101, 96, 96, 96, 96,
-  111,111,111,111,100,100,100,100,100, 36, 36, 36,108,108,108,108,
-  129,129,129,129,109,109,109,109,107,107,107,107,107,107,107,  1,
-  137,137,137,137,124,124,124,124,123,123,123,123,114,114,114,114,
-  102,102,102,102,126,126,126,126,142,142,142,142,125,125,125,125,
-  154,154,154,154,150,150,150,150,141,141,141,141,140,140,140,140,
-  121,121,121,121,133,133,133,133,134,134,134,134,138,138,138,138,
-  143,143,143,143,145,145,145,145,163,163,163,163, 63, 63, 63, 63,
-  157,157,157,157, 80, 80, 80, 80,127,127,127,127,115,115,115,115,
-  159,159,159,159,103,103,103,103,119,119,119,119,146,146,146,146,
-   99, 99, 99, 99,136,139, 13, 13,155,155,155,155,136,136,136,136,
-   17, 15, 15, 15, 17, 17, 15, 15, 15, 17, 17, 17,139,139,139,139,
-  105,105,105,105,  0,  0,  0,  1,  0,  0,  1,  1,131,131,131,131,
-  151,151,151,151,160,160,160,160,152,152,152,152,164,164,164,164,
-  113,113,113,113,132,132,132,132, 15,  0,  0,  0,  0,  1,  2,  3,
-    4,  5,  6,  7,  8,  9,  9,  9,  9, 10,  9, 11, 12, 13,  9,  9,
-    9, 14,  9,  9, 15,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+  144,144,144,144,165,165,165,165,156,156,156,156,156,156,  3,  3,
+  147,147,147,147,148,148,148,148,158,158,158,158,153,153,153,153,
+  149,149,149,149, 94, 94, 94, 94, 85, 85, 85, 85,101,101,101,101,
+   96, 96, 96, 96,111,111,111,111,100,100,100,100,100, 36, 36, 36,
+  108,108,108,108,129,129,129,129,109,109,109,109,107,107,107,107,
+  107,107,107,  1,171,171,171,171,137,137,137,137,124,124,124,124,
+  123,123,123,123,114,114,114,114,102,102,102,102,126,126,126,126,
+  142,142,142,142,125,125,125,125,154,154,154,154,150,150,150,150,
+  141,141,141,141,140,140,140,140,121,121,121,121,169,169,169,169,
+  133,133,133,133,134,134,134,134,138,138,138,138,143,143,143,143,
+  145,145,145,145,163,163,163,163, 63, 63, 63, 63,157,157,157,157,
+   80, 80, 80, 80,127,127,127,127,166,166,166,166,115,115,115,115,
+  159,159,159,159,103,103,103,103,119,119,119,119,167,167,167,167,
+  146,146,146,146, 99, 99, 99, 99,136,139, 13, 13,155,155,155,155,
+  136,136,136,136, 17, 15, 15, 15, 17, 17, 15, 15, 15, 17, 17, 17,
+  139,139,139,139,105,105,105,105,  0,  0,  0,  1,  0,  0,  1,  1,
+  131,131,131,131,151,151,151,151,160,160,160,160,152,152,152,152,
+  164,164,164,164,168,168,168,168,113,113,113,113,132,132,132,132,
+   15,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  9,  9,
+    9, 10,  9, 11, 12, 13,  9,  9,  9, 14,  9,  9, 15,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9, 16, 17,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9, 18, 19, 20,  9, 21,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+   16, 17,  9,  9,  9,  9, 18,  9,  9,  9,  9,  9, 19, 20, 21,  9,
+   22,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9, 23,  9,  9,  9,  9,  9, 24,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 25,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9, 22,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
@@ -5223,60 +5451,66 @@ _hb_ucd_u8[13386] =
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-    9,  9,  9,  9,  9,  9,  9,  9, 23, 24,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10,
-   11, 12,  0,  0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0,
-    0, 24, 25, 26, 27, 28, 29, 30,  0,  0, 31, 32,  0, 33,  0, 34,
-    0, 35,  0,  0,  0,  0, 36, 37, 38, 39,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 40,  0,  0,  0,
-    0,  0,  0,  0,  0,  0, 41, 42,  0,  0,  0,  0,  0,  0,  0,  0,
+   26, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,
+    3,  4,  5,  6,  7,  8,  9, 10, 11, 12,  0,  0, 13, 14, 15, 16,
+   17, 18, 19, 20, 21, 22,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0, 23,  0,  0, 24, 25, 26, 27, 28, 29, 30,
+    0,  0, 31, 32,  0, 33,  0, 34,  0, 35,  0,  0,  0,  0, 36, 37,
+   38, 39,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0, 40,  0,  0,  0,  0,  0,  0,  0,  0,  0, 41, 42,
+    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, 43, 44,  0, 45,  0,  0,  0,  0,  0,  0, 46, 47,
+    0,  0,  0,  0,  0, 48,  0, 49,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0, 50, 51,  0,  0,  0, 52,  0,  0, 53,  0,
+    0,  0,  0,  0,  0,  0, 54,  0,  0,  0,  0,  0,  0,  0, 55,  0,
+    0,  0,  0,  0,  0,  0, 56,  0,  0,  0,  0,  0,  0,  0,  0, 57,
     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, 43, 44,  0, 45,
-    0,  0,  0,  0,  0,  0, 46, 47,  0,  0,  0,  0,  0, 48,  0, 49,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 50, 51,
-    0,  0,  0, 52,  0,  0, 53,  0,  0,  0,  0,  0,  0,  0, 54,  0,
-    0,  0,  0,  0,  0,  0, 55,  0,  0,  0,  0,  0,  0,  0, 56,  0,
-    0,  0,  0,  0,  0,  0,  0, 57,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 58, 59,
-   60, 61, 62, 63, 64, 65,  0,  0,  0,  0,  0,  0, 66,  0,  0,  0,
+    0,  0,  0,  0,  0,  0, 58, 59, 60, 61, 62, 63, 64, 65,  0,  0,
+    0,  0,  0,  0, 66,  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,  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,  0,  0,  0,  0,  0,  0,  0, 67, 68,  0, 69, 70,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 71, 72, 73, 74, 75, 76,
-   77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
-   93, 94, 95, 96, 97, 98, 99,100,101,102,103,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,104,  0,  0,  0,
-    0,  0,  0,105,106,  0,107,  0,  0,  0,108,  0,109,  0,110,  0,
-  111,112,113,  0,114,  0,  0,  0,115,  0,  0,  0,116,  0,  0,  0,
+    0,  0, 67, 68,  0, 69, 70,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+   85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,
+  101,102,103,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,104,  0,  0,  0,  0,  0,  0,105,106,  0,107,  0,
+    0,  0,108,  0,109,  0,110,  0,111,112,113,  0,114,  0,  0,  0,
+  115,  0,  0,  0,116,  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,117,
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,117,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,118,119,
-  120,121,  0,122,123,124,125,126,  0,127,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,118,119,120,121,  0,122,123,124,125,126,
+    0,127,  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,  0,128,129,130,131,132,133,
-  134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,
-  150,151,152,153,154,155,156,157,  0,  0,  0,158,159,160,161,  0,
+    0,  0,128,129,130,131,132,133,134,135,136,137,138,139,140,141,
+  142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,
+    0,  0,  0,158,159,160,161,  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,162,163,  0,  0,  0,  0,  0,  0,  0,164,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,162,  0,
+  163,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,164,165,  0,  0,  0,
+    0,  0,  0,  0,166,  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,  0,  0,165,  0,
+    0,  0,  0,  0,  0,  0,167,  0,  0,  0,168,169,  0,  0,170,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,171,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,172,  0,  0,
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,166,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,167,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,168,  0,  0,
+    0,  0,  0,  0,  0,173,  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,  0,  0,169,
-  170,  0,  0,  0,  0,171,172,  0,  0,  0,173,174,175,176,177,178,
-  179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,
-  195,196,197,198,199,200,201,202,203,204,205,206,  0,  0,  0,  0,
+    0,  0,  0,  0,174,  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,  1,  2,  3,  4,
+    0,  0,  0,  0,  0,  0,  0,  0,175,  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,176,177,  0,  0,  0,  0,178,179,  0,
+    0,  0,180,181,182,183,184,185,186,187,188,189,190,191,192,193,
+  194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,
+  210,211,212,213,  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,  1,  2,
+    3,  4,
 };
 static const uint16_t
-_hb_ucd_u16[4920] =
+_hb_ucd_u16[5080] =
 {
      0,   0,   1,   2,   3,   4,   5,   6,   0,   0,   7,   8,   9,  10,  11,  12,
     13,  13,  13,  14,  15,  13,  13,  16,  17,  18,  19,  20,  21,  22,  13,  23,
@@ -5303,82 +5537,85 @@ _hb_ucd_u16[4920] =
     47,  47, 165, 166, 167,  47,  47,  47,  47,  47,  47,  47,  47, 168, 146, 146,
     47, 169,  47,  47,  47, 170, 171, 172, 160, 160, 173, 174,  32,  32,  32,  32,
    175,  47,  47, 176, 177, 122, 178, 179, 180,  47, 181,  61,  47,  47, 182, 183,
-    47,  47, 184, 185, 186,  61,  47, 187,  11,   9,   9,   9,  66, 188, 189, 190,
-    11,  11, 191,  27,  27,  27, 192, 193,  11, 194,  27,  27,  32,  32,  32,  32,
-    13,  13,  13,  13,  13,  13,  13,  13,  13, 195,  13,  13,  13,  13,  13,  13,
-   196, 196, 196, 196, 196, 197, 196,  11, 198, 198, 198, 199, 200, 201, 201, 200,
-   202, 203, 204, 205, 206, 207, 208, 209, 210,  27, 211, 211, 211, 212, 213,  32,
-   214, 215, 216, 217, 218, 145, 219, 219, 220, 221, 222, 146, 223, 224, 146, 225,
-   226, 226, 226, 226, 226, 226, 226, 226, 227, 146, 228, 146, 146, 146, 146, 229,
-   146, 230, 226, 231, 146, 232, 233, 146, 146, 146, 146, 146, 146, 146, 145, 145,
-   145, 234, 146, 146, 146, 146, 235, 145, 146, 146, 146, 146, 146, 146, 146, 146,
-   146, 146, 146, 236, 237, 146, 146, 238, 146, 146, 146, 146, 146, 146, 239, 146,
-   146, 146, 146, 146, 146, 146, 240, 241, 145, 242, 146, 146, 243, 226, 244, 226,
-   245, 246, 226, 226, 226, 247, 226, 248, 146, 146, 146, 226, 249, 146, 146, 146,
-     9,   9,   9,  11,  11,  11, 250, 251,  13,  13,  13,  13,  13,  13, 252, 253,
-    11,  11,  11,  47,  47,  47, 254, 255,  47,  47,  47,  47,  47,  47,  32,  32,
-   256, 257, 258, 259, 260, 261, 262, 262, 263, 264, 265, 266, 267,  47,  47,  47,
-    47, 268, 148,  47,  47,  47,  47, 269,  47, 270,  47,  47, 146, 146, 146,  47,
-   146, 146, 271, 146, 272, 273, 146, 146, 271, 146, 146, 273, 146, 146, 146, 146,
-    47,  47,  47,  47, 146, 146, 146, 146,  47, 274,  47,  47,  47,  47,  47,  47,
-    47, 146, 146, 146, 146,  47,  47, 187, 275,  47,  61,  47,  13,  13, 276, 277,
-    13, 278,  47,  47,  47,  47, 279, 280,  31, 281, 282, 283,  13,  13,  13, 284,
-   285, 286, 287, 288, 289, 290,  11, 291, 292,  47, 293, 294,  47,  47,  47, 295,
-   296,  47,  47, 297, 298, 160,  32, 299,  61,  47, 300,  47, 301, 302,  47,  47,
-    72,  47,  47, 303, 304, 305, 306,  61,  47,  47, 307, 308, 309, 310,  47, 311,
-    47,  47,  47, 312,  58, 313, 314, 315,  47,  47,  47,  11,  11, 316, 317,  11,
-    11,  11,  11,  11,  47,  47, 318, 160, 319, 319, 319, 319, 319, 319, 319, 319,
-   320, 320, 320, 320, 320, 320, 320, 320,  11, 321, 322,  47,  47,  47,  47,  47,
-    47,  47,  47, 323,  31, 324,  47,  47,  47,  47,  47, 325, 146,  47,  47,  47,
-    47,  47,  47,  47, 326, 146, 146, 327,  32, 328,  32, 329, 330, 331, 332,  47,
-    47,  47,  47,  47,  47,  47,  47, 333, 334,   2,   3,   4,   5, 335, 336, 337,
-    47, 338,  47,  47,  47,  47, 339, 340, 341, 145, 145, 342, 219, 219, 219, 343,
-   344, 146, 146, 146, 146, 146, 146, 345, 346, 346, 346, 346, 346, 346, 346, 346,
-    47,  47,  47,  47,  47,  47, 347, 145,  47,  47, 348,  47, 349,  47,  47,  60,
-    47, 350,  47,  47,  47, 351, 219, 219,   9,   9, 147,  11,  11,  47,  47,  47,
-    47,  47, 160,   9,   9, 147,  11,  11,  47,  47,  47,  47,  47,  47, 350,   9,
-     9, 352,  11,  11,  11,  11,  11,  11,  27,  27,  27,  27,  27,  27,  27,  27,
-    47,  47,  47,  47,  47, 353,  47, 354,  47,  47, 355, 145, 145, 145,  47, 356,
-    47, 357,  47, 350,  66,  66,  66,  66,  47,  47,  47, 358, 145, 145, 145, 145,
-   359,  47,  47, 360, 145,  66,  47, 361,  47, 362, 145, 145, 363,  47, 364,  66,
-    47,  47,  47, 365,  47, 366,  47, 366,  47, 365, 144, 145, 145, 145, 145, 145,
-     9,   9,   9,   9,  11,  11,  11, 367,  47,  47, 368, 160, 160, 160, 160, 160,
-   145, 145, 145, 145, 145, 145, 145, 145,  47,  47, 369,  47,  47,  47,  47, 143,
-    47, 362, 370,  47,  60, 371,  66,  47, 372,  66,  66,  47, 373, 145,  47,  47,
-   374,  47,  47, 360, 375, 376, 377, 378, 180,  47,  47, 379, 380,  47,  47, 160,
-    97,  47, 381, 382, 383,  47,  47, 384, 180,  47,  47, 385, 386, 387, 388, 145,
-    47,  47, 389, 390, 359,  32,  32,  32,  47,  47, 365,  47,  47, 391, 172, 160,
-    92,  47,  47, 113, 392, 393, 394,  32,  47,  47,  47, 395, 396, 397,  47,  47,
-    47,  47,  47, 398, 399, 160, 160, 160,  47,  47, 400, 401, 402, 403,  32,  32,
-    47,  47,  47, 404, 405, 160,  66,  66,  47,  47, 406, 407, 160, 160, 160, 160,
-    47, 143, 408, 409,  47,  47,  47,  47,  47,  47, 389, 410,  66,  66,  66,  66,
-     9,   9,   9,   9,  11,  11, 128, 411,  47,  47,  47, 412, 413, 160, 160, 160,
-    47,  47,  47,  47,  47, 414, 415, 416, 417,  47,  47, 418, 419, 420,  47,  47,
-   421, 422,  66,  47,  47,  47,  47,  47,  66,  66,  66,  66,  66,  66,  66,  66,
-    47,  47, 400, 423, 424, 128, 145, 425,  47, 156, 426, 427,  32,  32,  32,  32,
-    47,  47,  47, 359, 428, 160,  47,  47, 429, 430, 160, 160, 160, 160, 160, 160,
-    47,  47,  47,  47,  47,  47,  47, 431, 432,  47,  47, 433, 434, 160, 160, 160,
-    47,  47,  47,  47, 145, 435, 436, 437, 219, 219, 219, 219, 219, 219, 219,  66,
-    47,  47,  47,  47,  47,  47,  47, 424,  47,  47,  47, 208, 438,  32,  32,  32,
-    47,  47,  47,  47,  47,  47, 305,  47,  47,  47,  47,  47, 160,  47,  47, 439,
-    47,  47,  47, 440, 441, 442, 443,  47,   9,   9,   9,   9,   9,   9,  11,  11,
-   145, 444,  66,  66,  66,  66,  66,  66,  47,  47,  47,  47, 391, 445, 416, 416,
-   446, 447,  27,  27,  27,  27, 448, 416,  47, 449, 208, 208, 208, 208, 208, 208,
-    32,  32,  32,  32,  32, 146, 146, 146, 146, 146, 146, 146, 146, 146, 450, 451,
-   452, 146, 453, 146, 146, 146, 146, 146, 146, 146, 146, 146, 454, 146, 146, 146,
-     9, 455,  11, 456, 457,  11, 196,   9, 458, 459,   9, 460,  11,   9, 455,  11,
-   456, 457,  11, 196,   9, 458, 459,   9, 460,  11,   9, 455,  11, 456, 457,  11,
-   196,   9, 458, 459,   9, 460,  11,   9, 455,  11, 196,   9, 461, 462, 463, 464,
-    11, 465,   9, 466, 467, 468, 469,  11, 470,   9, 471,  11, 472, 160, 160, 160,
-    32,  32,  32, 473,  32,  32, 474, 475, 476, 477,  32,  32,  32,  32,  32,  32,
-   478,  11,  11,  11,  11,  11,  11,  11,  32,  32,  32,  27,  27,  27,  27,  27,
-    32,  32,  32,  32,  32,  32,  32,  32,  47,  47,  47, 479, 480, 146, 146, 146,
-    47,  47, 481,  32,  47,  47, 482, 483,  47,  47,  47,  47,  47,  47, 484, 160,
-    47,  47,  47,  47, 355,  32,  32,  32,   9,   9, 458,  11, 485, 305,  66,  66,
-   145, 145, 486, 487, 145, 145, 145, 145, 145, 145, 488, 145, 145, 145, 145, 145,
-    47,  47,  47,  47,  47,  47,  47, 226, 489, 146, 146, 146, 146, 146, 146, 146,
-   146, 146, 146, 146, 146, 146, 146, 490, 146, 146, 146, 146, 146, 146, 146, 160,
-   208, 208, 208, 208, 208, 208, 208, 208,   0,   0,   0,   0,   0,   0,   0,   0,
+    47,  47, 184, 185, 186,  61,  47, 187, 188,   9,   9,   9,  66, 189, 190, 191,
+    11,  11, 192,  27,  27,  27, 193, 194,  11, 195,  27,  27,  32,  32,  32,  32,
+    13,  13,  13,  13,  13,  13,  13,  13,  13, 196,  13,  13,  13,  13,  13,  13,
+   197, 197, 197, 197, 197, 198, 197,  11, 199, 199, 199, 200, 201, 202, 202, 201,
+   203, 204, 205, 206, 207, 208, 209, 210, 211,  27, 212, 212, 212, 213, 214,  32,
+   215, 216, 217, 218, 219, 145, 220, 220, 221, 222, 223, 146, 224, 225, 146, 226,
+   227, 227, 227, 227, 227, 227, 227, 227, 228, 146, 229, 146, 146, 146, 146, 230,
+   146, 231, 227, 232, 146, 233, 234, 146, 146, 146, 146, 146, 146, 146, 145, 145,
+   145, 235, 146, 146, 146, 146, 236, 145, 146, 146, 146, 146, 146, 146, 146, 146,
+   146, 146, 146, 237, 238, 146, 146, 239, 146, 146, 146, 146, 146, 146, 240, 146,
+   146, 146, 146, 146, 146, 146, 241, 242, 145, 243, 146, 146, 244, 227, 245, 227,
+   246, 247, 227, 227, 227, 248, 227, 249, 146, 146, 146, 227, 250, 146, 146, 146,
+     9,   9,   9,  11,  11,  11, 251, 252,  13,  13,  13,  13,  13,  13, 253, 254,
+    11,  11,  11,  47,  47,  47, 255, 256,  47,  47,  47,  47,  47,  47,  32,  32,
+   257, 258, 259, 260, 261, 262, 263, 263, 264, 265, 266, 267, 268,  47,  47,  47,
+    47, 269, 148,  47,  47,  47,  47, 270,  47, 271,  47,  47, 146, 146, 146,  47,
+   146, 146, 272, 146, 273, 274, 146, 146, 272, 146, 146, 274, 146, 146, 146, 146,
+    47,  47,  47,  47, 146, 146, 146, 146,  47, 275,  47,  47,  47,  47,  47,  47,
+    47, 146, 146, 146, 146,  47,  47, 187, 276,  47,  61,  47,  13,  13, 277, 278,
+    13, 279,  47,  47,  47,  47, 280, 281,  31, 282, 283, 284,  13,  13,  13, 285,
+   286, 287, 288, 289, 290, 291,   9, 292, 293,  47, 294, 295,  47,  47,  47, 296,
+   297,  47,  47, 298, 299, 160,  32, 300,  61,  47, 301,  47, 302, 303,  47,  47,
+    72,  47,  47, 304, 305, 306, 307,  61,  47,  47, 308, 309, 310, 311,  47, 312,
+    47,  47,  47, 313,  58, 314, 315, 316,  47,  47,  47,  11,  11, 317, 318,  11,
+    11,  11,  11,  11,  47,  47, 319, 160, 320, 320, 320, 320, 320, 320, 320, 320,
+   321, 321, 321, 321, 321, 321, 321, 321,  11, 322, 323,  47,  47,  47,  47,  47,
+    47,  47,  47, 324,  31, 325,  47,  47,  47,  47,  47, 326, 146,  47,  47,  47,
+    47,  47,  47,  47, 327, 146, 146, 328,  32, 329,  32, 330, 331, 332, 333,  47,
+    47,  47,  47,  47,  47,  47,  47, 334, 335,   2,   3,   4,   5, 336, 337, 338,
+    47, 339,  47,  47,  47,  47, 340, 341, 342, 145, 145, 343, 220, 220, 220, 344,
+   345, 146, 146, 146, 146, 146, 146, 346, 347, 347, 347, 347, 347, 347, 347, 347,
+    47,  47,  47,  47,  47,  47, 348, 145,  47,  47, 349,  47, 350,  47,  47,  60,
+    47, 351,  47,  47,  47, 352, 220, 220,   9,   9, 147,  11,  11,  47,  47,  47,
+    47,  47, 160,   9,   9, 147,  11,  11,  47,  47,  47,  47,  47,  47, 351,   9,
+     9, 353,  11,  11,  47,  47,  47,  47,  27,  27,  27,  27,  27,  27,  27,  27,
+    47,  47,  47,  47,  47, 354,  47, 355,  47,  47, 356, 145, 145, 145,  47, 357,
+    47, 358,  47, 351,  66,  66,  66,  66,  47,  47,  47, 359, 145, 145, 145, 145,
+   360,  47,  47, 361, 145,  66,  47, 362,  47, 363, 145, 145, 364,  47, 365,  66,
+    47,  47,  47, 366,  47, 367,  47, 367,  47, 366, 144, 145, 145, 145, 145, 145,
+     9,   9,   9,   9,  11,  11,  11, 368,  47,  47, 369, 160, 370,   9, 371,  11,
+   372, 227, 227, 227, 227, 227, 227, 227, 145, 145, 145, 145, 145, 145, 145, 145,
+    47,  47, 373,  47,  47,  47,  47, 374,  47, 363, 375,  47,  60, 376,  66,  47,
+   377,  66,  66,  47, 378, 145,  47,  47, 379,  47,  47, 361, 380, 381, 382, 383,
+   180,  47,  47, 384, 385,  47,  47, 160,  97,  47, 386, 387, 388,  47,  47, 389,
+   180,  47,  47, 390, 391, 392, 393, 145,  47,  47, 394, 395, 360,  32,  32,  32,
+    47,  47, 366,  47,  47, 396, 172, 160,  92,  47,  47, 113, 397, 398, 399,  32,
+    47,  47,  47, 400, 401, 402, 403,  32,  47,  47,  47, 404, 405, 406,  47,  47,
+    47,  47,  47, 407, 408, 160, 160, 160,  47,  47, 409, 410, 411, 412,  32,  32,
+    47,  47,  47, 413, 414, 160,  66,  66,  47,  47, 415, 416, 160, 160, 160, 160,
+    47, 417, 418, 419,  47,  47,  47,  47,  47,  47, 394, 420,  66,  66,  66,  66,
+     9,   9,   9,   9,  11,  11, 128, 421,  47,  47,  47, 422, 423, 160, 160, 160,
+    47,  47,  47,  47,  47, 424, 425, 426, 427,  47,  47, 428, 429, 430,  47,  47,
+   431, 432,  66,  47,  47,  47,  47,  47,  66,  66,  66,  66,  66,  66,  66,  66,
+    47,  47,  47,  47,  47,  47, 433, 160,  47,  47, 409, 434, 433, 128, 145, 435,
+    47, 156, 436, 437,  32,  32,  32,  32,  47,  47,  47, 360, 438, 160,  47,  47,
+   439, 440, 160, 160, 160, 160, 160, 160,  47,  47,  47,  47,  47,  47,  47, 441,
+   442,  47,  47, 443, 444, 445,  32,  32,  47,  47,  47,  47, 145, 446, 447, 448,
+   220, 220, 220, 220, 220, 220, 220,  66,  47,  47,  47,  47,  47,  47,  47, 433,
+    47,  47,  47, 209, 449,  32,  47,  47,  47, 450, 451, 160, 160, 160, 160, 160,
+    47,  47,  47,  47,  47,  47, 306,  47,  47,  47,  47,  47, 160,  47,  47, 452,
+    47,  47,  47, 453, 454, 455, 456,  47,  27,  27,  27,  27, 457,  47, 458, 160,
+     9,   9,   9,   9,   9,   9,  11,  11, 145, 459,  66,  66,  66,  66,  66,  66,
+    47,  47,  47,  47, 396, 460, 426, 426, 461, 462,  27,  27,  27,  27, 463, 426,
+    47, 464, 209, 209, 209, 209, 209, 209, 146, 146, 146, 146, 146, 146, 146, 160,
+    32,  32,  32,  32,  32, 146, 146, 146, 146, 146, 146, 146, 146, 146, 465, 466,
+   467, 146, 468, 146, 146, 146, 146, 146, 146, 146, 146, 146, 469, 146, 146, 146,
+     9, 470,  11, 471, 472,  11, 197,   9, 473, 474,   9, 475,  11,   9, 470,  11,
+   471, 472,  11, 197,   9, 473, 474,   9, 475,  11,   9, 470,  11, 471, 472,  11,
+   197,   9, 473, 474,   9, 475,  11,   9, 470,  11, 197,   9, 476, 477, 478, 479,
+    11, 480,   9, 481, 482, 483, 484,  11, 485,   9, 486,  11, 487, 160, 160, 160,
+    32,  32,  32, 488,  32,  32, 489, 490, 491, 492,  32,  32,  32,  32,  32,  32,
+   493,  11,  11,  11,  11,  11,  11,  11,  32,  32,  32,  27,  27,  27,  27,  27,
+    32,  32,  32,  32,  32,  32,  32,  32,  47,  47,  47, 494, 495, 146, 146, 146,
+    47,  47, 450,  32,  47,  47, 374, 496,  47,  47,  47,  47,  47,  47, 497, 160,
+    47,  47,  47,  47,  47,  47, 450, 498,  47,  47,  47,  47, 356,  32,  32,  32,
+     9,   9, 473,  11, 499, 306,  66,  66, 145, 145, 500, 501, 145, 145, 145, 145,
+   145, 145, 502, 145, 145, 145, 145, 145,  47,  47,  47,  47,  47,  47,  47, 227,
+   503, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 504,
+   209, 209, 209, 209, 209, 209, 209, 209,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0, 939, 940, 941, 942, 946, 948,   0, 962,
    969, 970, 971, 976,1001,1002,1003,1008,   0,1033,1040,1041,1042,1043,1047,   0,
      0,1080,1081,1082,1086,1110,   0,   0,1124,1125,1126,1127,1131,1133,   0,1147,
@@ -5541,16 +5778,23 @@ _hb_ucd_u16[4920] =
      0,   0,1602,1603,1934,1935,1574,1575,1576,1577,1579,1580,1581,1583,1584,   0,
   1585,1587,1588,1589,1591,   0,1592,   0,1593,1594,   0,1595,1596,   0,1598,1599,
   1600,1601,1604,1582,1578,1590,1597,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,1936,   0,1937,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,1938,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,1939,1940,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,1941,1942,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,1944,1943,   0,1945,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,1946,1947,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-  1948,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,   0,   0,   0,1949,1950,1951,1952,1953,1954,1955,   0,   0,   0,
+     0,1936,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1937,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,1938,   0,1939,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1940,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,1941,1942,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1943,1944,   0,   0,   0,   0,   0,   0,1945,   0,1946,   0,   0,
+     0,   0,   0,   0,   0,   0,1947,   0,   0,1948,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1950,   0,1949,
+  1951,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1953,1952,   0,1954,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,1955,1956,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1957,   0,   0,   0,   0,   0,   0,   0,   0,1958,1961,1959,1965,1960,1962,1964,
+  1963,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  1967,1966,1968,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,   0,   0,   0,1969,1970,1971,1972,1973,1974,1975,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-     0,   0,   0,1956,1957,1958,1960,1959,1961,   0,   0,   0,   0,   0,   0,   0,
+     0,   0,   0,1976,1977,1978,1980,1979,1981,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0, 106, 104, 107, 826, 114, 118, 119, 121,
    123, 124, 127, 125,  34, 830, 130, 131, 132, 137, 827,  35, 133, 139, 829, 142,
    143, 112, 144, 145, 924, 151, 152,  37, 157, 158, 159, 160,  38, 165, 166, 169,
@@ -5601,12 +5845,12 @@ _hb_ucd_i16[92] =
 static inline uint_fast8_t
 _hb_ucd_gc (unsigned u)
 {
-  return u<1114112u?_hb_ucd_u8[5096+(((_hb_ucd_u8[1168+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
+  return u<1114112u?_hb_ucd_u8[5208+(((_hb_ucd_u8[1168+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
 }
 static inline uint_fast8_t
 _hb_ucd_ccc (unsigned u)
 {
-  return u<125259u?_hb_ucd_u8[7054+(((_hb_ucd_u8[6498+(((_hb_ucd_u8[6038+(((_hb_ucd_u8[5686+(((_hb_ucd_u8[5440+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
+  return u<125259u?_hb_ucd_u8[7206+(((_hb_ucd_u8[6638+(((_hb_ucd_u8[6162+(((_hb_ucd_u8[5802+(((_hb_ucd_u8[5556+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
 }
 static inline unsigned
 _hb_ucd_b4 (const uint8_t* a, unsigned i)
@@ -5616,17 +5860,17 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i
 static inline int_fast16_t
 _hb_ucd_bmg (unsigned u)
 {
-  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[7946+(((_hb_ucd_u8[7714+(((_hb_ucd_u8[7618+(((_hb_ucd_b4(7554+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0;
+  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[8098+(((_hb_ucd_u8[7866+(((_hb_ucd_u8[7770+(((_hb_ucd_b4(7706+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0;
 }
 static inline uint_fast8_t
 _hb_ucd_sc (unsigned u)
 {
-  return u<918016u?_hb_ucd_u8[11244+(((_hb_ucd_u8[10280+(((_hb_ucd_u8[9292+(((_hb_ucd_u8[8612+(((_hb_ucd_u8[8308+(((_hb_ucd_u8[8194+(u>>2>>2>>2>>3>>4)])<<4)+((u>>2>>2>>2>>3)&15u))])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
+  return u<918016u?_hb_ucd_u8[11464+(((_hb_ucd_u8[10472+(((_hb_ucd_u8[9452+(((_hb_ucd_u8[8764+(((_hb_ucd_u8[8460+(((_hb_ucd_u8[8346+(u>>2>>2>>2>>3>>4)])<<4)+((u>>2>>2>>2>>3)&15u))])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
 }
 static inline uint_fast16_t
 _hb_ucd_dm (unsigned u)
 {
-  return u<195102u?_hb_ucd_u16[1608+(((_hb_ucd_u8[12586+(((_hb_ucd_u8[12204+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
+  return u<195102u?_hb_ucd_u16[1656+(((_hb_ucd_u8[12834+(((_hb_ucd_u8[12452+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
 }
 
 #endif
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-unicode-emoji-table.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-unicode-emoji-table.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-unicode-emoji-table.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-unicode-emoji-table.hh	2025-06-27 08:03:14.000000000 +0000
@@ -7,13 +7,13 @@
  * on file with this header:
  *
  * # emoji-data.txt
- * # Date: 2023-02-01, 02:22:54 GMT
- * # © 2023 Unicode®, Inc.
+ * # Date: 2024-05-01, 21:25:24 GMT
+ * # © 2024 Unicode®, Inc.
  * # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
- * # For terms of use, see https://www.unicode.org/terms_of_use.html
+ * # For terms of use and license, see https://www.unicode.org/terms_of_use.html
  * #
  * # Emoji Data for UTS #51
- * # Used with Emoji Version 15.1 and subsequent minor revisions (if any)
+ * # Used with Emoji Version 16.0 and subsequent minor revisions (if any)
  * #
  * # For documentation and usage, see https://www.unicode.org/reports/tr51
  */
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-utf.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-utf.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-utf.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-utf.hh	2025-06-27 08:03:14.000000000 +0000
@@ -458,19 +458,21 @@ struct hb_ascii_t
 template <typename utf_t>
 static inline const typename utf_t::codepoint_t *
 hb_utf_offset_to_pointer (const typename utf_t::codepoint_t *start,
+                          const typename utf_t::codepoint_t *text,
+                          unsigned text_len,
                           signed offset)
 {
   hb_codepoint_t unicode;
 
   while (offset-- > 0)
     start = utf_t::next (start,
-                         start + utf_t::max_len,
+                         text + text_len,
                          &unicode,
                          HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT);
 
   while (offset++ < 0)
     start = utf_t::prev (start,
-                         start - utf_t::max_len,
+                         text,
                          &unicode,
                          HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT);
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-vector.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-vector.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-vector.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-vector.hh	2025-06-27 08:03:14.000000000 +0000
@@ -37,6 +37,8 @@ template <typename Type,
           bool sorted=false>
 struct hb_vector_t
 {
+  static constexpr bool realloc_move = true;
+
   typedef Type item_t;
   static constexpr unsigned item_size = hb_static_size (Type);
   using array_t = typename std::conditional<sorted, hb_sorted_array_t<Type>, hb_array_t<Type>>::type;
@@ -51,32 +53,29 @@ struct hb_vector_t
   }
   template <typename Iterable,
             hb_requires (hb_is_iterable (Iterable))>
-  hb_vector_t (const Iterable &o) : hb_vector_t ()
+  explicit hb_vector_t (const Iterable &o) : hb_vector_t ()
   {
-    auto iter = hb_iter (o);
-    if (iter.is_random_access_iterator || iter.has_fast_len)
-      alloc (hb_len (iter), true);
-    hb_copy (iter, *this);
+    extend (o);
   }
   hb_vector_t (const hb_vector_t &o) : hb_vector_t ()
   {
-    alloc (o.length, true);
+    alloc_exact (o.length);
     if (unlikely (in_error ())) return;
     copy_array (o.as_array ());
   }
   hb_vector_t (array_t o) : hb_vector_t ()
   {
-    alloc (o.length, true);
+    alloc_exact (o.length);
     if (unlikely (in_error ())) return;
     copy_array (o);
   }
   hb_vector_t (c_array_t o) : hb_vector_t ()
   {
-    alloc (o.length, true);
+    alloc_exact (o.length);
     if (unlikely (in_error ())) return;
     copy_array (o);
   }
-  hb_vector_t (hb_vector_t &&o)
+  hb_vector_t (hb_vector_t &&o) noexcept
   {
     allocated = o.allocated;
     length = o.length;
@@ -85,6 +84,35 @@ struct hb_vector_t
   }
   ~hb_vector_t () { fini (); }
 
+  template <typename Iterable,
+            hb_requires (hb_is_iterable (Iterable))>
+  void extend (const Iterable &o)
+  {
+    auto iter = hb_iter (o);
+    if (iter.is_random_access_iterator || iter.has_fast_len)
+      alloc (hb_len (iter), true);
+    while (iter)
+    {
+      if (unlikely (!alloc (length + 1)))
+        return;
+      unsigned room = allocated - length;
+      for (unsigned i = 0; i < room && iter; i++)
+        push_has_room (*iter++);
+    }
+  }
+  void extend (array_t o)
+  {
+    alloc (length + o.length);
+    if (unlikely (in_error ())) return;
+    copy_array (o);
+  }
+  void extend (c_array_t o)
+  {
+    alloc (length + o.length);
+    if (unlikely (in_error ())) return;
+    copy_array (o);
+  }
+
   public:
   int allocated = 0; /* < 0 means allocation failed. */
   unsigned int length = 0;
@@ -120,7 +148,7 @@ struct hb_vector_t
     resize (0);
   }
 
-  friend void swap (hb_vector_t& a, hb_vector_t& b)
+  friend void swap (hb_vector_t& a, hb_vector_t& b) noexcept
   {
     hb_swap (a.allocated, b.allocated);
     hb_swap (a.length, b.length);
@@ -130,14 +158,15 @@ struct hb_vector_t
   hb_vector_t& operator = (const hb_vector_t &o)
   {
     reset ();
-    alloc (o.length, true);
+    alloc_exact (o.length);
     if (unlikely (in_error ())) return *this;
 
+    length = 0;
     copy_array (o.as_array ());
 
     return *this;
   }
-  hb_vector_t& operator = (hb_vector_t &&o)
+  hb_vector_t& operator = (hb_vector_t &&o) noexcept
   {
     hb_swap (*this, o);
     return *this;
@@ -216,6 +245,10 @@ struct hb_vector_t
       // reference to it.
       return std::addressof (Crap (Type));
 
+    return push_has_room (std::forward<Args> (args)...);
+  }
+  template <typename... Args> Type *push_has_room (Args&&... args)
+  {
     /* Emplace. */
     Type *p = std::addressof (arrayZ[length++]);
     return new (p) Type (std::forward<Args> (args)...);
@@ -268,10 +301,9 @@ struct hb_vector_t
     }
     return new_array;
   }
-  /* Specialization for hb_vector_t<hb_{vector,array}_t<U>> to speed up. */
+  /* Specialization for types that can be moved using realloc(). */
   template <typename T = Type,
-            hb_enable_if (hb_is_same (T, hb_vector_t<typename T::item_t>) ||
-                          hb_is_same (T, hb_array_t <typename T::item_t>))>
+            hb_enable_if (T::realloc_move)>
   Type *
   realloc_vector (unsigned new_allocated, hb_priority<1>)
   {
@@ -313,15 +345,20 @@ struct hb_vector_t
   template <typename T = Type,
             hb_enable_if (hb_is_trivially_copyable (T))>
   void
+  copy_array (hb_array_t<Type> other)
+  {
+    assert ((int) (length + other.length) <= allocated);
+    hb_memcpy ((void *) (arrayZ + length), (const void *) other.arrayZ, other.length * item_size);
+    length += other.length;
+  }
+  template <typename T = Type,
+            hb_enable_if (hb_is_trivially_copyable (T))>
+  void
   copy_array (hb_array_t<const Type> other)
   {
-    length = other.length;
-    if (!HB_OPTIMIZE_SIZE_VAL && sizeof (T) >= sizeof (long long))
-      /* This runs faster because of alignment. */
-      for (unsigned i = 0; i < length; i++)
-        arrayZ[i] = other.arrayZ[i];
-    else
-       hb_memcpy ((void *) arrayZ, (const void *) other.arrayZ, length * item_size);
+    assert ((int) (length + other.length) <= allocated);
+    hb_memcpy ((void *) (arrayZ + length), (const void *) other.arrayZ, other.length * item_size);
+    length += other.length;
   }
   template <typename T = Type,
             hb_enable_if (!hb_is_trivially_copyable (T) &&
@@ -329,12 +366,10 @@ struct hb_vector_t
   void
   copy_array (hb_array_t<const Type> other)
   {
-    length = 0;
-    while (length < other.length)
-    {
-      length++;
-      new (std::addressof (arrayZ[length - 1])) Type (other.arrayZ[length - 1]);
-    }
+    assert ((int) (length + other.length) <= allocated);
+    for (unsigned i = 0; i < other.length; i++)
+      new (std::addressof (arrayZ[length + i])) Type (other.arrayZ[i]);
+    length += other.length;
   }
   template <typename T = Type,
             hb_enable_if (!hb_is_trivially_copyable (T) &&
@@ -344,13 +379,13 @@ struct hb_vector_t
   void
   copy_array (hb_array_t<const Type> other)
   {
-    length = 0;
-    while (length < other.length)
+    assert ((int) (length + other.length) <= allocated);
+    for (unsigned i = 0; i < other.length; i++)
     {
-      length++;
-      new (std::addressof (arrayZ[length - 1])) Type ();
-      arrayZ[length - 1] = other.arrayZ[length - 1];
+      new (std::addressof (arrayZ[length + i])) Type ();
+      arrayZ[length + i] = other.arrayZ[i];
     }
+    length += other.length;
   }
 
   void
@@ -431,6 +466,15 @@ struct hb_vector_t
 
     return true;
   }
+  bool alloc_exact (unsigned int size)
+  {
+    return alloc (size, true);
+  }
+
+  void clear ()
+  {
+    resize (0);
+  }
 
   bool resize (int size_, bool initialize = true, bool exact = false)
   {
@@ -496,7 +540,7 @@ struct hb_vector_t
     shrink_vector (size);
 
     if (shrink_memory)
-      alloc (size, true); /* To force shrinking memory if needed. */
+      alloc_exact (size); /* To force shrinking memory if needed. */
   }
 
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-version.h 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-version.h
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb-version.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb-version.h	2025-06-27 08:03:14.000000000 +0000
@@ -41,26 +41,26 @@ HB_BEGIN_DECLS
  *
  * The major component of the library version available at compile-time.
  */
-#define HB_VERSION_MAJOR 8
+#define HB_VERSION_MAJOR 10
 /**
  * HB_VERSION_MINOR:
  *
  * The minor component of the library version available at compile-time.
  */
-#define HB_VERSION_MINOR 2
+#define HB_VERSION_MINOR 4
 /**
  * HB_VERSION_MICRO:
  *
  * The micro component of the library version available at compile-time.
  */
-#define HB_VERSION_MICRO 2
+#define HB_VERSION_MICRO 0
 
 /**
  * HB_VERSION_STRING:
  *
  * A string literal containing the library version available at compile-time.
  */
-#define HB_VERSION_STRING "8.2.2"
+#define HB_VERSION_STRING "10.4.0"
 
 /**
  * HB_VERSION_ATLEAST:
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb.hh 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb.hh
--- 24.0.1+9-1/src/java.desktop/share/native/libharfbuzz/hb.hh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libharfbuzz/hb.hh	2025-06-27 08:03:14.000000000 +0000
@@ -64,6 +64,7 @@
 #pragma GCC diagnostic error   "-Wbitwise-instead-of-logical"
 #pragma GCC diagnostic error   "-Wcast-align"
 #pragma GCC diagnostic error   "-Wcast-function-type"
+#pragma GCC diagnostic error   "-Wcast-function-type-strict"
 #pragma GCC diagnostic error   "-Wconstant-conversion"
 #pragma GCC diagnostic error   "-Wcomma"
 #pragma GCC diagnostic error   "-Wdelete-non-virtual-dtor"
@@ -83,6 +84,7 @@
 #pragma GCC diagnostic error   "-Wredundant-decls"
 #pragma GCC diagnostic error   "-Wreorder"
 #pragma GCC diagnostic error   "-Wsign-compare"
+#pragma GCC diagnostic error   "-Wstrict-flex-arrays"
 #pragma GCC diagnostic error   "-Wstrict-prototypes"
 #pragma GCC diagnostic error   "-Wstring-conversion"
 #pragma GCC diagnostic error   "-Wswitch-enum"
@@ -129,6 +131,7 @@
 #pragma GCC diagnostic ignored "-Wclass-memaccess"
 #pragma GCC diagnostic ignored "-Wcast-function-type-strict" // https://github.com/harfbuzz/harfbuzz/pull/3859#issuecomment-1295409126
 #pragma GCC diagnostic ignored "-Wdangling-reference" // https://github.com/harfbuzz/harfbuzz/issues/4043
+#pragma GCC diagnostic ignored "-Wdangling-pointer" // Trigerred by hb_decycler_node_t().
 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
 #pragma GCC diagnostic ignored "-Wformat-zero-length"
 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
@@ -177,6 +180,11 @@
 #define HB_EXTERN __declspec (dllexport) extern
 #endif
 
+// https://github.com/harfbuzz/harfbuzz/pull/4619
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS 1
+#endif
+
 #include "hb.h"
 #define HB_H_IN
 #include "hb-ot.h"
@@ -212,6 +220,12 @@
 #include <winapifamily.h>
 #endif
 
+#ifndef PRId32
+# define PRId32 "d"
+# define PRIu32 "u"
+# define PRIx32 "x"
+#endif
+
 #define HB_PASTE1(a,b) a##b
 #define HB_PASTE(a,b) HB_PASTE1(a,b)
 
@@ -268,7 +282,9 @@ extern "C" void  hb_free_impl(void *ptr)
 #define __attribute__(x)
 #endif
 
-#if defined(__GNUC__) && (__GNUC__ >= 3)
+#if defined(__MINGW32__) && (__GNUC__ >= 3)
+#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (gnu_printf, format_idx, arg_idx)))
+#elif defined(__GNUC__) && (__GNUC__ >= 3)
 #define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
 #else
 #define HB_PRINTF_FUNC(format_idx, arg_idx)
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libjsound/MidiInDevice.c 24.0.2+12-1/src/java.desktop/share/native/libjsound/MidiInDevice.c
--- 24.0.1+9-1/src/java.desktop/share/native/libjsound/MidiInDevice.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libjsound/MidiInDevice.c	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -137,7 +137,7 @@ Java_com_sun_media_sound_MidiInDevice_nG
 
     /* Handle error codes. */
     if (ret < -1) {
-        ERROR1("Java_com_sun_media_sound_MidiInDevice_nGetTimeStamp: MIDI_IN_GetTimeStamp returned %lld\n", ret);
+        ERROR1("Java_com_sun_media_sound_MidiInDevice_nGetTimeStamp: MIDI_IN_GetTimeStamp returned %lld\n", (long long int) ret);
         ret = -1;
     }
     return ret;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/libjsound/MidiOutDevice.c 24.0.2+12-1/src/java.desktop/share/native/libjsound/MidiOutDevice.c
--- 24.0.1+9-1/src/java.desktop/share/native/libjsound/MidiOutDevice.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/libjsound/MidiOutDevice.c	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -94,7 +94,7 @@ Java_com_sun_media_sound_MidiOutDevice_n
 
     /* Handle error codes. */
     if (ret < -1) {
-        ERROR1("Java_com_sun_media_sound_MidiOutDevice_nGetTimeStamp: MIDI_IN_GetTimeStamp returned %lld\n", ret);
+        ERROR1("Java_com_sun_media_sound_MidiOutDevice_nGetTimeStamp: MIDI_IN_GetTimeStamp returned %lld\n", (long long int) ret);
         ret = -1;
     }
     return ret;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsalpha.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsalpha.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsalpha.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsalpha.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -612,8 +612,8 @@ void _cmsHandleExtraChannels(_cmsTRANSFO
         cmsUInt8Number* SourcePtr;
         cmsUInt8Number* DestPtr;
 
-        cmsUInt32Number SourceStrideIncrement = 0;
-        cmsUInt32Number DestStrideIncrement = 0;
+        size_t SourceStrideIncrement = 0;
+        size_t DestStrideIncrement = 0;
 
         // The loop itself
         for (i = 0; i < LineCount; i++) {
@@ -640,8 +640,8 @@ void _cmsHandleExtraChannels(_cmsTRANSFO
         cmsUInt8Number* SourcePtr[cmsMAXCHANNELS];
         cmsUInt8Number* DestPtr[cmsMAXCHANNELS];
 
-        cmsUInt32Number SourceStrideIncrements[cmsMAXCHANNELS];
-        cmsUInt32Number DestStrideIncrements[cmsMAXCHANNELS];
+        size_t SourceStrideIncrements[cmsMAXCHANNELS];
+        size_t DestStrideIncrements[cmsMAXCHANNELS];
 
         memset(SourceStrideIncrements, 0, sizeof(SourceStrideIncrements));
         memset(DestStrideIncrements, 0, sizeof(DestStrideIncrements));
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmscam02.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmscam02.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmscam02.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmscam02.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -117,17 +117,16 @@ cmsFloat64Number computeFL(cmsCIECAM02*
     return FL;
 }
 
-static
-cmsFloat64Number computeD(cmsCIECAM02* pMod)
+static cmsFloat64Number computeD(cmsCIECAM02* pMod)
 {
-    cmsFloat64Number D;
+    cmsFloat64Number D, temp;
 
-    D = pMod->F - (1.0/3.6)*(exp(((-pMod ->LA-42) / 92.0)));
+    temp = 1.0 - ((1.0 / 3.6) * exp((-pMod->LA - 42) / 92.0));
 
+    D = pMod->F * temp;
     return D;
 }
 
-
 static
 CAM02COLOR XYZtoCAT02(CAM02COLOR clr)
 {
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmscgats.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmscgats.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmscgats.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmscgats.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -444,10 +444,11 @@ static
 void StringClear(string* s)
 {
     s->len = 0;
+    s->begin[0] = 0;
 }
 
 static
-void StringAppend(string* s, char c)
+cmsBool StringAppend(string* s, char c)
 {
     if (s->len + 1 >= s->max)
     {
@@ -455,6 +456,8 @@ void StringAppend(string* s, char c)
 
         s->max *= 10;
         new_ptr = (char*) AllocChunk(s->it8, s->max);
+        if (new_ptr == NULL) return FALSE;
+
         if (new_ptr != NULL && s->begin != NULL)
             memcpy(new_ptr, s->begin, s->len);
 
@@ -466,6 +469,8 @@ void StringAppend(string* s, char c)
         s->begin[s->len++] = c;
         s->begin[s->len] = 0;
     }
+
+    return TRUE;
 }
 
 static
@@ -475,13 +480,15 @@ char* StringPtr(string* s)
 }
 
 static
-void StringCat(string* s, const char* c)
+cmsBool StringCat(string* s, const char* c)
 {
     while (*c)
     {
-        StringAppend(s, *c);
+        if (!StringAppend(s, *c)) return FALSE;
         c++;
     }
+
+    return TRUE;
 }
 
 
@@ -830,7 +837,12 @@ void InStringSymbol(cmsIT8* it8)
 
             if (it8->ch == '\n' || it8->ch == '\r' || it8->ch == 0) break;
             else {
-                StringAppend(it8->str, (char)it8->ch);
+                if (!StringAppend(it8->str, (char)it8->ch)) {
+
+                    SynError(it8, "Out of memory");
+                    return;
+                }
+
                 NextCh(it8);
             }
         }
@@ -860,7 +872,11 @@ void InSymbol(cmsIT8* it8)
 
             do {
 
-                StringAppend(it8->id, (char) it8->ch);
+                if (!StringAppend(it8->id, (char)it8->ch)) {
+
+                    SynError(it8, "Out of memory");
+                    return;
+                }
 
                 NextCh(it8);
 
@@ -904,7 +920,6 @@ void InSymbol(cmsIT8* it8)
                             if ((cmsFloat64Number) it8->inum * 16.0 + (cmsFloat64Number) j > (cmsFloat64Number)+2147483647.0)
                             {
                                 SynError(it8, "Invalid hexadecimal number");
-                                it8->sy = SEOF;
                                 return;
                             }
 
@@ -926,7 +941,6 @@ void InSymbol(cmsIT8* it8)
                             if ((cmsFloat64Number) it8->inum * 2.0 + j > (cmsFloat64Number)+2147483647.0)
                             {
                                 SynError(it8, "Invalid binary number");
-                                it8->sy = SEOF;
                                 return;
                             }
 
@@ -979,11 +993,19 @@ void InSymbol(cmsIT8* it8)
                     }
 
                     StringClear(it8->id);
-                    StringCat(it8->id, buffer);
+                    if (!StringCat(it8->id, buffer)) {
+
+                        SynError(it8, "Out of memory");
+                        return;
+                    }
 
                     do {
 
-                        StringAppend(it8->id, (char) it8->ch);
+                        if (!StringAppend(it8->id, (char)it8->ch)) {
+
+                            SynError(it8, "Out of memory");
+                            return;
+                        }
 
                         NextCh(it8);
 
@@ -1038,7 +1060,6 @@ void InSymbol(cmsIT8* it8)
 
         default:
             SynError(it8, "Unrecognized character: 0x%x", it8 ->ch);
-            it8->sy = SEOF;
             return;
             }
 
@@ -1053,24 +1074,21 @@ void InSymbol(cmsIT8* it8)
                 if(it8 -> IncludeSP >= (MAXINCLUDE-1)) {
 
                     SynError(it8, "Too many recursion levels");
-                    it8->sy = SEOF;
                     return;
                 }
 
                 InStringSymbol(it8);
                 if (!Check(it8, SSTRING, "Filename expected"))
-                {
-                    it8->sy = SEOF;
                     return;
-                }
+
 
                 FileNest = it8 -> FileStack[it8 -> IncludeSP + 1];
                 if(FileNest == NULL) {
 
                     FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (FILECTX*)AllocChunk(it8, sizeof(FILECTX));
                     if (FileNest == NULL) {
+
                         SynError(it8, "Out of memory");
-                        it8->sy = SEOF;
                         return;
                     }
                 }
@@ -1078,8 +1096,8 @@ void InSymbol(cmsIT8* it8)
                 if (BuildAbsolutePath(StringPtr(it8->str),
                                       it8->FileStack[it8->IncludeSP]->FileName,
                                       FileNest->FileName, cmsMAX_PATH-1) == FALSE) {
+
                     SynError(it8, "File path too long");
-                    it8->sy = SEOF;
                     return;
                 }
 
@@ -1087,7 +1105,6 @@ void InSymbol(cmsIT8* it8)
                 if (FileNest->Stream == NULL) {
 
                         SynError(it8, "File %s not found", FileNest->FileName);
-                        it8->sy = SEOF;
                         return;
                 }
                 it8->IncludeSP++;
@@ -1102,10 +1119,10 @@ void InSymbol(cmsIT8* it8)
 static
 cmsBool CheckEOLN(cmsIT8* it8)
 {
-        if (!Check(it8, SEOLN, "Expected separator")) return FALSE;
-        while (it8 -> sy == SEOLN)
-                        InSymbol(it8);
-        return TRUE;
+    if (!Check(it8, SEOLN, "Expected separator")) return FALSE;
+    while (it8->sy == SEOLN)
+        InSymbol(it8);
+    return TRUE;
 
 }
 
@@ -1114,8 +1131,8 @@ cmsBool CheckEOLN(cmsIT8* it8)
 static
 void Skip(cmsIT8* it8, SYMBOL sy)
 {
-        if (it8->sy == sy && it8->sy != SEOF)
-                        InSymbol(it8);
+    if (it8->sy == sy && it8->sy != SEOF && it8->sy != SSYNERROR)
+        InSymbol(it8);
 }
 
 
@@ -1124,7 +1141,7 @@ static
 void SkipEOLN(cmsIT8* it8)
 {
     while (it8->sy == SEOLN) {
-             InSymbol(it8);
+        InSymbol(it8);
     }
 }
 
@@ -1235,9 +1252,12 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32N
     cmsUInt8Number* ptr;
 
     size = _cmsALIGNMEM(size);
+    if (size == 0) return NULL;
 
     if (size > Free) {
 
+        cmsUInt8Number* new_block;
+
         if (it8 -> Allocator.BlockSize == 0)
 
                 it8 -> Allocator.BlockSize = 20*1024;
@@ -1248,7 +1268,11 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32N
                 it8 ->Allocator.BlockSize = size;
 
         it8 ->Allocator.Used = 0;
-        it8 ->Allocator.Block = (cmsUInt8Number*) AllocBigBlock(it8, it8 ->Allocator.BlockSize);
+        new_block = (cmsUInt8Number*)AllocBigBlock(it8, it8->Allocator.BlockSize);
+        if (new_block == NULL)
+            return NULL;
+
+        it8->Allocator.Block = new_block;
     }
 
     if (it8->Allocator.Block == NULL)
@@ -1258,7 +1282,6 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32N
     it8 ->Allocator.Used += size;
 
     return (void*) ptr;
-
 }
 
 
@@ -1266,9 +1289,12 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32N
 static
 char *AllocString(cmsIT8* it8, const char* str)
 {
-    cmsUInt32Number Size = (cmsUInt32Number) strlen(str)+1;
+    cmsUInt32Number Size;
     char *ptr;
 
+    if (str == NULL) return NULL;
+
+    Size = (cmsUInt32Number)strlen(str) + 1;
 
     ptr = (char *) AllocChunk(it8, Size);
     if (ptr) memcpy(ptr, str, Size-1);
@@ -1404,10 +1430,13 @@ KEYVALUE* AddAvailableSampleID(cmsIT8* i
 
 
 static
-void AllocTable(cmsIT8* it8)
+cmsBool AllocTable(cmsIT8* it8)
 {
     TABLE* t;
 
+    if (it8->TablesCount >= (MAXTABLES-1))
+        return FALSE;
+
     t = it8 ->Tab + it8 ->TablesCount;
 
     t->HeaderList = NULL;
@@ -1415,6 +1444,7 @@ void AllocTable(cmsIT8* it8)
     t->Data       = NULL;
 
     it8 ->TablesCount++;
+    return TRUE;
 }
 
 
@@ -1426,7 +1456,10 @@ cmsInt32Number CMSEXPORT cmsIT8SetTable(
 
          if (nTable == it8 ->TablesCount) {
 
-             AllocTable(it8);
+             if (!AllocTable(it8)) {
+                 SynError(it8, "Too many tables");
+                 return -1;
+             }
          }
          else {
              SynError(it8, "Table %d is out of sequence", nTable);
@@ -1610,8 +1643,8 @@ cmsInt32Number satoi(const char* b)
     if (b == NULL) return 0;
 
     n = atoi(b);
-    if (n > 0x7fffffffL) return 0x7fffffffL;
-    if (n < -0x7ffffffeL) return -0x7ffffffeL;
+    if (n > 0x7ffffff0L) return 0x7ffffff0L;
+    if (n < -0x7ffffff0L) return -0x7ffffff0L;
 
     return (cmsInt32Number)n;
 }
@@ -1620,22 +1653,26 @@ cmsInt32Number satoi(const char* b)
 static
 cmsBool AllocateDataFormat(cmsIT8* it8)
 {
+    cmsUInt32Number size;
+
     TABLE* t = GetTable(it8);
 
-    if (t -> DataFormat) return TRUE;    // Already allocated
+    if (t->DataFormat) return TRUE;    // Already allocated
 
-    t -> nSamples  = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
+    t->nSamples = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
 
-    if (t -> nSamples <= 0) {
+    if (t->nSamples <= 0 || t->nSamples > 0x7ffe) {
 
-        SynError(it8, "AllocateDataFormat: Unknown NUMBER_OF_FIELDS");
+        SynError(it8, "Wrong NUMBER_OF_FIELDS");
         return FALSE;
-        }
+    }
+
+    size = ((cmsUInt32Number)t->nSamples + 1) * sizeof(char*);
 
-    t -> DataFormat = (char**) AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * sizeof(char *));
+    t->DataFormat = (char**)AllocChunk(it8, size);
     if (t->DataFormat == NULL) {
 
-        SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array");
+        SynError(it8, "Unable to allocate dataFormat array");
         return FALSE;
     }
 
@@ -1664,7 +1701,7 @@ cmsBool SetDataFormat(cmsIT8* it8, int n
             return FALSE;
     }
 
-    if (n > t -> nSamples) {
+    if (n >= t -> nSamples) {
         SynError(it8, "More than NUMBER_OF_FIELDS fields.");
         return FALSE;
     }
@@ -1713,13 +1750,14 @@ cmsBool AllocateDataSet(cmsIT8* it8)
     t-> nSamples   = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
     t-> nPatches   = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
 
-    if (t -> nSamples < 0 || t->nSamples > 0x7ffe || t->nPatches < 0 || t->nPatches > 0x7ffe)
+    if (t -> nSamples < 0 || t->nSamples > 0x7ffe || t->nPatches < 0 || t->nPatches > 0x7ffe ||
+        (t->nPatches * t->nSamples) > 200000)
     {
         SynError(it8, "AllocateDataSet: too much data");
         return FALSE;
     }
     else {
-        // Some dumb analizers warns of possible overflow here, just take a look couple of lines above.
+        // Some dumb analyzers warns of possible overflow here, just take a look couple of lines above.
         t->Data = (char**)AllocChunk(it8, ((cmsUInt32Number)t->nSamples + 1) * ((cmsUInt32Number)t->nPatches + 1) * sizeof(char*));
         if (t->Data == NULL) {
 
@@ -1748,8 +1786,11 @@ char* GetData(cmsIT8* it8, int nSet, int
 static
 cmsBool SetData(cmsIT8* it8, int nSet, int nField, const char *Val)
 {
+    char* ptr;
+
     TABLE* t = GetTable(it8);
 
+
     if (!t->Data) {
         if (!AllocateDataSet(it8)) return FALSE;
     }
@@ -1766,7 +1807,11 @@ cmsBool SetData(cmsIT8* it8, int nSet, i
 
     }
 
-    t->Data [nSet * t -> nSamples + nField] = AllocString(it8, Val);
+    ptr = AllocString(it8, Val);
+    if (ptr == NULL)
+        return FALSE;
+
+    t->Data [nSet * t -> nSamples + nField] = ptr;
     return TRUE;
 }
 
@@ -2121,7 +2166,7 @@ cmsBool DataSection (cmsIT8* it8)
         if (!AllocateDataSet(it8)) return FALSE;
     }
 
-    while (it8->sy != SEND_DATA && it8->sy != SEOF)
+    while (it8->sy != SEND_DATA && it8->sy != SEOF && it8->sy != SSYNERROR)
     {
         if (iField >= t -> nSamples) {
             iField = 0;
@@ -2129,7 +2174,7 @@ cmsBool DataSection (cmsIT8* it8)
 
         }
 
-        if (it8->sy != SEND_DATA && it8->sy != SEOF) {
+        if (it8->sy != SEND_DATA && it8->sy != SEOF && it8->sy != SSYNERROR) {
 
             switch (it8->sy)
             {
@@ -2225,8 +2270,8 @@ cmsBool HeaderSection(cmsIT8* it8)
             if (!GetVal(it8, Buffer, MAXSTR - 1, "Property data expected")) return FALSE;
 
             if (Key->WriteAs != WRITE_PAIR) {
-                AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer,
-                    (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED);
+                if (AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer,
+                    (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED) == NULL) return FALSE;
             }
             else {
                 const char *Subkey;
@@ -2332,9 +2377,10 @@ cmsBool ParseIT8(cmsIT8* it8, cmsBool no
 
                     if (!DataSection(it8)) return FALSE;
 
-                    if (it8 -> sy != SEOF) {
+                    if (it8 -> sy != SEOF && it8->sy != SSYNERROR) {
+
+                            if (!AllocTable(it8)) return FALSE;
 
-                            AllocTable(it8);
                             it8 ->nTable = it8 ->TablesCount - 1;
 
                             // Read sheet type if present. We only support identifier and string.
@@ -3064,7 +3110,8 @@ cmsBool ParseCube(cmsIT8* cube, cmsStage
 
     InSymbol(cube);
 
-    while (cube->sy != SEOF) {
+    while (cube->sy != SEOF && cube->sy != SSYNERROR) {
+
         switch (cube->sy)
         {
         // Set profile description
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmscnvrt.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmscnvrt.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmscnvrt.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmscnvrt.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -750,7 +750,6 @@ static
 cmsBool is_cmyk_devicelink(cmsHPROFILE hProfile)
 {
     return cmsGetDeviceClass(hProfile) == cmsSigLinkClass &&
-            cmsGetColorSpace(hProfile) == cmsSigCmykData &&
             cmsGetColorSpace(hProfile) == cmsSigCmykData;
 }
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmserr.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmserr.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmserr.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmserr.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsgamma.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsgamma.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsgamma.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsgamma.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsgmt.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsgmt.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsgmt.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsgmt.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2021 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -327,8 +327,9 @@ cmsPipeline* _cmsCreateGamutCheckPipelin
     cmsUInt32Number dwFormat;
     GAMUTCHAIN Chain;
     cmsUInt32Number nGridpoints;
-    cmsInt32Number nChannels;
+    cmsInt32Number nChannels, nInputChannels;
     cmsColorSpaceSignature ColorSpace;
+    cmsColorSpaceSignature InputColorSpace;
     cmsUInt32Number i;
     cmsHPROFILE ProfileList[256];
     cmsBool     BPCList[256];
@@ -374,11 +375,13 @@ cmsPipeline* _cmsCreateGamutCheckPipelin
     AdaptationList[nGamutPCSposition] = 1.0;
     IntentList[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC;
 
-
     ColorSpace  = cmsGetColorSpace(hGamut);
     nChannels   = cmsChannelsOfColorSpace(ColorSpace);
     nGridpoints = _cmsReasonableGridpointsByColorspace(ColorSpace, cmsFLAGS_HIGHRESPRECALC);
-    dwFormat    = (CHANNELS_SH(nChannels)|BYTES_SH(2));
+
+    InputColorSpace = cmsGetColorSpace(ProfileList[0]);
+    nInputChannels  = cmsChannelsOfColorSpace(InputColorSpace);
+    dwFormat        = (CHANNELS_SH(nInputChannels)|BYTES_SH(2));
 
     // 16 bits to Lab double
     Chain.hInput = cmsCreateExtendedTransform(ContextID,
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmshalf.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmshalf.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmshalf.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmshalf.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsintrp.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsintrp.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsintrp.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsintrp.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -524,7 +524,7 @@ void TrilinearInterpFloat(const cmsFloat
     py = fclamp(Input[1]) * p->Domain[1];
     pz = fclamp(Input[2]) * p->Domain[2];
 
-    x0 = (int) floor(px); fx = px - (cmsFloat32Number) x0;  // We need full floor funcionality here
+    x0 = (int) floor(px); fx = px - (cmsFloat32Number) x0;  // We need full floor functionality here
     y0 = (int) floor(py); fy = py - (cmsFloat32Number) y0;
     z0 = (int) floor(pz); fz = pz - (cmsFloat32Number) z0;
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsio0.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsio0.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsio0.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsio0.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -306,6 +306,11 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandler
         fm = (FILEMEM*) _cmsMallocZero(ContextID, sizeof(FILEMEM));
         if (fm == NULL) goto Error;
 
+        if (Buffer == NULL) {
+            cmsSignalError(ContextID, cmsERROR_WRITE, "Couldn't write profile to NULL pointer");
+            goto Error;
+        }
+
         fm ->Block = (cmsUInt8Number*) Buffer;
         fm ->FreeBlockOnClose = FALSE;
         fm ->Size    = size;
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsio1.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsio1.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsio1.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsio1.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmslut.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmslut.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmslut.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmslut.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -1109,7 +1109,7 @@ cmsStage* _cmsStageNormalizeFromLabFloat
     return mpe;
 }
 
-// Fom XYZ to floating point PCS
+// From XYZ to floating point PCS
 cmsStage* _cmsStageNormalizeFromXyzFloat(cmsContext ContextID)
 {
 #define n (32768.0/65535.0)
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsmd5.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsmd5.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsmd5.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsmd5.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -280,8 +280,8 @@ void CMSEXPORT cmsMD5finish(cmsProfileID
 
 
 // Assuming io points to an ICC profile, compute and store MD5 checksum
-// In the header, rendering intentent, attributes and ID should be set to zero
-// before computing MD5 checksum (per 6.1.13 in ICC spec)
+// In the header, rendering intentent, flags and ID should be set to zero
+// before computing MD5 checksum (per 7.2.18 of ICC spec 4.4)
 
 cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile)
 {
@@ -299,8 +299,8 @@ cmsBool CMSEXPORT cmsMD5computeID(cmsHPR
     // Save a copy of the profile header
     memmove(&Keep, Icc, sizeof(_cmsICCPROFILE));
 
-    // Set RI, attributes and ID
-    memset(&Icc ->attributes, 0, sizeof(Icc ->attributes));
+    // Set RI, flags and ID
+    Icc ->flags = 0;
     Icc ->RenderingIntent = 0;
     memset(&Icc ->ProfileID, 0, sizeof(Icc ->ProfileID));
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsmtrx.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsmtrx.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsmtrx.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsmtrx.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsnamed.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsnamed.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsnamed.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsnamed.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -598,7 +598,7 @@ cmsUInt32Number CMSEXPORT cmsMLUgetASCII
     if (BufferSize < ASCIIlen + 1)
         ASCIIlen = BufferSize - 1;
 
-    // Precess each character
+    // Process each character
     for (i=0; i < ASCIIlen; i++) {
 
         wchar_t wc = Wide[i];
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsopt.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsopt.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsopt.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsopt.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmspack.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmspack.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmspack.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmspack.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -217,7 +217,7 @@ cmsUInt8Number* UnrollPlanarBytes(CMSREG
     else
     {
         if (Premul && Extra)
-            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[(nChan) * Stride]));
+            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[nChan * Stride]));
     }
 
     for (i=0; i < nChan; i++) {
@@ -606,8 +606,8 @@ cmsUInt8Number* UnrollAnyWordsPremul(CMS
    cmsUInt32Number ExtraFirst  = DoSwap ^ SwapFirst;
    cmsUInt32Number i;
 
-   cmsUInt16Number alpha = (ExtraFirst ? accum[0] : accum[nChan - 1]);
-   cmsUInt32Number alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(alpha));
+   cmsUInt16Number alpha = (ExtraFirst ? ((cmsUInt16Number*)accum)[0] : ((cmsUInt16Number*)accum)[nChan]);
+   cmsUInt32Number alpha_factor = _cmsToFixedDomain(alpha);
 
     if (ExtraFirst) {
         accum += sizeof(cmsUInt16Number);
@@ -691,8 +691,8 @@ cmsUInt8Number* UnrollPlanarWordsPremul(
     cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
     cmsUInt8Number* Init = accum;
 
-    cmsUInt16Number  alpha = (ExtraFirst ? accum[0] : accum[(nChan - 1) * Stride]);
-    cmsUInt32Number alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(alpha));
+    cmsUInt16Number alpha = (ExtraFirst ? ((cmsUInt16Number*)accum)[0] : ((cmsUInt16Number*)accum)[nChan * Stride / 2]);
+    cmsUInt32Number alpha_factor = _cmsToFixedDomain(alpha);
 
     if (ExtraFirst) {
         accum += Stride;
@@ -1107,8 +1107,7 @@ cmsINLINE cmsBool IsInkSpace(cmsUInt32Nu
 }
 
 // Return the size in bytes of a given formatter
-static
-cmsUInt32Number PixelSize(cmsUInt32Number Format)
+cmsINLINE cmsUInt32Number PixelSize(cmsUInt32Number Format)
 {
     cmsUInt32Number fmt_bytes = T_BYTES(Format);
 
@@ -1454,7 +1453,7 @@ cmsUInt8Number* UnrollDoublesToFloat(_cm
     if (Premul && Extra)
     {
         if (Planar)
-            alpha_factor = (ExtraFirst ? ptr[0] : ptr[(nChan) * Stride]) / maximum;
+            alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan * Stride]) / maximum;
         else
             alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan]) / maximum;
     }
@@ -3052,6 +3051,7 @@ cmsUInt8Number* PackWordsFromFloat(_cmsT
     if (ExtraFirst)
         start = Extra;
 
+    Stride /= 2;
     for (i = 0; i < nChan; i++) {
 
         cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
@@ -3115,7 +3115,7 @@ cmsUInt8Number* PackFloatsFromFloat(_cms
                      v = maximum - v;
 
               if (Planar)
-                     ((cmsFloat32Number*)output)[(i + start)* Stride] = (cmsFloat32Number)v;
+                     ((cmsFloat32Number*)output)[(i + start) * Stride] = (cmsFloat32Number)v;
               else
                      ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v;
        }
@@ -3455,7 +3455,7 @@ cmsUInt8Number* UnrollHalfToFloat(_cmsTR
     cmsUInt32Number i, start = 0;
     cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F;
 
-    Stride /= PixelSize(info->OutputFormat);
+    Stride /= PixelSize(info->InputFormat);
 
     if (ExtraFirst)
             start = Extra;
@@ -4062,6 +4062,9 @@ cmsUInt32Number CMSEXPORT cmsFormatterFo
     // Unsupported color space?
     if (nOutputChans < 0) return 0;
 
+    // Fix float spaces
+    nBytes &= 7;
+
     // Create a fake formatter for result
     return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
 }
@@ -4079,6 +4082,9 @@ cmsUInt32Number CMSEXPORT cmsFormatterFo
     // Unsupported color space?
     if (nOutputChans < 0) return 0;
 
+    // Fix float spaces
+    nBytes &= 7;
+
     // Create a fake formatter for result
     return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
 }
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmspcs.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmspcs.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmspcs.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmspcs.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsplugin.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsplugin.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsplugin.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsplugin.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -935,7 +935,10 @@ cmsContext CMSEXPORT cmsDupContext(cmsCo
     if (!InitContextMutex()) return NULL;
 
     // Setup default memory allocators
-    memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
+    if (ContextID == NULL)
+        _cmsInstallAllocFunctions(NULL, &ctx->DefaultMemoryManager);
+    else
+        memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
 
     // Maintain the linked list
     _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsps2.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsps2.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsps2.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsps2.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -494,7 +494,7 @@ void Emit1Gamma(cmsIOHANDLER* m, cmsTone
     // Bounds check
     EmitRangeCheck(m);
 
-    // Emit intepolation code
+    // Emit interpolation code
 
     // PostScript code                      Stack
     // ===============                      ========================
@@ -618,7 +618,7 @@ int OutputValueSampler(CMSREGISTER const
     }
 
 
-    // Hadle the parenthesis on rows
+    // Handle the parenthesis on rows
 
     if (In[0] != sc ->FirstComponent) {
 
@@ -694,8 +694,10 @@ void WriteCLUT(cmsIOHANDLER* m, cmsStage
 
         _cmsIOPrintf(m, "[");
 
-        for (i = 0; i < sc.Pipeline->Params->nInputs; i++)
-            _cmsIOPrintf(m, " %d ", sc.Pipeline->Params->nSamples[i]);
+        for (i = 0; i < sc.Pipeline->Params->nInputs; i++) {
+            if (i < MAX_INPUT_DIMENSIONS)
+                _cmsIOPrintf(m, " %d ", sc.Pipeline->Params->nSamples[i]);
+        }
 
         _cmsIOPrintf(m, " [\n");
 
@@ -869,13 +871,13 @@ cmsToneCurve* ExtractGray2Y(cmsContext C
 // a more perceptually uniform space... I do choose Lab.
 
 static
-int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
+cmsBool WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
 {
     cmsHPROFILE hLab;
     cmsHTRANSFORM xform;
     cmsUInt32Number nChannels;
     cmsUInt32Number InputFormat;
-    int rc;
+
     cmsHPROFILE Profiles[2];
     cmsCIEXYZ BlackPointAdaptedToD50;
 
@@ -900,7 +902,7 @@ int WriteInputLUT(cmsIOHANDLER* m, cmsHP
     if (xform == NULL) {
 
         cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Profile -> Lab");
-        return 0;
+        return FALSE;
     }
 
     // Only 1, 3 and 4 channels are allowed
@@ -919,29 +921,35 @@ int WriteInputLUT(cmsIOHANDLER* m, cmsHP
             cmsUInt32Number OutFrm = TYPE_Lab_16;
             cmsPipeline* DeviceLink;
             _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform;
+            cmsBool rc;
 
             DeviceLink = cmsPipelineDup(v ->Lut);
-            if (DeviceLink == NULL) return 0;
+            if (DeviceLink == NULL) {
+                cmsDeleteTransform(xform);
+                return FALSE;
+            }
 
             dwFlags |= cmsFLAGS_FORCE_CLUT;
             _cmsOptimizePipeline(m->ContextID, &DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags);
 
             rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50);
             cmsPipelineFree(DeviceLink);
-            if (rc == 0) return 0;
+            if (!rc) {
+                cmsDeleteTransform(xform);
+                return FALSE;
+            }
             }
             break;
 
     default:
 
+        cmsDeleteTransform(xform);
         cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Only 3, 4 channels are supported for CSA. This profile has %d channels.", nChannels);
-        return 0;
+        return FALSE;
     }
 
-
     cmsDeleteTransform(xform);
-
-    return 1;
+    return TRUE;
 }
 
 static
@@ -1284,7 +1292,7 @@ void EmitXYZ2Lab(cmsIOHANDLER* m)
 // 8 bits.
 
 static
-int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
+cmsBool WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
 {
     cmsHPROFILE hLab;
     cmsHTRANSFORM xform;
@@ -1302,7 +1310,7 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsH
     cmsStage* first;
 
     hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL);
-    if (hLab == NULL) return 0;
+    if (hLab == NULL) return FALSE;
 
     OutputFormat = cmsFormatterForColorspaceOfProfile(hProfile, 2, FALSE);
     nChannels    = T_CHANNELS(OutputFormat);
@@ -1327,7 +1335,7 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsH
 
     if (xform == NULL) {
         cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Lab -> Profile in CRD creation");
-        return 0;
+        return FALSE;
     }
 
     // Get a copy of the internal devicelink
@@ -1335,17 +1343,22 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsH
     DeviceLink = cmsPipelineDup(v ->Lut);
     if (DeviceLink == NULL) {
         cmsDeleteTransform(xform);
-        return 0;
+        cmsSignalError(m->ContextID, cmsERROR_CORRUPTION_DETECTED, "Cannot access link for CRD");
+        return FALSE;
     }
 
      // We need a CLUT
     dwFlags |= cmsFLAGS_FORCE_CLUT;
-    _cmsOptimizePipeline(m->ContextID, &DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags);
+    if (!_cmsOptimizePipeline(m->ContextID, &DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags)) {
+        cmsPipelineFree(DeviceLink);
+        cmsDeleteTransform(xform);
+        cmsSignalError(m->ContextID, cmsERROR_CORRUPTION_DETECTED, "Cannot create CLUT table for CRD");
+        return FALSE;
+    }
 
     _cmsIOPrintf(m, "<<\n");
     _cmsIOPrintf(m, "/ColorRenderingType 1\n");
 
-
     cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, 0);
 
     // Emit headers, etc.
@@ -1367,6 +1380,13 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsH
 
     first = cmsPipelineGetPtrToFirstStage(DeviceLink);
     if (first != NULL) {
+        if (first->Type != cmsSigCLutElemType) {
+            cmsPipelineFree(DeviceLink);
+            cmsDeleteTransform(xform);
+            cmsSignalError(m->ContextID, cmsERROR_CORRUPTION_DETECTED, "Cannot create CLUT, revise your flags!");
+            return FALSE;
+        }
+
         WriteCLUT(m, first, "<", ">\n", "", "", lFixWhite, ColorSpace);
     }
 
@@ -1389,7 +1409,7 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsH
     cmsPipelineFree(DeviceLink);
     cmsDeleteTransform(xform);
 
-    return 1;
+    return TRUE;
 }
 
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmssamp.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmssamp.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmssamp.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmssamp.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmssm.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmssm.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmssm.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmssm.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmstypes.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmstypes.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmstypes.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmstypes.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -600,6 +600,178 @@ void Type_ColorantOrderType_Free(struct
 }
 
 // ********************************************************************************
+// Type cmsSigUInt8ArrayType
+// ********************************************************************************
+// This type represents an array of generic 1-byte/8-bit quantity.
+
+static
+void* Type_UInt8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
+{
+    cmsUInt8Number* array;
+    cmsUInt32Number i, n;
+
+    *nItems = 0;
+    n = SizeOfTag / sizeof(cmsUInt8Number);
+    array = (cmsUInt8Number*)_cmsCalloc(self->ContextID, n, sizeof(cmsUInt8Number));
+    if (array == NULL) return NULL;
+
+    for (i = 0; i < n; i++) {
+
+        if (!_cmsReadUInt8Number(io, &array[i])) {
+
+            _cmsFree(self->ContextID, array);
+            return NULL;
+        }
+    }
+
+    *nItems = n;
+    return (void*)array;
+}
+
+static
+cmsBool Type_UInt8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
+{
+    cmsUInt8Number* Value = (cmsUInt8Number*)Ptr;
+    cmsUInt32Number i;
+
+    for (i = 0; i < nItems; i++) {
+
+        if (!_cmsWriteUInt8Number(io, Value[i])) return FALSE;
+    }
+
+    return TRUE;
+
+    cmsUNUSED_PARAMETER(self);
+}
+
+static
+void* Type_UInt8_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
+{
+    return _cmsDupMem(self->ContextID, Ptr, n * sizeof(cmsUInt8Number));
+}
+
+
+static
+void Type_UInt8_Free(struct _cms_typehandler_struct* self, void* Ptr)
+{
+    _cmsFree(self->ContextID, Ptr);
+}
+
+// ********************************************************************************
+// Type cmsSigUInt32ArrayType
+// ********************************************************************************
+// This type represents an array of generic 4-byte/32-bit quantity.
+static
+void* Type_UInt32_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
+{
+    cmsUInt32Number* array;
+    cmsUInt32Number i, n;
+
+    *nItems = 0;
+    n = SizeOfTag / sizeof(cmsUInt32Number);
+    array = (cmsUInt32Number*)_cmsCalloc(self->ContextID, n, sizeof(cmsUInt32Number));
+    if (array == NULL) return NULL;
+
+    for (i = 0; i < n; i++) {
+
+        if (!_cmsReadUInt32Number(io, &array[i])) {
+
+            _cmsFree(self->ContextID, array);
+            return NULL;
+        }
+    }
+
+    *nItems = n;
+    return (void*)array;
+}
+
+static
+cmsBool Type_UInt32_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
+{
+    cmsUInt32Number* Value = (cmsUInt32Number*)Ptr;
+    cmsUInt32Number i;
+
+    for (i = 0; i < nItems; i++) {
+
+        if (!_cmsWriteUInt32Number(io, Value[i])) return FALSE;
+    }
+
+    return TRUE;
+
+    cmsUNUSED_PARAMETER(self);
+}
+
+static
+void* Type_UInt32_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
+{
+    return _cmsDupMem(self->ContextID, Ptr, n * sizeof(cmsUInt32Number));
+}
+
+
+static
+void Type_UInt32_Free(struct _cms_typehandler_struct* self, void* Ptr)
+{
+    _cmsFree(self->ContextID, Ptr);
+}
+
+// ********************************************************************************
+// Type cmsSigUInt64ArrayType
+// ********************************************************************************
+// This type represents an array of generic 8-byte/64-bit quantity.
+static
+void* Type_UInt64_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
+{
+    cmsUInt64Number* array;
+    cmsUInt32Number i, n;
+
+    *nItems = 0;
+    n = SizeOfTag / sizeof(cmsUInt64Number);
+    array = (cmsUInt64Number*)_cmsCalloc(self->ContextID, n, sizeof(cmsUInt64Number));
+    if (array == NULL) return NULL;
+
+    for (i = 0; i < n; i++) {
+
+        if (!_cmsReadUInt64Number(io, &array[i])) {
+
+            _cmsFree(self->ContextID, array);
+            return NULL;
+        }
+    }
+
+    *nItems = n;
+    return (void*)array;
+}
+
+static
+cmsBool Type_UInt64_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
+{
+    cmsUInt64Number* Value = (cmsUInt64Number*)Ptr;
+    cmsUInt32Number i;
+
+    for (i = 0; i < nItems; i++) {
+
+        if (!_cmsWriteUInt64Number(io, &Value[i])) return FALSE;
+    }
+
+    return TRUE;
+
+    cmsUNUSED_PARAMETER(self);
+}
+
+static
+void* Type_UInt64_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
+{
+    return _cmsDupMem(self->ContextID, Ptr, n * sizeof(cmsUInt64Number));
+}
+
+
+static
+void Type_UInt64_Free(struct _cms_typehandler_struct* self, void* Ptr)
+{
+    _cmsFree(self->ContextID, Ptr);
+}
+
+// ********************************************************************************
 // Type cmsSigS15Fixed16ArrayType
 // ********************************************************************************
 // This type represents an array of generic 4-byte/32-bit fixed point quantity.
@@ -968,6 +1140,8 @@ void *Type_Text_Description_Read(struct
 
     // Read len of ASCII
     if (!_cmsReadUInt32Number(io, &AsciiCount)) return NULL;
+    if (AsciiCount > 0x7ffff) return NULL;
+
     SizeOfTag -= sizeof(cmsUInt32Number);
 
     // Check for size
@@ -999,7 +1173,8 @@ void *Type_Text_Description_Read(struct
     if (!_cmsReadUInt32Number(io, &UnicodeCount)) goto Done;
     SizeOfTag -= 2* sizeof(cmsUInt32Number);
 
-    if (UnicodeCount == 0 || SizeOfTag < UnicodeCount*sizeof(cmsUInt16Number)) goto Done;
+    if (UnicodeCount == 0 || UnicodeCount > 0x7ffff ||
+        SizeOfTag < UnicodeCount*sizeof(cmsUInt16Number)) goto Done;
 
     UnicodeString = (wchar_t*)_cmsMallocZero(self->ContextID, (UnicodeCount + 1) * sizeof(wchar_t));
     if (UnicodeString == NULL) goto Done;
@@ -1129,7 +1304,7 @@ cmsBool  Type_Text_Description_Write(str
     if (!io ->Write(io, 67, Filler)) goto Error;
 
     // possibly add pad at the end of tag
-    if(len_aligned - len_tag_requirement > 0)
+    if (len_aligned > len_tag_requirement)
       if (!io ->Write(io, len_aligned - len_tag_requirement, Filler)) goto Error;
 
     rc = TRUE;
@@ -5191,7 +5366,7 @@ cmsBool ReadOneWChar(cmsIOHANDLER* io,
       if (!io -> Seek(io, e -> Offsets[i])) return FALSE;
 
       nChars = e ->Sizes[i] / sizeof(cmsUInt16Number);
-
+      if (nChars > 0x7ffff) return FALSE;
 
       *wcstr = (wchar_t*) _cmsMallocZero(e ->ContextID, (nChars + 1) * sizeof(wchar_t));
       if (*wcstr == NULL) return FALSE;
@@ -5772,7 +5947,10 @@ static const _cmsTagTypeLinkedList Suppo
 {TYPE_HANDLER(cmsSigDictType,                  Dictionary),         (_cmsTagTypeLinkedList*) &SupportedTagTypes[30] },
 {TYPE_HANDLER(cmsSigcicpType,                  VideoSignal),        (_cmsTagTypeLinkedList*) &SupportedTagTypes[31] },
 {TYPE_HANDLER(cmsSigVcgtType,                  vcgt),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[32] },
-{TYPE_HANDLER(cmsSigMHC2Type,                  MHC2),                NULL }
+{TYPE_HANDLER(cmsSigMHC2Type,                  MHC2),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[33] },
+{TYPE_HANDLER(cmsSigUInt8ArrayType,            UInt8),              (_cmsTagTypeLinkedList*) &SupportedTagTypes[34] },
+{TYPE_HANDLER(cmsSigUInt32ArrayType,           UInt32),             (_cmsTagTypeLinkedList*) &SupportedTagTypes[35] },
+{TYPE_HANDLER(cmsSigUInt64ArrayType,           UInt64),             NULL }
 };
 
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsvirt.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsvirt.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsvirt.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsvirt.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -412,7 +412,7 @@ int InkLimitingSampler(CMSREGISTER const
     Out[1] = _cmsQuickSaturateWord(In[1] * Ratio);     // M
     Out[2] = _cmsQuickSaturateWord(In[2] * Ratio);     // Y
 
-    Out[3] = In[3];                                 // K (untouched)
+    Out[3] = In[3];                                    // K (untouched)
 
     return TRUE;
 }
@@ -433,7 +433,7 @@ cmsHPROFILE CMSEXPORT cmsCreateInkLimiti
         return NULL;
     }
 
-    if (Limit < 0.0 || Limit > 400) {
+    if (Limit < 1.0 || Limit > 400) {
 
         cmsSignalError(ContextID, cmsERROR_RANGE, "InkLimiting: Limit should be between 1..400");
         if (Limit < 1) Limit = 1;
@@ -705,7 +705,7 @@ cmsHPROFILE CMSEXPORT cmsCreate_sRGBProf
 *
 * This virtual profile cannot be saved as an ICC file
 */
-cmsHPROFILE cmsCreate_OkLabProfile(cmsContext ctx)
+cmsHPROFILE CMSEXPORT cmsCreate_OkLabProfile(cmsContext ctx)
 {
     cmsStage* XYZPCS = _cmsStageNormalizeFromXyzFloat(ctx);
     cmsStage* PCSXYZ = _cmsStageNormalizeToXyzFloat(ctx);
@@ -774,6 +774,8 @@ cmsHPROFILE cmsCreate_OkLabProfile(cmsCo
     cmsPipeline* BToA = cmsPipelineAlloc(ctx, 3, 3);
 
     cmsHPROFILE hProfile = cmsCreateProfilePlaceholder(ctx);
+    if (!hProfile)            // can't allocate
+        goto error;
 
     cmsSetProfileVersion(hProfile, 4.4);
 
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmswtpnt.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmswtpnt.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmswtpnt.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmswtpnt.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsxform.c 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsxform.c
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/cmsxform.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/cmsxform.c	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -295,7 +295,7 @@ void FloatXFORM(_cmsTRANSFORM* p,
     cmsUInt8Number* output;
     cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS];
     cmsFloat32Number OutOfGamut;
-    cmsUInt32Number i, j, c, strideIn, strideOut;
+    size_t i, j, c, strideIn, strideOut;
 
     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 
@@ -322,9 +322,11 @@ void FloatXFORM(_cmsTRANSFORM* p,
                 // Is current color out of gamut?
                 if (OutOfGamut > 0.0) {
 
+                    _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*)_cmsContextGetClientChunk(p->ContextID, AlarmCodesContext);
+
                     // Certainly, out of gamut
                     for (c = 0; c < cmsMAXCHANNELS; c++)
-                        fOut[c] = -1.0;
+                        fOut[c] = ContextAlarmCodes->AlarmCodes[c] / 65535.0F;
 
                 }
                 else {
@@ -361,7 +363,7 @@ void NullFloatXFORM(_cmsTRANSFORM* p,
     cmsUInt8Number* accum;
     cmsUInt8Number* output;
     cmsFloat32Number fIn[cmsMAXCHANNELS];
-    cmsUInt32Number i, j, strideIn, strideOut;
+    size_t i, j, strideIn, strideOut;
 
     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 
@@ -399,7 +401,7 @@ void NullXFORM(_cmsTRANSFORM* p,
     cmsUInt8Number* accum;
     cmsUInt8Number* output;
     cmsUInt16Number wIn[cmsMAXCHANNELS];
-    cmsUInt32Number i, j, strideIn, strideOut;
+    size_t i, j, strideIn, strideOut;
 
     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 
@@ -409,17 +411,17 @@ void NullXFORM(_cmsTRANSFORM* p,
 
     for (i = 0; i < LineCount; i++) {
 
-           accum = (cmsUInt8Number*)in + strideIn;
-           output = (cmsUInt8Number*)out + strideOut;
+        accum = (cmsUInt8Number*)in + strideIn;
+        output = (cmsUInt8Number*)out + strideOut;
 
-           for (j = 0; j < PixelsPerLine; j++) {
+        for (j = 0; j < PixelsPerLine; j++) {
 
-                  accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
-                  output = p->ToOutput(p, wIn, output, Stride->BytesPerPlaneOut);
-    }
+            accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
+            output = p->ToOutput(p, wIn, output, Stride->BytesPerPlaneOut);
+        }
 
-           strideIn += Stride->BytesPerLineIn;
-           strideOut += Stride->BytesPerLineOut;
+        strideIn += Stride->BytesPerLineIn;
+        strideOut += Stride->BytesPerLineOut;
     }
 
 }
@@ -437,7 +439,7 @@ void PrecalculatedXFORM(_cmsTRANSFORM* p
     CMSREGISTER cmsUInt8Number* accum;
     CMSREGISTER cmsUInt8Number* output;
     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
-    cmsUInt32Number i, j, strideIn, strideOut;
+    size_t i, j, strideIn, strideOut;
 
     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 
@@ -500,7 +502,7 @@ void PrecalculatedXFORMGamutCheck(_cmsTR
     cmsUInt8Number* accum;
     cmsUInt8Number* output;
     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
-    cmsUInt32Number i, j, strideIn, strideOut;
+    size_t i, j, strideIn, strideOut;
 
     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 
@@ -511,18 +513,18 @@ void PrecalculatedXFORMGamutCheck(_cmsTR
 
     for (i = 0; i < LineCount; i++) {
 
-           accum = (cmsUInt8Number*)in + strideIn;
-           output = (cmsUInt8Number*)out + strideOut;
+        accum = (cmsUInt8Number*)in + strideIn;
+        output = (cmsUInt8Number*)out + strideOut;
 
-           for (j = 0; j < PixelsPerLine; j++) {
+        for (j = 0; j < PixelsPerLine; j++) {
 
-                  accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
-                  TransformOnePixelWithGamutCheck(p, wIn, wOut);
-                  output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
-           }
+            accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
+            TransformOnePixelWithGamutCheck(p, wIn, wOut);
+            output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
+        }
 
-           strideIn += Stride->BytesPerLineIn;
-           strideOut += Stride->BytesPerLineOut;
+        strideIn += Stride->BytesPerLineIn;
+        strideOut += Stride->BytesPerLineOut;
     }
 }
 
@@ -540,7 +542,7 @@ void CachedXFORM(_cmsTRANSFORM* p,
     cmsUInt8Number* output;
     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
     _cmsCACHE Cache;
-    cmsUInt32Number i, j, strideIn, strideOut;
+    size_t i, j, strideIn, strideOut;
 
     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 
@@ -595,7 +597,7 @@ void CachedXFORMGamutCheck(_cmsTRANSFORM
     cmsUInt8Number* output;
     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
     _cmsCACHE Cache;
-    cmsUInt32Number i, j, strideIn, strideOut;
+    size_t i, j, strideIn, strideOut;
 
     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 
@@ -712,7 +714,7 @@ void _cmsTransform2toTransformAdaptor(st
                                       const cmsStride* Stride)
 {
 
-       cmsUInt32Number i, strideIn, strideOut;
+       size_t i, strideIn, strideOut;
 
        _cmsHandleExtraChannels(CMMcargo, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, Stride);
 
@@ -1099,7 +1101,7 @@ cmsBool  IsProperColorSpace(cmsColorSpac
     int Space1 = (int) T_COLORSPACE(dwFormat);
     int Space2 = _cmsLCMScolorSpace(Check);
 
-    if (Space1 == PT_ANY) return TRUE;
+    if (Space1 == PT_ANY) return (T_CHANNELS(dwFormat) == cmsChannelsOf(Check));
     if (Space1 == Space2) return TRUE;
 
     if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE;
@@ -1160,7 +1162,15 @@ cmsHTRANSFORM CMSEXPORT cmsCreateExtende
     cmsColorSpaceSignature EntryColorSpace;
     cmsColorSpaceSignature ExitColorSpace;
     cmsPipeline* Lut;
-    cmsUInt32Number LastIntent = Intents[nProfiles-1];
+    cmsUInt32Number LastIntent;
+
+    // Safeguard
+    if (nProfiles <= 0 || nProfiles > 255) {
+        cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles);
+        return NULL;
+    }
+
+    LastIntent = Intents[nProfiles - 1];
 
     // If it is a fake transform
     if (dwFlags & cmsFLAGS_NULLTRANSFORM)
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/lcms2.h 24.0.2+12-1/src/java.desktop/share/native/liblcms/lcms2.h
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/lcms2.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/lcms2.h	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2025 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -52,7 +52,7 @@
 //
 //---------------------------------------------------------------------------------
 //
-// Version 2.16
+// Version 2.17
 //
 
 #ifndef _lcms2_H
@@ -93,6 +93,9 @@
 // Uncomment this to remove the "register" storage class
 // #define CMS_NO_REGISTER_KEYWORD 1
 
+// Uncomment this to remove visibility attribute when building shared objects
+// #define CMS_NO_VISIBILITY 1
+
 // ********** End of configuration toggles ******************************
 
 // Needed for streams
@@ -113,7 +116,7 @@ extern "C" {
 #endif
 
 // Version/release
-#define LCMS_VERSION        2160
+#define LCMS_VERSION        2170
 
 // I will give the chance of redefining basic types for compilers that are not fully C99 compliant
 #ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
@@ -277,7 +280,7 @@ typedef int                  cmsBool;
 #     define CMSAPI
 #  endif
 #else  // not Windows
-#  ifdef HAVE_FUNC_ATTRIBUTE_VISIBILITY
+#  if defined(HAVE_FUNC_ATTRIBUTE_VISIBILITY) && !defined(CMS_NO_VISIBILITY)
 #     define CMSEXPORT
 #     define CMSAPI    __attribute__((visibility("default")))
 #  else
@@ -987,7 +990,6 @@ typedef void* cmsHTRANSFORM;
 // IEEE 754-2008 "half"
 #define TYPE_GRAY_HALF_FLT    (FLOAT_SH(1)|COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2))
 #define TYPE_RGB_HALF_FLT     (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2))
-#define TYPE_RGBA_HALF_FLT    (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2))
 #define TYPE_CMYK_HALF_FLT    (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2))
 
 #define TYPE_RGBA_HALF_FLT    (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2))
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/lcms2_internal.h 24.0.2+12-1/src/java.desktop/share/native/liblcms/lcms2_internal.h
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/lcms2_internal.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/lcms2_internal.h	2025-06-27 08:03:14.000000000 +0000
@@ -27,9 +27,10 @@
 // However, the following notice accompanied the original version of this
 // file:
 //
+
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -467,7 +468,7 @@ cmsBool  _cmsRegisterTransformPlugin(cms
 // Mutex
 cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
 
-// Paralellization
+// Parallelization
 cmsBool _cmsRegisterParallelizationPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
 
 // ---------------------------------------------------------------------------------------------------------
@@ -1000,7 +1001,7 @@ cmsBool           _cmsReadCHAD(cmsMAT3*
 
 // Link several profiles to obtain a single LUT modelling the whole color transform. Intents, Black point
 // compensation and Adaptation parameters may vary across profiles. BPC and Adaptation refers to the PCS
-// after the profile. I.e, BPC[0] refers to connexion between profile(0) and profile(1)
+// after the profile. I.e, BPC[0] refers to connetion between profile(0) and profile(1)
 cmsPipeline* _cmsLinkProfiles(cmsContext         ContextID,
                               cmsUInt32Number    nProfiles,
                               cmsUInt32Number    TheIntents[],
diff -pruN 24.0.1+9-1/src/java.desktop/share/native/liblcms/lcms2_plugin.h 24.0.2+12-1/src/java.desktop/share/native/liblcms/lcms2_plugin.h
--- 24.0.1+9-1/src/java.desktop/share/native/liblcms/lcms2_plugin.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/share/native/liblcms/lcms2_plugin.h	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff -pruN 24.0.1+9-1/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java 24.0.2+12-1/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java
--- 24.0.1+9-1/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -72,6 +72,15 @@ public final class X11GraphicsDevice ext
     private boolean shutdownHookRegistered;
     private int scale;
 
+    // Wayland clients are by design not allowed to change the resolution in Wayland.
+    // XRandR in Xwayland is just an emulation, it doesn't actually change the resolution.
+    // This emulation is per window/x11 client, so different clients can have
+    // different emulated resolutions at the same time.
+    // So any request to get the current display mode will always return
+    // the original screen resolution, even if we are in emulated resolution.
+    // To handle this situation, we store the last set display mode in this variable.
+    private volatile DisplayMode xwlCurrentDisplayMode;
+
     public X11GraphicsDevice(int screennum) {
         this.screen = screennum;
         this.scale = initScaleFactor();
@@ -117,6 +126,20 @@ public final class X11GraphicsDevice ext
 
     private Rectangle getBoundsImpl() {
         Rectangle rect = pGetBounds(getScreen());
+
+        if (XToolkit.isOnWayland() && xwlCurrentDisplayMode != null) {
+            // XRandR resolution change in Xwayland is an emulation,
+            // and implemented in such a way that multiple display modes
+            // for a device are only available in a single screen scenario,
+            // if we have multiple screens they will each have a single display mode
+            // (no emulated resolution change is available).
+            // So we don't have to worry about x and y for a screen here.
+            rect.setSize(
+                    xwlCurrentDisplayMode.getWidth(),
+                    xwlCurrentDisplayMode.getHeight()
+            );
+        }
+
         if (getScaleFactor() != 1) {
             rect.x = scaleDown(rect.x);
             rect.y = scaleDown(rect.y);
@@ -400,10 +423,19 @@ public final class X11GraphicsDevice ext
     @Override
     public synchronized DisplayMode getDisplayMode() {
         if (isFullScreenSupported()) {
+            if (XToolkit.isOnWayland() && xwlCurrentDisplayMode != null) {
+                return xwlCurrentDisplayMode;
+            }
+
             DisplayMode mode = getCurrentDisplayMode(screen);
             if (mode == null) {
                 mode = getDefaultDisplayMode();
             }
+
+            if (XToolkit.isOnWayland()) {
+                xwlCurrentDisplayMode = mode;
+            }
+
             return mode;
         } else {
             if (origDisplayMode == null) {
@@ -474,6 +506,10 @@ public final class X11GraphicsDevice ext
                           dm.getWidth(), dm.getHeight(),
                           dm.getRefreshRate());
 
+        if (XToolkit.isOnWayland()) {
+            xwlCurrentDisplayMode = dm;
+        }
+
         // update bounds of the fullscreen window
         w.setBounds(0, 0, dm.getWidth(), dm.getHeight());
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/legal/pipewire.md 24.0.2+12-1/src/java.desktop/unix/legal/pipewire.md
--- 24.0.1+9-1/src/java.desktop/unix/legal/pipewire.md	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/legal/pipewire.md	2025-06-27 08:03:14.000000000 +0000
@@ -1,4 +1,4 @@
-## PipeWire 0.3.68
+## PipeWire 1.3.81
 
 ### PipeWire license:
 
@@ -39,3 +39,8 @@ spa/include/spa/utils/string.h
 ```
 Copyright © 2021 Red Hat, Inc.
 ```
+
+spa/utils/cleanup.h:
+```
+Copyright © 2023 PipeWire authors
+```
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c 24.0.2+12-1/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
--- 24.0.1+9-1/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 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
@@ -30,6 +30,8 @@
 #include <dlfcn.h>
 #include "jni_util.h"
 #include "awt.h"
+
+#ifndef _AIX
 #include "screencast_pipewire.h"
 #include "fp_pipewire.h"
 #include <stdio.h>
@@ -1039,3 +1041,28 @@ JNIEXPORT jint JNICALL Java_sun_awt_scre
     releaseToken(env, jtoken, token);
     return 0;
 }
+#else
+JNIEXPORT void JNICALL
+Java_sun_awt_screencast_ScreencastHelper_closeSession(JNIEnv *env, jclass cls) {
+}
+
+JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_getRGBPixelsImpl(
+        JNIEnv *env,
+        jclass cls,
+        jint jx,
+        jint jy,
+        jint jwidth,
+        jint jheight,
+        jintArray pixelArray,
+        jintArray affectedScreensBoundsArray,
+        jstring jtoken
+) {
+    return -1; /* RESULT_ERROR */
+}
+
+JNIEXPORT jboolean JNICALL Java_sun_awt_screencast_ScreencastHelper_loadPipewire(
+        JNIEnv *env, jclass cls, jboolean screencastDebug
+) {
+    return JNI_FALSE;
+}
+#endif
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c 24.0.2+12-1/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c
--- 24.0.1+9-1/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c	2025-06-27 08:03:14.000000000 +0000
@@ -29,7 +29,10 @@
 #include <string.h>
 #include <pwd.h>
 #include <unistd.h>
+
+#ifndef _AIX
 #include "screencast_pipewire.h"
+
 #include "screencast_portal.h"
 
 extern volatile bool isGtkMainThread;
@@ -925,3 +928,4 @@ int getPipewireFd(const gchar *token,
     DEBUG_SCREENCAST("pwFd %i\n", pipewireFd);
     return pipewireFd;
 }
+#endif
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/context.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/context.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/context.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/context.h	2025-06-27 08:03:14.000000000 +0000
@@ -43,6 +43,7 @@ struct pw_context;
 
 struct pw_global;
 struct pw_impl_client;
+struct pw_impl_node;
 
 #include <pipewire/core.h>
 #include <pipewire/loop.h>
@@ -50,7 +51,7 @@ struct pw_impl_client;
 
 /** context events emitted by the context object added with \ref pw_context_add_listener */
 struct pw_context_events {
-#define PW_VERSION_CONTEXT_EVENTS    0
+#define PW_VERSION_CONTEXT_EVENTS    1
     uint32_t version;
 
     /** The context is being destroyed */
@@ -63,12 +64,24 @@ struct pw_context_events {
     void (*global_added) (void *data, struct pw_global *global);
     /** a global object was removed */
     void (*global_removed) (void *data, struct pw_global *global);
+
+    /** a driver was added, since 0.3.75 version:1 */
+    void (*driver_added) (void *data, struct pw_impl_node *node);
+    /** a driver was removed, since 0.3.75 version:1 */
+    void (*driver_removed) (void *data, struct pw_impl_node *node);
 };
 
-/** Make a new context object for a given main_loop. Ownership of the properties is taken */
-struct pw_context * pw_context_new(struct pw_loop *main_loop,        /**< a main loop to run in */
-                 struct pw_properties *props,    /**< extra properties */
-                 size_t user_data_size        /**< extra user data size */);
+/** Make a new context object for a given main_loop. Ownership of the properties is taken, even
+ * if the function returns NULL.
+ *
+ * \param main_loop A main loop to run in. This must stay alive unil pw_context_destroy() is called.
+ * \param props extra properties
+ * \param user_data_size extra user data size
+ * \return The context object on success, or NULL on failure, in which case errno is set.
+ * */
+struct pw_context * pw_context_new(struct pw_loop *main_loop,
+                 struct pw_properties *props,
+                 size_t user_data_size);
 
 /** destroy a context object, all resources except the main_loop will be destroyed */
 void pw_context_destroy(struct pw_context *context);
@@ -113,15 +126,27 @@ int pw_context_conf_section_match_rules(
 /** Get the context support objects */
 const struct spa_support *pw_context_get_support(struct pw_context *context, uint32_t *n_support);
 
-/** get the context main loop */
+/** Get the context main loop. Returns the value passed to pw_context_new(). */
 struct pw_loop *pw_context_get_main_loop(struct pw_context *context);
 
-/** get the context data loop. Since 0.3.56 */
+/** Get the context data loop. This loop runs on the realtime thread. This
+ * acquires a loop from the generic data.rt class. Use pw_context_acquire_loop() instead.
+ * Since 0.3.56 */
 struct pw_data_loop *pw_context_get_data_loop(struct pw_context *context);
 
+/** Get a data-loop.
+ * Since 1.1.0 */
+struct pw_loop *pw_context_acquire_loop(struct pw_context *context, const struct spa_dict *props);
+/** Release a data-loop.
+ * Since 1.1.0 */
+void pw_context_release_loop(struct pw_context *context, struct pw_loop *loop);
+
 /** Get the work queue from the context: Since 0.3.26 */
 struct pw_work_queue *pw_context_get_work_queue(struct pw_context *context);
 
+/** Get the memory pool from the context: Since 0.3.74 */
+struct pw_mempool *pw_context_get_mempool(struct pw_context *context);
+
 /** Iterate the globals of the context. The callback should return
  * 0 to fetch the next item, any other value stops the iteration and returns
  * the value. When all callbacks return 0, this function returns 0 when all
@@ -130,7 +155,10 @@ int pw_context_for_each_global(struct pw
                 int (*callback) (void *data, struct pw_global *global),
                 void *data);
 
-/** Find a context global by id */
+/** Find a context global by id.
+ *
+ * \return The global on success, or NULL on failure. If id is \ref PW_ID_CORE,
+ *         this function will always return a non-NULL value. */
 struct pw_global *pw_context_find_global(struct pw_context *context,    /**< the context */
                       uint32_t id        /**< the global id */);
 
@@ -140,6 +168,7 @@ int pw_context_add_spa_lib(struct pw_con
 /** find the library name for a spa factory */
 const char * pw_context_find_spa_lib(struct pw_context *context, const char *factory_name);
 
+/** Load a SPA handle from a context. On failure returns NULL and sets errno. */
 struct spa_handle *pw_context_load_spa_handle(struct pw_context *context,
         const char *factory_name,
         const struct spa_dict *info);
@@ -160,9 +189,21 @@ int pw_context_register_export_type(stru
 /** find information about registered export type */
 const struct pw_export_type *pw_context_find_export_type(struct pw_context *context, const char *type);
 
-/** add an object to the context */
+/** add an object to the context
+ *
+ * \param context The context.
+ * \param type The type of the object, usually a `TYPE_INTERFACE_` value.
+ * \param value The object value. Must last as long as the context and must
+ *              be of the type corresponding to the type.
+ * \return A negative number on failure (out of memory).
+ * */
 int pw_context_set_object(struct pw_context *context, const char *type, void *value);
-/** get an object from the context */
+/** get an object from the context
+ *
+ * \param context The context.
+ * \param type The string corresponding to the object's interface.
+ * \return The object, or NULL if the object does not exist.
+ * */
 void *pw_context_get_object(struct pw_context *context, const char *type);
 
 /**
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/core.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/core.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/core.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/core.h	2025-06-27 08:03:14.000000000 +0000
@@ -14,6 +14,8 @@ extern "C" {
 
 #include <spa/utils/hook.h>
 
+#include <pipewire/type.h>
+
 /** \defgroup pw_core Core
  *
  * \brief The core global object.
@@ -34,11 +36,20 @@ extern "C" {
 #define PW_TYPE_INTERFACE_Core        PW_TYPE_INFO_INTERFACE_BASE "Core"
 #define PW_TYPE_INTERFACE_Registry    PW_TYPE_INFO_INTERFACE_BASE "Registry"
 
+#define PW_CORE_PERM_MASK        PW_PERM_R|PW_PERM_X|PW_PERM_M
+
 #define PW_VERSION_CORE        4
 struct pw_core;
 #define PW_VERSION_REGISTRY    3
 struct pw_registry;
 
+#ifndef PW_API_CORE_IMPL
+#define PW_API_CORE_IMPL static inline
+#endif
+#ifndef PW_API_REGISTRY_IMPL
+#define PW_API_REGISTRY_IMPL static inline
+#endif
+
 /** The default remote name to connect to */
 #define PW_DEFAULT_REMOTE    "pipewire-0"
 
@@ -67,11 +78,13 @@ struct pw_core_info {
 #include <pipewire/properties.h>
 #include <pipewire/proxy.h>
 
-/** Update an existing \ref pw_core_info with \a update with reset */
+/** Update an existing \ref pw_core_info with \a update with reset. When info is NULL,
+ * a new one will be allocated. Returns NULL on failure. */
 struct pw_core_info *
 pw_core_info_update(struct pw_core_info *info,
         const struct pw_core_info *update);
-/** Update an existing \ref pw_core_info with \a update */
+/** Update an existing \ref pw_core_info with \a update. When info is NULL, a new one
+ * will be allocated. Returns NULL on failure */
 struct pw_core_info *
 pw_core_info_merge(struct pw_core_info *info,
         const struct pw_core_info *update, bool reset);
@@ -162,6 +175,9 @@ struct pw_core_events {
      * global ID. It is emitted before the global becomes visible in the
      * registry.
      *
+     * The bound_props event is an enhanced version of this event that
+     * also contains the extra global properties.
+     *
      * \param id bound object ID
      * \param global_id the global id bound to
      */
@@ -190,6 +206,21 @@ struct pw_core_events {
      */
     void (*remove_mem) (void *data, uint32_t id);
 
+    /**
+     * Notify an object binding
+     *
+     * This event is emitted when a local object ID is bound to a
+     * global ID. It is emitted before the global becomes visible in the
+     * registry.
+     *
+     * This is an enhanced version of the bound_id event.
+     *
+     * \param id bound object ID
+     * \param global_id the global id bound to
+     * \param props The properties of the new global object.
+     *
+     * Since version 4:1
+     */
     void (*bound_props) (void *data, uint32_t id, uint32_t global_id, const struct spa_dict *props);
 };
 
@@ -223,6 +254,8 @@ struct pw_core_methods {
      * Start a conversation with the server. This will send
      * the core info and will destroy all resources for the client
      * (except the core and client resource).
+     *
+     * This requires X permissions on the core.
      */
     int (*hello) (void *object, uint32_t version);
     /**
@@ -235,6 +268,8 @@ struct pw_core_methods {
      * methods and the resulting events have been handled.
      *
      * \param seq the seq number passed to the done event
+     *
+     * This requires X permissions on the core.
      */
     int (*sync) (void *object, uint32_t id, int seq);
     /**
@@ -243,6 +278,8 @@ struct pw_core_methods {
      * Reply to the server ping event with the same seq.
      *
      * \param seq the seq number received in the ping event
+     *
+     * This requires X permissions on the core.
      */
     int (*pong) (void *object, uint32_t id, int seq);
     /**
@@ -257,9 +294,11 @@ struct pw_core_methods {
      * This method is usually also emitted on the resource object with
      * \a id.
      *
-         * \param id object where the error occurred
+         * \param id resource id where the error occurred
          * \param res error code
          * \param message error description
+     *
+     * This requires X permissions on the core.
      */
     int (*error) (void *object, uint32_t id, int seq, int res, const char *message);
     /**
@@ -269,6 +308,8 @@ struct pw_core_methods {
      * the global objects available from the PipeWire server
      * \param version the client version
      * \param user_data_size extra size
+     *
+     * This requires X permissions on the core.
      */
     struct pw_registry * (*get_registry) (void *object, uint32_t version,
             size_t user_data_size);
@@ -281,6 +322,8 @@ struct pw_core_methods {
      * \param version the version of the interface
      * \param props extra properties
      * \param user_data_size extra size
+     *
+     * This requires X permissions on the core.
      */
     void * (*create_object) (void *object,
                    const char *factory_name,
@@ -294,27 +337,57 @@ struct pw_core_methods {
      * Destroy the server resource for the given proxy.
      *
      * \param obj the proxy to destroy
+     *
+     * This requires X permissions on the core.
      */
     int (*destroy) (void *object, void *proxy);
 };
 
-#define pw_core_method(o,method,version,...)            \
-({                                    \
-    int _res = -ENOTSUP;                        \
-    spa_interface_call_res((struct spa_interface*)o,        \
-            struct pw_core_methods, _res,        \
-            method, version, ##__VA_ARGS__);        \
-    _res;                                \
-})
-
-#define pw_core_add_listener(c,...)    pw_core_method(c,add_listener,0,__VA_ARGS__)
-#define pw_core_hello(c,...)        pw_core_method(c,hello,0,__VA_ARGS__)
-#define pw_core_sync(c,...)        pw_core_method(c,sync,0,__VA_ARGS__)
-#define pw_core_pong(c,...)        pw_core_method(c,pong,0,__VA_ARGS__)
-#define pw_core_error(c,...)        pw_core_method(c,error,0,__VA_ARGS__)
-
 
-static inline
+/** \copydoc pw_core_methods.add_listener
+ * \sa pw_core_methods.add_listener */
+PW_API_CORE_IMPL int pw_core_add_listener(struct pw_core *object,
+            struct spa_hook *listener,
+            const struct pw_core_events *events,
+            void *data)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            pw_core, (struct spa_interface*)object, add_listener, 0,
+            listener, events, data);
+}
+/** \copydoc pw_core_methods.hello
+ * \sa pw_core_methods.hello */
+PW_API_CORE_IMPL int pw_core_hello(struct pw_core *object, uint32_t version)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            pw_core, (struct spa_interface*)object, hello, 0,
+            version);
+}
+/** \copydoc pw_core_methods.sync
+ * \sa pw_core_methods.sync */
+PW_API_CORE_IMPL int pw_core_sync(struct pw_core *object, uint32_t id, int seq)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            pw_core, (struct spa_interface*)object, sync, 0,
+            id, seq);
+}
+/** \copydoc pw_core_methods.pong
+ * \sa pw_core_methods.pong */
+PW_API_CORE_IMPL int pw_core_pong(struct pw_core *object, uint32_t id, int seq)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            pw_core, (struct spa_interface*)object, pong, 0,
+            id, seq);
+}
+/** \copydoc pw_core_methods.error
+ * \sa pw_core_methods.error */
+PW_API_CORE_IMPL int pw_core_error(struct pw_core *object, uint32_t id, int seq, int res, const char *message)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            pw_core, (struct spa_interface*)object, error, 0,
+            id, seq, res, message);
+}
+PW_API_CORE_IMPL
 SPA_PRINTF_FUNC(5, 0) int
 pw_core_errorv(struct pw_core *core, uint32_t id, int seq,
         int res, const char *message, va_list args)
@@ -325,7 +398,7 @@ pw_core_errorv(struct pw_core *core, uin
     return pw_core_error(core, id, seq, res, buffer);
 }
 
-static inline
+PW_API_CORE_IMPL
 SPA_PRINTF_FUNC(5, 6) int
 pw_core_errorf(struct pw_core *core, uint32_t id, int seq,
         int res, const char *message, ...)
@@ -338,17 +411,18 @@ pw_core_errorf(struct pw_core *core, uin
     return r;
 }
 
-static inline struct pw_registry *
+/** \copydoc pw_core_methods.get_registry
+ * \sa pw_core_methods.get_registry */
+PW_API_CORE_IMPL struct pw_registry *
 pw_core_get_registry(struct pw_core *core, uint32_t version, size_t user_data_size)
 {
-    struct pw_registry *res = NULL;
-    spa_interface_call_res((struct spa_interface*)core,
-            struct pw_core_methods, res,
-            get_registry, 0, version, user_data_size);
-    return res;
+    return spa_api_method_r(struct pw_registry*, NULL,
+            pw_core, (struct spa_interface*)core, get_registry, 0,
+            version, user_data_size);
 }
-
-static inline void *
+/** \copydoc pw_core_methods.create_object
+ * \sa pw_core_methods.create_object */
+PW_API_CORE_IMPL void *
 pw_core_create_object(struct pw_core *core,
                 const char *factory_name,
                 const char *type,
@@ -356,15 +430,18 @@ pw_core_create_object(struct pw_core *co
                 const struct spa_dict *props,
                 size_t user_data_size)
 {
-    void *res = NULL;
-    spa_interface_call_res((struct spa_interface*)core,
-            struct pw_core_methods, res,
-            create_object, 0, factory_name,
-            type, version, props, user_data_size);
-    return res;
+    return spa_api_method_r(void*, NULL,
+            pw_core, (struct spa_interface*)core, create_object, 0,
+            factory_name, type, version, props, user_data_size);
+}
+/** \copydoc pw_core_methods.destroy
+ * \sa pw_core_methods.destroy */
+PW_API_CORE_IMPL void
+pw_core_destroy(struct pw_core *core, void *proxy)
+{
+    spa_api_method_v(pw_core, (struct spa_interface*)core, destroy, 0,
+            proxy);
 }
-
-#define pw_core_destroy(c,...)        pw_core_method(c,destroy,0,__VA_ARGS__)
 
 /**
  * \}
@@ -474,36 +551,44 @@ struct pw_registry_methods {
      *
      * Try to destroy the global object.
      *
-     * \param id the global id to destroy
+     * \param id the global id to destroy. The client needs X permissions
+     * on the global.
      */
     int (*destroy) (void *object, uint32_t id);
 };
 
-#define pw_registry_method(o,method,version,...)            \
-({                                    \
-    int _res = -ENOTSUP;                        \
-    spa_interface_call_res((struct spa_interface*)o,        \
-            struct pw_registry_methods, _res,        \
-            method, version, ##__VA_ARGS__);        \
-    _res;                                \
-})
 
 /** Registry */
-#define pw_registry_add_listener(p,...)    pw_registry_method(p,add_listener,0,__VA_ARGS__)
-
-static inline void *
+/** \copydoc pw_registry_methods.add_listener
+ * \sa pw_registry_methods.add_listener */
+PW_API_REGISTRY_IMPL int pw_registry_add_listener(struct pw_registry *registry,
+            struct spa_hook *listener,
+            const struct pw_registry_events *events,
+            void *data)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            pw_registry, (struct spa_interface*)registry, add_listener, 0,
+            listener, events, data);
+}
+/** \copydoc pw_registry_methods.bind
+ * \sa pw_registry_methods.bind */
+PW_API_REGISTRY_IMPL void *
 pw_registry_bind(struct pw_registry *registry,
                uint32_t id, const char *type, uint32_t version,
                size_t user_data_size)
 {
-    void *res = NULL;
-    spa_interface_call_res((struct spa_interface*)registry,
-            struct pw_registry_methods, res,
-            bind, 0, id, type, version, user_data_size);
-    return res;
+    return spa_api_method_r(void*, NULL,
+            pw_registry, (struct spa_interface*)registry, bind, 0,
+            id, type, version, user_data_size);
+}
+/** \copydoc pw_registry_methods.destroy
+ * \sa pw_registry_methods.destroy */
+PW_API_REGISTRY_IMPL int
+pw_registry_destroy(struct pw_registry *registry, uint32_t id)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            pw_registry, (struct spa_interface*)registry, destroy, 0, id);
 }
-
-#define pw_registry_destroy(p,...)    pw_registry_method(p,destroy,0,__VA_ARGS__)
 
 /**
  * \}
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/keys.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/keys.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/keys.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/keys.h	2025-06-27 08:03:14.000000000 +0000
@@ -38,6 +38,14 @@ extern "C" {
 #define PW_KEY_SEC_GID            "pipewire.sec.gid"    /**< client gid, set by protocol*/
 #define PW_KEY_SEC_LABEL        "pipewire.sec.label"    /**< client security label, set by protocol*/
 
+#define PW_KEY_SEC_SOCKET        "pipewire.sec.socket"    /**< client socket name, set by protocol */
+
+#define PW_KEY_SEC_ENGINE        "pipewire.sec.engine"    /**< client secure context engine, set by protocol.
+                                  *  This can also be set by a client when making a
+                                  *  new security context. */
+#define PW_KEY_SEC_APP_ID        "pipewire.sec.app-id"    /**< client secure application id */
+#define PW_KEY_SEC_INSTANCE_ID        "pipewire.sec.instance-id"    /**< client secure instance id */
+
 #define PW_KEY_LIBRARY_NAME_SYSTEM    "library.name.system"    /**< name of the system library to use */
 #define PW_KEY_LIBRARY_NAME_LOOP    "library.name.loop"    /**< name of the loop library to use */
 #define PW_KEY_LIBRARY_NAME_DBUS    "library.name.dbus"    /**< name of the dbus library to use */
@@ -52,7 +60,8 @@ extern "C" {
 #define PW_KEY_OBJECT_LINGER        "object.linger"        /**< the object lives on even after the client
                                   *  that created it has been destroyed */
 #define PW_KEY_OBJECT_REGISTER        "object.register"    /**< If the object should be registered. */
-
+#define PW_KEY_OBJECT_EXPORT        "object.export"        /**< If the object should be exported,
+                                  *  since 0.3.72 */
 
 /* config */
 #define PW_KEY_CONFIG_PREFIX        "config.prefix"        /**< a config prefix directory */
@@ -60,6 +69,12 @@ extern "C" {
 #define PW_KEY_CONFIG_OVERRIDE_PREFIX    "config.override.prefix"    /**< a config override prefix directory */
 #define PW_KEY_CONFIG_OVERRIDE_NAME    "config.override.name"    /**< a config override file name */
 
+/* loop */
+#define PW_KEY_LOOP_NAME        "loop.name"        /**< the name of a loop */
+#define PW_KEY_LOOP_CLASS        "loop.class"        /**< the classes this loop handles, array of strings */
+#define PW_KEY_LOOP_RT_PRIO        "loop.rt-prio"        /**< realtime priority of the loop */
+#define PW_KEY_LOOP_CANCEL        "loop.cancel"        /**< if the loop can be canceled */
+
 /* context */
 #define PW_KEY_CONTEXT_PROFILE_MODULES    "context.profile.modules"    /**< a context profile for modules, deprecated */
 #define PW_KEY_USER_NAME        "context.user-name"    /**< The user name that runs pipewire */
@@ -87,7 +102,9 @@ extern "C" {
 /* remote keys */
 #define PW_KEY_REMOTE_NAME        "remote.name"        /**< The name of the remote to connect to,
                                   *  default pipewire-0, overwritten by
-                                  *  env(PIPEWIRE_REMOTE) */
+                                  *  env(PIPEWIRE_REMOTE). May also be
+                                  *  a SPA-JSON array of sockets, to be tried
+                                  *  in order. */
 #define PW_KEY_REMOTE_INTENTION        "remote.intention"    /**< The intention of the remote connection,
                                   *  "generic", "screencast" */
 
@@ -132,7 +149,14 @@ extern "C" {
 #define PW_KEY_NODE_SESSION        "node.session"        /**< the session id this node is part of */
 #define PW_KEY_NODE_GROUP        "node.group"        /**< the group id this node is part of. Nodes
                                   *  in the same group are always scheduled
-                                  *  with the same driver. */
+                                  *  with the same driver. Can be an array of
+                                  *  group names. */
+#define PW_KEY_NODE_SYNC_GROUP        "node.sync-group"    /**< the sync group this node is part of. Nodes
+                                  *  in the same sync group are always scheduled
+                                  *  together with the same driver when the sync
+                                  *  is active. Can be an array of sync names. */
+#define PW_KEY_NODE_SYNC        "node.sync"        /**< if the sync-group is active or not */
+#define PW_KEY_NODE_TRANSPORT        "node.transport"    /**< if the transport is active or not */
 #define PW_KEY_NODE_EXCLUSIVE        "node.exclusive"    /**< node wants exclusive access to resources */
 #define PW_KEY_NODE_AUTOCONNECT        "node.autoconnect"    /**< node wants to be automatically connected
                                   *  to a compatible node */
@@ -163,7 +187,23 @@ extern "C" {
 #define PW_KEY_NODE_SUSPEND_ON_IDLE    "node.suspend-on-idle"    /**< suspend the node when idle */
 #define PW_KEY_NODE_CACHE_PARAMS    "node.cache-params"    /**< cache the node params */
 #define PW_KEY_NODE_TRANSPORT_SYNC    "node.transport.sync"    /**< the node handles transport sync */
-#define PW_KEY_NODE_DRIVER        "node.driver"        /**< node can drive the graph */
+#define PW_KEY_NODE_DRIVER        "node.driver"        /**< node can drive the graph. When the node is
+                                  *  selected as the driver, it needs to start
+                                  *  the graph periodically. */
+#define PW_KEY_NODE_SUPPORTS_LAZY    "node.supports-lazy"    /**< the node can be a lazy driver. It will listen
+                                  *  to RequestProcess commands and take them into
+                                  *  account when deciding to start the graph.
+                                  *  A value of 0 disables support, a value of > 0
+                                  *  enables with increasing preference. */
+#define PW_KEY_NODE_SUPPORTS_REQUEST    "node.supports-request"    /**< The node supports emiting RequestProcess events
+                                  *  when it wants the graph to be scheduled.
+                                  *  A value of 0 disables support, a value of > 0
+                                  *  enables with increasing preference. */
+#define PW_KEY_NODE_DRIVER_ID        "node.driver-id"    /**< the node id of the node assigned as driver
+                                  *   for this node */
+#define PW_KEY_NODE_ASYNC        "node.async"        /**< the node wants async scheduling */
+#define PW_KEY_NODE_LOOP_NAME        "node.loop.name"    /**< the loop name fnmatch pattern to run in */
+#define PW_KEY_NODE_LOOP_CLASS        "node.loop.class"    /**< the loop class fnmatch pattern to run in */
 #define PW_KEY_NODE_STREAM        "node.stream"        /**< node is a stream, the server side should
                                   *  add a converter */
 #define PW_KEY_NODE_VIRTUAL        "node.virtual"        /**< the node is some sort of virtual
@@ -172,17 +212,20 @@ extern "C" {
                                   *  on output/input/all ports when the value is
                                   *  "out"/"in"/"true" respectively */
 #define PW_KEY_NODE_LINK_GROUP        "node.link-group"    /**< the node is internally linked to
-                                  *  nodes with the same link-group */
+                                  *  nodes with the same link-group. Can be an
+                                  *  array of group names. */
 #define PW_KEY_NODE_NETWORK        "node.network"        /**< the node is on a network */
 #define PW_KEY_NODE_TRIGGER        "node.trigger"        /**< the node is not scheduled automatically
                                   *   based on the dependencies in the graph
                                   *   but it will be triggered explicitly. */
-#define PW_KEY_NODE_CHANNELNAMES        "node.channel-names"        /**< names of node's
-                                    *   channels (unrelated to positions) */
-#define PW_KEY_NODE_DEVICE_PORT_NAME_PREFIX            "node.device-port-name-prefix"        /** override
-                                    *        port name prefix for device ports, like capture and playback
-                                    *        or disable the prefix completely if an empty string is provided */
-
+#define PW_KEY_NODE_CHANNELNAMES    "node.channel-names"    /**< names of node's
+                                *   channels (unrelated to positions) */
+#define PW_KEY_NODE_DEVICE_PORT_NAME_PREFIX    \
+                    "node.device-port-name-prefix"    /**< override port name prefix for
+                                      *  device ports, like capture and
+                                      *  playback or disable the prefix
+                                      *  completely if an empty string
+                                      *  is provided */
 /** Port keys */
 #define PW_KEY_PORT_ID            "port.id"        /**< port id */
 #define PW_KEY_PORT_NAME        "port.name"        /**< port name */
@@ -197,6 +240,8 @@ extern "C" {
 #define PW_KEY_PORT_EXTRA        "port.extra"        /**< api specific extra port info, API name
                                   *  should be prefixed. "jack:flags:56" */
 #define PW_KEY_PORT_PASSIVE        "port.passive"        /**< the ports wants passive links, since 0.3.67 */
+#define PW_KEY_PORT_IGNORE_LATENCY    "port.ignore-latency"    /**< latency ignored by peers, since 0.3.71 */
+#define PW_KEY_PORT_GROUP        "port.group"        /**< the port group of the port 1.2.0 */
 
 /** link properties */
 #define PW_KEY_LINK_ID            "link.id"        /**< a link id */
@@ -210,6 +255,7 @@ extern "C" {
 #define PW_KEY_LINK_FEEDBACK        "link.feedback"        /**< indicate that a link is a feedback
                                   *  link and the target will receive data
                                   *  in the next cycle */
+#define PW_KEY_LINK_ASYNC        "link.async"        /**< the link is using async io */
 
 /** device properties */
 #define PW_KEY_DEVICE_ID        "device.id"        /**< device id */
@@ -260,6 +306,7 @@ extern "C" {
 #define PW_KEY_MODULE_USAGE        "module.usage"        /**< a human readable usage description of
                                   *  the module's arguments. */
 #define PW_KEY_MODULE_VERSION        "module.version"    /**< a version string for the module. */
+#define PW_KEY_MODULE_DEPRECATED    "module.deprecated"    /**< the module is deprecated with this message */
 
 /** Factory properties */
 #define PW_KEY_FACTORY_ID        "factory.id"        /**< the factory id */
@@ -274,7 +321,10 @@ extern "C" {
 #define PW_KEY_STREAM_LATENCY_MAX    "stream.latency.max"    /**< The maximum latency of the stream */
 #define PW_KEY_STREAM_MONITOR        "stream.monitor"    /**< Indicates that the stream is monitoring
                                   *  and might select a less accurate but faster
-                                  *  conversion algorithm. */
+                                  *  conversion algorithm. Monitor streams are also
+                                  *  ignored when calculating the latency of their peer
+                                  *  ports (since 0.3.71).
+                                  */
 #define PW_KEY_STREAM_DONT_REMIX    "stream.dont-remix"    /**< don't remix channels */
 #define PW_KEY_STREAM_CAPTURE_SINK    "stream.capture.sink"    /**< Try to capture the sink output instead of
                                   *  source output */
@@ -292,6 +342,7 @@ extern "C" {
 #define PW_KEY_MEDIA_NAME        "media.name"        /**< media name. Ex: "Pink Floyd: Time" */
 #define PW_KEY_MEDIA_TITLE        "media.title"        /**< title. Ex: "Time" */
 #define PW_KEY_MEDIA_ARTIST        "media.artist"        /**< artist. Ex: "Pink Floyd" */
+#define PW_KEY_MEDIA_ALBUM        "media.album"        /**< album. Ex: "Dark Side of the Moon" */
 #define PW_KEY_MEDIA_COPYRIGHT        "media.copyright"    /**< copyright string */
 #define PW_KEY_MEDIA_SOFTWARE        "media.software"    /**< generator software */
 #define PW_KEY_MEDIA_LANGUAGE        "media.language"    /**< language in POSIX format. Ex: en_GB */
@@ -327,9 +378,11 @@ extern "C" {
 # ifdef PW_ENABLE_DEPRECATED
 #  define PW_KEY_PRIORITY_MASTER    "priority.master"    /**< deprecated, use priority.driver */
 #  define PW_KEY_NODE_TARGET        "node.target"        /**< deprecated since 0.3.64, use target.object. */
+#  define PW_KEY_LOOP_RETRY_TIMEOUT    "loop.retry-timeout"    /**< deprecated since 1.3.0 */
 # else
 #  define PW_KEY_PRIORITY_MASTER    PW_DEPRECATED("priority.master")
 #  define PW_KEY_NODE_TARGET        PW_DEPRECATED("node.target")
+#  define PW_KEY_LOOP_RETRY_TIMEOUT    PW_DEPRECATED("loop.retry-timeout")
 # endif /* PW_ENABLE_DEPRECATED */
 #endif /* PW_REMOVE_DEPRECATED */
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/loop.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/loop.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/loop.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/loop.h	2025-06-27 08:03:14.000000000 +0000
@@ -17,6 +17,8 @@ extern "C" {
  * PipeWire loop object provides an implementation of
  * the spa loop interfaces. It can be used to implement various
  * event loops.
+ *
+ * The members of \ref pw_loop are read-only.
  */
 
 /**
@@ -29,35 +31,118 @@ struct pw_loop {
     struct spa_loop *loop;            /**< wrapped loop */
     struct spa_loop_control *control;    /**< loop control */
     struct spa_loop_utils *utils;        /**< loop utils */
+    const char *name;
 };
 
+#ifndef PW_API_LOOP_IMPL
+#define PW_API_LOOP_IMPL static inline
+#endif
+
 struct pw_loop *
 pw_loop_new(const struct spa_dict *props);
 
 void
 pw_loop_destroy(struct pw_loop *loop);
 
-#define pw_loop_add_source(l,...)    spa_loop_add_source((l)->loop,__VA_ARGS__)
-#define pw_loop_update_source(l,...)    spa_loop_update_source((l)->loop,__VA_ARGS__)
-#define pw_loop_remove_source(l,...)    spa_loop_remove_source((l)->loop,__VA_ARGS__)
-#define pw_loop_invoke(l,...)        spa_loop_invoke((l)->loop,__VA_ARGS__)
-
-#define pw_loop_get_fd(l)        spa_loop_control_get_fd((l)->control)
-#define pw_loop_add_hook(l,...)        spa_loop_control_add_hook((l)->control,__VA_ARGS__)
-#define pw_loop_enter(l)        spa_loop_control_enter((l)->control)
-#define pw_loop_iterate(l,...)        spa_loop_control_iterate((l)->control,__VA_ARGS__)
-#define pw_loop_leave(l)        spa_loop_control_leave((l)->control)
-
-#define pw_loop_add_io(l,...)        spa_loop_utils_add_io((l)->utils,__VA_ARGS__)
-#define pw_loop_update_io(l,...)    spa_loop_utils_update_io((l)->utils,__VA_ARGS__)
-#define pw_loop_add_idle(l,...)        spa_loop_utils_add_idle((l)->utils,__VA_ARGS__)
-#define pw_loop_enable_idle(l,...)    spa_loop_utils_enable_idle((l)->utils,__VA_ARGS__)
-#define pw_loop_add_event(l,...)    spa_loop_utils_add_event((l)->utils,__VA_ARGS__)
-#define pw_loop_signal_event(l,...)    spa_loop_utils_signal_event((l)->utils,__VA_ARGS__)
-#define pw_loop_add_timer(l,...)    spa_loop_utils_add_timer((l)->utils,__VA_ARGS__)
-#define pw_loop_update_timer(l,...)    spa_loop_utils_update_timer((l)->utils,__VA_ARGS__)
-#define pw_loop_add_signal(l,...)    spa_loop_utils_add_signal((l)->utils,__VA_ARGS__)
-#define pw_loop_destroy_source(l,...)    spa_loop_utils_destroy_source((l)->utils,__VA_ARGS__)
+int pw_loop_set_name(struct pw_loop *loop, const char *name);
+
+PW_API_LOOP_IMPL int pw_loop_add_source(struct pw_loop *object, struct spa_source *source)
+{
+    return spa_loop_add_source(object->loop, source);
+}
+PW_API_LOOP_IMPL int pw_loop_update_source(struct pw_loop *object, struct spa_source *source)
+{
+    return spa_loop_update_source(object->loop, source);
+}
+PW_API_LOOP_IMPL int pw_loop_remove_source(struct pw_loop *object, struct spa_source *source)
+{
+    return spa_loop_remove_source(object->loop, source);
+}
+PW_API_LOOP_IMPL int pw_loop_invoke(struct pw_loop *object,
+                spa_invoke_func_t func, uint32_t seq, const void *data,
+                size_t size, bool block, void *user_data)
+{
+    return spa_loop_invoke(object->loop, func, seq, data, size, block, user_data);
+}
+
+PW_API_LOOP_IMPL int pw_loop_get_fd(struct pw_loop *object)
+{
+    return spa_loop_control_get_fd(object->control);
+}
+PW_API_LOOP_IMPL void pw_loop_add_hook(struct pw_loop *object,
+                struct spa_hook *hook, const struct spa_loop_control_hooks *hooks,
+                void *data)
+{
+    spa_loop_control_add_hook(object->control, hook, hooks, data);
+}
+PW_API_LOOP_IMPL void pw_loop_enter(struct pw_loop *object)
+{
+    spa_loop_control_enter(object->control);
+}
+PW_API_LOOP_IMPL void pw_loop_leave(struct pw_loop *object)
+{
+    spa_loop_control_leave(object->control);
+}
+PW_API_LOOP_IMPL int pw_loop_iterate(struct pw_loop *object,
+                int timeout)
+{
+    return spa_loop_control_iterate_fast(object->control, timeout);
+}
+
+PW_API_LOOP_IMPL struct spa_source *
+pw_loop_add_io(struct pw_loop *object, int fd, uint32_t mask,
+                bool close, spa_source_io_func_t func, void *data)
+{
+    return spa_loop_utils_add_io(object->utils, fd, mask, close, func, data);
+}
+PW_API_LOOP_IMPL int pw_loop_update_io(struct pw_loop *object,
+                struct spa_source *source, uint32_t mask)
+{
+    return spa_loop_utils_update_io(object->utils, source, mask);
+}
+PW_API_LOOP_IMPL struct spa_source *
+pw_loop_add_idle(struct pw_loop *object, bool enabled,
+                spa_source_idle_func_t func, void *data)
+{
+    return spa_loop_utils_add_idle(object->utils, enabled, func, data);
+}
+PW_API_LOOP_IMPL int pw_loop_enable_idle(struct pw_loop *object,
+                struct spa_source *source, bool enabled)
+{
+    return spa_loop_utils_enable_idle(object->utils, source, enabled);
+}
+PW_API_LOOP_IMPL struct spa_source *
+pw_loop_add_event(struct pw_loop *object, spa_source_event_func_t func, void *data)
+{
+    return spa_loop_utils_add_event(object->utils, func, data);
+}
+PW_API_LOOP_IMPL int pw_loop_signal_event(struct pw_loop *object,
+                struct spa_source *source)
+{
+    return spa_loop_utils_signal_event(object->utils, source);
+}
+PW_API_LOOP_IMPL struct spa_source *
+pw_loop_add_timer(struct pw_loop *object, spa_source_timer_func_t func, void *data)
+{
+    return spa_loop_utils_add_timer(object->utils, func, data);
+}
+PW_API_LOOP_IMPL int pw_loop_update_timer(struct pw_loop *object,
+                struct spa_source *source, struct timespec *value,
+                struct timespec *interval, bool absolute)
+{
+    return spa_loop_utils_update_timer(object->utils, source, value, interval, absolute);
+}
+PW_API_LOOP_IMPL struct spa_source *
+pw_loop_add_signal(struct pw_loop *object, int signal_number,
+                spa_source_signal_func_t func, void *data)
+{
+    return spa_loop_utils_add_signal(object->utils, signal_number, func, data);
+}
+PW_API_LOOP_IMPL void pw_loop_destroy_source(struct pw_loop *object,
+                struct spa_source *source)
+{
+    return spa_loop_utils_destroy_source(object->utils, source);
+}
 
 /**
  * \}
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/port.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/port.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/port.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/port.h	2025-06-27 08:03:14.000000000 +0000
@@ -29,9 +29,15 @@ extern "C" {
 
 #define PW_TYPE_INTERFACE_Port    PW_TYPE_INFO_INTERFACE_BASE "Port"
 
+#define PW_PORT_PERM_MASK    PW_PERM_R|PW_PERM_X|PW_PERM_M
+
 #define PW_VERSION_PORT        3
 struct pw_port;
 
+#ifndef PW_API_PORT_IMPL
+#define PW_API_PORT_IMPL static inline
+#endif
+
 /** The direction of a port */
 #define pw_direction spa_direction
 #define PW_DIRECTION_INPUT SPA_DIRECTION_INPUT
@@ -115,6 +121,8 @@ struct pw_port_methods {
      *
      * \param ids an array of param ids
      * \param n_ids the number of ids in \a ids
+     *
+     * This requires X permissions on the port.
      */
     int (*subscribe_params) (void *object, uint32_t *ids, uint32_t n_ids);
 
@@ -129,24 +137,43 @@ struct pw_port_methods {
      * \param start the start index or 0 for the first param
      * \param num the maximum number of params to retrieve
      * \param filter a param filter or NULL
+     *
+     * This requires X permissions on the port.
      */
     int (*enum_params) (void *object, int seq,
             uint32_t id, uint32_t start, uint32_t num,
             const struct spa_pod *filter);
 };
 
-#define pw_port_method(o,method,version,...)                \
-({                                    \
-    int _res = -ENOTSUP;                        \
-    spa_interface_call_res((struct spa_interface*)o,        \
-            struct pw_port_methods, _res,            \
-            method, version, ##__VA_ARGS__);        \
-    _res;                                \
-})
-
-#define pw_port_add_listener(c,...)    pw_port_method(c,add_listener,0,__VA_ARGS__)
-#define pw_port_subscribe_params(c,...)    pw_port_method(c,subscribe_params,0,__VA_ARGS__)
-#define pw_port_enum_params(c,...)    pw_port_method(c,enum_params,0,__VA_ARGS__)
+/** \copydoc pw_port_methods.add_listener
+ * \sa pw_port_methods.add_listener */
+PW_API_PORT_IMPL int pw_port_add_listener(struct pw_port *object,
+            struct spa_hook *listener,
+            const struct pw_port_events *events,
+            void *data)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            pw_port, (struct spa_interface*)object, add_listener, 0,
+            listener, events, data);
+}
+/** \copydoc pw_port_methods.subscribe_params
+ * \sa pw_port_methods.subscribe_params */
+PW_API_PORT_IMPL int pw_port_subscribe_params(struct pw_port *object, uint32_t *ids, uint32_t n_ids)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            pw_port, (struct spa_interface*)object, subscribe_params, 0,
+            ids, n_ids);
+}
+/** \copydoc pw_port_methods.enum_params
+ * \sa pw_port_methods.enum_params */
+PW_API_PORT_IMPL int pw_port_enum_params(struct pw_port *object,
+        int seq, uint32_t id, uint32_t start, uint32_t num,
+                const struct spa_pod *filter)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            pw_port, (struct spa_interface*)object, enum_params, 0,
+            seq, id, start, num, filter);
+}
 
 /**
  * \}
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/properties.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/properties.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/properties.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/properties.h	2025-06-27 08:03:14.000000000 +0000
@@ -11,9 +11,14 @@ extern "C" {
 
 #include <stdarg.h>
 
+#include <spa/utils/cleanup.h>
 #include <spa/utils/dict.h>
 #include <spa/utils/string.h>
 
+#ifndef PW_API_PROPERTIES
+#define PW_API_PROPERTIES static inline
+#endif
+
 /** \defgroup pw_properties Properties
  *
  * Properties are used to pass around arbitrary key/value pairs.
@@ -41,6 +46,10 @@ struct pw_properties *
 pw_properties_new_string(const char *args);
 
 struct pw_properties *
+pw_properties_new_string_checked(const char *args, size_t size,
+        struct spa_error_location *loc);
+
+struct pw_properties *
 pw_properties_copy(const struct pw_properties *properties);
 
 int pw_properties_update_keys(struct pw_properties *props,
@@ -51,10 +60,14 @@ int pw_properties_update_ignore(struct p
 /* Update props with all key/value pairs from dict */
 int pw_properties_update(struct pw_properties *props,
              const struct spa_dict *dict);
+
 /* Update props with all key/value pairs from str */
 int pw_properties_update_string(struct pw_properties *props,
         const char *str, size_t size);
 
+int pw_properties_update_string_checked(struct pw_properties *props,
+        const char *str, size_t size, struct spa_error_location *loc);
+
 int pw_properties_add(struct pw_properties *oldprops,
              const struct spa_dict *dict);
 int pw_properties_add_keys(struct pw_properties *oldprops,
@@ -92,7 +105,7 @@ pw_properties_fetch_int64(const struct p
 int
 pw_properties_fetch_bool(const struct pw_properties *properties, const char *key, bool *value);
 
-static inline uint32_t
+PW_API_PROPERTIES uint32_t
 pw_properties_get_uint32(const struct pw_properties *properties, const char *key, uint32_t deflt)
 {
     uint32_t val = deflt;
@@ -100,7 +113,7 @@ pw_properties_get_uint32(const struct pw
     return val;
 }
 
-static inline int32_t
+PW_API_PROPERTIES int32_t
 pw_properties_get_int32(const struct pw_properties *properties, const char *key, int32_t deflt)
 {
     int32_t val = deflt;
@@ -108,7 +121,7 @@ pw_properties_get_int32(const struct pw_
     return val;
 }
 
-static inline uint64_t
+PW_API_PROPERTIES uint64_t
 pw_properties_get_uint64(const struct pw_properties *properties, const char *key, uint64_t deflt)
 {
     uint64_t val = deflt;
@@ -116,7 +129,7 @@ pw_properties_get_uint64(const struct pw
     return val;
 }
 
-static inline int64_t
+PW_API_PROPERTIES int64_t
 pw_properties_get_int64(const struct pw_properties *properties, const char *key, int64_t deflt)
 {
     int64_t val = deflt;
@@ -125,7 +138,7 @@ pw_properties_get_int64(const struct pw_
 }
 
 
-static inline bool
+PW_API_PROPERTIES bool
 pw_properties_get_bool(const struct pw_properties *properties, const char *key, bool deflt)
 {
     bool val = deflt;
@@ -136,34 +149,38 @@ pw_properties_get_bool(const struct pw_p
 const char *
 pw_properties_iterate(const struct pw_properties *properties, void **state);
 
-#define PW_PROPERTIES_FLAG_NL    (1<<0)
+#define PW_PROPERTIES_FLAG_NL        (1<<0)
+#define PW_PROPERTIES_FLAG_RECURSE    (1<<1)
+#define PW_PROPERTIES_FLAG_ENCLOSE    (1<<2)
+#define PW_PROPERTIES_FLAG_ARRAY    (1<<3)
+#define PW_PROPERTIES_FLAG_COLORS    (1<<4)
 int pw_properties_serialize_dict(FILE *f, const struct spa_dict *dict, uint32_t flags);
 
-static inline bool pw_properties_parse_bool(const char *value) {
+PW_API_PROPERTIES bool pw_properties_parse_bool(const char *value) {
     return spa_atob(value);
 }
 
-static inline int pw_properties_parse_int(const char *value) {
+PW_API_PROPERTIES int pw_properties_parse_int(const char *value) {
     int v;
     return spa_atoi32(value, &v, 0) ? v: 0;
 }
 
-static inline int64_t pw_properties_parse_int64(const char *value) {
+PW_API_PROPERTIES int64_t pw_properties_parse_int64(const char *value) {
     int64_t v;
     return spa_atoi64(value, &v, 0) ? v : 0;
 }
 
-static inline uint64_t pw_properties_parse_uint64(const char *value) {
+PW_API_PROPERTIES uint64_t pw_properties_parse_uint64(const char *value) {
     uint64_t v;
     return spa_atou64(value, &v, 0) ? v : 0;
 }
 
-static inline float pw_properties_parse_float(const char *value) {
+PW_API_PROPERTIES float pw_properties_parse_float(const char *value) {
     float v;
     return spa_atof(value, &v) ? v : 0.0f;
 }
 
-static inline double pw_properties_parse_double(const char *value) {
+PW_API_PROPERTIES double pw_properties_parse_double(const char *value) {
     double v;
     return spa_atod(value, &v) ? v : 0.0;
 }
@@ -172,6 +189,10 @@ static inline double pw_properties_parse
  * \}
  */
 
+SPA_DEFINE_AUTOPTR_CLEANUP(pw_properties, struct pw_properties, {
+    spa_clear_ptr(*thing, pw_properties_free);
+})
+
 #ifdef __cplusplus
 }
 #endif
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/protocol.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/protocol.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/protocol.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/protocol.h	2025-06-27 08:03:14.000000000 +0000
@@ -81,7 +81,7 @@ struct pw_protocol_marshal {
 };
 
 struct pw_protocol_implementation {
-#define PW_VERSION_PROTOCOL_IMPLEMENTATION    0
+#define PW_VERSION_PROTOCOL_IMPLEMENTATION    1
     uint32_t version;
 
     struct pw_protocol_client * (*new_client) (struct pw_protocol *protocol,
@@ -90,6 +90,10 @@ struct pw_protocol_implementation {
     struct pw_protocol_server * (*add_server) (struct pw_protocol *protocol,
                            struct pw_impl_core *core,
                            const struct spa_dict *props);
+    struct pw_protocol_server * (*add_fd_server) (struct pw_protocol *protocol,
+                           struct pw_impl_core *core,
+                           int listen_fd, int close_fd,
+                           const struct spa_dict *props);
 };
 
 struct pw_protocol_events {
@@ -101,6 +105,7 @@ struct pw_protocol_events {
 
 #define pw_protocol_new_client(p,...)    (pw_protocol_get_implementation(p)->new_client(p,__VA_ARGS__))
 #define pw_protocol_add_server(p,...)    (pw_protocol_get_implementation(p)->add_server(p,__VA_ARGS__))
+#define pw_protocol_add_fd_server(p,...)    (pw_protocol_get_implementation(p)->add_fd_server(p,__VA_ARGS__))
 #define pw_protocol_ext(p,type,method,...)    (((type*)pw_protocol_get_extension(p))->method( __VA_ARGS__))
 
 struct pw_protocol *pw_protocol_new(struct pw_context *context, const char *name, size_t user_data_size);
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/proxy.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/proxy.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/proxy.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/proxy.h	2025-06-27 08:03:14.000000000 +0000
@@ -13,6 +13,8 @@ extern "C" {
 
 /** \page page_proxy Proxy
  *
+ * \see \ref pw_proxy
+ *
  * \section sec_page_proxy_overview Overview
  *
  * The proxy object is a client side representation of a resource
@@ -76,7 +78,7 @@ extern "C" {
  * invoked by the client to PipeWire messages. Events will call the handlers
  * set in listener.
  *
- * See \ref page_proxy
+ * \see \ref page_proxy
  */
 
 /**
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/stream.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/stream.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/stream.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/stream.h	2025-06-27 08:03:14.000000000 +0000
@@ -11,6 +11,8 @@ extern "C" {
 
 /** \page page_streams Streams
  *
+ * \see \ref pw_stream
+ *
  * \section sec_overview Overview
  *
  * \ref pw_stream "Streams" are used to exchange data with the
@@ -56,11 +58,15 @@ extern "C" {
 
  * \li PW_DIRECTION_INPUT for a stream that *consumes* data. This can be a
  * stream that captures from a Source or a when the stream is used to
- * implement a Sink.
+ * implement a Sink. An application will use a \ref PW_DIRECTION_INPUT
+ * stream to record data. A virtual sound card will use a
+ * \ref PW_DIRECTION_INPUT stream to implement audio playback.
  *
  * \li PW_DIRECTION_OUTPUT for a stream that *produces* data. This can be a
  * stream that plays to a Sink or when the stream is used to implement
- * a Source.
+ * a Source. An application will use a \ref PW_DIRECTION_OUTPUT
+ * stream to produce data. A virtual sound card or camera will use a
+ * \ref PW_DIRECTION_OUTPUT stream to implement audio or video recording.
  *
  * \subsection ssec_stream_target Stream target
  *
@@ -127,8 +133,25 @@ extern "C" {
  * When the buffer has been processed, call \ref pw_stream_queue_buffer()
  * to let PipeWire reuse the buffer.
  *
+ * Although not strictly required, it is recommended to call \ref
+ * pw_stream_dequeue_buffer() and pw_stream_queue_buffer() from the
+ * process() callback to minimize the amount of buffering and
+ * maximize the amount of buffer reuse in the stream.
+ *
+ * It is also possible to dequeue the buffer from the process event,
+ * then process and queue the buffer from a helper thread. It is also
+ * possible to dequeue, process and queue a buffer from a helper thread
+ * after receiving the process event.
+ *
  * \subsection ssec_produce Produce data
  *
+ * The process event is emitted when a new buffer should be queued.
+ *
+ * When the PW_STREAM_FLAG_RT_PROCESS flag was given, this function will be
+ * called from a realtime thread and it is not safe to call non-reatime
+ * functions such as doing file operations, blocking operations or any of
+ * the PipeWire functions that are not explicitly marked as being RT safe.
+ *
  * \ref pw_stream_dequeue_buffer() gives an empty buffer that can be filled.
  *
  * The buffer is owned by the stream and stays alive until the
@@ -136,8 +159,45 @@ extern "C" {
  *
  * Filled buffers should be queued with \ref pw_stream_queue_buffer().
  *
- * The process event is emitted when PipeWire has emptied a buffer that
- * can now be refilled.
+ * Although not strictly required, it is recommended to call \ref
+ * pw_stream_dequeue_buffer() and pw_stream_queue_buffer() from the
+ * process() callback to minimize the amount of buffering and
+ * maximize the amount of buffer reuse in the stream.
+ *
+ * Buffers that are queued after the process event completes will be delayed
+ * to the next processing cycle.
+ *
+ * \section sec_stream_driving Driving the graph
+ *
+ * Starting in 0.3.34, it is possible for a stream to drive the graph.
+ * This allows interrupt-driven scheduling for drivers implemented as
+ * PipeWire streams, without having to reimplement the stream as a SPA
+ * plugin.
+ *
+ * A stream cannot drive the graph unless it is in the
+ * \ref PW_STREAM_STATE_STREAMING state and \ref pw_stream_is_driving() returns
+ * true. It must then use pw_stream_trigger_process() to start the graph
+ * cycle.
+ *
+ * \ref pw_stream_trigger_process() will result in a process event, where a buffer
+ * should be dequeued, and queued again. This is the recommended behaviour that
+ * minimizes buffering and maximized buffer reuse.
+ *
+ * Producers of data that drive the graph can also dequeue a buffer in a helper
+ * thread, fill it with data and then call \ref pw_stream_trigger_process() to
+ * start the graph cycle. In the process event they will then queue the filled
+ * buffer and dequeue a new empty buffer to fill again in the helper thread,
+ *
+ * Consumers of data that drive the graph (pull based scheduling) will use
+ * \ref pw_stream_trigger_process() to start the graph and will dequeue, process
+ * and queue the buffers in the process event.
+ *
+ * \section sec_stream_process_requests Request processing
+ *
+ * A stream that is not driving the graph can request a new graph cycle by doing
+ * \ref pw_stream_trigger_process(). This will result in a RequestProcess command
+ * in the driver stream. If the driver supports this, it can then perform
+ * \ref pw_stream_trigger_process() to start the actual graph cycle.
  *
  * \section sec_stream_disconnect Disconnect
  *
@@ -151,6 +211,9 @@ extern "C" {
  *
  * \section sec_stream_environment Environment Variables
  *
+ * The environment variable PIPEWIRE_AUTOCONNECT can be used to override the
+ * flag and force apps to autoconnect or not.
+ *
  */
 /** \defgroup pw_stream Stream
  *
@@ -159,7 +222,7 @@ extern "C" {
  * The stream object provides a convenient way to send and
  * receive data streams from/to PipeWire.
  *
- * See also \ref page_streams and \ref api_pw_core
+ * \see \ref page_streams, \ref api_pw_core
  */
 
 /**
@@ -171,6 +234,7 @@ struct pw_stream;
 #include <spa/buffer/buffer.h>
 #include <spa/param/param.h>
 #include <spa/pod/command.h>
+#include <spa/pod/event.h>
 
 /** \enum pw_stream_state The state of a stream */
 enum pw_stream_state {
@@ -182,19 +246,29 @@ enum pw_stream_state {
 };
 
 /** a buffer structure obtained from pw_stream_dequeue_buffer(). The size of this
-  * structure can grow as more field are added in the future */
+  * structure can grow as more fields are added in the future */
 struct pw_buffer {
     struct spa_buffer *buffer;    /**< the spa buffer */
-    void *user_data;        /**< user data attached to the buffer */
+    void *user_data;        /**< user data attached to the buffer. The user of
+                      *  the stream can set custom data associated with the
+                      *  buffer, typically in the add_buffer event. Any
+                      *  cleanup should be performed in the remove_buffer
+                      *  event. The user data is returned unmodified each
+                      *  time a buffer is dequeued. */
     uint64_t size;            /**< This field is set by the user and the sum of
-                      *  all queued buffer is returned in the time info.
+                      *  all queued buffers is returned in the time info.
                       *  For audio, it is advised to use the number of
-                      *  samples in the buffer for this field. */
+                      *  frames in the buffer for this field. */
     uint64_t requested;        /**< For playback streams, this field contains the
                       *  suggested amount of data to provide. For audio
-                      *  streams this will be the amount of samples
+                      *  streams this will be the amount of frames
                       *  required by the resampler. This field is 0
                       *  when no suggestion is provided. Since 0.3.49 */
+    uint64_t time;            /**< For capture streams, this field contains the
+                      *  cycle time in nanoseconds when this buffer was
+                      *  queued in the stream. It can be compared against
+                      *  the pw_time values or pw_stream_get_nsec()
+                      *  Since 1.0.5 */
 };
 
 struct pw_stream_control {
@@ -223,25 +297,33 @@ struct pw_stream_control {
  * value, and pw_time.ticks, were captured at pw_time.now and can be extrapolated
  * to the current time like this:
  *
- *    struct timespec ts;
- *    clock_gettime(CLOCK_MONOTONIC, &ts);
- *    int64_t diff = SPA_TIMESPEC_TO_NSEC(&ts) - pw_time.now;
+ *\code{.c}
+ *    uint64_t now = pw_stream_get_nsec(stream);
+ *    int64_t diff = now - pw_time.now;
  *    int64_t elapsed = (pw_time.rate.denom * diff) / (pw_time.rate.num * SPA_NSEC_PER_SEC);
+ *\endcode
  *
  * pw_time.delay contains the total delay that a signal will travel through the
  * graph. This includes the delay caused by filters in the graph as well as delays
  * caused by the hardware. The delay is usually quite stable and should only change when
  * the topology, quantum or samplerate of the graph changes.
  *
+ * The delay requires the application to send the stream early relative to other synchronized
+ * streams in order to arrive at the edge of the graph in time. This is usually done by
+ * delaying the other streams with the given delay.
+ *
+ * Note that the delay can be negative. A negative delay means that this stream should be
+ * delayed with the (positive) delay relative to other streams.
+ *
  * pw_time.queued and pw_time.buffered is expressed in the time domain of the stream,
  * or the format that is used for the buffers of this stream.
  *
  * pw_time.queued is the sum of all the pw_buffer.size fields of the buffers that are
  * currently queued in the stream but not yet processed. The application can choose
- * the units of this value, for example, time, samples or bytes (below expressed
- * as app.rate).
+ * the units of this value, for example, time, samples, frames or bytes (below
+ * expressed as app.rate).
  *
- * pw_time.buffered is format dependent, for audio/raw it contains the number of samples
+ * pw_time.buffered is format dependent, for audio/raw it contains the number of frames
  * that are buffered inside the resampler/converter.
  *
  * The total delay of data in a stream is the sum of the queued and buffered data
@@ -252,15 +334,21 @@ struct pw_stream_control {
  * in milliseconds for the first sample in the newly queued buffer to be played
  * by the hardware can be calculated as:
  *
+ *\code{.unparsed}
  *  (pw_time.buffered * 1000 / stream.samplerate) +
  *    (pw_time.queued * 1000 / app.rate) +
  *     ((pw_time.delay - elapsed) * 1000 * pw_time.rate.num / pw_time.rate.denom)
+ *\endcode
  *
  * The current extrapolated time (in ms) in the source or sink can be calculated as:
  *
+ *\code{.unparsed}
  *  (pw_time.ticks + elapsed) * 1000 * pw_time.rate.num / pw_time.rate.denom
+ *\endcode
  *
+ * Below is an overview of the different timing values:
  *
+ *\code{.unparsed}
  *           stream time domain           graph time domain
  *         /-----------------------\/-----------------------------\
  *
@@ -272,14 +360,15 @@ struct pw_stream_control {
  *                                    latency             latency
  *         \--------/\-------------/\-----------------------------/
  *           queued      buffered            delay
+ *\endcode
  */
 struct pw_time {
-    int64_t now;            /**< the monotonic time in nanoseconds. This is the time
-                      *  when this time report was updated. It is usually
-                      *  updated every graph cycle. You can use the current
-                      *  monotonic time to calculate the elapsed time between
-                      *  this report and the current state and calculate
-                      *  updated ticks and delay values. */
+    int64_t now;            /**< the time in nanoseconds. This is the time when this
+                      *  time report was updated. It is usually updated every
+                      *  graph cycle. You can use pw_stream_get_nsec() to
+                      *  calculate the elapsed time between this report and
+                      *  the current time and calculate updated ticks and delay
+                      *  values. */
     struct spa_fraction rate;    /**< the rate of \a ticks and delay. This is usually
                       *  expressed in 1/<samplerate>. */
     uint64_t ticks;            /**< the ticks at \a now. This is the current time that
@@ -298,10 +387,14 @@ struct pw_time {
                       *  of the size fields in the pw_buffer that are
                       *  currently queued */
     uint64_t buffered;        /**< for audio/raw streams, this contains the extra
-                      *  number of samples buffered in the resampler.
+                      *  number of frames buffered in the resampler.
                       *  Since 0.3.50. */
-    uint32_t queued_buffers;    /**< The number of buffers that are queued. Since 0.3.50 */
-    uint32_t avail_buffers;        /**< The number of buffers that can be dequeued. Since 0.3.50 */
+    uint32_t queued_buffers;    /**< the number of buffers that are queued. Since 0.3.50 */
+    uint32_t avail_buffers;        /**< the number of buffers that can be dequeued. Since 0.3.50 */
+    uint64_t size;            /**< for audio/raw playback streams, this contains the number of
+                      *  samples requested by the resampler for the current
+                      *  quantum. for audio/raw capture streams this will be the number
+                      *  of samples available for the current quantum. Since 1.1.0 */
 };
 
 #include <pipewire/port.h>
@@ -342,7 +435,10 @@ struct pw_stream_events {
     /** A command notify, Since 0.3.39:1 */
     void (*command) (void *data, const struct spa_command *command);
 
-    /** a trigger_process completed. Since version 0.3.40:2 */
+    /** a trigger_process completed. Since version 0.3.40:2.
+     *  This is normally called from the mainloop but since 1.1.0 it
+     *  can also be called directly from the realtime data
+     *  thread if the user is prepared to deal with this. */
     void (*trigger_done) (void *data);
 };
 
@@ -357,7 +453,8 @@ enum pw_stream_flags {
     PW_STREAM_FLAG_INACTIVE        = (1 << 1),    /**< start the stream inactive,
                               *  pw_stream_set_active() needs to be
                               *  called explicitly */
-    PW_STREAM_FLAG_MAP_BUFFERS    = (1 << 2),    /**< mmap the buffers except DmaBuf */
+    PW_STREAM_FLAG_MAP_BUFFERS    = (1 << 2),    /**< mmap the buffers except DmaBuf that is not
+                              *  explicitly marked as mappable. */
     PW_STREAM_FLAG_DRIVER        = (1 << 3),    /**< be a driver */
     PW_STREAM_FLAG_RT_PROCESS    = (1 << 4),    /**< call process from the realtime
                               *  thread. You MUST use RT safe functions
@@ -375,9 +472,24 @@ enum pw_stream_flags {
                               *  needs to be called. This can be used
                               *  when the output of the stream depends
                               *  on input from other streams. */
+    PW_STREAM_FLAG_ASYNC        = (1 << 10),    /**< Buffers will not be dequeued/queued from
+                              *  the realtime process() function. This is
+                              *  assumed when RT_PROCESS is unset but can
+                              *  also be the case when the process() function
+                              *  does a trigger_process() that will then
+                              *  dequeue/queue a buffer from another process()
+                              *  function. since 0.3.73 */
+    PW_STREAM_FLAG_EARLY_PROCESS    = (1 << 11),    /**< Call process as soon as there is a buffer
+                              *  to dequeue. This is only relevant for
+                              *  playback and when not using RT_PROCESS. It
+                              *  can be used to keep the maximum number of
+                              *  buffers queued. Since 0.3.81 */
+    PW_STREAM_FLAG_RT_TRIGGER_DONE    = (1 << 12),    /**< Call trigger_done from the realtime
+                              *  thread. You MUST use RT safe functions
+                              *  in the trigger_done callback. Since 1.1.0 */
 };
 
-/** Create a new unconneced \ref pw_stream
+/** Create a new unconnected \ref pw_stream
  * \return a newly allocated \ref pw_stream */
 struct pw_stream *
 pw_stream_new(struct pw_core *core,        /**< a \ref pw_core */
@@ -385,7 +497,7 @@ pw_stream_new(struct pw_core *core,
           struct pw_properties *props    /**< stream properties, ownership is taken */);
 
 struct pw_stream *
-pw_stream_new_simple(struct pw_loop *loop,    /**< a \ref pw_loop to use */
+pw_stream_new_simple(struct pw_loop *loop,    /**< a \ref pw_loop to use as the main loop */
              const char *name,        /**< a stream media name */
              struct pw_properties *props,/**< stream properties, ownership is taken */
              const struct pw_stream_events *events,    /**< stream events */
@@ -447,45 +559,62 @@ int pw_stream_set_error(struct pw_stream
             const char *error,        /**< an error message */
             ...) SPA_PRINTF_FUNC(3, 4);
 
-/** Complete the negotiation process with result code \a res
- *
- * This function should be called after notification of the format.
-
- * When \a res indicates success, \a params contain the parameters for the
- * allocation state.  */
+/** Update the param exposed on the stream. */
 int
 pw_stream_update_params(struct pw_stream *stream,    /**< a \ref pw_stream */
-            const struct spa_pod **params,    /**< an array of params. The params should
-                              *  ideally contain parameters for doing
-                              *  buffer allocation. */
+            const struct spa_pod **params,    /**< an array of params. */
             uint32_t n_params        /**< number of elements in \a params */);
 
+/**
+ * Set a parameter on the stream. This is like pw_stream_set_control() but with
+ * a complete spa_pod param. It can also be called from the param_changed event handler
+ * to intercept and modify the param for the adapter. Since 0.3.70 */
+int pw_stream_set_param(struct pw_stream *stream,    /**< a \ref pw_stream */
+            uint32_t id,            /**< the id of the param */
+            const struct spa_pod *param    /**< the params to set */);
+
 /** Get control values */
 const struct pw_stream_control *pw_stream_get_control(struct pw_stream *stream, uint32_t id);
 
 /** Set control values */
 int pw_stream_set_control(struct pw_stream *stream, uint32_t id, uint32_t n_values, float *values, ...);
 
-/** Query the time on the stream */
+/** Query the time on the stream, RT safe */
 int pw_stream_get_time_n(struct pw_stream *stream, struct pw_time *time, size_t size);
 
+/** Get the current time in nanoseconds. This value can be compared with
+ * the \ref pw_time.now value. RT safe. Since 1.1.0 */
+uint64_t pw_stream_get_nsec(struct pw_stream *stream);
+
+/** Get the data loop that is doing the processing of this stream. This loop
+ * is assigned after pw_stream_connect().  * Since 1.1.0 */
+struct pw_loop *pw_stream_get_data_loop(struct pw_stream *stream);
+
 /** Query the time on the stream, deprecated since 0.3.50,
- * use pw_stream_get_time_n() to get the fields added since 0.3.50. */
+ * use pw_stream_get_time_n() to get the fields added since 0.3.50. RT safe. */
 SPA_DEPRECATED
 int pw_stream_get_time(struct pw_stream *stream, struct pw_time *time);
 
 /** Get a buffer that can be filled for playback streams or consumed
- * for capture streams. */
+ * for capture streams. RT safe. */
 struct pw_buffer *pw_stream_dequeue_buffer(struct pw_stream *stream);
 
-/** Submit a buffer for playback or recycle a buffer for capture. */
+/** Submit a buffer for playback or recycle a buffer for capture. RT safe. */
 int pw_stream_queue_buffer(struct pw_stream *stream, struct pw_buffer *buffer);
 
+/** Return a buffer to the queue without using it. This makes the buffer
+ * immediately available to dequeue again. RT safe. */
+int pw_stream_return_buffer(struct pw_stream *stream, struct pw_buffer *buffer);
+
 /** Activate or deactivate the stream */
 int pw_stream_set_active(struct pw_stream *stream, bool active);
 
 /** Flush a stream. When \a drain is true, the drained callback will
- * be called when all data is played or recorded */
+ * be called when all data is played or recorded. The stream can be resumed
+ * after the drain by setting it active again with
+ * \ref pw_stream_set_active(). A flush without a drain is mostly useful afer
+ * a state change to PAUSED, to flush any remaining data from the queues and
+ * the converters. RT safe. */
 int pw_stream_flush(struct pw_stream *stream, bool drain);
 
 /** Check if the stream is driving. The stream needs to have the
@@ -494,10 +623,64 @@ int pw_stream_flush(struct pw_stream *st
  * available (output) or needed (input). Since 0.3.34 */
 bool pw_stream_is_driving(struct pw_stream *stream);
 
+/** Check if the graph is using lazy scheduling. If the stream is
+ * driving according to \ref pw_stream_is_driving(), then it should
+ * consider taking into account the RequestProcess commands when
+ * driving the graph.
+ *
+ * If the stream is not driving, it should send out RequestProcess
+ * events with \ref pw_stream_emit_event() or indirectly with
+ * \ref pw_stream_trigger_process() to suggest a new graph cycle
+ * to the driver.
+ *
+ * It is not a requirement that all RequestProcess events/commands
+ * need to start a graph cycle.
+ * Since 1.4.0 */
+bool pw_stream_is_lazy(struct pw_stream *stream);
+
 /** Trigger a push/pull on the stream. One iteration of the graph will
- * scheduled and process() will be called. Since 0.3.34 */
+ * be scheduled when the stream is driving according to
+ * \ref pw_stream_is_driving(). If it successfully finishes, process()
+ * will be called and the trigger_done event will be emitted. It is
+ * possible for the graph iteration to not finish, so
+ * pw_stream_trigger_process() needs to be called again even if process()
+ * and trigger_done is not called.
+ *
+ * If there is a deadline after which the stream will have xrun,
+ * pw_stream_trigger_process() should be called then, whether or not
+ * process()/trigger_done has been called. Sound hardware will xrun if
+ * there is any delay in audio processing, so the ALSA plugin triggers the
+ * graph every quantum to ensure audio keeps flowing. Drivers that
+ * do not have a deadline, such as the freewheel driver, should
+ * use a timeout to ensure that forward progress keeps being made.
+ * A reasonable choice of deadline is three times the quantum: if
+ * the graph is taking 3x longer than normal, it is likely that it
+ * is hung and should be retriggered.
+ *
+ * Streams that are not drivers according to \ref pw_stream_is_driving()
+ * can also call this method. The result is that a RequestProcess event
+ * is sent to the driver. If the graph is lazy scheduling according to
+ * \ref pw_stream_is_lazy(), this might result in a graph cycle by the
+ * driver. If the graph is not lazy scheduling and the stream is not a
+ * driver, this method will have no effect.
+ *
+ * RT safe.
+ *
+ * Since 0.3.34 */
 int pw_stream_trigger_process(struct pw_stream *stream);
 
+/** Emit an event from this stream. RT safe.
+ * Since 1.2.6 */
+int pw_stream_emit_event(struct pw_stream *stream, const struct spa_event *event);
+
+/** Adjust the rate of the stream.
+ * When the stream is using an adaptive resampler, adjust the resampler rate.
+ * When there is no resampler, -ENOTSUP is returned. Activating the adaptive
+ * resampler will add a small amount of delay to the samples, you can deactivate
+ * it again by setting a value <= 0.0. RT safe.
+ * Since 1.4.0 */
+int pw_stream_set_rate(struct pw_stream *stream, double rate);
+
 /**
  * \}
  */
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/type.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/type.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/type.h	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/type.h	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,45 @@
+/* PipeWire */
+/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
+/* SPDX-License-Identifier: MIT */
+
+#ifndef PIPEWIRE_TYPE_H
+#define PIPEWIRE_TYPE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <spa/utils/type.h>
+
+/** \defgroup pw_type Type info
+ * Type information
+ */
+
+/**
+ * \addtogroup pw_type
+ * \{
+ */
+
+enum {
+    PW_TYPE_FIRST = SPA_TYPE_VENDOR_PipeWire,
+};
+
+#define PW_TYPE_INFO_BASE        "PipeWire:"
+
+#define PW_TYPE_INFO_Object        PW_TYPE_INFO_BASE "Object"
+#define PW_TYPE_INFO_OBJECT_BASE    PW_TYPE_INFO_Object ":"
+
+#define PW_TYPE_INFO_Interface        PW_TYPE_INFO_BASE "Interface"
+#define PW_TYPE_INFO_INTERFACE_BASE    PW_TYPE_INFO_Interface ":"
+
+const struct spa_type_info * pw_type_info(void);
+
+/**
+ * \}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PIPEWIRE_TYPE_H */
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/utils.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/utils.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/pipewire/utils.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/pipewire/utils.h	2025-06-27 08:03:14.000000000 +0000
@@ -15,11 +15,13 @@ extern "C" {
 #ifndef _POSIX_C_SOURCE
 # include <sys/mount.h>
 #endif
+#include <errno.h>
 
 #ifndef ENODATA
 #define ENODATA 9919
 #endif
 
+#include <spa/utils/cleanup.h>
 #include <spa/utils/defs.h>
 #include <spa/pod/pod.h>
 
@@ -45,6 +47,12 @@ pw_split_strv(const char *str, const cha
 int
 pw_split_ip(char *str, const char *delimiter, int max_tokens, char *tokens[]);
 
+char **pw_strv_parse(const char *val, size_t len, int max_tokens, int *n_tokens);
+
+int pw_strv_find(char **a, const char *b);
+
+int pw_strv_find_common(char **a, char **b);
+
 void
 pw_free_strv(char **str);
 
@@ -92,6 +100,10 @@ void* pw_reallocarray(void *ptr, size_t
  * \}
  */
 
+SPA_DEFINE_AUTO_CLEANUP(pw_strv, char **, {
+    spa_clear_ptr(*thing, pw_free_strv);
+})
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/buffer/buffer.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/buffer/buffer.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/buffer/buffer.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/buffer/buffer.h	2025-06-27 08:03:14.000000000 +0000
@@ -12,6 +12,14 @@ extern "C" {
 #include <spa/utils/defs.h>
 #include <spa/buffer/meta.h>
 
+#ifndef SPA_API_BUFFER
+ #ifdef SPA_API_IMPL
+  #define SPA_API_BUFFER SPA_API_IMPL
+ #else
+  #define SPA_API_BUFFER static inline
+ #endif
+#endif
+
 /** \defgroup spa_buffer Buffers
  *
  * Buffers describe the data and metadata that is exchanged between
@@ -27,9 +35,15 @@ enum spa_data_type {
     SPA_DATA_Invalid,
     SPA_DATA_MemPtr,        /**< pointer to memory, the data field in
                       *  struct spa_data is set. */
-    SPA_DATA_MemFd,            /**< generic fd, mmap to get to memory */
-    SPA_DATA_DmaBuf,        /**< fd to dmabuf memory */
-    SPA_DATA_MemId,            /**< memory is identified with an id */
+    SPA_DATA_MemFd,            /**< memfd, mmap to get to memory. */
+    SPA_DATA_DmaBuf,        /**< fd to dmabuf memory. This might not be readily
+                      *  mappable (unless the MAPPABLE flag is set) and should
+                      *  normally be handled with DMABUF apis. */
+    SPA_DATA_MemId,            /**< memory is identified with an id. The actual memory
+                      *  can be obtained in some other way and can be identified
+                      *  with this id. */
+    SPA_DATA_SyncObj,        /**< a syncobj, usually requires a spa_meta_sync_timeline metadata
+                      *  with timeline points. */
 
     _SPA_DATA_LAST,            /**< not part of ABI */
 };
@@ -65,9 +79,12 @@ struct spa_data {
 #define SPA_DATA_FLAG_WRITABLE    (1u<<1)    /**< data is writable */
 #define SPA_DATA_FLAG_DYNAMIC    (1u<<2)    /**< data pointer can be changed */
 #define SPA_DATA_FLAG_READWRITE    (SPA_DATA_FLAG_READABLE|SPA_DATA_FLAG_WRITABLE)
+#define SPA_DATA_FLAG_MAPPABLE    (1u<<3)    /**< data is mappable with simple mmap/munmap. Some memory
+                      *  types are not simply mappable (DmaBuf) unless explicitly
+                      *  specified with this flag. */
     uint32_t flags;            /**< data flags */
     int64_t fd;            /**< optional fd for data */
-    uint32_t mapoffset;        /**< offset to map fd at */
+    uint32_t mapoffset;        /**< offset to map fd at, this is page aligned */
     uint32_t maxsize;        /**< max size of data */
     void *data;            /**< optional data pointer */
     struct spa_chunk *chunk;    /**< valid chunk of memory */
@@ -82,7 +99,7 @@ struct spa_buffer {
 };
 
 /** Find metadata in a buffer */
-static inline struct spa_meta *spa_buffer_find_meta(const struct spa_buffer *b, uint32_t type)
+SPA_API_BUFFER struct spa_meta *spa_buffer_find_meta(const struct spa_buffer *b, uint32_t type)
 {
     uint32_t i;
 
@@ -93,7 +110,7 @@ static inline struct spa_meta *spa_buffe
     return NULL;
 }
 
-static inline void *spa_buffer_find_meta_data(const struct spa_buffer *b, uint32_t type, size_t size)
+SPA_API_BUFFER void *spa_buffer_find_meta_data(const struct spa_buffer *b, uint32_t type, size_t size)
 {
     struct spa_meta *m;
     if ((m = spa_buffer_find_meta(b, type)) && m->size >= size)
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/buffer/meta.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/buffer/meta.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/buffer/meta.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/buffer/meta.h	2025-06-27 08:03:14.000000000 +0000
@@ -12,6 +12,14 @@ extern "C" {
 #include <spa/utils/defs.h>
 #include <spa/pod/pod.h>
 
+#ifndef SPA_API_META
+ #ifdef SPA_API_IMPL
+  #define SPA_API_META SPA_API_IMPL
+ #else
+  #define SPA_API_META static inline
+ #endif
+#endif
+
 /**
  * \addtogroup spa_buffer
  * \{
@@ -28,6 +36,7 @@ enum spa_meta_type {
                       *  associated with the data */
     SPA_META_Busy,            /**< don't write to buffer when count > 0 */
     SPA_META_VideoTransform,    /**< struct spa_meta_transform */
+    SPA_META_SyncTimeline,        /**< struct spa_meta_sync_timeline */
 
     _SPA_META_LAST,            /**< not part of ABI/API */
 };
@@ -45,14 +54,13 @@ struct spa_meta {
     void *data;        /**< pointer to metadata */
 };
 
-static inline void *spa_meta_first(const struct spa_meta *m) {
+SPA_API_META void *spa_meta_first(const struct spa_meta *m) {
     return m->data;
 }
-#define spa_meta_first spa_meta_first
-static inline void *spa_meta_end(const struct spa_meta *m) {
+
+SPA_API_META void *spa_meta_end(const struct spa_meta *m) {
     return SPA_PTROFF(m->data,m->size,void);
 }
-#define spa_meta_end spa_meta_end
 #define spa_meta_check(p,m)    (SPA_PTROFF(p,sizeof(*(p)),void) <= spa_meta_end(m))
 
 /**
@@ -79,19 +87,16 @@ struct spa_meta_region {
     struct spa_region region;
 };
 
-static inline bool spa_meta_region_is_valid(const struct spa_meta_region *m) {
+SPA_API_META bool spa_meta_region_is_valid(const struct spa_meta_region *m) {
     return m->region.size.width != 0 && m->region.size.height != 0;
 }
-#define spa_meta_region_is_valid spa_meta_region_is_valid
 
 /** iterate all the items in a metadata */
 #define spa_meta_for_each(pos,meta)                    \
-    for ((pos) = (__typeof(pos))spa_meta_first(meta);            \
+    for ((pos) = (__typeof(pos))spa_meta_first(meta);        \
         spa_meta_check(pos, meta);                    \
             (pos)++)
 
-#define spa_meta_bitmap_is_valid(m)    ((m)->format != 0)
-
 /**
  * Bitmap information
  *
@@ -111,7 +116,9 @@ struct spa_meta_bitmap {
                       *  info. */
 };
 
-#define spa_meta_cursor_is_valid(m)    ((m)->id != 0)
+SPA_API_META bool spa_meta_bitmap_is_valid(const struct spa_meta_bitmap *m) {
+    return m->format != 0;
+}
 
 /**
  * Cursor information
@@ -131,6 +138,10 @@ struct spa_meta_cursor {
                       *  struct spa_meta_bitmap at the offset. */
 };
 
+SPA_API_META bool spa_meta_cursor_is_valid(const struct spa_meta_cursor *m) {
+    return m->id != 0;
+}
+
 /** a timed set of events associated with the buffer */
 struct spa_meta_control {
     struct spa_pod_sequence sequence;
@@ -149,7 +160,7 @@ enum spa_meta_videotransform_value {
     SPA_META_TRANSFORMATION_270,        /**< 270 degree counter-clockwise */
     SPA_META_TRANSFORMATION_Flipped,    /**< 180 degree flipped around the vertical axis. Equivalent
                           * to a reflexion through the vertical line splitting the
-                          * bufffer in two equal sized parts */
+                          * buffer in two equal sized parts */
     SPA_META_TRANSFORMATION_Flipped90,    /**< flip then rotate around 90 degree counter-clockwise */
     SPA_META_TRANSFORMATION_Flipped180,    /**< flip then rotate around 180 degree counter-clockwise */
     SPA_META_TRANSFORMATION_Flipped270,    /**< flip then rotate around 270 degree counter-clockwise */
@@ -162,6 +173,26 @@ struct spa_meta_videotransform {
 };
 
 /**
+ * A timeline point for explicit sync
+ *
+ * Metadata to describe the time on the timeline when the buffer
+ * can be acquired and when it can be reused.
+ *
+ * This metadata will require negotiation of 2 extra fds for the acquire
+ * and release timelines respectively.  One way to achieve this is to place
+ * this metadata as SPA_PARAM_BUFFERS_metaType when negotiating a buffer
+ * layout with 2 extra fds.
+ */
+struct spa_meta_sync_timeline {
+    uint32_t flags;
+    uint32_t padding;
+    uint64_t acquire_point;            /**< the timeline acquire point, this is when the data
+                          *  can be accessed. */
+    uint64_t release_point;            /**< the timeline release point, this timeline point should
+                          *  be signaled when the data is no longer accessed. */
+};
+
+/**
  * \}
  */
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/buffer/type-info.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/buffer/type-info.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/buffer/type-info.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/buffer/type-info.h	2025-06-27 08:03:14.000000000 +0000
@@ -35,6 +35,7 @@ static const struct spa_type_info spa_ty
     { SPA_DATA_MemFd, SPA_TYPE_Int, SPA_TYPE_INFO_DATA_FD_BASE "MemFd", NULL },
     { SPA_DATA_DmaBuf, SPA_TYPE_Int, SPA_TYPE_INFO_DATA_FD_BASE "DmaBuf", NULL },
     { SPA_DATA_MemId, SPA_TYPE_Int, SPA_TYPE_INFO_DATA_BASE "MemId", NULL },
+    { SPA_DATA_SyncObj, SPA_TYPE_Int, SPA_TYPE_INFO_DATA_BASE "SyncObj", NULL },
     { 0, 0, NULL, NULL },
 };
 
@@ -50,6 +51,22 @@ static const struct spa_type_info spa_ty
 #define SPA_TYPE_INFO_META_ARRAY_Region        SPA_TYPE_INFO_META_ARRAY_BASE "Region"
 #define SPA_TYPE_INFO_META_ARRAY_REGION_BASE    SPA_TYPE_INFO_META_ARRAY_Region ":"
 
+/* VideoTransform meta */
+#define SPA_TYPE_INFO_META_Transformation    SPA_TYPE_INFO_ENUM_BASE "Meta:Transformation"
+#define SPA_TYPE_INFO_META_TRANSFORMATION_BASE    SPA_TYPE_INFO_META_Transformation ":"
+
+static const struct spa_type_info spa_type_meta_videotransform_type[] = {
+    { SPA_META_TRANSFORMATION_None, SPA_TYPE_Int, SPA_TYPE_INFO_META_TRANSFORMATION_BASE "None", NULL },
+    { SPA_META_TRANSFORMATION_90, SPA_TYPE_Int, SPA_TYPE_INFO_META_TRANSFORMATION_BASE "90", NULL },
+    { SPA_META_TRANSFORMATION_180, SPA_TYPE_Int, SPA_TYPE_INFO_META_TRANSFORMATION_BASE "180", NULL },
+    { SPA_META_TRANSFORMATION_270, SPA_TYPE_Int, SPA_TYPE_INFO_META_TRANSFORMATION_BASE "270", NULL },
+    { SPA_META_TRANSFORMATION_Flipped, SPA_TYPE_Int, SPA_TYPE_INFO_META_TRANSFORMATION_BASE "Flipped", NULL },
+    { SPA_META_TRANSFORMATION_Flipped90, SPA_TYPE_Int, SPA_TYPE_INFO_META_TRANSFORMATION_BASE "Flipped90", NULL },
+    { SPA_META_TRANSFORMATION_Flipped180, SPA_TYPE_Int, SPA_TYPE_INFO_META_TRANSFORMATION_BASE "Flipped180", NULL },
+    { SPA_META_TRANSFORMATION_Flipped270, SPA_TYPE_Int, SPA_TYPE_INFO_META_TRANSFORMATION_BASE "Flipped270", NULL },
+    { 0, 0, NULL, NULL },
+};
+
 static const struct spa_type_info spa_type_meta_type[] = {
     { SPA_META_Invalid, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "Invalid", NULL },
     { SPA_META_Header, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "Header", NULL },
@@ -60,6 +77,7 @@ static const struct spa_type_info spa_ty
     { SPA_META_Control, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "Control", NULL },
     { SPA_META_Busy, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "Busy", NULL },
     { SPA_META_VideoTransform, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "VideoTransform", NULL },
+    { SPA_META_SyncTimeline, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "SyncTimeline", NULL },
     { 0, 0, NULL, NULL },
 };
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/control/control.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/control/control.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/control/control.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/control/control.h	2025-06-27 08:03:14.000000000 +0000
@@ -24,9 +24,12 @@ extern "C" {
 /** Different Control types */
 enum spa_control_type {
     SPA_CONTROL_Invalid,
-    SPA_CONTROL_Properties,        /**< data contains a SPA_TYPE_OBJECT_Props */
-    SPA_CONTROL_Midi,        /**< data contains a spa_pod_bytes with raw midi data */
-    SPA_CONTROL_OSC,        /**< data contains a spa_pod_bytes with an OSC packet */
+    SPA_CONTROL_Properties,        /**< SPA_TYPE_OBJECT_Props */
+    SPA_CONTROL_Midi,        /**< spa_pod_bytes with raw midi data (deprecated, use SPA_CONTROL_UMP) */
+    SPA_CONTROL_OSC,        /**< spa_pod_bytes with an OSC packet */
+    SPA_CONTROL_UMP,        /**< spa_pod_bytes with raw UMP (universal MIDI packet)
+                      *  data. The UMP 32 bit words are stored in native endian
+                      *  format. */
 
     _SPA_CONTROL_LAST,        /**< not part of ABI */
 };
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/control/type-info.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/control/type-info.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/control/type-info.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/control/type-info.h	2025-06-27 08:03:14.000000000 +0000
@@ -27,6 +27,7 @@ static const struct spa_type_info spa_ty
     { SPA_CONTROL_Properties, SPA_TYPE_Int, SPA_TYPE_INFO_CONTROL_BASE "Properties", NULL },
     { SPA_CONTROL_Midi, SPA_TYPE_Int, SPA_TYPE_INFO_CONTROL_BASE "Midi", NULL },
     { SPA_CONTROL_OSC, SPA_TYPE_Int, SPA_TYPE_INFO_CONTROL_BASE "OSC", NULL },
+    { SPA_CONTROL_UMP, SPA_TYPE_Int, SPA_TYPE_INFO_CONTROL_BASE "UMP", NULL },
     { 0, 0, NULL, NULL },
 };
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/debug/types.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/debug/types.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/debug/types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/debug/types.h	2025-06-27 08:03:14.000000000 +0000
@@ -18,7 +18,16 @@ extern "C" {
 
 #include <string.h>
 
-static inline const struct spa_type_info *spa_debug_type_find(const struct spa_type_info *info, uint32_t type)
+#ifndef SPA_API_DEBUG_TYPES
+ #ifdef SPA_API_IMPL
+  #define SPA_API_DEBUG_TYPES SPA_API_IMPL
+ #else
+  #define SPA_API_DEBUG_TYPES static inline
+ #endif
+#endif
+
+
+SPA_API_DEBUG_TYPES const struct spa_type_info *spa_debug_type_find(const struct spa_type_info *info, uint32_t type)
 {
     const struct spa_type_info *res;
 
@@ -37,22 +46,19 @@ static inline const struct spa_type_info
     return NULL;
 }
 
-static inline const char *spa_debug_type_short_name(const char *name)
+SPA_API_DEBUG_TYPES const char *spa_debug_type_short_name(const char *name)
 {
-    const char *h;
-    if ((h = strrchr(name, ':')) != NULL)
-        name = h + 1;
-    return name;
+    return spa_type_short_name(name);
 }
 
-static inline const char *spa_debug_type_find_name(const struct spa_type_info *info, uint32_t type)
+SPA_API_DEBUG_TYPES const char *spa_debug_type_find_name(const struct spa_type_info *info, uint32_t type)
 {
     if ((info = spa_debug_type_find(info, type)) == NULL)
         return NULL;
     return info->name;
 }
 
-static inline const char *spa_debug_type_find_short_name(const struct spa_type_info *info, uint32_t type)
+SPA_API_DEBUG_TYPES const char *spa_debug_type_find_short_name(const struct spa_type_info *info, uint32_t type)
 {
     const char *str;
     if ((str = spa_debug_type_find_name(info, type)) == NULL)
@@ -60,7 +66,7 @@ static inline const char *spa_debug_type
     return spa_debug_type_short_name(str);
 }
 
-static inline uint32_t spa_debug_type_find_type(const struct spa_type_info *info, const char *name)
+SPA_API_DEBUG_TYPES uint32_t spa_debug_type_find_type(const struct spa_type_info *info, const char *name)
 {
     if (info == NULL)
         info = SPA_TYPE_ROOT;
@@ -76,7 +82,7 @@ static inline uint32_t spa_debug_type_fi
     return SPA_ID_INVALID;
 }
 
-static inline const struct spa_type_info *spa_debug_type_find_short(const struct spa_type_info *info, const char *name)
+SPA_API_DEBUG_TYPES const struct spa_type_info *spa_debug_type_find_short(const struct spa_type_info *info, const char *name)
 {
     while (info && info->name) {
         if (strcmp(spa_debug_type_short_name(info->name), name) == 0)
@@ -90,7 +96,7 @@ static inline const struct spa_type_info
     return NULL;
 }
 
-static inline uint32_t spa_debug_type_find_type_short(const struct spa_type_info *info, const char *name)
+SPA_API_DEBUG_TYPES uint32_t spa_debug_type_find_type_short(const struct spa_type_info *info, const char *name)
 {
     if ((info = spa_debug_type_find_short(info, name)) == NULL)
         return SPA_ID_INVALID;
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/node/io.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/node/io.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/node/io.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/node/io.h	2025-06-27 08:03:14.000000000 +0000
@@ -31,14 +31,16 @@ extern "C" {
 enum spa_io_type {
     SPA_IO_Invalid,
     SPA_IO_Buffers,        /**< area to exchange buffers, struct spa_io_buffers */
-    SPA_IO_Range,        /**< expected byte range, struct spa_io_range */
+    SPA_IO_Range,        /**< expected byte range, struct spa_io_range (currently not used in PipeWire) */
     SPA_IO_Clock,        /**< area to update clock information, struct spa_io_clock */
-    SPA_IO_Latency,        /**< latency reporting, struct spa_io_latency */
+    SPA_IO_Latency,        /**< latency reporting, struct spa_io_latency (currently not used in
+                  * PipeWire). \see spa_param_latency */
     SPA_IO_Control,        /**< area for control messages, struct spa_io_sequence */
     SPA_IO_Notify,        /**< area for notify messages, struct spa_io_sequence */
     SPA_IO_Position,    /**< position information in the graph, struct spa_io_position */
     SPA_IO_RateMatch,    /**< rate matching between nodes, struct spa_io_rate_match */
-    SPA_IO_Memory,        /**< memory pointer, struct spa_io_memory */
+    SPA_IO_Memory,        /**< memory pointer, struct spa_io_memory (currently not used in PipeWire) */
+    SPA_IO_AsyncBuffers,    /**< async area to exchange buffers, struct spa_io_async_buffers */
 };
 
 /**
@@ -108,29 +110,52 @@ struct spa_io_range {
  *
  * The clock counts the elapsed time according to the clock provider
  * since the provider was last started.
+ *
+ * Driver nodes are supposed to update the contents of \ref SPA_IO_Clock before
+ * signaling the start of a graph cycle.  These updated clock values become
+ * visible to other nodes in \ref SPA_IO_Position. Non-driver nodes do
+ * not need to update the contents of their \ref SPA_IO_Clock.
+ *
+ * The host generally gives each node a separate \ref spa_io_clock in \ref
+ * SPA_IO_Clock, so that updates made by the driver are not visible in the
+ * contents of \ref SPA_IO_Clock of other nodes. Instead, \ref SPA_IO_Position
+ * is used to look up the current graph time.
+ *
+ * A node is a driver when \ref spa_io_clock.id in \ref SPA_IO_Clock and
+ * \ref spa_io_position.clock.id in \ref SPA_IO_Position are the same.
  */
 struct spa_io_clock {
-#define SPA_IO_CLOCK_FLAG_FREEWHEEL (1u<<0)
-    uint32_t flags;            /**< clock flags */
-    uint32_t id;            /**< unique clock id, set by application */
-    char name[64];            /**< clock name prefixed with API, set by node. The clock name
-                      *  is unique per clock and can be used to check if nodes
-                      *  share the same clock. */
-    uint64_t nsec;            /**< time in nanoseconds against monotonic clock */
-    struct spa_fraction rate;    /**< rate for position/duration/delay */
-    uint64_t position;        /**< current position */
-    uint64_t duration;        /**< duration of current cycle */
-    int64_t delay;            /**< delay between position and hardware,
-                      *  positive for capture, negative for playback */
-    double rate_diff;        /**< rate difference between clock and monotonic time */
-    uint64_t next_nsec;        /**< estimated next wakeup time in nanoseconds */
-
-    struct spa_fraction target_rate;    /**< target rate of next cycle */
-    uint64_t target_duration;        /**< target duration of next cycle */
-    uint32_t target_seq;            /**< seq counter. must be equal at start and
+#define SPA_IO_CLOCK_FLAG_FREEWHEEL    (1u<<0) /* graph is freewheeling */
+#define SPA_IO_CLOCK_FLAG_XRUN_RECOVER    (1u<<1) /* recovering from xrun */
+#define SPA_IO_CLOCK_FLAG_LAZY        (1u<<2) /* lazy scheduling */
+#define SPA_IO_CLOCK_FLAG_NO_RATE    (1u<<3) /* the rate of the clock is only approximately.
+                         * it is recommended to use the nsec as a clock source.
+                         * The rate_diff contains the measured inaccuracy. */
+    uint32_t flags;            /**< Clock flags */
+    uint32_t id;            /**< Unique clock id, set by host application */
+    char name[64];            /**< Clock name prefixed with API, set by node when it receives
+                      *  \ref SPA_IO_Clock. The clock name is unique per clock and
+                      *  can be used to check if nodes share the same clock. */
+    uint64_t nsec;            /**< Time in nanoseconds against monotonic clock
+                      * (CLOCK_MONOTONIC). This fields reflects a real time instant
+                      * in the past. The value may have jitter. */
+    struct spa_fraction rate;    /**< Rate for position/duration/delay/xrun */
+    uint64_t position;        /**< Current position, in samples @ \ref rate */
+    uint64_t duration;        /**< Duration of current cycle, in samples @ \ref rate */
+    int64_t delay;            /**< Delay between position and hardware, in samples @ \ref rate */
+    double rate_diff;        /**< Rate difference between clock and monotonic time, as a ratio of
+                      *  clock speeds. */
+    uint64_t next_nsec;        /**< Estimated next wakeup time in nanoseconds.
+                      *  This time is a logical start time of the next cycle, and
+                      *  is not necessarily in the future.
+                      */
+
+    struct spa_fraction target_rate;    /**< Target rate of next cycle */
+    uint64_t target_duration;        /**< Target duration of next cycle */
+    uint32_t target_seq;            /**< Seq counter. must be equal at start and
                           *  end of read and lower bit must be 0 */
-
-    uint32_t padding[3];
+    uint32_t cycle;            /**< incremented each time the graph is started */
+    uint64_t xrun;            /**< Estimated accumulated xrun duration */
 };
 
 /* the size of the video in this cycle */
@@ -145,7 +170,11 @@ struct spa_io_video_size {
     uint32_t padding[4];
 };
 
-/** latency reporting */
+/**
+ * Latency reporting
+ *
+ * Currently not used in PipeWire. Instead, \see spa_param_latency
+ */
 struct spa_io_latency {
     struct spa_fraction rate;    /**< rate for min/max */
     uint64_t min;            /**< min latency */
@@ -166,7 +195,9 @@ struct spa_io_segment_bar {
     float signature_denom;        /**< time signature denominator */
     double bpm;            /**< beats per minute */
     double beat;            /**< current beat in segment */
-    uint32_t padding[8];
+    double bar_start_tick;
+    double ticks_per_beat;
+    uint32_t padding[4];
 };
 
 /** video frame segment */
@@ -245,8 +276,13 @@ enum spa_io_position_state {
 /**
  * The position information adds extra meaning to the raw clock times.
  *
- * It is set on all nodes and the clock id will contain the clock of the
- * driving node in the graph.
+ * It is set on all nodes in \ref SPA_IO_Position, and the contents of \ref
+ * spa_io_position.clock contain the clock updates made by the driving node in
+ * the graph in its \ref SPA_IO_Clock.  Also, \ref spa_io_position.clock.id
+ * will contain the clock id of the driving node in the graph.
+ *
+ * The position clock indicates the logical start time of the current graph
+ * cycle.
  *
  * The position information contains 1 or more segments that convert the
  * raw clock times to a stream time. They are sorted based on their
@@ -269,14 +305,56 @@ struct spa_io_position {
     struct spa_io_segment segments[SPA_IO_POSITION_MAX_SEGMENTS];    /**< segments */
 };
 
-/** rate matching */
+/**
+ * Rate matching.
+ *
+ * It is usually set on the nodes that process resampled data, by
+ * the component (audioadapter) that handles resampling between graph
+ * and node rates. The \a flags and \a rate fields may be modified by the node.
+ *
+ * The node can request a correction to the resampling rate in its process(), by setting
+ * \ref SPA_IO_RATE_MATCH_ACTIVE on \a flags, and setting \a rate to the desired rate
+ * correction.  Usually the rate is obtained from DLL or other adaptive mechanism that
+ * e.g. drives the node buffer fill level toward a specific value.
+ *
+ * When resampling to (graph->node) direction, the number of samples produced
+ * by the resampler varies on each cycle, as the rates are not commensurate.
+ *
+ * When resampling to (node->graph) direction, the number of samples consumed by the
+ * resampler varies. Node output ports in process() should produce \a size number of
+ * samples to match what the resampler needs to produce one graph quantum of output
+ * samples.
+ *
+ * Resampling filters introduce processing delay, given by \a delay and \a delay_frac, in
+ * samples at node rate. The delay varies on each cycle e.g. when resampling between
+ * noncommensurate rates.
+ *
+ * The first sample output (graph->node) or consumed (node->graph) by the resampler is
+ * offset by \a delay + \a delay_frac / 1e9 node samples relative to the nominal graph
+ * cycle start position:
+ *
+ * \code{.unparsed}
+ * first_resampled_sample_nsec =
+ *    first_original_sample_nsec
+ *    - (rate_match->delay * SPA_NSEC_PER_SEC + rate_match->delay_frac) / node_rate
+ * \endcode
+ */
 struct spa_io_rate_match {
-    uint32_t delay;            /**< extra delay in samples for resampler */
+    uint32_t delay;            /**< resampling delay, in samples at
+                     * node rate */
     uint32_t size;            /**< requested input size for resampler */
-    double rate;            /**< rate for resampler */
+    double rate;            /**< rate for resampler (set by node) */
 #define SPA_IO_RATE_MATCH_FLAG_ACTIVE    (1 << 0)
-    uint32_t flags;            /**< extra flags */
-    uint32_t padding[7];
+    uint32_t flags;            /**< extra flags (set by node) */
+    int32_t delay_frac;        /**< resampling delay fractional part,
+                     * in units of nanosamples (1/10^9 sample) at node rate */
+    uint32_t padding[6];
+};
+
+/** async buffers */
+struct spa_io_async_buffers {
+    struct spa_io_buffers buffers[2];    /**< async buffers, writers write to current (cycle+1)&1,
+                          *  readers read from (cycle)&1 */
 };
 
 /**
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/node/type-info.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/node/type-info.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/node/type-info.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/node/type-info.h	2025-06-27 08:03:14.000000000 +0000
@@ -34,6 +34,7 @@ static const struct spa_type_info spa_ty
     { SPA_IO_Position, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Position", NULL },
     { SPA_IO_RateMatch, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "RateMatch", NULL },
     { SPA_IO_Memory, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Memory", NULL },
+    { SPA_IO_AsyncBuffers, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "AsyncBuffers", NULL },
     { 0, 0, NULL, NULL },
 };
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/aac-types.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/aac-types.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/aac-types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/aac-types.h	2025-06-27 08:03:14.000000000 +0000
@@ -12,6 +12,11 @@ extern "C" {
 #include <spa/utils/type.h>
 #include <spa/param/audio/aac.h>
 
+/**
+ * \addtogroup spa_param
+ * \{
+ */
+
 #define SPA_TYPE_INFO_AudioAACStreamFormat        SPA_TYPE_INFO_ENUM_BASE "AudioAACStreamFormat"
 #define SPA_TYPE_INFO_AUDIO_AAC_STREAM_FORMAT_BASE    SPA_TYPE_INFO_AudioAACStreamFormat ":"
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/aac.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/aac.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/aac.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/aac.h	2025-06-27 08:03:14.000000000 +0000
@@ -11,6 +11,11 @@ extern "C" {
 
 #include <spa/param/audio/raw.h>
 
+/**
+ * \addtogroup spa_param
+ * \{
+ */
+
 enum spa_audio_aac_stream_format {
     SPA_AUDIO_AAC_STREAM_FORMAT_UNKNOWN,
     /* Raw AAC frames */
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/amr-types.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/amr-types.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/amr-types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/amr-types.h	2025-06-27 08:03:14.000000000 +0000
@@ -12,6 +12,11 @@ extern "C" {
 #include <spa/utils/type.h>
 #include <spa/param/audio/amr.h>
 
+/**
+ * \addtogroup spa_param
+ * \{
+ */
+
 #define SPA_TYPE_INFO_AudioAMRBandMode        SPA_TYPE_INFO_ENUM_BASE "AudioAMRBandMode"
 #define SPA_TYPE_INFO_AUDIO_AMR_BAND_MODE_BASE    SPA_TYPE_INFO_AudioAMRBandMode ":"
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/amr.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/amr.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/amr.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/amr.h	2025-06-27 08:03:14.000000000 +0000
@@ -11,6 +11,11 @@ extern "C" {
 
 #include <spa/param/audio/raw.h>
 
+/**
+ * \addtogroup spa_param
+ * \{
+ */
+
 enum spa_audio_amr_band_mode {
     SPA_AUDIO_AMR_BAND_MODE_UNKNOWN,
     SPA_AUDIO_AMR_BAND_MODE_NB,
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/iec958-types.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/iec958-types.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/iec958-types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/iec958-types.h	2025-06-27 08:03:14.000000000 +0000
@@ -12,6 +12,19 @@ extern "C" {
 #include <spa/utils/type.h>
 #include <spa/param/audio/iec958.h>
 
+/**
+ * \addtogroup spa_param
+ * \{
+ */
+
+#ifndef SPA_API_AUDIO_IEC958_TYPES
+ #ifdef SPA_API_IMPL
+  #define SPA_API_AUDIO_IEC958_TYPES SPA_API_IMPL
+ #else
+  #define SPA_API_AUDIO_IEC958_TYPES static inline
+ #endif
+#endif
+
 #define SPA_TYPE_INFO_AudioIEC958Codec        SPA_TYPE_INFO_ENUM_BASE "AudioIEC958Codec"
 #define SPA_TYPE_INFO_AUDIO_IEC958_CODEC_BASE    SPA_TYPE_INFO_AudioIEC958Codec ":"
 
@@ -28,6 +41,14 @@ static const struct spa_type_info spa_ty
     { 0, 0, NULL, NULL },
 };
 
+SPA_API_AUDIO_IEC958_TYPES uint32_t spa_type_audio_iec958_codec_from_short_name(const char *name)
+{
+    return spa_type_from_short_name(name, spa_type_audio_iec958_codec, SPA_AUDIO_IEC958_CODEC_UNKNOWN);
+}
+SPA_API_AUDIO_IEC958_TYPES const char * spa_type_audio_iec958_codec_to_short_name(uint32_t type)
+{
+    return spa_type_to_short_name(type, spa_type_audio_iec958_codec, "UNKNOWN");
+}
 /**
  * \}
  */
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/mp3-types.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/mp3-types.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/mp3-types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/mp3-types.h	2025-06-27 08:03:14.000000000 +0000
@@ -12,6 +12,11 @@ extern "C" {
 #include <spa/utils/type.h>
 #include <spa/param/audio/mp3.h>
 
+/**
+ * \addtogroup spa_param
+ * \{
+ */
+
 #define SPA_TYPE_INFO_AudioMP3ChannelMode        SPA_TYPE_INFO_ENUM_BASE "AudioMP3ChannelMode"
 #define SPA_TYPE_INFO_AUDIO_MP3_CHANNEL_MODE_BASE    SPA_TYPE_INFO_AudioMP3ChannelMode ":"
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/mp3.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/mp3.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/mp3.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/mp3.h	2025-06-27 08:03:14.000000000 +0000
@@ -11,6 +11,11 @@ extern "C" {
 
 #include <spa/param/audio/raw.h>
 
+/**
+ * \addtogroup spa_param
+ * \{
+ */
+
 enum spa_audio_mp3_channel_mode {
     SPA_AUDIO_MP3_CHANNEL_MODE_UNKNOWN,
     SPA_AUDIO_MP3_CHANNEL_MODE_MONO,
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/raw-types.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/raw-types.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/raw-types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/raw-types.h	2025-06-27 08:03:14.000000000 +0000
@@ -15,8 +15,17 @@ extern "C" {
  */
 
 #include <spa/utils/type.h>
+#include <spa/utils/string.h>
 #include <spa/param/audio/raw.h>
 
+#ifndef SPA_API_AUDIO_RAW_TYPES
+ #ifdef SPA_API_IMPL
+  #define SPA_API_AUDIO_RAW_TYPES SPA_API_IMPL
+ #else
+  #define SPA_API_AUDIO_RAW_TYPES static inline
+ #endif
+#endif
+
 #define SPA_TYPE_INFO_AudioFormat        SPA_TYPE_INFO_ENUM_BASE "AudioFormat"
 #define SPA_TYPE_INFO_AUDIO_FORMAT_BASE        SPA_TYPE_INFO_AudioFormat ":"
 
@@ -128,6 +137,15 @@ static const struct spa_type_info spa_ty
     { 0, 0, NULL, NULL },
 };
 
+SPA_API_AUDIO_RAW_TYPES uint32_t spa_type_audio_format_from_short_name(const char *name)
+{
+    return spa_type_from_short_name(name, spa_type_audio_format, SPA_AUDIO_FORMAT_UNKNOWN);
+}
+SPA_API_AUDIO_RAW_TYPES const char * spa_type_audio_format_to_short_name(uint32_t type)
+{
+    return spa_type_to_short_name(type, spa_type_audio_format, "UNKNOWN");
+}
+
 #define SPA_TYPE_INFO_AudioFlags    SPA_TYPE_INFO_FLAGS_BASE "AudioFlags"
 #define SPA_TYPE_INFO_AUDIO_FLAGS_BASE    SPA_TYPE_INFO_AudioFlags ":"
 
@@ -247,6 +265,16 @@ static const struct spa_type_info spa_ty
     { 0, 0, NULL, NULL },
 };
 
+SPA_API_AUDIO_RAW_TYPES uint32_t spa_type_audio_channel_from_short_name(const char *name)
+{
+    return spa_type_from_short_name(name, spa_type_audio_channel, SPA_AUDIO_CHANNEL_UNKNOWN);
+}
+SPA_API_AUDIO_RAW_TYPES const char * spa_type_audio_channel_to_short_name(uint32_t type)
+{
+    return spa_type_to_short_name(type, spa_type_audio_channel, "UNK");
+}
+
+
 /**
  * \}
  */
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/raw.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/raw.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/raw.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/raw.h	2025-06-27 08:03:14.000000000 +0000
@@ -11,15 +11,7 @@ extern "C" {
 
 #include <stdint.h>
 
-#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) && !defined(AIX)
-#include <endian.h>
-#endif
-
-#if defined(AIX)
-#include <sys/machine.h>
-#define __BIG_ENDIAN      BIG_ENDIAN
-#define __BYTE_ORDER      BIG_ENDIAN
-#endif
+#include <spa/utils/endian.h>
 
 /**
  * \addtogroup spa_param
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/wma-types.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/wma-types.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/wma-types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/wma-types.h	2025-06-27 08:03:14.000000000 +0000
@@ -12,6 +12,11 @@ extern "C" {
 #include <spa/utils/type.h>
 #include <spa/param/audio/wma.h>
 
+/**
+ * \addtogroup spa_param
+ * \{
+ */
+
 #define SPA_TYPE_INFO_AudioWMAProfile        SPA_TYPE_INFO_ENUM_BASE "AudioWMAProfile"
 #define SPA_TYPE_INFO_AUDIO_WMA_PROFILE_BASE    SPA_TYPE_INFO_AudioWMAProfile ":"
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/wma.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/wma.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/wma.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/audio/wma.h	2025-06-27 08:03:14.000000000 +0000
@@ -11,6 +11,11 @@ extern "C" {
 
 #include <spa/param/audio/raw.h>
 
+/**
+ * \addtogroup spa_param
+ * \{
+ */
+
 enum spa_audio_wma_profile {
     SPA_AUDIO_WMA_PROFILE_UNKNOWN,
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/bluetooth/audio.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/bluetooth/audio.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/bluetooth/audio.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/bluetooth/audio.h	2025-06-27 08:03:14.000000000 +0000
@@ -21,6 +21,7 @@ enum spa_bluetooth_audio_codec {
     SPA_BLUETOOTH_AUDIO_CODEC_SBC_XQ,
     SPA_BLUETOOTH_AUDIO_CODEC_MPEG,
     SPA_BLUETOOTH_AUDIO_CODEC_AAC,
+    SPA_BLUETOOTH_AUDIO_CODEC_AAC_ELD,
     SPA_BLUETOOTH_AUDIO_CODEC_APTX,
     SPA_BLUETOOTH_AUDIO_CODEC_APTX_HD,
     SPA_BLUETOOTH_AUDIO_CODEC_LDAC,
@@ -34,13 +35,18 @@ enum spa_bluetooth_audio_codec {
     SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_71,
     SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_DUPLEX,
     SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_PRO,
+    SPA_BLUETOOTH_AUDIO_CODEC_OPUS_G,
 
     /* HFP */
     SPA_BLUETOOTH_AUDIO_CODEC_CVSD = 0x100,
     SPA_BLUETOOTH_AUDIO_CODEC_MSBC,
+    SPA_BLUETOOTH_AUDIO_CODEC_LC3_SWB,
 
     /* BAP */
     SPA_BLUETOOTH_AUDIO_CODEC_LC3 = 0x200,
+
+    /* ASHA */
+    SPA_BLUETOOTH_AUDIO_CODEC_G722 = 0x300,
 };
 
 /**
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/bluetooth/type-info.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/bluetooth/type-info.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/bluetooth/type-info.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/bluetooth/type-info.h	2025-06-27 08:03:14.000000000 +0000
@@ -25,6 +25,7 @@ static const struct spa_type_info spa_ty
     { SPA_BLUETOOTH_AUDIO_CODEC_SBC_XQ, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "sbc_xq", NULL },
     { SPA_BLUETOOTH_AUDIO_CODEC_MPEG, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "mpeg", NULL },
     { SPA_BLUETOOTH_AUDIO_CODEC_AAC, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "aac", NULL },
+    { SPA_BLUETOOTH_AUDIO_CODEC_AAC_ELD, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "aac_eld", NULL },
     { SPA_BLUETOOTH_AUDIO_CODEC_APTX, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "aptx", NULL },
     { SPA_BLUETOOTH_AUDIO_CODEC_APTX_HD, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "aptx_hd", NULL },
     { SPA_BLUETOOTH_AUDIO_CODEC_LDAC, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "ldac", NULL },
@@ -38,12 +39,16 @@ static const struct spa_type_info spa_ty
     { SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_71, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "opus_05_71", NULL },
     { SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_DUPLEX, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "opus_05_duplex", NULL },
     { SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_PRO, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "opus_05_pro", NULL },
+    { SPA_BLUETOOTH_AUDIO_CODEC_OPUS_G, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "opus_g", NULL },
 
     { SPA_BLUETOOTH_AUDIO_CODEC_CVSD, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "cvsd", NULL },
     { SPA_BLUETOOTH_AUDIO_CODEC_MSBC, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "msbc", NULL },
+    { SPA_BLUETOOTH_AUDIO_CODEC_LC3_SWB, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "lc3_swb", NULL },
 
     { SPA_BLUETOOTH_AUDIO_CODEC_LC3, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "lc3", NULL },
 
+    { SPA_BLUETOOTH_AUDIO_CODEC_G722, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "g722", NULL },
+
     { 0, 0, NULL, NULL },
 };
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/buffers-types.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/buffers-types.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/buffers-types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/buffers-types.h	2025-06-27 08:03:14.000000000 +0000
@@ -56,6 +56,7 @@ static const struct spa_type_info spa_ty
     { SPA_PARAM_BUFFERS_stride,   SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BLOCK_INFO_BASE "stride", NULL },
     { SPA_PARAM_BUFFERS_align,    SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BLOCK_INFO_BASE "align", NULL },
     { SPA_PARAM_BUFFERS_dataType, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BLOCK_INFO_BASE "dataType", NULL },
+    { SPA_PARAM_BUFFERS_metaType, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BLOCK_INFO_BASE "metaType", NULL },
     { 0, 0, NULL, NULL },
 };
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/buffers.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/buffers.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/buffers.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/buffers.h	2025-06-27 08:03:14.000000000 +0000
@@ -24,14 +24,15 @@ enum spa_param_buffers {
     SPA_PARAM_BUFFERS_size,        /**< size of a data block memory (Int)*/
     SPA_PARAM_BUFFERS_stride,    /**< stride of data block memory (Int) */
     SPA_PARAM_BUFFERS_align,    /**< alignment of data block memory (Int) */
-    SPA_PARAM_BUFFERS_dataType,    /**< possible memory types (Int, mask of enum spa_data_type) */
+    SPA_PARAM_BUFFERS_dataType,    /**< possible memory types (flags choice Int, mask of enum spa_data_type) */
+    SPA_PARAM_BUFFERS_metaType,    /**< required meta data types (Int, mask of enum spa_meta_type) */
 };
 
 /** properties for SPA_TYPE_OBJECT_ParamMeta */
 enum spa_param_meta {
     SPA_PARAM_META_START,
-    SPA_PARAM_META_type,    /**< the metadata, one of enum spa_meta_type (Id enum spa_meta_type) */
-    SPA_PARAM_META_size,    /**< the expected maximum size the meta (Int) */
+    SPA_PARAM_META_type,        /**< the metadata, one of enum spa_meta_type (Id enum spa_meta_type) */
+    SPA_PARAM_META_size,        /**< the expected maximum size the meta (Int) */
 };
 
 /** properties for SPA_TYPE_OBJECT_ParamIO */
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/format-utils.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/format-utils.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/format-utils.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/format-utils.h	2025-06-27 08:03:14.000000000 +0000
@@ -18,7 +18,15 @@ extern "C" {
 #include <spa/pod/parser.h>
 #include <spa/param/format.h>
 
-static inline int
+#ifndef SPA_API_FORMAT_UTILS
+ #ifdef SPA_API_IMPL
+  #define SPA_API_FORMAT_UTILS SPA_API_IMPL
+ #else
+  #define SPA_API_FORMAT_UTILS static inline
+ #endif
+#endif
+
+SPA_API_FORMAT_UTILS int
 spa_format_parse(const struct spa_pod *format, uint32_t *media_type, uint32_t *media_subtype)
 {
     return spa_pod_parse_object(format,
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/format.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/format.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/format.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/format.h	2025-06-27 08:03:14.000000000 +0000
@@ -141,6 +141,8 @@ enum spa_format {
     SPA_FORMAT_START_Stream = 0x50000,
     /* Application Format keys */
     SPA_FORMAT_START_Application = 0x60000,
+    SPA_FORMAT_CONTROL_types,        /**< possible control types (flags choice Int,
+                          *  mask of enum spa_control_type) */
 };
 
 #define SPA_KEY_FORMAT_DSP        "format.dsp"        /**< a predefined DSP format,
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/latency.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/latency.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/latency.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/latency.h	2025-06-27 08:03:14.000000000 +0000
@@ -16,14 +16,31 @@ extern "C" {
 
 #include <spa/param/param.h>
 
-/** properties for SPA_TYPE_OBJECT_ParamLatency */
+/**
+ * Properties for SPA_TYPE_OBJECT_ParamLatency
+ *
+ * The latency indicates:
+ *
+ * - for playback: time delay between start of a graph cycle, and the rendering of
+ *   the first sample of that cycle in audio output.
+ *
+ * - for capture: time delay between start of a graph cycle, and the first sample
+ *   of that cycle having occurred in audio input.
+ *
+ * For physical output/input, the latency is intended to correspond to the
+ * rendering/capture of physical audio, including hardware internal rendering delay.
+ *
+ * The latency values are adjusted by \ref SPA_PROP_latencyOffsetNsec or
+ * SPA_PARAM_ProcessLatency, if present. (e.g. for ALSA this is used to adjust for
+ * the internal hardware latency).
+ */
 enum spa_param_latency {
     SPA_PARAM_LATENCY_START,
     SPA_PARAM_LATENCY_direction,        /**< direction, input/output (Id enum spa_direction) */
     SPA_PARAM_LATENCY_minQuantum,        /**< min latency relative to quantum (Float) */
     SPA_PARAM_LATENCY_maxQuantum,        /**< max latency relative to quantum (Float) */
-    SPA_PARAM_LATENCY_minRate,        /**< min latency (Int) relative to rate */
-    SPA_PARAM_LATENCY_maxRate,        /**< max latency (Int) relative to rate */
+    SPA_PARAM_LATENCY_minRate,        /**< min latency (Int) relative to graph rate */
+    SPA_PARAM_LATENCY_maxRate,        /**< max latency (Int) relative to graph rate */
     SPA_PARAM_LATENCY_minNs,        /**< min latency (Long) in nanoseconds */
     SPA_PARAM_LATENCY_maxNs,        /**< max latency (Long) in nanoseconds */
 };
@@ -33,27 +50,32 @@ struct spa_latency_info {
     enum spa_direction direction;
     float min_quantum;
     float max_quantum;
-    uint32_t min_rate;
-    uint32_t max_rate;
-    uint64_t min_ns;
-    uint64_t max_ns;
+    int32_t min_rate;
+    int32_t max_rate;
+    int64_t min_ns;
+    int64_t max_ns;
 };
 
 #define SPA_LATENCY_INFO(dir,...) ((struct spa_latency_info) { .direction = (dir), ## __VA_ARGS__ })
 
-/** properties for SPA_TYPE_OBJECT_ParamProcessLatency */
+/**
+ * Properties for SPA_TYPE_OBJECT_ParamProcessLatency
+ *
+ * The processing latency indicates logical time delay between a sample in an input port,
+ * and a corresponding sample in an output port, relative to the graph time.
+ */
 enum spa_param_process_latency {
     SPA_PARAM_PROCESS_LATENCY_START,
     SPA_PARAM_PROCESS_LATENCY_quantum,    /**< latency relative to quantum (Float) */
-    SPA_PARAM_PROCESS_LATENCY_rate,        /**< latency (Int) relative to rate */
+    SPA_PARAM_PROCESS_LATENCY_rate,        /**< latency (Int) relative to graph rate */
     SPA_PARAM_PROCESS_LATENCY_ns,        /**< latency (Long) in nanoseconds */
 };
 
 /** Helper structure for managing process latency objects */
 struct spa_process_latency_info {
     float quantum;
-    uint32_t rate;
-    uint64_t ns;
+    int32_t rate;
+    int64_t ns;
 };
 
 #define SPA_PROCESS_LATENCY_INFO_INIT(...)    ((struct spa_process_latency_info) { __VA_ARGS__ })
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/param-types.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/param-types.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/param-types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/param-types.h	2025-06-27 08:03:14.000000000 +0000
@@ -40,6 +40,7 @@ static const struct spa_type_info spa_ty
     { SPA_PARAM_Control, SPA_TYPE_Sequence, SPA_TYPE_INFO_PARAM_ID_BASE "Control", NULL },
     { SPA_PARAM_Latency, SPA_TYPE_OBJECT_ParamLatency, SPA_TYPE_INFO_PARAM_ID_BASE "Latency", NULL },
     { SPA_PARAM_ProcessLatency, SPA_TYPE_OBJECT_ParamProcessLatency, SPA_TYPE_INFO_PARAM_ID_BASE "ProcessLatency", NULL },
+    { SPA_PARAM_Tag, SPA_TYPE_OBJECT_ParamTag, SPA_TYPE_INFO_PARAM_ID_BASE "Tag", NULL },
     { 0, 0, NULL, NULL },
 };
 
@@ -54,6 +55,11 @@ static const struct spa_type_info spa_ty
     { 0, 0, NULL, NULL },
 };
 
+static const struct spa_type_info spa_type_prop_int_array[] = {
+    { SPA_PROP_START, SPA_TYPE_Int, SPA_TYPE_INFO_BASE "intArray", NULL, },
+    { 0, 0, NULL, NULL },
+};
+
 static const struct spa_type_info spa_type_prop_channel_map[] = {
     { SPA_PROP_START, SPA_TYPE_Id, SPA_TYPE_INFO_BASE "channelMap", spa_type_audio_channel, },
     { 0, 0, NULL, NULL },
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/param.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/param.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/param.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/param.h	2025-06-27 08:03:14.000000000 +0000
@@ -39,6 +39,7 @@ enum spa_param_type {
     SPA_PARAM_Control,        /**< Control parameter, a SPA_TYPE_Sequence */
     SPA_PARAM_Latency,        /**< latency reporting, a SPA_TYPE_OBJECT_ParamLatency */
     SPA_PARAM_ProcessLatency,    /**< processing latency, a SPA_TYPE_OBJECT_ParamProcessLatency */
+    SPA_PARAM_Tag,            /**< tag reporting, a SPA_TYPE_OBJECT_ParamTag. Since 0.3.79 */
 };
 
 /** information about a parameter */
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/profiler-types.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/profiler-types.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/profiler-types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/profiler-types.h	2025-06-27 08:03:14.000000000 +0000
@@ -26,6 +26,7 @@ static const struct spa_type_info spa_ty
     { SPA_PROFILER_clock, SPA_TYPE_Struct, SPA_TYPE_INFO_PROFILER_BASE "clock", NULL, },
     { SPA_PROFILER_driverBlock, SPA_TYPE_Struct, SPA_TYPE_INFO_PROFILER_BASE "driverBlock", NULL, },
     { SPA_PROFILER_followerBlock, SPA_TYPE_Struct, SPA_TYPE_INFO_PROFILER_BASE "followerBlock", NULL, },
+    { SPA_PROFILER_followerClock, SPA_TYPE_Struct, SPA_TYPE_INFO_PROFILER_BASE "followerClock", NULL, },
     { 0, 0, NULL, NULL },
 };
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/profiler.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/profiler.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/profiler.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/profiler.h	2025-06-27 08:03:14.000000000 +0000
@@ -39,7 +39,10 @@ enum spa_profiler {
                               *      Long : clock duration,
                               *      Long : clock delay,
                               *      Double : clock rate_diff,
-                              *      Long : clock next_nsec)) */
+                              *      Long : clock next_nsec,
+                              *      Int : transport_state,
+                              *      Int : clock cycle,
+                              *      Long : xrun duration)) */
     SPA_PROFILER_driverBlock,            /**< generic driver info block
                               *  (Struct(
                               *      Int : driver_id,
@@ -48,8 +51,9 @@ enum spa_profiler {
                               *      Long : driver signal,
                               *      Long : driver awake,
                               *      Long : driver finish,
-                              *      Int : driver status),
-                              *      Fraction : latency))  */
+                              *      Int : driver status,
+                              *      Fraction : latency,
+                              *      Int : xrun_count))  */
 
     SPA_PROFILER_START_Follower    = 0x20000,    /**< follower related profiler properties */
     SPA_PROFILER_followerBlock,            /**< generic follower info block
@@ -61,8 +65,20 @@ enum spa_profiler {
                               *      Long : awake,
                               *      Long : finish,
                               *      Int : status,
-                              *      Fraction : latency))  */
-
+                              *      Fraction : latency,
+                              *      Int : xrun_count))  */
+    SPA_PROFILER_followerClock,            /**< follower clock information
+                              *  (Struct(
+                              *      Int : clock id,
+                              *      String: clock name,
+                              *      Long : clock nsec,
+                              *      Fraction : clock rate,
+                              *      Long : clock position,
+                              *      Long : clock duration,
+                              *      Long : clock delay,
+                              *      Double : clock rate_diff,
+                              *      Long : clock next_nsec,
+                              *      Long : xrun duration)) */
     SPA_PROFILER_START_CUSTOM    = 0x1000000,
 };
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/props-types.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/props-types.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/props-types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/props-types.h	2025-06-27 08:03:14.000000000 +0000
@@ -64,14 +64,14 @@ static const struct spa_type_info spa_ty
     { SPA_PROP_volumeRampStepTime, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "volumeRampStepTime", NULL },
     { SPA_PROP_volumeRampScale, SPA_TYPE_Id, SPA_TYPE_INFO_PROPS_BASE "volumeRampScale", NULL },
 
-    { SPA_PROP_brightness, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "brightness", NULL },
-    { SPA_PROP_contrast, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "contrast", NULL },
-    { SPA_PROP_saturation, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "saturation", NULL },
+    { SPA_PROP_brightness, SPA_TYPE_Float, SPA_TYPE_INFO_PROPS_BASE "brightness", NULL },
+    { SPA_PROP_contrast, SPA_TYPE_Float, SPA_TYPE_INFO_PROPS_BASE "contrast", NULL },
+    { SPA_PROP_saturation, SPA_TYPE_Float, SPA_TYPE_INFO_PROPS_BASE "saturation", NULL },
     { SPA_PROP_hue, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "hue", NULL },
     { SPA_PROP_gamma, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "gamma", NULL },
     { SPA_PROP_exposure, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "exposure", NULL },
-    { SPA_PROP_gain, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "gain", NULL },
-    { SPA_PROP_sharpness, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "sharpness", NULL },
+    { SPA_PROP_gain, SPA_TYPE_Float, SPA_TYPE_INFO_PROPS_BASE "gain", NULL },
+    { SPA_PROP_sharpness, SPA_TYPE_Float, SPA_TYPE_INFO_PROPS_BASE "sharpness", NULL },
 
     { SPA_PROP_params, SPA_TYPE_Struct, SPA_TYPE_INFO_PROPS_BASE "params", NULL },
     { 0, 0, NULL, NULL },
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/props.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/props.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/props.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/props.h	2025-06-27 08:03:14.000000000 +0000
@@ -59,24 +59,31 @@ enum spa_prop {
     SPA_PROP_START_Audio    = 0x10000,    /**< audio related properties */
     SPA_PROP_waveType,
     SPA_PROP_frequency,
-    SPA_PROP_volume,                /**< a volume (Float), 0.0 silence, 1.0 normal */
+    SPA_PROP_volume,            /**< a volume (Float), 0.0 silence, 1.0 no attenutation */
     SPA_PROP_mute,                /**< mute (Bool) */
     SPA_PROP_patternType,
     SPA_PROP_ditherType,
     SPA_PROP_truncate,
-    SPA_PROP_channelVolumes,        /**< a volume array, one volume per
-                          *  channel (Array of Float) */
+    SPA_PROP_channelVolumes,        /**< a volume array, one (linear) volume per channel
+                          * (Array of Float). 0.0 is silence, 1.0 is
+                          *  without attenuation. This is the effective
+                          *  volume that is applied. It can result
+                          *  in a hardware volume and software volume
+                          *  (see softVolumes) */
     SPA_PROP_volumeBase,            /**< a volume base (Float) */
     SPA_PROP_volumeStep,            /**< a volume step (Float) */
     SPA_PROP_channelMap,            /**< a channelmap array
                           * (Array (Id enum spa_audio_channel)) */
     SPA_PROP_monitorMute,            /**< mute (Bool) */
-    SPA_PROP_monitorVolumes,        /**< a volume array, one volume per
+    SPA_PROP_monitorVolumes,        /**< a volume array, one (linear) volume per
                           *  channel (Array of Float) */
     SPA_PROP_latencyOffsetNsec,        /**< delay adjustment */
-    SPA_PROP_softMute,            /**< mute (Bool) */
-    SPA_PROP_softVolumes,            /**< a volume array, one volume per
-                          *  channel (Array of Float) */
+    SPA_PROP_softMute,            /**< mute (Bool) applied in software */
+    SPA_PROP_softVolumes,            /**< a volume array, one (linear) volume per channel
+                          * (Array of Float). 0.0 is silence, 1.0 is without
+                          * attenuation. This is the volume applied in
+                          * software, there might be a part applied in
+                          * hardware. */
 
     SPA_PROP_iec958Codecs,            /**< enabled IEC958 (S/PDIF) codecs,
                           *  (Array (Id enum spa_audio_iec958_codec) */
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/route-types.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/route-types.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/route-types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/route-types.h	2025-06-27 08:03:14.000000000 +0000
@@ -32,9 +32,9 @@ static const struct spa_type_info spa_ty
     { SPA_PARAM_ROUTE_priority, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_ROUTE_BASE "priority", NULL, },
     { SPA_PARAM_ROUTE_available, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_ROUTE_BASE "available", spa_type_param_availability, },
     { SPA_PARAM_ROUTE_info, SPA_TYPE_Struct, SPA_TYPE_INFO_PARAM_ROUTE_BASE "info", NULL, },
-    { SPA_PARAM_ROUTE_profiles, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_ROUTE_BASE "profiles", NULL, },
+    { SPA_PARAM_ROUTE_profiles, SPA_TYPE_Array, SPA_TYPE_INFO_PARAM_ROUTE_BASE "profiles", spa_type_prop_int_array, },
     { SPA_PARAM_ROUTE_props, SPA_TYPE_OBJECT_Props, SPA_TYPE_INFO_PARAM_ROUTE_BASE "props", NULL, },
-    { SPA_PARAM_ROUTE_devices, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_ROUTE_BASE "devices", NULL, },
+    { SPA_PARAM_ROUTE_devices, SPA_TYPE_Array, SPA_TYPE_INFO_PARAM_ROUTE_BASE "devices", spa_type_prop_int_array, },
     { SPA_PARAM_ROUTE_profile, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_ROUTE_BASE "profile", NULL, },
     { SPA_PARAM_ROUTE_save, SPA_TYPE_Bool, SPA_TYPE_INFO_PARAM_ROUTE_BASE "save", NULL, },
     { 0, 0, NULL, NULL },
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/tag-types.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/tag-types.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/tag-types.h	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/tag-types.h	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,39 @@
+/* Simple Plugin API */
+/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
+/* SPDX-License-Identifier: MIT */
+
+#ifndef SPA_PARAM_TAG_TYPES_H
+#define SPA_PARAM_TAG_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \addtogroup spa_param
+ * \{
+ */
+
+#include <spa/utils/enum-types.h>
+#include <spa/param/param-types.h>
+#include <spa/param/tag.h>
+
+#define SPA_TYPE_INFO_PARAM_Tag        SPA_TYPE_INFO_PARAM_BASE "Tag"
+#define SPA_TYPE_INFO_PARAM_TAG_BASE    SPA_TYPE_INFO_PARAM_Tag ":"
+
+static const struct spa_type_info spa_type_param_tag[] = {
+    { SPA_PARAM_TAG_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_TAG_BASE, spa_type_param, },
+    { SPA_PARAM_TAG_direction, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_TAG_BASE "direction", spa_type_direction, },
+    { SPA_PARAM_TAG_info, SPA_TYPE_Struct, SPA_TYPE_INFO_PARAM_TAG_BASE "info", NULL, },
+    { 0, 0, NULL, NULL },
+};
+
+/**
+ * \}
+ */
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif /* SPA_PARAM_TAG_TYPES_H */
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/tag.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/tag.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/tag.h	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/tag.h	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,46 @@
+/* Simple Plugin API */
+/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */
+/* SPDX-License-Identifier: MIT */
+
+#ifndef SPA_PARAM_TAG_H
+#define SPA_PARAM_TAG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \addtogroup spa_param
+ * \{
+ */
+
+#include <spa/param/param.h>
+
+/** properties for SPA_TYPE_OBJECT_ParamTag */
+enum spa_param_tag {
+    SPA_PARAM_TAG_START,
+    SPA_PARAM_TAG_direction,        /**< direction, input/output (Id enum spa_direction) */
+    SPA_PARAM_TAG_info,            /**< Struct(
+                          *      Int: n_items
+                          *      (String: key
+                          *       String: value)*
+                          *  ) */
+};
+
+/** helper structure for managing tag objects */
+struct spa_tag_info {
+    enum spa_direction direction;
+    const struct spa_pod *info;
+};
+
+#define SPA_TAG_INFO(dir,...) ((struct spa_tag_info) { .direction = (dir), ## __VA_ARGS__ })
+
+/**
+ * \}
+ */
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif /* SPA_PARAM_TAG_H */
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/type-info.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/type-info.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/type-info.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/type-info.h	2025-06-27 08:03:14.000000000 +0000
@@ -14,5 +14,6 @@
 #include <spa/param/profiler-types.h>
 #include <spa/param/profile-types.h>
 #include <spa/param/route-types.h>
+#include <spa/param/tag-types.h>
 
 #endif /* SPA_PARAM_TYPE_INFO_H */
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/dsp-utils.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/dsp-utils.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/dsp-utils.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/dsp-utils.h	2025-06-27 08:03:14.000000000 +0000
@@ -18,13 +18,24 @@ extern "C" {
 #include <spa/pod/builder.h>
 #include <spa/param/video/dsp.h>
 
-static inline int
+#ifndef SPA_API_VIDEO_DSP_UTILS
+ #ifdef SPA_API_IMPL
+  #define SPA_API_VIDEO_DSP_UTILS SPA_API_IMPL
+ #else
+  #define SPA_API_VIDEO_DSP_UTILS static inline
+ #endif
+#endif
+
+SPA_API_VIDEO_DSP_UTILS int
 spa_format_video_dsp_parse(const struct spa_pod *format,
                struct spa_video_info_dsp *info)
 {
     info->flags = SPA_VIDEO_FLAG_NONE;
-    if (spa_pod_find_prop (format, NULL, SPA_FORMAT_VIDEO_modifier)) {
+    const struct spa_pod_prop *mod_prop;
+    if ((mod_prop = spa_pod_find_prop (format, NULL, SPA_FORMAT_VIDEO_modifier)) != NULL) {
         info->flags |= SPA_VIDEO_FLAG_MODIFIER;
+        if ((mod_prop->flags & SPA_POD_PROP_FLAG_DONT_FIXATE) == SPA_POD_PROP_FLAG_DONT_FIXATE)
+            info->flags |= SPA_VIDEO_FLAG_MODIFIER_FIXATION_REQUIRED;
     }
 
     return spa_pod_parse_object(format,
@@ -33,9 +44,9 @@ spa_format_video_dsp_parse(const struct
         SPA_FORMAT_VIDEO_modifier,        SPA_POD_OPT_Long(&info->modifier));
 }
 
-static inline struct spa_pod *
+SPA_API_VIDEO_DSP_UTILS struct spa_pod *
 spa_format_video_dsp_build(struct spa_pod_builder *builder, uint32_t id,
-               struct spa_video_info_dsp *info)
+               const struct spa_video_info_dsp *info)
 {
     struct spa_pod_frame f;
     spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id);
@@ -46,9 +57,11 @@ spa_format_video_dsp_build(struct spa_po
     if (info->format != SPA_VIDEO_FORMAT_UNKNOWN)
         spa_pod_builder_add(builder,
             SPA_FORMAT_VIDEO_format,    SPA_POD_Id(info->format), 0);
-    if (info->modifier != 0 || info->flags & SPA_VIDEO_FLAG_MODIFIER)
-        spa_pod_builder_add(builder,
-            SPA_FORMAT_VIDEO_modifier,    SPA_POD_Long(info->modifier), 0);
+    if (info->modifier != 0 || info->flags & SPA_VIDEO_FLAG_MODIFIER) {
+        spa_pod_builder_prop(builder,
+            SPA_FORMAT_VIDEO_modifier,    SPA_POD_PROP_FLAG_MANDATORY);
+        spa_pod_builder_long(builder,           info->modifier);
+    }
     return (struct spa_pod*)spa_pod_builder_pop(builder, &f);
 }
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/format-utils.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/format-utils.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/format-utils.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/format-utils.h	2025-06-27 08:03:14.000000000 +0000
@@ -16,7 +16,15 @@ extern "C" {
 #include <spa/param/video/h264-utils.h>
 #include <spa/param/video/mjpg-utils.h>
 
-static inline int
+#ifndef SPA_API_VIDEO_FORMAT_UTILS
+ #ifdef SPA_API_IMPL
+  #define SPA_API_VIDEO_FORMAT_UTILS SPA_API_IMPL
+ #else
+  #define SPA_API_VIDEO_FORMAT_UTILS static inline
+ #endif
+#endif
+
+SPA_API_VIDEO_FORMAT_UTILS int
 spa_format_video_parse(const struct spa_pod *format, struct spa_video_info *info)
 {
     int res;
@@ -40,8 +48,9 @@ spa_format_video_parse(const struct spa_
     return -ENOTSUP;
 }
 
-static inline struct spa_pod *
-spa_format_video_build(struct spa_pod_builder *builder, uint32_t id, struct spa_video_info *info)
+SPA_API_VIDEO_FORMAT_UTILS struct spa_pod *
+spa_format_video_build(struct spa_pod_builder *builder, uint32_t id,
+               const struct spa_video_info *info)
 {
     switch (info->media_subtype) {
     case SPA_MEDIA_SUBTYPE_raw:
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/h264-utils.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/h264-utils.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/h264-utils.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/h264-utils.h	2025-06-27 08:03:14.000000000 +0000
@@ -18,7 +18,15 @@ extern "C" {
 #include <spa/pod/builder.h>
 #include <spa/param/video/h264.h>
 
-static inline int
+#ifndef SPA_API_VIDEO_H264_UTILS
+ #ifdef SPA_API_IMPL
+  #define SPA_API_VIDEO_H264_UTILS SPA_API_IMPL
+ #else
+  #define SPA_API_VIDEO_H264_UTILS static inline
+ #endif
+#endif
+
+SPA_API_VIDEO_H264_UTILS int
 spa_format_video_h264_parse(const struct spa_pod *format,
                 struct spa_video_info_h264 *info)
 {
@@ -31,9 +39,9 @@ spa_format_video_h264_parse(const struct
             SPA_FORMAT_VIDEO_H264_alignment,    SPA_POD_OPT_Id(&info->alignment));
 }
 
-static inline struct spa_pod *
+SPA_API_VIDEO_H264_UTILS struct spa_pod *
 spa_format_video_h264_build(struct spa_pod_builder *builder, uint32_t id,
-               struct spa_video_info_h264 *info)
+                const struct spa_video_info_h264 *info)
 {
     struct spa_pod_frame f;
     spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id);
@@ -49,7 +57,7 @@ spa_format_video_h264_build(struct spa_p
             SPA_FORMAT_VIDEO_framerate,    SPA_POD_Fraction(&info->framerate), 0);
     if (info->max_framerate.denom != 0)
         spa_pod_builder_add(builder,
-            SPA_FORMAT_VIDEO_maxFramerate,    SPA_POD_Fraction(info->max_framerate), 0);
+            SPA_FORMAT_VIDEO_maxFramerate,    SPA_POD_Fraction(&info->max_framerate), 0);
     if (info->stream_format != 0)
         spa_pod_builder_add(builder,
             SPA_FORMAT_VIDEO_H264_streamFormat, SPA_POD_Id(info->stream_format), 0);
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/mjpg-utils.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/mjpg-utils.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/mjpg-utils.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/mjpg-utils.h	2025-06-27 08:03:14.000000000 +0000
@@ -18,7 +18,15 @@ extern "C" {
 #include <spa/pod/builder.h>
 #include <spa/param/video/mjpg.h>
 
-static inline int
+#ifndef SPA_API_VIDEO_MJPG_UTILS
+ #ifdef SPA_API_IMPL
+  #define SPA_API_VIDEO_MJPG_UTILS SPA_API_IMPL
+ #else
+  #define SPA_API_VIDEO_MJPG_UTILS static inline
+ #endif
+#endif
+
+SPA_API_VIDEO_MJPG_UTILS int
 spa_format_video_mjpg_parse(const struct spa_pod *format,
                 struct spa_video_info_mjpg *info)
 {
@@ -29,9 +37,9 @@ spa_format_video_mjpg_parse(const struct
             SPA_FORMAT_VIDEO_maxFramerate,    SPA_POD_OPT_Fraction(&info->max_framerate));
 }
 
-static inline struct spa_pod *
+SPA_API_VIDEO_MJPG_UTILS struct spa_pod *
 spa_format_video_mjpg_build(struct spa_pod_builder *builder, uint32_t id,
-               struct spa_video_info_mjpg *info)
+                const struct spa_video_info_mjpg *info)
 {
     struct spa_pod_frame f;
     spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id);
@@ -47,7 +55,7 @@ spa_format_video_mjpg_build(struct spa_p
             SPA_FORMAT_VIDEO_framerate,    SPA_POD_Fraction(&info->framerate), 0);
     if (info->max_framerate.denom != 0)
         spa_pod_builder_add(builder,
-            SPA_FORMAT_VIDEO_maxFramerate,    SPA_POD_Fraction(info->max_framerate), 0);
+            SPA_FORMAT_VIDEO_maxFramerate,    SPA_POD_Fraction(&info->max_framerate), 0);
     return (struct spa_pod*)spa_pod_builder_pop(builder, &f);
 }
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/multiview.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/multiview.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/multiview.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/multiview.h	2025-06-27 08:03:14.000000000 +0000
@@ -59,12 +59,11 @@ enum spa_video_multiview_mode {
                                 *   sequence. This method only applies to
                                 *   raw video buffers at the moment.
                                 *   Specific view identification is via
-                                *   \ref spa_video_multiview_meta on raw
-                                *   video buffers. */
+                                *   metadata on raw video buffers. */
     SPA_VIDEO_MULTIVIEW_MODE_SEPARATED,        /**< Multiple views are provided as separate
                              *   \ref spa_data framebuffers attached
                              *   to each \ref spa_buffer, described
-                             *   by the \ref spa_video_multiview_meta */
+                             *   by the metadata */
     /* future expansion for annotated modes */
 };
 
@@ -97,9 +96,7 @@ enum spa_video_multiview_flags {
     SPA_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO = (1 << 15),    /**< The video stream contains both
                                  *   mono and multiview portions,
                                  *   signalled on each buffer by the
-                                 *   absence or presence of the
-                                 *   \ref SPA_VIDEO_BUFFER_FLAG_MULTIPLE_VIEW
-                                 *   buffer flag. */
+                                 *   absence or presence of a buffer flag. */
 };
 
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/raw-types.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/raw-types.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/raw-types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/raw-types.h	2025-06-27 08:03:14.000000000 +0000
@@ -16,11 +16,20 @@ extern "C" {
 #include <spa/utils/type.h>
 #include <spa/param/video/raw.h>
 
+#ifndef SPA_API_VIDEO_RAW_TYPES
+ #ifdef SPA_API_IMPL
+  #define SPA_API_VIDEO_RAW_TYPES SPA_API_IMPL
+ #else
+  #define SPA_API_VIDEO_RAW_TYPES static inline
+ #endif
+#endif
+
 #define SPA_TYPE_INFO_VideoFormat        SPA_TYPE_INFO_ENUM_BASE "VideoFormat"
 #define SPA_TYPE_INFO_VIDEO_FORMAT_BASE        SPA_TYPE_INFO_VideoFormat ":"
 
 static const struct spa_type_info spa_type_video_format[] = {
-    { SPA_VIDEO_FORMAT_ENCODED,    SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "encoded", NULL },
+    { SPA_VIDEO_FORMAT_UNKNOWN,    SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "UNKNOWN", NULL },
+    { SPA_VIDEO_FORMAT_ENCODED,    SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "ENCODED", NULL },
     { SPA_VIDEO_FORMAT_I420,    SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I420", NULL },
     { SPA_VIDEO_FORMAT_YV12,    SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "YV12", NULL },
     { SPA_VIDEO_FORMAT_YUY2,    SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "YUY2", NULL },
@@ -110,6 +119,15 @@ static const struct spa_type_info spa_ty
     { 0, 0, NULL, NULL },
 };
 
+SPA_API_VIDEO_RAW_TYPES uint32_t spa_type_video_format_from_short_name(const char *name)
+{
+    return spa_type_from_short_name(name, spa_type_video_format, SPA_VIDEO_FORMAT_UNKNOWN);
+}
+SPA_API_VIDEO_RAW_TYPES const char * spa_type_video_format_to_short_name(uint32_t type)
+{
+    return spa_type_to_short_name(type, spa_type_video_format, "UNKNOWN");
+}
+
 #define SPA_TYPE_INFO_VideoFlags    SPA_TYPE_INFO_FLAGS_BASE "VideoFlags"
 #define SPA_TYPE_INFO_VIDEO_FLAGS_BASE    SPA_TYPE_INFO_VideoFlags ":"
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/raw-utils.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/raw-utils.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/raw-utils.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/raw-utils.h	2025-06-27 08:03:14.000000000 +0000
@@ -18,13 +18,24 @@ extern "C" {
 #include <spa/pod/builder.h>
 #include <spa/param/video/raw.h>
 
-static inline int
+#ifndef SPA_API_VIDEO_RAW_UTILS
+ #ifdef SPA_API_IMPL
+  #define SPA_API_VIDEO_RAW_UTILS SPA_API_IMPL
+ #else
+  #define SPA_API_VIDEO_RAW_UTILS static inline
+ #endif
+#endif
+
+SPA_API_VIDEO_RAW_UTILS int
 spa_format_video_raw_parse(const struct spa_pod *format,
                struct spa_video_info_raw *info)
 {
     info->flags = SPA_VIDEO_FLAG_NONE;
-    if (spa_pod_find_prop (format, NULL, SPA_FORMAT_VIDEO_modifier)) {
+    const struct spa_pod_prop *mod_prop;
+    if ((mod_prop = spa_pod_find_prop (format, NULL, SPA_FORMAT_VIDEO_modifier)) != NULL) {
         info->flags |= SPA_VIDEO_FLAG_MODIFIER;
+        if ((mod_prop->flags & SPA_POD_PROP_FLAG_DONT_FIXATE) == SPA_POD_PROP_FLAG_DONT_FIXATE)
+            info->flags |= SPA_VIDEO_FLAG_MODIFIER_FIXATION_REQUIRED;
     }
 
     return spa_pod_parse_object(format,
@@ -46,9 +57,9 @@ spa_format_video_raw_parse(const struct
         SPA_FORMAT_VIDEO_colorPrimaries,    SPA_POD_OPT_Id(&info->color_primaries));
 }
 
-static inline struct spa_pod *
+SPA_API_VIDEO_RAW_UTILS struct spa_pod *
 spa_format_video_raw_build(struct spa_pod_builder *builder, uint32_t id,
-               struct spa_video_info_raw *info)
+               const struct spa_video_info_raw *info)
 {
     struct spa_pod_frame f;
     spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id);
@@ -65,12 +76,14 @@ spa_format_video_raw_build(struct spa_po
     if (info->framerate.denom != 0)
         spa_pod_builder_add(builder,
             SPA_FORMAT_VIDEO_framerate,    SPA_POD_Fraction(&info->framerate), 0);
-    if (info->modifier != 0 || info->flags & SPA_VIDEO_FLAG_MODIFIER)
-        spa_pod_builder_add(builder,
-            SPA_FORMAT_VIDEO_modifier,    SPA_POD_Long(info->modifier), 0);
+    if (info->modifier != 0 || info->flags & SPA_VIDEO_FLAG_MODIFIER) {
+        spa_pod_builder_prop(builder,
+            SPA_FORMAT_VIDEO_modifier,    SPA_POD_PROP_FLAG_MANDATORY);
+        spa_pod_builder_long(builder,           info->modifier);
+    }
     if (info->max_framerate.denom != 0)
         spa_pod_builder_add(builder,
-            SPA_FORMAT_VIDEO_maxFramerate,    SPA_POD_Fraction(info->max_framerate), 0);
+            SPA_FORMAT_VIDEO_maxFramerate,    SPA_POD_Fraction(&info->max_framerate), 0);
     if (info->views != 0)
         spa_pod_builder_add(builder,
             SPA_FORMAT_VIDEO_views,        SPA_POD_Int(info->views), 0);
@@ -79,7 +92,7 @@ spa_format_video_raw_build(struct spa_po
             SPA_FORMAT_VIDEO_interlaceMode,    SPA_POD_Id(info->interlace_mode), 0);
     if (info->pixel_aspect_ratio.denom != 0)
         spa_pod_builder_add(builder,
-            SPA_FORMAT_VIDEO_pixelAspectRatio,SPA_POD_Fraction(info->pixel_aspect_ratio), 0);
+            SPA_FORMAT_VIDEO_pixelAspectRatio, SPA_POD_Fraction(&info->pixel_aspect_ratio), 0);
     if (info->multiview_mode != 0)
         spa_pod_builder_add(builder,
             SPA_FORMAT_VIDEO_multiviewMode,    SPA_POD_Id(info->multiview_mode), 0);
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/raw.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/raw.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/raw.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/param/video/raw.h	2025-06-27 08:03:14.000000000 +0000
@@ -134,11 +134,12 @@ enum spa_video_format {
  * Extra video flags
  */
 enum spa_video_flags {
-    SPA_VIDEO_FLAG_NONE = 0,            /**< no flags */
-    SPA_VIDEO_FLAG_VARIABLE_FPS = (1 << 0),        /**< a variable fps is selected, fps_n and fps_d
-                             *   denote the maximum fps of the video */
-    SPA_VIDEO_FLAG_PREMULTIPLIED_ALPHA = (1 << 1),  /**< Each color has been scaled by the alpha value. */
-    SPA_VIDEO_FLAG_MODIFIER = (1 << 2),        /**< use the format modifier */
+    SPA_VIDEO_FLAG_NONE = 0,                /**< no flags */
+    SPA_VIDEO_FLAG_VARIABLE_FPS = (1 << 0),            /**< a variable fps is selected, fps_n and fps_d
+                                 *   denote the maximum fps of the video */
+    SPA_VIDEO_FLAG_PREMULTIPLIED_ALPHA = (1 << 1),        /**< Each color has been scaled by the alpha value. */
+    SPA_VIDEO_FLAG_MODIFIER = (1 << 2),            /**< use the format modifier */
+    SPA_VIDEO_FLAG_MODIFIER_FIXATION_REQUIRED = (1 << 3),    /**< format modifier was not fixated yet */
 };
 
 /**
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/builder.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/builder.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/builder.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/builder.h	2025-06-27 08:03:14.000000000 +0000
@@ -24,6 +24,14 @@ extern "C" {
 #include <spa/pod/iter.h>
 #include <spa/pod/vararg.h>
 
+#ifndef SPA_API_POD_BUILDER
+ #ifdef SPA_API_IMPL
+  #define SPA_API_POD_BUILDER SPA_API_IMPL
+ #else
+  #define SPA_API_POD_BUILDER static inline
+ #endif
+#endif
+
 struct spa_pod_builder_state {
     uint32_t offset;
 #define SPA_POD_BUILDER_FLAG_BODY    (1<<0)
@@ -49,22 +57,22 @@ struct spa_pod_builder {
     struct spa_callbacks callbacks;
 };
 
-#define SPA_POD_BUILDER_INIT(buffer,size)  ((struct spa_pod_builder){ (buffer), (size), 0, {}, {} })
+#define SPA_POD_BUILDER_INIT(buffer,size)  ((struct spa_pod_builder){ (buffer), (size), 0, {0,0,NULL},{NULL,NULL}})
 
-static inline void
+SPA_API_POD_BUILDER void
 spa_pod_builder_get_state(struct spa_pod_builder *builder, struct spa_pod_builder_state *state)
 {
     *state = builder->state;
 }
 
-static inline void
+SPA_API_POD_BUILDER void
 spa_pod_builder_set_callbacks(struct spa_pod_builder *builder,
         const struct spa_pod_builder_callbacks *callbacks, void *data)
 {
     builder->callbacks = SPA_CALLBACKS_INIT(callbacks, data);
 }
 
-static inline void
+SPA_API_POD_BUILDER void
 spa_pod_builder_reset(struct spa_pod_builder *builder, struct spa_pod_builder_state *state)
 {
     struct spa_pod_frame *f;
@@ -74,12 +82,12 @@ spa_pod_builder_reset(struct spa_pod_bui
         f->pod.size -= size;
 }
 
-static inline void spa_pod_builder_init(struct spa_pod_builder *builder, void *data, uint32_t size)
+SPA_API_POD_BUILDER void spa_pod_builder_init(struct spa_pod_builder *builder, void *data, uint32_t size)
 {
     *builder = SPA_POD_BUILDER_INIT(data, size);
 }
 
-static inline struct spa_pod *
+SPA_API_POD_BUILDER struct spa_pod *
 spa_pod_builder_deref(struct spa_pod_builder *builder, uint32_t offset)
 {
     uint32_t size = builder->size;
@@ -91,7 +99,7 @@ spa_pod_builder_deref(struct spa_pod_bui
     return NULL;
 }
 
-static inline struct spa_pod *
+SPA_API_POD_BUILDER struct spa_pod *
 spa_pod_builder_frame(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
 {
     if (frame->offset + SPA_POD_SIZE(&frame->pod) <= builder->size)
@@ -99,7 +107,7 @@ spa_pod_builder_frame(struct spa_pod_bui
     return NULL;
 }
 
-static inline void
+SPA_API_POD_BUILDER void
 spa_pod_builder_push(struct spa_pod_builder *builder,
              struct spa_pod_frame *frame,
              const struct spa_pod *pod,
@@ -115,7 +123,7 @@ spa_pod_builder_push(struct spa_pod_buil
         builder->state.flags = SPA_POD_BUILDER_FLAG_FIRST | SPA_POD_BUILDER_FLAG_BODY;
 }
 
-static inline int spa_pod_builder_raw(struct spa_pod_builder *builder, const void *data, uint32_t size)
+SPA_API_POD_BUILDER int spa_pod_builder_raw(struct spa_pod_builder *builder, const void *data, uint32_t size)
 {
     int res = 0;
     struct spa_pod_frame *f;
@@ -139,14 +147,14 @@ static inline int spa_pod_builder_raw(st
     return res;
 }
 
-static inline int spa_pod_builder_pad(struct spa_pod_builder *builder, uint32_t size)
+SPA_API_POD_BUILDER int spa_pod_builder_pad(struct spa_pod_builder *builder, uint32_t size)
 {
     uint64_t zeroes = 0;
     size = SPA_ROUND_UP_N(size, 8) - size;
     return size ? spa_pod_builder_raw(builder, &zeroes, size) : 0;
 }
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_raw_padded(struct spa_pod_builder *builder, const void *data, uint32_t size)
 {
     int r, res = spa_pod_builder_raw(builder, data, size);
@@ -155,7 +163,7 @@ spa_pod_builder_raw_padded(struct spa_po
     return res;
 }
 
-static inline void *spa_pod_builder_pop(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
+SPA_API_POD_BUILDER void *spa_pod_builder_pop(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
 {
     struct spa_pod *pod;
 
@@ -172,7 +180,7 @@ static inline void *spa_pod_builder_pop(
     return pod;
 }
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_primitive(struct spa_pod_builder *builder, const struct spa_pod *p)
 {
     const void *data;
@@ -198,13 +206,13 @@ spa_pod_builder_primitive(struct spa_pod
 
 #define SPA_POD_INIT_None() SPA_POD_INIT(0, SPA_TYPE_None)
 
-static inline int spa_pod_builder_none(struct spa_pod_builder *builder)
+SPA_API_POD_BUILDER int spa_pod_builder_none(struct spa_pod_builder *builder)
 {
     const struct spa_pod p = SPA_POD_INIT_None();
     return spa_pod_builder_primitive(builder, &p);
 }
 
-static inline int spa_pod_builder_child(struct spa_pod_builder *builder, uint32_t size, uint32_t type)
+SPA_API_POD_BUILDER int spa_pod_builder_child(struct spa_pod_builder *builder, uint32_t size, uint32_t type)
 {
     const struct spa_pod p = SPA_POD_INIT(size,type);
     SPA_FLAG_CLEAR(builder->state.flags, SPA_POD_BUILDER_FLAG_FIRST);
@@ -213,7 +221,7 @@ static inline int spa_pod_builder_child(
 
 #define SPA_POD_INIT_Bool(val) ((struct spa_pod_bool){ { sizeof(uint32_t), SPA_TYPE_Bool }, (val) ? 1 : 0, 0 })
 
-static inline int spa_pod_builder_bool(struct spa_pod_builder *builder, bool val)
+SPA_API_POD_BUILDER int spa_pod_builder_bool(struct spa_pod_builder *builder, bool val)
 {
     const struct spa_pod_bool p = SPA_POD_INIT_Bool(val);
     return spa_pod_builder_primitive(builder, &p.pod);
@@ -221,7 +229,7 @@ static inline int spa_pod_builder_bool(s
 
 #define SPA_POD_INIT_Id(val) ((struct spa_pod_id){ { sizeof(uint32_t), SPA_TYPE_Id }, (val), 0 })
 
-static inline int spa_pod_builder_id(struct spa_pod_builder *builder, uint32_t val)
+SPA_API_POD_BUILDER int spa_pod_builder_id(struct spa_pod_builder *builder, uint32_t val)
 {
     const struct spa_pod_id p = SPA_POD_INIT_Id(val);
     return spa_pod_builder_primitive(builder, &p.pod);
@@ -229,7 +237,7 @@ static inline int spa_pod_builder_id(str
 
 #define SPA_POD_INIT_Int(val) ((struct spa_pod_int){ { sizeof(int32_t), SPA_TYPE_Int }, (val), 0 })
 
-static inline int spa_pod_builder_int(struct spa_pod_builder *builder, int32_t val)
+SPA_API_POD_BUILDER int spa_pod_builder_int(struct spa_pod_builder *builder, int32_t val)
 {
     const struct spa_pod_int p = SPA_POD_INIT_Int(val);
     return spa_pod_builder_primitive(builder, &p.pod);
@@ -237,7 +245,7 @@ static inline int spa_pod_builder_int(st
 
 #define SPA_POD_INIT_Long(val) ((struct spa_pod_long){ { sizeof(int64_t), SPA_TYPE_Long }, (val) })
 
-static inline int spa_pod_builder_long(struct spa_pod_builder *builder, int64_t val)
+SPA_API_POD_BUILDER int spa_pod_builder_long(struct spa_pod_builder *builder, int64_t val)
 {
     const struct spa_pod_long p = SPA_POD_INIT_Long(val);
     return spa_pod_builder_primitive(builder, &p.pod);
@@ -245,7 +253,7 @@ static inline int spa_pod_builder_long(s
 
 #define SPA_POD_INIT_Float(val) ((struct spa_pod_float){ { sizeof(float), SPA_TYPE_Float }, (val), 0 })
 
-static inline int spa_pod_builder_float(struct spa_pod_builder *builder, float val)
+SPA_API_POD_BUILDER int spa_pod_builder_float(struct spa_pod_builder *builder, float val)
 {
     const struct spa_pod_float p = SPA_POD_INIT_Float(val);
     return spa_pod_builder_primitive(builder, &p.pod);
@@ -253,7 +261,7 @@ static inline int spa_pod_builder_float(
 
 #define SPA_POD_INIT_Double(val) ((struct spa_pod_double){ { sizeof(double), SPA_TYPE_Double }, (val) })
 
-static inline int spa_pod_builder_double(struct spa_pod_builder *builder, double val)
+SPA_API_POD_BUILDER int spa_pod_builder_double(struct spa_pod_builder *builder, double val)
 {
     const struct spa_pod_double p = SPA_POD_INIT_Double(val);
     return spa_pod_builder_primitive(builder, &p.pod);
@@ -261,7 +269,7 @@ static inline int spa_pod_builder_double
 
 #define SPA_POD_INIT_String(len) ((struct spa_pod_string){ { (len), SPA_TYPE_String } })
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_write_string(struct spa_pod_builder *builder, const char *str, uint32_t len)
 {
     int r, res;
@@ -273,7 +281,7 @@ spa_pod_builder_write_string(struct spa_
     return res;
 }
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_string_len(struct spa_pod_builder *builder, const char *str, uint32_t len)
 {
     const struct spa_pod_string p = SPA_POD_INIT_String(len+1);
@@ -283,7 +291,7 @@ spa_pod_builder_string_len(struct spa_po
     return res;
 }
 
-static inline int spa_pod_builder_string(struct spa_pod_builder *builder, const char *str)
+SPA_API_POD_BUILDER int spa_pod_builder_string(struct spa_pod_builder *builder, const char *str)
 {
     uint32_t len = str ? strlen(str) : 0;
     return spa_pod_builder_string_len(builder, str ? str : "", len);
@@ -291,7 +299,7 @@ static inline int spa_pod_builder_string
 
 #define SPA_POD_INIT_Bytes(len) ((struct spa_pod_bytes){ { (len), SPA_TYPE_Bytes } })
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_bytes(struct spa_pod_builder *builder, const void *bytes, uint32_t len)
 {
     const struct spa_pod_bytes p = SPA_POD_INIT_Bytes(len);
@@ -300,7 +308,7 @@ spa_pod_builder_bytes(struct spa_pod_bui
         res = r;
     return res;
 }
-static inline void *
+SPA_API_POD_BUILDER void *
 spa_pod_builder_reserve_bytes(struct spa_pod_builder *builder, uint32_t len)
 {
     uint32_t offset = builder->state.offset;
@@ -311,7 +319,7 @@ spa_pod_builder_reserve_bytes(struct spa
 
 #define SPA_POD_INIT_Pointer(type,value) ((struct spa_pod_pointer){ { sizeof(struct spa_pod_pointer_body), SPA_TYPE_Pointer }, { (type), 0, (value) } })
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_pointer(struct spa_pod_builder *builder, uint32_t type, const void *val)
 {
     const struct spa_pod_pointer p = SPA_POD_INIT_Pointer(type, val);
@@ -320,7 +328,7 @@ spa_pod_builder_pointer(struct spa_pod_b
 
 #define SPA_POD_INIT_Fd(fd) ((struct spa_pod_fd){ { sizeof(int64_t), SPA_TYPE_Fd }, (fd) })
 
-static inline int spa_pod_builder_fd(struct spa_pod_builder *builder, int64_t fd)
+SPA_API_POD_BUILDER int spa_pod_builder_fd(struct spa_pod_builder *builder, int64_t fd)
 {
     const struct spa_pod_fd p = SPA_POD_INIT_Fd(fd);
     return spa_pod_builder_primitive(builder, &p.pod);
@@ -328,7 +336,7 @@ static inline int spa_pod_builder_fd(str
 
 #define SPA_POD_INIT_Rectangle(val) ((struct spa_pod_rectangle){ { sizeof(struct spa_rectangle), SPA_TYPE_Rectangle }, (val) })
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_rectangle(struct spa_pod_builder *builder, uint32_t width, uint32_t height)
 {
     const struct spa_pod_rectangle p = SPA_POD_INIT_Rectangle(SPA_RECTANGLE(width, height));
@@ -337,14 +345,14 @@ spa_pod_builder_rectangle(struct spa_pod
 
 #define SPA_POD_INIT_Fraction(val) ((struct spa_pod_fraction){ { sizeof(struct spa_fraction), SPA_TYPE_Fraction }, (val) })
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_fraction(struct spa_pod_builder *builder, uint32_t num, uint32_t denom)
 {
     const struct spa_pod_fraction p = SPA_POD_INIT_Fraction(SPA_FRACTION(num, denom));
     return spa_pod_builder_primitive(builder, &p.pod);
 }
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_push_array(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
 {
     const struct spa_pod_array p =
@@ -356,7 +364,7 @@ spa_pod_builder_push_array(struct spa_po
     return res;
 }
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_array(struct spa_pod_builder *builder,
               uint32_t child_size, uint32_t child_type, uint32_t n_elems, const void *elems)
 {
@@ -378,7 +386,7 @@ spa_pod_builder_array(struct spa_pod_bui
     { { { (n_vals) * sizeof(ctype) + sizeof(struct spa_pod_choice_body), SPA_TYPE_Choice },    \
         { (type), 0, { sizeof(ctype), (child_type) } } }, { __VA_ARGS__ } })
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_push_choice(struct spa_pod_builder *builder, struct spa_pod_frame *frame,
         uint32_t type, uint32_t flags)
 {
@@ -393,7 +401,7 @@ spa_pod_builder_push_choice(struct spa_p
 
 #define SPA_POD_INIT_Struct(size) ((struct spa_pod_struct){ { (size), SPA_TYPE_Struct } })
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_push_struct(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
 {
     const struct spa_pod_struct p = SPA_POD_INIT_Struct(0);
@@ -405,7 +413,7 @@ spa_pod_builder_push_struct(struct spa_p
 
 #define SPA_POD_INIT_Object(size,type,id,...)    ((struct spa_pod_object){ { (size), SPA_TYPE_Object }, { (type), (id) }, ##__VA_ARGS__ })
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_push_object(struct spa_pod_builder *builder, struct spa_pod_frame *frame,
         uint32_t type, uint32_t id)
 {
@@ -420,7 +428,7 @@ spa_pod_builder_push_object(struct spa_p
 #define SPA_POD_INIT_Prop(key,flags,size,type)    \
     ((struct spa_pod_prop){ (key), (flags), { (size), (type) } })
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_prop(struct spa_pod_builder *builder, uint32_t key, uint32_t flags)
 {
     const struct { uint32_t key; uint32_t flags; } p = { key, flags };
@@ -430,7 +438,7 @@ spa_pod_builder_prop(struct spa_pod_buil
 #define SPA_POD_INIT_Sequence(size,unit)    \
     ((struct spa_pod_sequence){ { (size), SPA_TYPE_Sequence}, {(unit), 0 } })
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_push_sequence(struct spa_pod_builder *builder, struct spa_pod_frame *frame, uint32_t unit)
 {
     const struct spa_pod_sequence p =
@@ -441,14 +449,14 @@ spa_pod_builder_push_sequence(struct spa
     return res;
 }
 
-static inline uint32_t
+SPA_API_POD_BUILDER int
 spa_pod_builder_control(struct spa_pod_builder *builder, uint32_t offset, uint32_t type)
 {
     const struct { uint32_t offset; uint32_t type; } p = { offset, type };
     return spa_pod_builder_raw(builder, &p, sizeof(p));
 }
 
-static inline uint32_t spa_choice_from_id(char id)
+SPA_API_POD_BUILDER uint32_t spa_choice_from_id(char id)
 {
     switch (id) {
     case 'r':
@@ -481,7 +489,7 @@ do {
         spa_pod_builder_long(builder, va_arg(args, int64_t));        \
         break;                                \
     case 'f':                                \
-        spa_pod_builder_float(builder, va_arg(args, double));        \
+        spa_pod_builder_float(builder, (float)va_arg(args, double));    \
         break;                                \
     case 'd':                                \
         spa_pod_builder_double(builder, va_arg(args, double));        \
@@ -560,7 +568,7 @@ do {
     }                                    \
 } while(false)
 
-static inline int
+SPA_API_POD_BUILDER int
 spa_pod_builder_addv(struct spa_pod_builder *builder, va_list args)
 {
     int res = 0;
@@ -618,7 +626,7 @@ spa_pod_builder_addv(struct spa_pod_buil
     return res;
 }
 
-static inline int spa_pod_builder_add(struct spa_pod_builder *builder, ...)
+SPA_API_POD_BUILDER int spa_pod_builder_add(struct spa_pod_builder *builder, ...)
 {
     int res;
     va_list args;
@@ -658,7 +666,7 @@ static inline int spa_pod_builder_add(st
 })
 
 /** Copy a pod structure */
-static inline struct spa_pod *
+SPA_API_POD_BUILDER struct spa_pod *
 spa_pod_copy(const struct spa_pod *pod)
 {
     size_t size;
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/event.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/event.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/event.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/event.h	2025-06-27 08:03:14.000000000 +0000
@@ -30,7 +30,7 @@ struct spa_event {
                     (ev)->body.body.id : SPA_ID_INVALID)
 
 #define SPA_EVENT_INIT_FULL(t,size,type,id,...) ((t)            \
-    { { (size), SPA_TYPE_OBJECT },                    \
+    { { (size), SPA_TYPE_Object },                    \
       { { (type), (id) }, ##__VA_ARGS__ } })            \
 
 #define SPA_EVENT_INIT(type,id)                        \
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/iter.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/iter.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/iter.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/iter.h	2025-06-27 08:03:14.000000000 +0000
@@ -14,6 +14,14 @@ extern "C" {
 
 #include <spa/pod/pod.h>
 
+#ifndef SPA_API_POD_ITER
+ #ifdef SPA_API_IMPL
+  #define SPA_API_POD_ITER SPA_API_IMPL
+ #else
+  #define SPA_API_POD_ITER static inline
+ #endif
+#endif
+
 /**
  * \addtogroup spa_pod
  * \{
@@ -26,54 +34,60 @@ struct spa_pod_frame {
     uint32_t flags;
 };
 
-static inline bool spa_pod_is_inside(const void *pod, uint32_t size, const void *iter)
+SPA_API_POD_ITER bool spa_pod_is_inside(const void *pod, uint32_t size, const void *iter)
 {
-    return SPA_POD_BODY(iter) <= SPA_PTROFF(pod, size, void) &&
-        SPA_PTROFF(iter, SPA_POD_SIZE(iter), void) <= SPA_PTROFF(pod, size, void);
+    size_t remaining;
+
+    return spa_ptr_type_inside(pod, size, iter, struct spa_pod, &remaining) &&
+           remaining >= SPA_POD_BODY_SIZE(iter);
 }
 
-static inline void *spa_pod_next(const void *iter)
+SPA_API_POD_ITER void *spa_pod_next(const void *iter)
 {
     return SPA_PTROFF(iter, SPA_ROUND_UP_N(SPA_POD_SIZE(iter), 8), void);
 }
 
-static inline struct spa_pod_prop *spa_pod_prop_first(const struct spa_pod_object_body *body)
+SPA_API_POD_ITER struct spa_pod_prop *spa_pod_prop_first(const struct spa_pod_object_body *body)
 {
     return SPA_PTROFF(body, sizeof(struct spa_pod_object_body), struct spa_pod_prop);
 }
 
-static inline bool spa_pod_prop_is_inside(const struct spa_pod_object_body *body,
+SPA_API_POD_ITER bool spa_pod_prop_is_inside(const struct spa_pod_object_body *body,
         uint32_t size, const struct spa_pod_prop *iter)
 {
-    return SPA_POD_CONTENTS(struct spa_pod_prop, iter) <= SPA_PTROFF(body, size, void) &&
-        SPA_PTROFF(iter, SPA_POD_PROP_SIZE(iter), void) <= SPA_PTROFF(body, size, void);
+    size_t remaining;
+
+    return spa_ptr_type_inside(body, size, iter, struct spa_pod_prop, &remaining) &&
+           remaining >= iter->value.size;
 }
 
-static inline struct spa_pod_prop *spa_pod_prop_next(const struct spa_pod_prop *iter)
+SPA_API_POD_ITER struct spa_pod_prop *spa_pod_prop_next(const struct spa_pod_prop *iter)
 {
     return SPA_PTROFF(iter, SPA_ROUND_UP_N(SPA_POD_PROP_SIZE(iter), 8), struct spa_pod_prop);
 }
 
-static inline struct spa_pod_control *spa_pod_control_first(const struct spa_pod_sequence_body *body)
+SPA_API_POD_ITER struct spa_pod_control *spa_pod_control_first(const struct spa_pod_sequence_body *body)
 {
     return SPA_PTROFF(body, sizeof(struct spa_pod_sequence_body), struct spa_pod_control);
 }
 
-static inline bool spa_pod_control_is_inside(const struct spa_pod_sequence_body *body,
+SPA_API_POD_ITER bool spa_pod_control_is_inside(const struct spa_pod_sequence_body *body,
         uint32_t size, const struct spa_pod_control *iter)
 {
-    return SPA_POD_CONTENTS(struct spa_pod_control, iter) <= SPA_PTROFF(body, size, void) &&
-        SPA_PTROFF(iter, SPA_POD_CONTROL_SIZE(iter), void) <= SPA_PTROFF(body, size, void);
+    size_t remaining;
+
+    return spa_ptr_type_inside(body, size, iter, struct spa_pod_control, &remaining) &&
+           remaining >= iter->value.size;
 }
 
-static inline struct spa_pod_control *spa_pod_control_next(const struct spa_pod_control *iter)
+SPA_API_POD_ITER struct spa_pod_control *spa_pod_control_next(const struct spa_pod_control *iter)
 {
     return SPA_PTROFF(iter, SPA_ROUND_UP_N(SPA_POD_CONTROL_SIZE(iter), 8), struct spa_pod_control);
 }
 
 #define SPA_POD_ARRAY_BODY_FOREACH(body, _size, iter)                            \
     for ((iter) = (__typeof__(iter))SPA_PTROFF((body), sizeof(struct spa_pod_array_body), void);    \
-         (iter) < (__typeof__(iter))SPA_PTROFF((body), (_size), void);                \
+         (body)->child.size > 0 && spa_ptrinside(body, _size, iter, (body)->child.size, NULL);    \
          (iter) = (__typeof__(iter))SPA_PTROFF((iter), (body)->child.size, void))
 
 #define SPA_POD_ARRAY_FOREACH(obj, iter)                            \
@@ -81,7 +95,7 @@ static inline struct spa_pod_control *sp
 
 #define SPA_POD_CHOICE_BODY_FOREACH(body, _size, iter)                            \
     for ((iter) = (__typeof__(iter))SPA_PTROFF((body), sizeof(struct spa_pod_choice_body), void);    \
-         (iter) < (__typeof__(iter))SPA_PTROFF((body), (_size), void);                \
+         (body)->child.size > 0 && spa_ptrinside(body, _size, iter, (body)->child.size, NULL);    \
          (iter) = (__typeof__(iter))SPA_PTROFF((iter), (body)->child.size, void))
 
 #define SPA_POD_CHOICE_FOREACH(obj, iter)                            \
@@ -112,7 +126,7 @@ static inline struct spa_pod_control *sp
     SPA_POD_SEQUENCE_BODY_FOREACH(&(seq)->body, SPA_POD_BODY_SIZE(seq), iter)
 
 
-static inline void *spa_pod_from_data(void *data, size_t maxsize, off_t offset, size_t size)
+SPA_API_POD_ITER void *spa_pod_from_data(void *data, size_t maxsize, off_t offset, size_t size)
 {
     void *pod;
     if (size < sizeof(struct spa_pod) || offset + size > maxsize)
@@ -123,17 +137,17 @@ static inline void *spa_pod_from_data(vo
     return pod;
 }
 
-static inline int spa_pod_is_none(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_none(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_None);
 }
 
-static inline int spa_pod_is_bool(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_bool(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Bool && SPA_POD_BODY_SIZE(pod) >= sizeof(int32_t));
 }
 
-static inline int spa_pod_get_bool(const struct spa_pod *pod, bool *value)
+SPA_API_POD_ITER int spa_pod_get_bool(const struct spa_pod *pod, bool *value)
 {
     if (!spa_pod_is_bool(pod))
         return -EINVAL;
@@ -141,12 +155,12 @@ static inline int spa_pod_get_bool(const
     return 0;
 }
 
-static inline int spa_pod_is_id(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_id(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Id && SPA_POD_BODY_SIZE(pod) >= sizeof(uint32_t));
 }
 
-static inline int spa_pod_get_id(const struct spa_pod *pod, uint32_t *value)
+SPA_API_POD_ITER int spa_pod_get_id(const struct spa_pod *pod, uint32_t *value)
 {
     if (!spa_pod_is_id(pod))
         return -EINVAL;
@@ -154,12 +168,12 @@ static inline int spa_pod_get_id(const s
     return 0;
 }
 
-static inline int spa_pod_is_int(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_int(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Int && SPA_POD_BODY_SIZE(pod) >= sizeof(int32_t));
 }
 
-static inline int spa_pod_get_int(const struct spa_pod *pod, int32_t *value)
+SPA_API_POD_ITER int spa_pod_get_int(const struct spa_pod *pod, int32_t *value)
 {
     if (!spa_pod_is_int(pod))
         return -EINVAL;
@@ -167,12 +181,12 @@ static inline int spa_pod_get_int(const
     return 0;
 }
 
-static inline int spa_pod_is_long(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_long(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Long && SPA_POD_BODY_SIZE(pod) >= sizeof(int64_t));
 }
 
-static inline int spa_pod_get_long(const struct spa_pod *pod, int64_t *value)
+SPA_API_POD_ITER int spa_pod_get_long(const struct spa_pod *pod, int64_t *value)
 {
     if (!spa_pod_is_long(pod))
         return -EINVAL;
@@ -180,12 +194,12 @@ static inline int spa_pod_get_long(const
     return 0;
 }
 
-static inline int spa_pod_is_float(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_float(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Float && SPA_POD_BODY_SIZE(pod) >= sizeof(float));
 }
 
-static inline int spa_pod_get_float(const struct spa_pod *pod, float *value)
+SPA_API_POD_ITER int spa_pod_get_float(const struct spa_pod *pod, float *value)
 {
     if (!spa_pod_is_float(pod))
         return -EINVAL;
@@ -193,12 +207,12 @@ static inline int spa_pod_get_float(cons
     return 0;
 }
 
-static inline int spa_pod_is_double(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_double(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Double && SPA_POD_BODY_SIZE(pod) >= sizeof(double));
 }
 
-static inline int spa_pod_get_double(const struct spa_pod *pod, double *value)
+SPA_API_POD_ITER int spa_pod_get_double(const struct spa_pod *pod, double *value)
 {
     if (!spa_pod_is_double(pod))
         return -EINVAL;
@@ -206,7 +220,7 @@ static inline int spa_pod_get_double(con
     return 0;
 }
 
-static inline int spa_pod_is_string(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_string(const struct spa_pod *pod)
 {
     const char *s = (const char *)SPA_POD_CONTENTS(struct spa_pod_string, pod);
     return (SPA_POD_TYPE(pod) == SPA_TYPE_String &&
@@ -214,7 +228,7 @@ static inline int spa_pod_is_string(cons
             s[SPA_POD_BODY_SIZE(pod)-1] == '\0');
 }
 
-static inline int spa_pod_get_string(const struct spa_pod *pod, const char **value)
+SPA_API_POD_ITER int spa_pod_get_string(const struct spa_pod *pod, const char **value)
 {
     if (!spa_pod_is_string(pod))
         return -EINVAL;
@@ -222,7 +236,7 @@ static inline int spa_pod_get_string(con
     return 0;
 }
 
-static inline int spa_pod_copy_string(const struct spa_pod *pod, size_t maxlen, char *dest)
+SPA_API_POD_ITER int spa_pod_copy_string(const struct spa_pod *pod, size_t maxlen, char *dest)
 {
     const char *s = (const char *)SPA_POD_CONTENTS(struct spa_pod_string, pod);
     if (!spa_pod_is_string(pod) || maxlen < 1)
@@ -232,12 +246,12 @@ static inline int spa_pod_copy_string(co
     return 0;
 }
 
-static inline int spa_pod_is_bytes(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_bytes(const struct spa_pod *pod)
 {
     return SPA_POD_TYPE(pod) == SPA_TYPE_Bytes;
 }
 
-static inline int spa_pod_get_bytes(const struct spa_pod *pod, const void **value, uint32_t *len)
+SPA_API_POD_ITER int spa_pod_get_bytes(const struct spa_pod *pod, const void **value, uint32_t *len)
 {
     if (!spa_pod_is_bytes(pod))
         return -EINVAL;
@@ -246,13 +260,13 @@ static inline int spa_pod_get_bytes(cons
     return 0;
 }
 
-static inline int spa_pod_is_pointer(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_pointer(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Pointer &&
             SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_pointer_body));
 }
 
-static inline int spa_pod_get_pointer(const struct spa_pod *pod, uint32_t *type, const void **value)
+SPA_API_POD_ITER int spa_pod_get_pointer(const struct spa_pod *pod, uint32_t *type, const void **value)
 {
     if (!spa_pod_is_pointer(pod))
         return -EINVAL;
@@ -261,13 +275,13 @@ static inline int spa_pod_get_pointer(co
     return 0;
 }
 
-static inline int spa_pod_is_fd(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_fd(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Fd &&
             SPA_POD_BODY_SIZE(pod) >= sizeof(int64_t));
 }
 
-static inline int spa_pod_get_fd(const struct spa_pod *pod, int64_t *value)
+SPA_API_POD_ITER int spa_pod_get_fd(const struct spa_pod *pod, int64_t *value)
 {
     if (!spa_pod_is_fd(pod))
         return -EINVAL;
@@ -275,13 +289,13 @@ static inline int spa_pod_get_fd(const s
     return 0;
 }
 
-static inline int spa_pod_is_rectangle(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_rectangle(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Rectangle &&
             SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_rectangle));
 }
 
-static inline int spa_pod_get_rectangle(const struct spa_pod *pod, struct spa_rectangle *value)
+SPA_API_POD_ITER int spa_pod_get_rectangle(const struct spa_pod *pod, struct spa_rectangle *value)
 {
     if (!spa_pod_is_rectangle(pod))
         return -EINVAL;
@@ -289,39 +303,39 @@ static inline int spa_pod_get_rectangle(
     return 0;
 }
 
-static inline int spa_pod_is_fraction(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_fraction(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Fraction &&
             SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_fraction));
 }
 
-static inline int spa_pod_get_fraction(const struct spa_pod *pod, struct spa_fraction *value)
+SPA_API_POD_ITER int spa_pod_get_fraction(const struct spa_pod *pod, struct spa_fraction *value)
 {
     spa_return_val_if_fail(spa_pod_is_fraction(pod), -EINVAL);
     *value = SPA_POD_VALUE(struct spa_pod_fraction, pod);
     return 0;
 }
 
-static inline int spa_pod_is_bitmap(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_bitmap(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Bitmap &&
             SPA_POD_BODY_SIZE(pod) >= sizeof(uint8_t));
 }
 
-static inline int spa_pod_is_array(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_array(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Array &&
             SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_array_body));
 }
 
-static inline void *spa_pod_get_array(const struct spa_pod *pod, uint32_t *n_values)
+SPA_API_POD_ITER void *spa_pod_get_array(const struct spa_pod *pod, uint32_t *n_values)
 {
     spa_return_val_if_fail(spa_pod_is_array(pod), NULL);
     *n_values = SPA_POD_ARRAY_N_VALUES(pod);
     return SPA_POD_ARRAY_VALUES(pod);
 }
 
-static inline uint32_t spa_pod_copy_array(const struct spa_pod *pod, uint32_t type,
+SPA_API_POD_ITER uint32_t spa_pod_copy_array(const struct spa_pod *pod, uint32_t type,
         void *values, uint32_t max_values)
 {
     uint32_t n_values;
@@ -333,13 +347,13 @@ static inline uint32_t spa_pod_copy_arra
     return n_values;
 }
 
-static inline int spa_pod_is_choice(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_choice(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Choice &&
             SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_choice_body));
 }
 
-static inline struct spa_pod *spa_pod_get_values(const struct spa_pod *pod, uint32_t *n_vals, uint32_t *choice)
+SPA_API_POD_ITER struct spa_pod *spa_pod_get_values(const struct spa_pod *pod, uint32_t *n_vals, uint32_t *choice)
 {
     if (pod->type == SPA_TYPE_Choice) {
         *n_vals = SPA_POD_CHOICE_N_VALUES(pod);
@@ -353,34 +367,34 @@ static inline struct spa_pod *spa_pod_ge
     }
 }
 
-static inline int spa_pod_is_struct(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_struct(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Struct);
 }
 
-static inline int spa_pod_is_object(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_object(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Object &&
             SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_object_body));
 }
 
-static inline bool spa_pod_is_object_type(const struct spa_pod *pod, uint32_t type)
+SPA_API_POD_ITER bool spa_pod_is_object_type(const struct spa_pod *pod, uint32_t type)
 {
     return (pod && spa_pod_is_object(pod) && SPA_POD_OBJECT_TYPE(pod) == type);
 }
 
-static inline bool spa_pod_is_object_id(const struct spa_pod *pod, uint32_t id)
+SPA_API_POD_ITER bool spa_pod_is_object_id(const struct spa_pod *pod, uint32_t id)
 {
     return (pod && spa_pod_is_object(pod) && SPA_POD_OBJECT_ID(pod) == id);
 }
 
-static inline int spa_pod_is_sequence(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_is_sequence(const struct spa_pod *pod)
 {
     return (SPA_POD_TYPE(pod) == SPA_TYPE_Sequence &&
             SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_sequence_body));
 }
 
-static inline const struct spa_pod_prop *spa_pod_object_find_prop(const struct spa_pod_object *pod,
+SPA_API_POD_ITER const struct spa_pod_prop *spa_pod_object_find_prop(const struct spa_pod_object *pod,
         const struct spa_pod_prop *start, uint32_t key)
 {
     const struct spa_pod_prop *first, *res;
@@ -400,7 +414,7 @@ static inline const struct spa_pod_prop
     return NULL;
 }
 
-static inline const struct spa_pod_prop *spa_pod_find_prop(const struct spa_pod *pod,
+SPA_API_POD_ITER const struct spa_pod_prop *spa_pod_find_prop(const struct spa_pod *pod,
         const struct spa_pod_prop *start, uint32_t key)
 {
     if (!spa_pod_is_object(pod))
@@ -408,7 +422,7 @@ static inline const struct spa_pod_prop
     return spa_pod_object_find_prop((const struct spa_pod_object *)pod, start, key);
 }
 
-static inline int spa_pod_object_fixate(struct spa_pod_object *pod)
+SPA_API_POD_ITER int spa_pod_object_fixate(struct spa_pod_object *pod)
 {
     struct spa_pod_prop *res;
     SPA_POD_OBJECT_FOREACH(pod, res) {
@@ -419,14 +433,14 @@ static inline int spa_pod_object_fixate(
     return 0;
 }
 
-static inline int spa_pod_fixate(struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_fixate(struct spa_pod *pod)
 {
     if (!spa_pod_is_object(pod))
         return -EINVAL;
     return spa_pod_object_fixate((struct spa_pod_object *)pod);
 }
 
-static inline int spa_pod_object_is_fixated(const struct spa_pod_object *pod)
+SPA_API_POD_ITER int spa_pod_object_is_fixated(const struct spa_pod_object *pod)
 {
     struct spa_pod_prop *res;
     SPA_POD_OBJECT_FOREACH(pod, res) {
@@ -437,7 +451,15 @@ static inline int spa_pod_object_is_fixa
     return 1;
 }
 
-static inline int spa_pod_is_fixated(const struct spa_pod *pod)
+SPA_API_POD_ITER int spa_pod_object_has_props(const struct spa_pod_object *pod)
+{
+    struct spa_pod_prop *res;
+    SPA_POD_OBJECT_FOREACH(pod, res)
+        return 1;
+    return 0;
+}
+
+SPA_API_POD_ITER int spa_pod_is_fixated(const struct spa_pod *pod)
 {
     if (!spa_pod_is_object(pod))
         return -EINVAL;
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/parser.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/parser.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/parser.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/pod/parser.h	2025-06-27 08:03:14.000000000 +0000
@@ -15,6 +15,14 @@ extern "C" {
 #include <spa/pod/iter.h>
 #include <spa/pod/vararg.h>
 
+#ifndef SPA_API_POD_PARSER
+ #ifdef SPA_API_IMPL
+  #define SPA_API_POD_PARSER SPA_API_IMPL
+ #else
+  #define SPA_API_POD_PARSER static inline
+ #endif
+#endif
+
 /**
  * \addtogroup spa_pod
  * \{
@@ -33,33 +41,33 @@ struct spa_pod_parser {
     struct spa_pod_parser_state state;
 };
 
-#define SPA_POD_PARSER_INIT(buffer,size)  ((struct spa_pod_parser){ (buffer), (size), 0, {} })
+#define SPA_POD_PARSER_INIT(buffer,size)  ((struct spa_pod_parser){ (buffer), (size), 0, {0,0,NULL}})
 
-static inline void spa_pod_parser_init(struct spa_pod_parser *parser,
+SPA_API_POD_PARSER void spa_pod_parser_init(struct spa_pod_parser *parser,
                        const void *data, uint32_t size)
 {
     *parser = SPA_POD_PARSER_INIT(data, size);
 }
 
-static inline void spa_pod_parser_pod(struct spa_pod_parser *parser,
+SPA_API_POD_PARSER void spa_pod_parser_pod(struct spa_pod_parser *parser,
                       const struct spa_pod *pod)
 {
     spa_pod_parser_init(parser, pod, SPA_POD_SIZE(pod));
 }
 
-static inline void
+SPA_API_POD_PARSER void
 spa_pod_parser_get_state(struct spa_pod_parser *parser, struct spa_pod_parser_state *state)
 {
     *state = parser->state;
 }
 
-static inline void
+SPA_API_POD_PARSER void
 spa_pod_parser_reset(struct spa_pod_parser *parser, struct spa_pod_parser_state *state)
 {
     parser->state = *state;
 }
 
-static inline struct spa_pod *
+SPA_API_POD_PARSER struct spa_pod *
 spa_pod_parser_deref(struct spa_pod_parser *parser, uint32_t offset, uint32_t size)
 {
     /* Cast to uint64_t to avoid wraparound.  Add 8 for the pod itself. */
@@ -78,12 +86,12 @@ spa_pod_parser_deref(struct spa_pod_pars
     return NULL;
 }
 
-static inline struct spa_pod *spa_pod_parser_frame(struct spa_pod_parser *parser, struct spa_pod_frame *frame)
+SPA_API_POD_PARSER struct spa_pod *spa_pod_parser_frame(struct spa_pod_parser *parser, struct spa_pod_frame *frame)
 {
     return SPA_PTROFF(parser->data, frame->offset, struct spa_pod);
 }
 
-static inline void spa_pod_parser_push(struct spa_pod_parser *parser,
+SPA_API_POD_PARSER void spa_pod_parser_push(struct spa_pod_parser *parser,
               struct spa_pod_frame *frame, const struct spa_pod *pod, uint32_t offset)
 {
     frame->pod = *pod;
@@ -93,19 +101,19 @@ static inline void spa_pod_parser_push(s
     parser->state.frame = frame;
 }
 
-static inline struct spa_pod *spa_pod_parser_current(struct spa_pod_parser *parser)
+SPA_API_POD_PARSER struct spa_pod *spa_pod_parser_current(struct spa_pod_parser *parser)
 {
     struct spa_pod_frame *f = parser->state.frame;
     uint32_t size = f ? f->offset + SPA_POD_SIZE(&f->pod) : parser->size;
     return spa_pod_parser_deref(parser, parser->state.offset, size);
 }
 
-static inline void spa_pod_parser_advance(struct spa_pod_parser *parser, const struct spa_pod *pod)
+SPA_API_POD_PARSER void spa_pod_parser_advance(struct spa_pod_parser *parser, const struct spa_pod *pod)
 {
     parser->state.offset += SPA_ROUND_UP_N(SPA_POD_SIZE(pod), 8);
 }
 
-static inline struct spa_pod *spa_pod_parser_next(struct spa_pod_parser *parser)
+SPA_API_POD_PARSER struct spa_pod *spa_pod_parser_next(struct spa_pod_parser *parser)
 {
     struct spa_pod *pod = spa_pod_parser_current(parser);
     if (pod)
@@ -113,7 +121,7 @@ static inline struct spa_pod *spa_pod_pa
     return pod;
 }
 
-static inline int spa_pod_parser_pop(struct spa_pod_parser *parser,
+SPA_API_POD_PARSER int spa_pod_parser_pop(struct spa_pod_parser *parser,
               struct spa_pod_frame *frame)
 {
     parser->state.frame = frame->parent;
@@ -121,7 +129,7 @@ static inline int spa_pod_parser_pop(str
     return 0;
 }
 
-static inline int spa_pod_parser_get_bool(struct spa_pod_parser *parser, bool *value)
+SPA_API_POD_PARSER int spa_pod_parser_get_bool(struct spa_pod_parser *parser, bool *value)
 {
     int res = -EPIPE;
     const struct spa_pod *pod = spa_pod_parser_current(parser);
@@ -130,7 +138,7 @@ static inline int spa_pod_parser_get_boo
     return res;
 }
 
-static inline int spa_pod_parser_get_id(struct spa_pod_parser *parser, uint32_t *value)
+SPA_API_POD_PARSER int spa_pod_parser_get_id(struct spa_pod_parser *parser, uint32_t *value)
 {
     int res = -EPIPE;
     const struct spa_pod *pod = spa_pod_parser_current(parser);
@@ -139,7 +147,7 @@ static inline int spa_pod_parser_get_id(
     return res;
 }
 
-static inline int spa_pod_parser_get_int(struct spa_pod_parser *parser, int32_t *value)
+SPA_API_POD_PARSER int spa_pod_parser_get_int(struct spa_pod_parser *parser, int32_t *value)
 {
     int res = -EPIPE;
     const struct spa_pod *pod = spa_pod_parser_current(parser);
@@ -148,7 +156,7 @@ static inline int spa_pod_parser_get_int
     return res;
 }
 
-static inline int spa_pod_parser_get_long(struct spa_pod_parser *parser, int64_t *value)
+SPA_API_POD_PARSER int spa_pod_parser_get_long(struct spa_pod_parser *parser, int64_t *value)
 {
     int res = -EPIPE;
     const struct spa_pod *pod = spa_pod_parser_current(parser);
@@ -157,7 +165,7 @@ static inline int spa_pod_parser_get_lon
     return res;
 }
 
-static inline int spa_pod_parser_get_float(struct spa_pod_parser *parser, float *value)
+SPA_API_POD_PARSER int spa_pod_parser_get_float(struct spa_pod_parser *parser, float *value)
 {
     int res = -EPIPE;
     const struct spa_pod *pod = spa_pod_parser_current(parser);
@@ -166,7 +174,7 @@ static inline int spa_pod_parser_get_flo
     return res;
 }
 
-static inline int spa_pod_parser_get_double(struct spa_pod_parser *parser, double *value)
+SPA_API_POD_PARSER int spa_pod_parser_get_double(struct spa_pod_parser *parser, double *value)
 {
     int res = -EPIPE;
     const struct spa_pod *pod = spa_pod_parser_current(parser);
@@ -175,7 +183,7 @@ static inline int spa_pod_parser_get_dou
     return res;
 }
 
-static inline int spa_pod_parser_get_string(struct spa_pod_parser *parser, const char **value)
+SPA_API_POD_PARSER int spa_pod_parser_get_string(struct spa_pod_parser *parser, const char **value)
 {
     int res = -EPIPE;
     const struct spa_pod *pod = spa_pod_parser_current(parser);
@@ -184,7 +192,7 @@ static inline int spa_pod_parser_get_str
     return res;
 }
 
-static inline int spa_pod_parser_get_bytes(struct spa_pod_parser *parser, const void **value, uint32_t *len)
+SPA_API_POD_PARSER int spa_pod_parser_get_bytes(struct spa_pod_parser *parser, const void **value, uint32_t *len)
 {
     int res = -EPIPE;
     const struct spa_pod *pod = spa_pod_parser_current(parser);
@@ -193,7 +201,7 @@ static inline int spa_pod_parser_get_byt
     return res;
 }
 
-static inline int spa_pod_parser_get_pointer(struct spa_pod_parser *parser, uint32_t *type, const void **value)
+SPA_API_POD_PARSER int spa_pod_parser_get_pointer(struct spa_pod_parser *parser, uint32_t *type, const void **value)
 {
     int res = -EPIPE;
     const struct spa_pod *pod = spa_pod_parser_current(parser);
@@ -202,7 +210,7 @@ static inline int spa_pod_parser_get_poi
     return res;
 }
 
-static inline int spa_pod_parser_get_fd(struct spa_pod_parser *parser, int64_t *value)
+SPA_API_POD_PARSER int spa_pod_parser_get_fd(struct spa_pod_parser *parser, int64_t *value)
 {
     int res = -EPIPE;
     const struct spa_pod *pod = spa_pod_parser_current(parser);
@@ -211,7 +219,7 @@ static inline int spa_pod_parser_get_fd(
     return res;
 }
 
-static inline int spa_pod_parser_get_rectangle(struct spa_pod_parser *parser, struct spa_rectangle *value)
+SPA_API_POD_PARSER int spa_pod_parser_get_rectangle(struct spa_pod_parser *parser, struct spa_rectangle *value)
 {
     int res = -EPIPE;
     const struct spa_pod *pod = spa_pod_parser_current(parser);
@@ -220,7 +228,7 @@ static inline int spa_pod_parser_get_rec
     return res;
 }
 
-static inline int spa_pod_parser_get_fraction(struct spa_pod_parser *parser, struct spa_fraction *value)
+SPA_API_POD_PARSER int spa_pod_parser_get_fraction(struct spa_pod_parser *parser, struct spa_fraction *value)
 {
     int res = -EPIPE;
     const struct spa_pod *pod = spa_pod_parser_current(parser);
@@ -229,7 +237,7 @@ static inline int spa_pod_parser_get_fra
     return res;
 }
 
-static inline int spa_pod_parser_get_pod(struct spa_pod_parser *parser, struct spa_pod **value)
+SPA_API_POD_PARSER int spa_pod_parser_get_pod(struct spa_pod_parser *parser, struct spa_pod **value)
 {
     struct spa_pod *pod = spa_pod_parser_current(parser);
     if (pod == NULL)
@@ -238,7 +246,7 @@ static inline int spa_pod_parser_get_pod
     spa_pod_parser_advance(parser, pod);
     return 0;
 }
-static inline int spa_pod_parser_push_struct(struct spa_pod_parser *parser,
+SPA_API_POD_PARSER int spa_pod_parser_push_struct(struct spa_pod_parser *parser,
         struct spa_pod_frame *frame)
 {
     const struct spa_pod *pod = spa_pod_parser_current(parser);
@@ -251,7 +259,7 @@ static inline int spa_pod_parser_push_st
     return 0;
 }
 
-static inline int spa_pod_parser_push_object(struct spa_pod_parser *parser,
+SPA_API_POD_PARSER int spa_pod_parser_push_object(struct spa_pod_parser *parser,
         struct spa_pod_frame *frame, uint32_t type, uint32_t *id)
 {
     const struct spa_pod *pod = spa_pod_parser_current(parser);
@@ -268,7 +276,7 @@ static inline int spa_pod_parser_push_ob
     return 0;
 }
 
-static inline bool spa_pod_parser_can_collect(const struct spa_pod *pod, char type)
+SPA_API_POD_PARSER bool spa_pod_parser_can_collect(const struct spa_pod *pod, char type)
 {
     if (pod == NULL)
         return false;
@@ -443,7 +451,7 @@ do {
     }                                        \
 } while(false)
 
-static inline int spa_pod_parser_getv(struct spa_pod_parser *parser, va_list args)
+SPA_API_POD_PARSER int spa_pod_parser_getv(struct spa_pod_parser *parser, va_list args)
 {
     struct spa_pod_frame *f = parser->state.frame;
         uint32_t ftype = f ? f->pod.type : (uint32_t)SPA_TYPE_Struct;
@@ -455,7 +463,7 @@ static inline int spa_pod_parser_getv(st
         const struct spa_pod *pod = NULL;
         const char *format;
 
-        if (ftype == SPA_TYPE_Object) {
+        if (f && ftype == SPA_TYPE_Object) {
             uint32_t key = va_arg(args, uint32_t);
             const struct spa_pod_object *object;
 
@@ -496,7 +504,7 @@ static inline int spa_pod_parser_getv(st
     return count;
 }
 
-static inline int spa_pod_parser_get(struct spa_pod_parser *parser, ...)
+SPA_API_POD_PARSER int spa_pod_parser_get(struct spa_pod_parser *parser, ...)
 {
     int res;
     va_list args;
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/support/loop.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/support/loop.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/support/loop.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/support/loop.h	2025-06-27 08:03:14.000000000 +0000
@@ -9,10 +9,20 @@
 extern "C" {
 #endif
 
+#include <errno.h>
+
 #include <spa/utils/defs.h>
 #include <spa/utils/hook.h>
 #include <spa/support/system.h>
 
+#ifndef SPA_API_LOOP
+ #ifdef SPA_API_IMPL
+  #define SPA_API_LOOP SPA_API_IMPL
+ #else
+  #define SPA_API_LOOP static inline
+ #endif
+#endif
+
 /** \defgroup spa_loop Loop
  * Event loop interface
  */
@@ -66,19 +76,56 @@ struct spa_loop_methods {
 #define SPA_VERSION_LOOP_METHODS    0
     uint32_t version;
 
-    /** add a source to the loop */
+    /** Add a source to the loop. Must be called from the loop's own thread.
+     *
+     * \param[in] object The callbacks data.
+     * \param[in] source The source.
+     * \return 0 on success, negative errno-style value on failure.
+     */
     int (*add_source) (void *object,
                struct spa_source *source);
 
-    /** update the source io mask */
+    /** Update the source io mask. Must be called from the loop's own thread.
+     *
+     * \param[in] object The callbacks data.
+     * \param[in] source The source.
+     * \return 0 on success, negative errno-style value on failure.
+     */
     int (*update_source) (void *object,
             struct spa_source *source);
 
-    /** remove a source from the loop */
+    /** Remove a source from the loop. Must be called from the loop's own thread.
+     *
+     * \param[in] object The callbacks data.
+     * \param[in] source The source.
+     * \return 0 on success, negative errno-style value on failure.
+     */
     int (*remove_source) (void *object,
             struct spa_source *source);
 
-    /** invoke a function in the context of this loop */
+    /** Invoke a function in the context of this loop.
+     * May be called from any thread and multiple threads at the same time.
+     * If called from the loop's thread, all callbacks previously queued with
+     * invoke() will be run synchronously, which might cause unexpected
+     * reentrancy problems.
+     *
+     * \param[in] object The callbacks data.
+     * \param func The function to be invoked.
+     * \param seq An opaque sequence number. This will be made
+     *            available to func.
+     * \param[in] data Data that will be copied into the internal ring buffer and made
+     *             available to func. Because this data is copied, it is okay to
+     *             pass a pointer to a local variable, but do not pass a pointer to
+     *             an object that has identity.
+     * \param size The size of data to copy.
+     * \param block If \true, do not return until func has been called. Otherwise,
+     *              returns immediately. Passing \true does not risk a deadlock because
+     *              the data thread is never allowed to wait on any other thread.
+     * \param user_data An opaque pointer passed to func.
+     * \return `-EPIPE` if the internal ring buffer filled up,
+     *         if block is \false, 0 if seq was SPA_ID_INVALID or
+     *         seq with the ASYNC flag set
+     *         or the return value of func otherwise. */
     int (*invoke) (void *object,
                spa_invoke_func_t func,
                uint32_t seq,
@@ -88,21 +135,29 @@ struct spa_loop_methods {
                void *user_data);
 };
 
-#define spa_loop_method(o,method,version,...)                \
-({                                    \
-    int _res = -ENOTSUP;                        \
-    struct spa_loop *_o = o;                    \
-    spa_interface_call_res(&_o->iface,                \
-            struct spa_loop_methods, _res,            \
-            method, version, ##__VA_ARGS__);        \
-    _res;                                \
-})
-
-#define spa_loop_add_source(l,...)    spa_loop_method(l,add_source,0,##__VA_ARGS__)
-#define spa_loop_update_source(l,...)    spa_loop_method(l,update_source,0,##__VA_ARGS__)
-#define spa_loop_remove_source(l,...)    spa_loop_method(l,remove_source,0,##__VA_ARGS__)
-#define spa_loop_invoke(l,...)        spa_loop_method(l,invoke,0,##__VA_ARGS__)
-
+SPA_API_LOOP int spa_loop_add_source(struct spa_loop *object, struct spa_source *source)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            spa_loop, &object->iface, add_source, 0, source);
+}
+SPA_API_LOOP int spa_loop_update_source(struct spa_loop *object, struct spa_source *source)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            spa_loop, &object->iface, update_source, 0, source);
+}
+SPA_API_LOOP int spa_loop_remove_source(struct spa_loop *object, struct spa_source *source)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            spa_loop, &object->iface, remove_source, 0, source);
+}
+SPA_API_LOOP int spa_loop_invoke(struct spa_loop *object,
+        spa_invoke_func_t func, uint32_t seq, const void *data,
+        size_t size, bool block, void *user_data)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            spa_loop, &object->iface, invoke, 0, func, seq, data,
+            size, block, user_data);
+}
 
 /** Control hooks. These hooks can't be removed from their
  *  callbacks and must be removed from a safe place (when the loop
@@ -118,24 +173,42 @@ struct spa_loop_control_hooks {
     void (*after) (void *data);
 };
 
-#define spa_loop_control_hook_before(l)                            \
-({                                            \
-    struct spa_hook_list *_l = l;                            \
-    struct spa_hook *_h;                                \
-    spa_list_for_each_reverse(_h, &_l->list, link)                    \
-        spa_callbacks_call(&_h->cb, struct spa_loop_control_hooks, before, 0);    \
-})
-
-#define spa_loop_control_hook_after(l)                            \
-({                                            \
-    struct spa_hook_list *_l = l;                            \
-    struct spa_hook *_h;                                \
-    spa_list_for_each(_h, &_l->list, link)                        \
-        spa_callbacks_call(&_h->cb, struct spa_loop_control_hooks, after, 0);    \
-})
+SPA_API_LOOP void spa_loop_control_hook_before(struct spa_hook_list *l)
+{
+    struct spa_hook *h;
+    spa_list_for_each_reverse(h, &l->list, link)
+        spa_callbacks_call_fast(&h->cb, struct spa_loop_control_hooks, before, 0);
+}
+
+SPA_API_LOOP void spa_loop_control_hook_after(struct spa_hook_list *l)
+{
+    struct spa_hook *h;
+    spa_list_for_each(h, &l->list, link)
+        spa_callbacks_call_fast(&h->cb, struct spa_loop_control_hooks, after, 0);
+}
 
 /**
  * Control an event loop
+ *
+ * The event loop control function provide API to run the event loop.
+ *
+ * The below (pseudo)code is a minimal example outlining the use of the loop
+ * control:
+ * \code{.c}
+ * spa_loop_control_enter(loop);
+ * while (running) {
+ *   spa_loop_control_iterate(loop, -1);
+ * }
+ * spa_loop_control_leave(loop);
+ * \endcode
+ *
+ * It is also possible to add the loop to an existing event loop by using the
+ * spa_loop_control_get_fd() call. This fd will become readable when activity
+ * has been detected on the sources in the loop. spa_loop_control_iterate() with
+ * a 0 timeout should be called to process the pending sources.
+ *
+ * spa_loop_control_enter() and spa_loop_control_leave() should be called once
+ * from the thread that will run the iterate() function.
  */
 struct spa_loop_control_methods {
     /* the version of this structure. This can be used to expand this
@@ -143,10 +216,19 @@ struct spa_loop_control_methods {
 #define SPA_VERSION_LOOP_CONTROL_METHODS    1
     uint32_t version;
 
+    /** get the loop fd
+     * \param object the control to query
+     *
+     * Get the fd of this loop control. This fd will be readable when a
+     * source in the loop has activity. The user should call iterate()
+     * with a 0 timeout to schedule one iteration of the loop and dispatch
+     * the sources.
+     * \return the fd of the loop
+     */
     int (*get_fd) (void *object);
 
     /** Add a hook
-     * \param ctrl the control to change
+     * \param object the control to change
      * \param hooks the hooks to add
      *
      * Adds hooks to the loop controlled by \a ctrl.
@@ -157,18 +239,19 @@ struct spa_loop_control_methods {
               void *data);
 
     /** Enter a loop
-     * \param ctrl the control
+     * \param object the control
      *
-     * Start an iteration of the loop. This function should be called
-     * before calling iterate and is typically used to capture the thread
-     * that this loop will run in.
+     * This function should be called before calling iterate and is
+     * typically used to capture the thread that this loop will run in.
+     * It should ideally be called once from the thread that will run
+     * the loop.
      */
     void (*enter) (void *object);
     /** Leave a loop
-     * \param ctrl the control
+     * \param object the control
      *
-     * Ends the iteration of a loop. This should be called after calling
-     * iterate.
+     * It should ideally be called once after calling iterate when the loop
+     * will no longer be iterated from the thread that called enter().
      */
     void (*leave) (void *object);
 
@@ -194,30 +277,43 @@ struct spa_loop_control_methods {
     int (*check) (void *object);
 };
 
-#define spa_loop_control_method_v(o,method,version,...)            \
-({                                    \
-    struct spa_loop_control *_o = o;                \
-    spa_interface_call(&_o->iface,                    \
-            struct spa_loop_control_methods,        \
-            method, version, ##__VA_ARGS__);        \
-})
-
-#define spa_loop_control_method_r(o,method,version,...)            \
-({                                    \
-    int _res = -ENOTSUP;                        \
-    struct spa_loop_control *_o = o;                \
-    spa_interface_call_res(&_o->iface,                \
-            struct spa_loop_control_methods, _res,        \
-            method, version, ##__VA_ARGS__);        \
-    _res;                                \
-})
-
-#define spa_loop_control_get_fd(l)        spa_loop_control_method_r(l,get_fd,0)
-#define spa_loop_control_add_hook(l,...)    spa_loop_control_method_v(l,add_hook,0,__VA_ARGS__)
-#define spa_loop_control_enter(l)        spa_loop_control_method_v(l,enter,0)
-#define spa_loop_control_leave(l)        spa_loop_control_method_v(l,leave,0)
-#define spa_loop_control_iterate(l,...)        spa_loop_control_method_r(l,iterate,0,__VA_ARGS__)
-#define spa_loop_control_check(l)        spa_loop_control_method_r(l,check,1)
+SPA_API_LOOP int spa_loop_control_get_fd(struct spa_loop_control *object)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            spa_loop_control, &object->iface, get_fd, 0);
+}
+SPA_API_LOOP void spa_loop_control_add_hook(struct spa_loop_control *object,
+        struct spa_hook *hook, const struct spa_loop_control_hooks *hooks,
+        void *data)
+{
+    spa_api_method_v(spa_loop_control, &object->iface, add_hook, 0,
+            hook, hooks, data);
+}
+SPA_API_LOOP void spa_loop_control_enter(struct spa_loop_control *object)
+{
+    spa_api_method_v(spa_loop_control, &object->iface, enter, 0);
+}
+SPA_API_LOOP void spa_loop_control_leave(struct spa_loop_control *object)
+{
+    spa_api_method_v(spa_loop_control, &object->iface, leave, 0);
+}
+SPA_API_LOOP int spa_loop_control_iterate(struct spa_loop_control *object,
+        int timeout)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            spa_loop_control, &object->iface, iterate, 0, timeout);
+}
+SPA_API_LOOP int spa_loop_control_iterate_fast(struct spa_loop_control *object,
+        int timeout)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP,
+            spa_loop_control, &object->iface, iterate, 0, timeout);
+}
+SPA_API_LOOP int spa_loop_control_check(struct spa_loop_control *object)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            spa_loop_control, &object->iface, check, 1);
+}
 
 typedef void (*spa_source_io_func_t) (void *data, int fd, uint32_t mask);
 typedef void (*spa_source_idle_func_t) (void *data);
@@ -268,44 +364,71 @@ struct spa_loop_utils_methods {
     void (*destroy_source) (void *object, struct spa_source *source);
 };
 
-#define spa_loop_utils_method_v(o,method,version,...)            \
-({                                    \
-    struct spa_loop_utils *_o = o;                    \
-    spa_interface_call(&_o->iface,                    \
-            struct spa_loop_utils_methods,            \
-            method, version, ##__VA_ARGS__);        \
-})
-
-#define spa_loop_utils_method_r(o,method,version,...)            \
-({                                    \
-    int _res = -ENOTSUP;                        \
-    struct spa_loop_utils *_o = o;                    \
-    spa_interface_call_res(&_o->iface,                \
-            struct spa_loop_utils_methods, _res,        \
-            method, version, ##__VA_ARGS__);        \
-    _res;                                \
-})
-#define spa_loop_utils_method_s(o,method,version,...)            \
-({                                    \
-    struct spa_source *_res = NULL;                    \
-    struct spa_loop_utils *_o = o;                    \
-    spa_interface_call_res(&_o->iface,                \
-            struct spa_loop_utils_methods, _res,        \
-            method, version, ##__VA_ARGS__);        \
-    _res;                                \
-})
-
-
-#define spa_loop_utils_add_io(l,...)        spa_loop_utils_method_s(l,add_io,0,__VA_ARGS__)
-#define spa_loop_utils_update_io(l,...)        spa_loop_utils_method_r(l,update_io,0,__VA_ARGS__)
-#define spa_loop_utils_add_idle(l,...)        spa_loop_utils_method_s(l,add_idle,0,__VA_ARGS__)
-#define spa_loop_utils_enable_idle(l,...)    spa_loop_utils_method_r(l,enable_idle,0,__VA_ARGS__)
-#define spa_loop_utils_add_event(l,...)        spa_loop_utils_method_s(l,add_event,0,__VA_ARGS__)
-#define spa_loop_utils_signal_event(l,...)    spa_loop_utils_method_r(l,signal_event,0,__VA_ARGS__)
-#define spa_loop_utils_add_timer(l,...)        spa_loop_utils_method_s(l,add_timer,0,__VA_ARGS__)
-#define spa_loop_utils_update_timer(l,...)    spa_loop_utils_method_r(l,update_timer,0,__VA_ARGS__)
-#define spa_loop_utils_add_signal(l,...)    spa_loop_utils_method_s(l,add_signal,0,__VA_ARGS__)
-#define spa_loop_utils_destroy_source(l,...)    spa_loop_utils_method_v(l,destroy_source,0,__VA_ARGS__)
+SPA_API_LOOP struct spa_source *
+spa_loop_utils_add_io(struct spa_loop_utils *object, int fd, uint32_t mask,
+        bool close, spa_source_io_func_t func, void *data)
+{
+    return spa_api_method_r(struct spa_source *, NULL,
+            spa_loop_utils, &object->iface, add_io, 0, fd, mask, close, func, data);
+}
+SPA_API_LOOP int spa_loop_utils_update_io(struct spa_loop_utils *object,
+        struct spa_source *source, uint32_t mask)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            spa_loop_utils, &object->iface, update_io, 0, source, mask);
+}
+SPA_API_LOOP struct spa_source *
+spa_loop_utils_add_idle(struct spa_loop_utils *object, bool enabled,
+        spa_source_idle_func_t func, void *data)
+{
+    return spa_api_method_r(struct spa_source *, NULL,
+            spa_loop_utils, &object->iface, add_idle, 0, enabled, func, data);
+}
+SPA_API_LOOP int spa_loop_utils_enable_idle(struct spa_loop_utils *object,
+        struct spa_source *source, bool enabled)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            spa_loop_utils, &object->iface, enable_idle, 0, source, enabled);
+}
+SPA_API_LOOP struct spa_source *
+spa_loop_utils_add_event(struct spa_loop_utils *object, spa_source_event_func_t func, void *data)
+{
+    return spa_api_method_r(struct spa_source *, NULL,
+            spa_loop_utils, &object->iface, add_event, 0, func, data);
+}
+SPA_API_LOOP int spa_loop_utils_signal_event(struct spa_loop_utils *object,
+        struct spa_source *source)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            spa_loop_utils, &object->iface, signal_event, 0, source);
+}
+SPA_API_LOOP struct spa_source *
+spa_loop_utils_add_timer(struct spa_loop_utils *object, spa_source_timer_func_t func, void *data)
+{
+    return spa_api_method_r(struct spa_source *, NULL,
+            spa_loop_utils, &object->iface, add_timer, 0, func, data);
+}
+SPA_API_LOOP int spa_loop_utils_update_timer(struct spa_loop_utils *object,
+        struct spa_source *source, struct timespec *value,
+        struct timespec *interval, bool absolute)
+{
+    return spa_api_method_r(int, -ENOTSUP,
+            spa_loop_utils, &object->iface, update_timer, 0, source,
+            value, interval, absolute);
+}
+SPA_API_LOOP struct spa_source *
+spa_loop_utils_add_signal(struct spa_loop_utils *object, int signal_number,
+        spa_source_signal_func_t func, void *data)
+{
+    return spa_api_method_r(struct spa_source *, NULL,
+            spa_loop_utils, &object->iface, add_signal, 0,
+            signal_number, func, data);
+}
+SPA_API_LOOP void spa_loop_utils_destroy_source(struct spa_loop_utils *object,
+        struct spa_source *source)
+{
+    spa_api_method_v(spa_loop_utils, &object->iface, destroy_source, 0, source);
+}
 
 /**
  * \}
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/support/system.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/support/system.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/support/system.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/support/system.h	2025-06-27 08:03:14.000000000 +0000
@@ -12,11 +12,20 @@ extern "C" {
 struct itimerspec;
 
 #include <time.h>
+#include <errno.h>
 #include <sys/types.h>
 
 #include <spa/utils/defs.h>
 #include <spa/utils/hook.h>
 
+#ifndef SPA_API_SYSTEM
+ #ifdef SPA_API_IMPL
+  #define SPA_API_SYSTEM SPA_API_IMPL
+ #else
+  #define SPA_API_SYSTEM static inline
+ #endif
+#endif
+
 /** \defgroup spa_system System
  * I/O, clock, polling, timer, and signal interfaces
  */
@@ -97,42 +106,106 @@ struct spa_system_methods {
     int (*signalfd_read) (void *object, int fd, int *signal);
 };
 
-#define spa_system_method_r(o,method,version,...)            \
-({                                    \
-    volatile int _res = -ENOTSUP;                    \
-    struct spa_system *_o = o;                    \
-    spa_interface_call_res(&_o->iface,                \
-            struct spa_system_methods, _res,        \
-            method, version, ##__VA_ARGS__);        \
-    _res;                                \
-})
-
-
-#define spa_system_read(s,...)            spa_system_method_r(s,read,0,__VA_ARGS__)
-#define spa_system_write(s,...)            spa_system_method_r(s,write,0,__VA_ARGS__)
-#define spa_system_ioctl(s,...)            spa_system_method_r(s,ioctl,0,__VA_ARGS__)
-#define spa_system_close(s,...)            spa_system_method_r(s,close,0,__VA_ARGS__)
-
-#define spa_system_clock_gettime(s,...)        spa_system_method_r(s,clock_gettime,0,__VA_ARGS__)
-#define spa_system_clock_getres(s,...)        spa_system_method_r(s,clock_getres,0,__VA_ARGS__)
-
-#define spa_system_pollfd_create(s,...)        spa_system_method_r(s,pollfd_create,0,__VA_ARGS__)
-#define spa_system_pollfd_add(s,...)        spa_system_method_r(s,pollfd_add,0,__VA_ARGS__)
-#define spa_system_pollfd_mod(s,...)        spa_system_method_r(s,pollfd_mod,0,__VA_ARGS__)
-#define spa_system_pollfd_del(s,...)        spa_system_method_r(s,pollfd_del,0,__VA_ARGS__)
-#define spa_system_pollfd_wait(s,...)        spa_system_method_r(s,pollfd_wait,0,__VA_ARGS__)
-
-#define spa_system_timerfd_create(s,...)    spa_system_method_r(s,timerfd_create,0,__VA_ARGS__)
-#define spa_system_timerfd_settime(s,...)    spa_system_method_r(s,timerfd_settime,0,__VA_ARGS__)
-#define spa_system_timerfd_gettime(s,...)    spa_system_method_r(s,timerfd_gettime,0,__VA_ARGS__)
-#define spa_system_timerfd_read(s,...)        spa_system_method_r(s,timerfd_read,0,__VA_ARGS__)
-
-#define spa_system_eventfd_create(s,...)    spa_system_method_r(s,eventfd_create,0,__VA_ARGS__)
-#define spa_system_eventfd_write(s,...)        spa_system_method_r(s,eventfd_write,0,__VA_ARGS__)
-#define spa_system_eventfd_read(s,...)        spa_system_method_r(s,eventfd_read,0,__VA_ARGS__)
+SPA_API_SYSTEM ssize_t spa_system_read(struct spa_system *object, int fd, void *buf, size_t count)
+{
+    return spa_api_method_fast_r(ssize_t, -ENOTSUP, spa_system, &object->iface, read, 0, fd, buf, count);
+}
+SPA_API_SYSTEM ssize_t spa_system_write(struct spa_system *object, int fd, const void *buf, size_t count)
+{
+    return spa_api_method_fast_r(ssize_t, -ENOTSUP, spa_system, &object->iface, write, 0, fd, buf, count);
+}
+#define spa_system_ioctl(object,fd,request,...)    \
+    spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, ioctl, 0, fd, request, ##__VA_ARGS__)
+
+SPA_API_SYSTEM int spa_system_close(struct spa_system *object, int fd)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, close, 0, fd);
+}
+SPA_API_SYSTEM int spa_system_clock_gettime(struct spa_system *object,
+            int clockid, struct timespec *value)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, clock_gettime, 0, clockid, value);
+}
+SPA_API_SYSTEM int spa_system_clock_getres(struct spa_system *object,
+            int clockid, struct timespec *res)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, clock_getres, 0, clockid, res);
+}
+
+SPA_API_SYSTEM int spa_system_pollfd_create(struct spa_system *object, int flags)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, pollfd_create, 0, flags);
+}
+SPA_API_SYSTEM int spa_system_pollfd_add(struct spa_system *object, int pfd, int fd, uint32_t events, void *data)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, pollfd_add, 0, pfd, fd, events, data);
+}
+SPA_API_SYSTEM int spa_system_pollfd_mod(struct spa_system *object, int pfd, int fd, uint32_t events, void *data)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, pollfd_mod, 0, pfd, fd, events, data);
+}
+SPA_API_SYSTEM int spa_system_pollfd_del(struct spa_system *object, int pfd, int fd)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, pollfd_del, 0, pfd, fd);
+}
+SPA_API_SYSTEM int spa_system_pollfd_wait(struct spa_system *object, int pfd,
+            struct spa_poll_event *ev, int n_ev, int timeout)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, pollfd_wait, 0, pfd, ev, n_ev, timeout);
+}
+
+SPA_API_SYSTEM int spa_system_timerfd_create(struct spa_system *object, int clockid, int flags)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, timerfd_create, 0, clockid, flags);
+}
 
-#define spa_system_signalfd_create(s,...)    spa_system_method_r(s,signalfd_create,0,__VA_ARGS__)
-#define spa_system_signalfd_read(s,...)        spa_system_method_r(s,signalfd_read,0,__VA_ARGS__)
+SPA_API_SYSTEM int spa_system_timerfd_settime(struct spa_system *object,
+            int fd, int flags,
+            const struct itimerspec *new_value,
+            struct itimerspec *old_value)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, timerfd_settime, 0,
+            fd, flags, new_value, old_value);
+}
+
+SPA_API_SYSTEM int spa_system_timerfd_gettime(struct spa_system *object,
+            int fd, struct itimerspec *curr_value)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, timerfd_gettime, 0,
+            fd, curr_value);
+}
+SPA_API_SYSTEM int spa_system_timerfd_read(struct spa_system *object, int fd, uint64_t *expirations)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, timerfd_read, 0,
+            fd, expirations);
+}
+
+SPA_API_SYSTEM int spa_system_eventfd_create(struct spa_system *object, int flags)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, eventfd_create, 0, flags);
+}
+SPA_API_SYSTEM int spa_system_eventfd_write(struct spa_system *object, int fd, uint64_t count)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, eventfd_write, 0,
+            fd, count);
+}
+SPA_API_SYSTEM int spa_system_eventfd_read(struct spa_system *object, int fd, uint64_t *count)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, eventfd_read, 0,
+            fd, count);
+}
+
+SPA_API_SYSTEM int spa_system_signalfd_create(struct spa_system *object, int signal, int flags)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, signalfd_create, 0,
+            signal, flags);
+}
+
+SPA_API_SYSTEM int spa_system_signalfd_read(struct spa_system *object, int fd, int *signal)
+{
+    return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, signalfd_read, 0,
+            fd, signal);
+}
 
 /**
  * \}
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/cleanup.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/cleanup.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/cleanup.h	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/cleanup.h	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,124 @@
+/* Simple Plugin API */
+/* SPDX-FileCopyrightText: Copyright © 2023 PipeWire authors */
+/* SPDX-License-Identifier: MIT */
+
+#ifndef SPA_UTILS_CLEANUP_H
+#define SPA_UTILS_CLEANUP_H
+
+#define spa_exchange(var, new_value) \
+__extension__ ({ \
+    __typeof__(var) *_ptr_ = &(var); \
+    __typeof__(var) _old_value_ = *_ptr_; \
+    *_ptr_ = (new_value); \
+    _old_value_; \
+})
+
+/* ========================================================================== */
+
+#if __GNUC__ >= 10 || defined(__clang__)
+#define spa_steal_ptr(ptr) ((__typeof__(*(ptr)) *) spa_exchange((ptr), NULL))
+#else
+#define spa_steal_ptr(ptr) spa_exchange((ptr), NULL)
+#endif
+
+#define spa_clear_ptr(ptr, destructor) \
+__extension__ ({ \
+    __typeof__(ptr) _old_value = spa_steal_ptr(ptr); \
+    if (_old_value) \
+        destructor(_old_value); \
+    (void) 0; \
+})
+
+/* ========================================================================== */
+
+#include <errno.h>
+#include <unistd.h>
+
+#define spa_steal_fd(fd) spa_exchange((fd), -1)
+
+#define spa_clear_fd(fd) \
+__extension__ ({ \
+    int _old_value = spa_steal_fd(fd), _res = 0; \
+    if (_old_value >= 0) \
+        _res = close(_old_value); \
+    _res; \
+})
+
+/* ========================================================================== */
+
+#if defined(__has_attribute) && __has_attribute(__cleanup__)
+
+#define spa_cleanup(func) __attribute__((__cleanup__(func)))
+
+#define SPA_DEFINE_AUTO_CLEANUP(name, type, ...) \
+typedef __typeof__(type) _spa_auto_cleanup_type_ ## name; \
+static inline void _spa_auto_cleanup_func_ ## name (__typeof__(type) *thing) \
+{ \
+    int _save_errno = errno; \
+    __VA_ARGS__ \
+    errno = _save_errno; \
+}
+
+#define spa_auto(name) \
+    spa_cleanup(_spa_auto_cleanup_func_ ## name) \
+    _spa_auto_cleanup_type_ ## name
+
+#define SPA_DEFINE_AUTOPTR_CLEANUP(name, type, ...) \
+typedef __typeof__(type) * _spa_autoptr_cleanup_type_ ## name; \
+static inline void _spa_autoptr_cleanup_func_ ## name (__typeof__(type) **thing) \
+{ \
+    int _save_errno = errno; \
+    __VA_ARGS__ \
+    errno = _save_errno; \
+}
+
+#define spa_autoptr(name) \
+    spa_cleanup(_spa_autoptr_cleanup_func_ ## name) \
+    _spa_autoptr_cleanup_type_ ## name
+
+/* ========================================================================== */
+
+#include <stdlib.h>
+
+static inline void _spa_autofree_cleanup_func(void *p)
+{
+    int save_errno = errno;
+    free(*(void **) p);
+    errno = save_errno;
+}
+#define spa_autofree spa_cleanup(_spa_autofree_cleanup_func)
+
+/* ========================================================================== */
+
+static inline void _spa_autoclose_cleanup_func(int *fd)
+{
+    int save_errno = errno;
+    spa_clear_fd(*fd);
+    errno = save_errno;
+}
+#define spa_autoclose spa_cleanup(_spa_autoclose_cleanup_func)
+
+/* ========================================================================== */
+
+#include <stdio.h>
+
+SPA_DEFINE_AUTOPTR_CLEANUP(FILE, FILE, {
+    spa_clear_ptr(*thing, fclose);
+})
+
+/* ========================================================================== */
+
+#include <dirent.h>
+
+SPA_DEFINE_AUTOPTR_CLEANUP(DIR, DIR, {
+    spa_clear_ptr(*thing, closedir);
+})
+
+#else
+
+#define SPA_DEFINE_AUTO_CLEANUP(name, type, ...)
+#define SPA_DEFINE_AUTOPTR_CLEANUP(name, type, ...)
+
+#endif
+
+#endif /* SPA_UTILS_CLEANUP_H */
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/defs.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/defs.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/defs.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/defs.h	2025-06-27 08:03:14.000000000 +0000
@@ -9,20 +9,31 @@
 extern "C" {
 # if __cplusplus >= 201103L
 #  define SPA_STATIC_ASSERT_IMPL(expr, msg, ...) static_assert(expr, msg)
+#  define SPA_ALIGNOF alignof
 # endif
+#elif __STDC_VERSION__ >= 202311L
+#  define SPA_STATIC_ASSERT_IMPL(expr, msg, ...) static_assert(expr, msg)
+#  define SPA_ALIGNOF alignof
 #else
 # include <stdbool.h>
 # if __STDC_VERSION__ >= 201112L
 #  define SPA_STATIC_ASSERT_IMPL(expr, msg, ...) _Static_assert(expr, msg)
+#  define SPA_ALIGNOF _Alignof
 # endif
 #endif
 #ifndef SPA_STATIC_ASSERT_IMPL
 #define SPA_STATIC_ASSERT_IMPL(expr, ...) \
     ((void)sizeof(struct { int spa_static_assertion_failed : 2 * !!(expr) - 1; }))
 #endif
+#ifndef SPA_ALIGNOF
+#define SPA_ALIGNOF __alignof__
+#endif
 
 #define SPA_STATIC_ASSERT(expr, ...) SPA_STATIC_ASSERT_IMPL(expr, ## __VA_ARGS__, "`" #expr "` evaluated to false")
 
+#define SPA_CONCAT_NOEXPAND(a, b) a ## b
+#define SPA_CONCAT(a, b) SPA_CONCAT_NOEXPAND(a, b)
+
 #include <inttypes.h>
 #include <signal.h>
 #include <stdlib.h>
@@ -122,10 +133,10 @@ struct spa_fraction {
  * ```
  */
 #define SPA_FOR_EACH_ELEMENT(arr, ptr) \
-    for ((ptr) = arr; (void*)(ptr) < SPA_PTROFF(arr, sizeof(arr), void); (ptr)++)
+    for ((ptr) = arr; (ptr) < (arr) + SPA_N_ELEMENTS(arr); (ptr)++)
 
 #define SPA_FOR_EACH_ELEMENT_VAR(arr, var) \
-    for (__typeof__((arr)[0])* var = arr; (void*)(var) < SPA_PTROFF(arr, sizeof(arr), void); (var)++)
+    for (__typeof__((arr)[0])* var = arr; (var) < (arr) + SPA_N_ELEMENTS(arr); (var)++)
 
 #define SPA_ABS(a)            \
 ({                    \
@@ -156,6 +167,10 @@ struct spa_fraction {
 ({                            \
     fminf(fmaxf(v, low), high);            \
 })
+#define SPA_CLAMPD(v,low,high)                \
+({                            \
+    fmin(fmax(v, low), high);            \
+})
 
 
 #define SPA_SWAP(a,b)                    \
@@ -171,6 +186,16 @@ struct spa_fraction {
     x;                \
 })
 
+/** 3-way comparison. NaN > NaN and NaN > finite numbers */
+#define SPA_CMP(a, b)                    \
+({                            \
+    __typeof__(a) _a = (a);                \
+    __typeof__(b) _b = (b);                \
+    (_a > _b) ? 1 : (_a == _b) ? 0 : (_a < _b) ? -1 \
+        : (_a == _a) ? -1 : (_b == _b) ? 1     \
+        : 1;                    \
+})
+
 /**
  * Return the address (buffer + offset) as pointer of \a type
  */
@@ -178,7 +203,6 @@ struct spa_fraction {
 #define SPA_PTROFF_ALIGN(ptr_,offset_,alignment_,type_) \
    SPA_PTR_ALIGN(SPA_PTROFF(ptr_,offset_,type_),alignment_,type_)
 
-
 /**
  * Deprecated, use SPA_PTROFF and SPA_PTROFF_ALIGN instead
  */
@@ -189,9 +213,6 @@ struct spa_fraction {
 
 #define SPA_PTRDIFF(p1,p2) ((intptr_t)(p1) - (intptr_t)(p2))
 
-#define SPA_PTR_TO_INT(p) ((int) ((intptr_t) (p)))
-#define SPA_INT_TO_PTR(u) ((void*) ((intptr_t) (u)))
-
 #define SPA_PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
 #define SPA_UINT32_TO_PTR(u) ((void*) ((uintptr_t) (u)))
 
@@ -233,6 +254,20 @@ struct spa_fraction {
 #define SPA_WARN_UNUSED_RESULT
 #endif
 
+#ifndef SPA_API_IMPL
+#define SPA_API_PROTO static inline
+#define SPA_API_IMPL static inline
+#endif
+
+#ifndef SPA_API_UTILS_DEFS
+ #ifdef SPA_API_IMPL
+  #define SPA_API_UTILS_DEFS SPA_API_IMPL
+ #else
+  #define SPA_API_UTILS_DEFS static inline
+ #endif
+#endif
+
+
 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
 #define SPA_RESTRICT restrict
 #elif defined(__GNUC__) && __GNUC__ >= 4
@@ -265,7 +300,7 @@ struct spa_fraction {
 })
 
 
-#define SPA_PTR_ALIGNMENT(p,align)    ((intptr_t)(p) & ((align)-1))
+#define SPA_PTR_ALIGNMENT(p,align)    ((uintptr_t)(p) & ((align)-1))
 #define SPA_IS_ALIGNED(p,align)        (SPA_PTR_ALIGNMENT(p,align) == 0)
 #define SPA_PTR_ALIGN(p,align,type)    ((type*)SPA_ROUND_UP_N((intptr_t)(p), (intptr_t)(align)))
 
@@ -279,9 +314,51 @@ struct spa_fraction {
 #endif
 #endif
 
+SPA_API_UTILS_DEFS bool spa_ptrinside(const void *p1, size_t s1, const void *p2, size_t s2,
+                                 size_t *remaining)
+{
+    if (SPA_LIKELY((uintptr_t)p1 <= (uintptr_t)p2 && s2 <= s1 &&
+                   (uintptr_t)p2 - (uintptr_t)p1 <= s1 - s2)) {
+        if (remaining != NULL)
+            *remaining = ((uintptr_t)p1 + s1) - ((uintptr_t)p2 + s2);
+        return true;
+    } else {
+        if (remaining != NULL)
+            *remaining = 0;
+        return false;
+    }
+}
+
+SPA_API_UTILS_DEFS bool spa_ptr_inside_and_aligned(const void *p1, size_t s1,
+                                              const void *p2, size_t s2, size_t align,
+                                              size_t *remaining)
+{
+    if (SPA_IS_ALIGNED(p2, align)) {
+        return spa_ptrinside(p1, s1, p2, s2, remaining);
+    } else {
+        if (remaining != NULL)
+            *remaining = 0;
+        return false;
+    }
+}
+
+#define spa_ptr_type_inside(p1, s1, p2, type, remaining) \
+    spa_ptr_inside_and_aligned(p1, s1, p2, sizeof(type), SPA_ALIGNOF(type), remaining)
+
+#define SPA_PTR_TO_INT(p) ((int) ((intptr_t) (p)))
+#define SPA_INT_TO_PTR(u) ((void*) ((intptr_t) (u)))
+
 #define SPA_STRINGIFY_1(...)    #__VA_ARGS__
 #define SPA_STRINGIFY(...)    SPA_STRINGIFY_1(__VA_ARGS__)
 
+struct spa_error_location {
+    int line;
+    int col;
+    size_t len;
+    const char *location;
+    const char *reason;
+};
+
 #define spa_return_if_fail(expr)                    \
     do {                                \
         if (SPA_UNLIKELY(!(expr))) {                \
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/dict.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/dict.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/dict.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/dict.h	2025-06-27 08:03:14.000000000 +0000
@@ -13,6 +13,14 @@ extern "C" {
 
 #include <spa/utils/defs.h>
 
+#ifndef SPA_API_DICT
+ #ifdef SPA_API_IMPL
+  #define SPA_API_DICT SPA_API_IMPL
+ #else
+  #define SPA_API_DICT static inline
+ #endif
+#endif
+
 /**
  * \defgroup spa_dict Dictionary
  * Dictionary data structure
@@ -28,7 +36,8 @@ struct spa_dict_item {
     const char *value;
 };
 
-#define SPA_DICT_ITEM_INIT(key,value) ((struct spa_dict_item) { (key), (value) })
+#define SPA_DICT_ITEM(key,value) ((struct spa_dict_item) { (key), (value) })
+#define SPA_DICT_ITEM_INIT(key,value) SPA_DICT_ITEM(key,value)
 
 struct spa_dict {
 #define SPA_DICT_FLAG_SORTED    (1<<0)        /**< items are sorted */
@@ -37,22 +46,26 @@ struct spa_dict {
     const struct spa_dict_item *items;
 };
 
-#define SPA_DICT_INIT(items,n_items) ((struct spa_dict) { 0, (n_items), (items) })
-#define SPA_DICT_INIT_ARRAY(items) ((struct spa_dict) { 0, SPA_N_ELEMENTS(items), (items) })
+#define SPA_DICT(items,n_items) ((struct spa_dict) { 0, (n_items), (items) })
+#define SPA_DICT_ARRAY(items) SPA_DICT((items),SPA_N_ELEMENTS(items))
+#define SPA_DICT_ITEMS(...) SPA_DICT_ARRAY(((struct spa_dict_item[]) { __VA_ARGS__}))
+
+#define SPA_DICT_INIT(items,n_items) SPA_DICT(items,n_items)
+#define SPA_DICT_INIT_ARRAY(items) SPA_DICT_ARRAY(items)
 
 #define spa_dict_for_each(item, dict)                \
     for ((item) = (dict)->items;                \
          (item) < &(dict)->items[(dict)->n_items];        \
          (item)++)
 
-static inline int spa_dict_item_compare(const void *i1, const void *i2)
+SPA_API_DICT int spa_dict_item_compare(const void *i1, const void *i2)
 {
     const struct spa_dict_item *it1 = (const struct spa_dict_item *)i1,
           *it2 = (const struct spa_dict_item *)i2;
     return strcmp(it1->key, it2->key);
 }
 
-static inline void spa_dict_qsort(struct spa_dict *dict)
+SPA_API_DICT void spa_dict_qsort(struct spa_dict *dict)
 {
     if (dict->n_items > 0)
         qsort((void*)dict->items, dict->n_items, sizeof(struct spa_dict_item),
@@ -60,7 +73,7 @@ static inline void spa_dict_qsort(struct
     SPA_FLAG_SET(dict->flags, SPA_DICT_FLAG_SORTED);
 }
 
-static inline const struct spa_dict_item *spa_dict_lookup_item(const struct spa_dict *dict,
+SPA_API_DICT const struct spa_dict_item *spa_dict_lookup_item(const struct spa_dict *dict,
                                    const char *key)
 {
     const struct spa_dict_item *item;
@@ -83,7 +96,7 @@ static inline const struct spa_dict_item
     return NULL;
 }
 
-static inline const char *spa_dict_lookup(const struct spa_dict *dict, const char *key)
+SPA_API_DICT const char *spa_dict_lookup(const struct spa_dict *dict, const char *key)
 {
     const struct spa_dict_item *item = spa_dict_lookup_item(dict, key);
     return item ? item->value : NULL;
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/endian.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/endian.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/endian.h	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/endian.h	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,26 @@
+/* Spa */
+/* SPDX-FileCopyrightText: Copyright © 2019 Wim Taymans */
+/* SPDX-License-Identifier: MIT */
+
+#ifndef SPA_ENDIAN_H
+#define SPA_ENDIAN_H
+
+#if defined(__FreeBSD__) || defined(__MidnightBSD__)
+#include <sys/endian.h>
+#define bswap_16 bswap16
+#define bswap_32 bswap32
+#define bswap_64 bswap64
+#elif defined(_MSC_VER) && defined(_WIN32)
+#include <stdlib.h>
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#define bswap_16 _byteswap_ushort
+#define bswap_32 _byteswap_ulong
+#define bswap_64 _byteswap_uint64
+#else
+#include <endian.h>
+#include <byteswap.h>
+#endif
+
+#endif /* SPA_ENDIAN_H */
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/enum-types.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/enum-types.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/enum-types.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/enum-types.h	2025-06-27 08:03:14.000000000 +0000
@@ -10,6 +10,12 @@ extern "C" {
 #endif
 
 #include <spa/utils/type.h>
+#include <spa/pod/pod.h>
+
+/**
+ * \addtogroup spa_types
+ * \{
+ */
 
 #define SPA_TYPE_INFO_Direction            SPA_TYPE_INFO_ENUM_BASE "Direction"
 #define SPA_TYPE_INFO_DIRECTION_BASE        SPA_TYPE_INFO_Direction ":"
@@ -20,8 +26,6 @@ static const struct spa_type_info spa_ty
     { 0, 0, NULL, NULL }
 };
 
-#include <spa/pod/pod.h>
-
 #define SPA_TYPE_INFO_Choice            SPA_TYPE_INFO_ENUM_BASE "Choice"
 #define SPA_TYPE_INFO_CHOICE_BASE        SPA_TYPE_INFO_Choice ":"
 
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/hook.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/hook.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/hook.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/hook.h	2025-06-27 08:03:14.000000000 +0000
@@ -12,6 +12,14 @@ extern "C" {
 #include <spa/utils/defs.h>
 #include <spa/utils/list.h>
 
+#ifndef SPA_API_HOOK
+ #ifdef SPA_API_IMPL
+  #define SPA_API_HOOK SPA_API_IMPL
+ #else
+  #define SPA_API_HOOK static inline
+ #endif
+#endif
+
 /** \defgroup spa_interfaces Interfaces
  *
  * \brief Generic implementation of implementation-independent interfaces
@@ -158,10 +166,18 @@ struct spa_interface {
     const type *_f = (const type *) (callbacks)->funcs;            \
     bool _res = SPA_CALLBACK_CHECK(_f,method,vers);                \
     if (SPA_LIKELY(_res))                            \
-        _f->method((callbacks)->data, ## __VA_ARGS__);            \
+        (_f->method)((callbacks)->data, ## __VA_ARGS__);        \
     _res;                                    \
 })
 
+#define spa_callbacks_call_fast(callbacks,type,method,vers,...)            \
+({                                        \
+    const type *_f = (const type *) (callbacks)->funcs;            \
+    (_f->method)((callbacks)->data, ## __VA_ARGS__);            \
+    true;                                    \
+})
+
+
 /**
  * True if the \a callbacks are of version \a vers, false otherwise
  */
@@ -191,9 +207,14 @@ struct spa_interface {
 ({                                        \
     const type *_f = (const type *) (callbacks)->funcs;            \
     if (SPA_LIKELY(SPA_CALLBACK_CHECK(_f,method,vers)))            \
-        res = _f->method((callbacks)->data, ## __VA_ARGS__);        \
+        res = (_f->method)((callbacks)->data, ## __VA_ARGS__);        \
     res;                                    \
 })
+#define spa_callbacks_call_fast_res(callbacks,type,res,method,vers,...)        \
+({                                        \
+    const type *_f = (const type *) (callbacks)->funcs;            \
+    res = (_f->method)((callbacks)->data, ## __VA_ARGS__);            \
+})
 
 /**
  * True if the \a iface's callbacks are of version \a vers, false otherwise
@@ -216,6 +237,9 @@ struct spa_interface {
 #define spa_interface_call(iface,method_type,method,vers,...)            \
     spa_callbacks_call(&(iface)->cb,method_type,method,vers,##__VA_ARGS__)
 
+#define spa_interface_call_fast(iface,method_type,method,vers,...)        \
+    spa_callbacks_call_fast(&(iface)->cb,method_type,method,vers,##__VA_ARGS__)
+
 /**
  * Invoke method named \a method in the callbacks on the given interface object.
  * The \a method_type defines the type of the method struct, not the interface
@@ -226,6 +250,76 @@ struct spa_interface {
 #define spa_interface_call_res(iface,method_type,res,method,vers,...)            \
     spa_callbacks_call_res(&(iface)->cb,method_type,res,method,vers,##__VA_ARGS__)
 
+#define spa_interface_call_fast_res(iface,method_type,res,method,vers,...)        \
+    spa_callbacks_call_fast_res(&(iface)->cb,method_type,res,method,vers,##__VA_ARGS__)
+
+
+#define spa_api_func_v(o,method,version,...)                \
+({                                    \
+    if (SPA_LIKELY(SPA_CALLBACK_CHECK(o,method,version)))        \
+        ((o)->method)(o, ##__VA_ARGS__);            \
+})
+#define spa_api_func_r(rtype,def,o,method,version,...)            \
+({                                    \
+    rtype _res = def;                        \
+    if (SPA_LIKELY(SPA_CALLBACK_CHECK(o,method,version)))        \
+        _res = ((o)->method)(o, ##__VA_ARGS__);            \
+    _res;                                \
+})
+#define spa_api_func_fast(o,method,...)                    \
+({                                    \
+    ((o)->method)(o, ##__VA_ARGS__);                \
+})
+
+#define spa_api_method_v(type,o,method,version,...)            \
+({                                    \
+    struct spa_interface *_i = o;            \
+    spa_interface_call(_i, struct type ##_methods,            \
+            method, version, ##__VA_ARGS__);        \
+})
+#define spa_api_method_r(rtype,def,type,o,method,version,...)        \
+({                                    \
+    rtype _res = def;                        \
+    struct spa_interface *_i = o;            \
+    spa_interface_call_res(_i, struct type ##_methods,        \
+            _res, method, version, ##__VA_ARGS__);        \
+    _res;                                \
+})
+#define spa_api_method_null_v(type,co,o,method,version,...)        \
+({                                    \
+    struct type *_co = co;                        \
+    if (SPA_LIKELY(_co != NULL)) {                    \
+        struct spa_interface *_i = o;                \
+        spa_interface_call(_i, struct type ##_methods,        \
+            method, version, ##__VA_ARGS__);        \
+    }                                \
+})
+#define spa_api_method_null_r(rtype,def,type,co,o,method,version,...)    \
+({                                    \
+    rtype _res = def;                        \
+    struct type *_co = co;                        \
+    if (SPA_LIKELY(_co != NULL)) {                    \
+        struct spa_interface *_i = o;                \
+        spa_interface_call_res(_i, struct type ##_methods,    \
+                _res, method, version, ##__VA_ARGS__);    \
+    }                                \
+    _res;                                \
+})
+#define spa_api_method_fast_v(type,o,method,version,...)        \
+({                                    \
+    struct spa_interface *_i = o;                    \
+    spa_interface_call_fast(_i, struct type ##_methods,        \
+            method, version, ##__VA_ARGS__);        \
+})
+#define spa_api_method_fast_r(rtype,def,type,o,method,version,...)    \
+({                                    \
+    rtype _res = def;                        \
+    struct spa_interface *_i = o;                    \
+    spa_interface_call_fast_res(_i, struct type ##_methods,        \
+            _res, method, version, ##__VA_ARGS__);        \
+    _res;                                \
+})
+
 /**
  * \}
  */
@@ -329,18 +423,18 @@ struct spa_hook {
 };
 
 /** Initialize a hook list to the empty list*/
-static inline void spa_hook_list_init(struct spa_hook_list *list)
+SPA_API_HOOK void spa_hook_list_init(struct spa_hook_list *list)
 {
     spa_list_init(&list->list);
 }
 
-static inline bool spa_hook_list_is_empty(struct spa_hook_list *list)
+SPA_API_HOOK bool spa_hook_list_is_empty(struct spa_hook_list *list)
 {
     return spa_list_is_empty(&list->list);
 }
 
 /** Append a hook. */
-static inline void spa_hook_list_append(struct spa_hook_list *list,
+SPA_API_HOOK void spa_hook_list_append(struct spa_hook_list *list,
                     struct spa_hook *hook,
                     const void *funcs, void *data)
 {
@@ -350,7 +444,7 @@ static inline void spa_hook_list_append(
 }
 
 /** Prepend a hook */
-static inline void spa_hook_list_prepend(struct spa_hook_list *list,
+SPA_API_HOOK void spa_hook_list_prepend(struct spa_hook_list *list,
                      struct spa_hook *hook,
                      const void *funcs, void *data)
 {
@@ -360,7 +454,7 @@ static inline void spa_hook_list_prepend
 }
 
 /** Remove a hook */
-static inline void spa_hook_remove(struct spa_hook *hook)
+SPA_API_HOOK void spa_hook_remove(struct spa_hook *hook)
 {
     if (spa_list_is_initialized(&hook->link))
         spa_list_remove(&hook->link);
@@ -369,14 +463,14 @@ static inline void spa_hook_remove(struc
 }
 
 /** Remove all hooks from the list */
-static inline void spa_hook_list_clean(struct spa_hook_list *list)
+SPA_API_HOOK void spa_hook_list_clean(struct spa_hook_list *list)
 {
     struct spa_hook *h;
     spa_list_consume(h, &list->list, link)
         spa_hook_remove(h);
 }
 
-static inline void
+SPA_API_HOOK void
 spa_hook_list_isolate(struct spa_hook_list *list,
         struct spa_hook_list *save,
         struct spa_hook *hook,
@@ -390,7 +484,7 @@ spa_hook_list_isolate(struct spa_hook_li
     spa_hook_list_append(list, hook, funcs, data);
 }
 
-static inline void
+SPA_API_HOOK void
 spa_hook_list_join(struct spa_hook_list *list,
         struct spa_hook_list *save)
 {
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/list.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/list.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/list.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/list.h	2025-06-27 08:03:14.000000000 +0000
@@ -9,6 +9,16 @@
 extern "C" {
 #endif
 
+#include <spa/utils/defs.h>
+
+#ifndef SPA_API_LIST
+ #ifdef SPA_API_IMPL
+  #define SPA_API_LIST SPA_API_IMPL
+ #else
+  #define SPA_API_LIST static inline
+ #endif
+#endif
+
 /**
  * \defgroup spa_list List
  * Doubly linked list data structure
@@ -26,19 +36,19 @@ struct spa_list {
 
 #define SPA_LIST_INIT(list) ((struct spa_list){ (list), (list) })
 
-static inline void spa_list_init(struct spa_list *list)
+SPA_API_LIST void spa_list_init(struct spa_list *list)
 {
     *list = SPA_LIST_INIT(list);
 }
 
-static inline int spa_list_is_initialized(struct spa_list *list)
+SPA_API_LIST int spa_list_is_initialized(struct spa_list *list)
 {
     return !!list->prev;
 }
 
 #define spa_list_is_empty(l)  ((l)->next == (l))
 
-static inline void spa_list_insert(struct spa_list *list, struct spa_list *elem)
+SPA_API_LIST void spa_list_insert(struct spa_list *list, struct spa_list *elem)
 {
     elem->prev = list;
     elem->next = list->next;
@@ -46,7 +56,7 @@ static inline void spa_list_insert(struc
     elem->next->prev = elem;
 }
 
-static inline void spa_list_insert_list(struct spa_list *list, struct spa_list *other)
+SPA_API_LIST void spa_list_insert_list(struct spa_list *list, struct spa_list *other)
 {
     if (spa_list_is_empty(other))
         return;
@@ -56,7 +66,7 @@ static inline void spa_list_insert_list(
     list->next = other->next;
 }
 
-static inline void spa_list_remove(struct spa_list *elem)
+SPA_API_LIST void spa_list_remove(struct spa_list *elem)
 {
     elem->prev->next = elem->next;
     elem->next->prev = elem->prev;
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/string.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/string.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/string.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/string.h	2025-06-27 08:03:14.000000000 +0000
@@ -17,6 +17,14 @@ extern "C" {
 
 #include <spa/utils/defs.h>
 
+#ifndef SPA_API_STRING
+ #ifdef SPA_API_IMPL
+  #define SPA_API_STRING SPA_API_IMPL
+ #else
+  #define SPA_API_STRING static inline
+ #endif
+#endif
+
 /**
  * \defgroup spa_string String handling
  * String handling utilities
@@ -33,7 +41,7 @@ extern "C" {
  * If both \a a and \a b are NULL, the two are considered equal.
  *
  */
-static inline bool spa_streq(const char *s1, const char *s2)
+SPA_API_STRING bool spa_streq(const char *s1, const char *s2)
 {
     return SPA_LIKELY(s1 && s2) ? strcmp(s1, s2) == 0 : s1 == s2;
 }
@@ -43,7 +51,7 @@ static inline bool spa_streq(const char
  *
  * If both \a a and \a b are NULL, the two are considered equal.
  */
-static inline bool spa_strneq(const char *s1, const char *s2, size_t len)
+SPA_API_STRING bool spa_strneq(const char *s1, const char *s2, size_t len)
 {
     return SPA_LIKELY(s1 && s2) ? strncmp(s1, s2, len) == 0 : s1 == s2;
 }
@@ -54,7 +62,7 @@ static inline bool spa_strneq(const char
  * A \a s is NULL, it never starts with the given \a prefix. A \a prefix of
  * NULL is a bug in the caller.
  */
-static inline bool spa_strstartswith(const char *s, const char *prefix)
+SPA_API_STRING bool spa_strstartswith(const char *s, const char *prefix)
 {
     if (SPA_UNLIKELY(s == NULL))
         return false;
@@ -70,7 +78,7 @@ static inline bool spa_strstartswith(con
  * A \a s is NULL, it never ends with the given \a suffix. A \a suffix of
  * NULL is a bug in the caller.
  */
-static inline bool spa_strendswith(const char *s, const char *suffix)
+SPA_API_STRING bool spa_strendswith(const char *s, const char *suffix)
 {
     size_t l1, l2;
 
@@ -92,7 +100,7 @@ static inline bool spa_strendswith(const
  *
  * \return true on success, false otherwise
  */
-static inline bool spa_atoi32(const char *str, int32_t *val, int base)
+SPA_API_STRING bool spa_atoi32(const char *str, int32_t *val, int base)
 {
     char *endptr;
     long v;
@@ -120,7 +128,7 @@ static inline bool spa_atoi32(const char
  *
  * \return true on success, false otherwise
  */
-static inline bool spa_atou32(const char *str, uint32_t *val, int base)
+SPA_API_STRING bool spa_atou32(const char *str, uint32_t *val, int base)
 {
     char *endptr;
     unsigned long long v;
@@ -148,7 +156,7 @@ static inline bool spa_atou32(const char
  *
  * \return true on success, false otherwise
  */
-static inline bool spa_atoi64(const char *str, int64_t *val, int base)
+SPA_API_STRING bool spa_atoi64(const char *str, int64_t *val, int base)
 {
     char *endptr;
     long long v;
@@ -173,7 +181,7 @@ static inline bool spa_atoi64(const char
  *
  * \return true on success, false otherwise
  */
-static inline bool spa_atou64(const char *str, uint64_t *val, int base)
+SPA_API_STRING bool spa_atou64(const char *str, uint64_t *val, int base)
 {
     char *endptr;
     unsigned long long v;
@@ -196,7 +204,7 @@ static inline bool spa_atou64(const char
  *
  * \return true on success, false otherwise
  */
-static inline bool spa_atob(const char *str)
+SPA_API_STRING bool spa_atob(const char *str)
 {
     return spa_streq(str, "true") || spa_streq(str, "1");
 }
@@ -210,7 +218,7 @@ static inline bool spa_atob(const char *
  * number on error.
  */
 SPA_PRINTF_FUNC(3, 0)
-static inline int spa_vscnprintf(char *buffer, size_t size, const char *format, va_list args)
+SPA_API_STRING int spa_vscnprintf(char *buffer, size_t size, const char *format, va_list args)
 {
     int r;
 
@@ -233,7 +241,7 @@ static inline int spa_vscnprintf(char *b
  * number on error.
  */
 SPA_PRINTF_FUNC(3, 4)
-static inline int spa_scnprintf(char *buffer, size_t size, const char *format, ...)
+SPA_API_STRING int spa_scnprintf(char *buffer, size_t size, const char *format, ...)
 {
     int r;
     va_list args;
@@ -253,7 +261,7 @@ static inline int spa_scnprintf(char *bu
  *
  * \return the result float.
  */
-static inline float spa_strtof(const char *str, char **endptr)
+SPA_API_STRING float spa_strtof(const char *str, char **endptr)
 {
 #ifndef __LOCALE_C_ONLY
     static locale_t locale = NULL;
@@ -279,7 +287,7 @@ static inline float spa_strtof(const cha
  *
  * \return true on success, false otherwise
  */
-static inline bool spa_atof(const char *str, float *val)
+SPA_API_STRING bool spa_atof(const char *str, float *val)
 {
     char *endptr;
     float v;
@@ -303,7 +311,7 @@ static inline bool spa_atof(const char *
  *
  * \return the result float.
  */
-static inline double spa_strtod(const char *str, char **endptr)
+SPA_API_STRING double spa_strtod(const char *str, char **endptr)
 {
 #ifndef __LOCALE_C_ONLY
     static locale_t locale = NULL;
@@ -329,7 +337,7 @@ static inline double spa_strtod(const ch
  *
  * \return true on success, false otherwise
  */
-static inline bool spa_atod(const char *str, double *val)
+SPA_API_STRING bool spa_atod(const char *str, double *val)
 {
     char *endptr;
     double v;
@@ -346,7 +354,7 @@ static inline bool spa_atod(const char *
     return true;
 }
 
-static inline char *spa_dtoa(char *str, size_t size, double val)
+SPA_API_STRING char *spa_dtoa(char *str, size_t size, double val)
 {
     int i, l;
     l = spa_scnprintf(str, size, "%f", val);
@@ -362,15 +370,17 @@ struct spa_strbuf {
     size_t pos;
 };
 
-static inline void spa_strbuf_init(struct spa_strbuf *buf, char *buffer, size_t maxsize)
+SPA_API_STRING void spa_strbuf_init(struct spa_strbuf *buf, char *buffer, size_t maxsize)
 {
     buf->buffer = buffer;
     buf->maxsize = maxsize;
     buf->pos = 0;
+    if (maxsize > 0)
+        buf->buffer[0] = '\0';
 }
 
 SPA_PRINTF_FUNC(2, 3)
-static inline int spa_strbuf_append(struct spa_strbuf *buf, const char *fmt, ...)
+SPA_API_STRING int spa_strbuf_append(struct spa_strbuf *buf, const char *fmt, ...)
 {
     size_t remain = buf->maxsize - buf->pos;
     ssize_t written;
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/type-info.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/type-info.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/type-info.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/type-info.h	2025-06-27 08:03:14.000000000 +0000
@@ -20,10 +20,6 @@ extern "C" {
 #define SPA_TYPE_ROOT    spa_types
 #endif
 
-static inline bool spa_type_is_a(const char *type, const char *parent)
-{
-    return type != NULL && parent != NULL && strncmp(type, parent, strlen(parent)) == 0;
-}
 
 #include <spa/utils/type.h>
 #include <spa/utils/enum-types.h>
@@ -83,6 +79,7 @@ static const struct spa_type_info spa_ty
     { SPA_TYPE_OBJECT_Profiler, SPA_TYPE_Object, SPA_TYPE_INFO_Profiler, spa_type_profiler },
     { SPA_TYPE_OBJECT_ParamLatency, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Latency, spa_type_param_latency },
     { SPA_TYPE_OBJECT_ParamProcessLatency, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_ProcessLatency, spa_type_param_process_latency },
+    { SPA_TYPE_OBJECT_ParamTag, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Tag, spa_type_param_tag },
 
     { 0, 0, NULL, NULL }
 };
diff -pruN 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/type.h 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/type.h
--- 24.0.1+9-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/type.h	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/unix/native/libpipewire/include/spa/utils/type.h	2025-06-27 08:03:14.000000000 +0000
@@ -10,6 +10,15 @@ extern "C" {
 #endif
 
 #include <spa/utils/defs.h>
+#include <spa/utils/string.h>
+
+#ifndef SPA_API_TYPE
+ #ifdef SPA_API_IMPL
+  #define SPA_API_TYPE SPA_API_IMPL
+ #else
+  #define SPA_API_TYPE static inline
+ #endif
+#endif
 
 /** \defgroup spa_types Types
  * Data type information enumerations
@@ -78,6 +87,7 @@ enum {
     SPA_TYPE_OBJECT_Profiler,
     SPA_TYPE_OBJECT_ParamLatency,
     SPA_TYPE_OBJECT_ParamProcessLatency,
+    SPA_TYPE_OBJECT_ParamTag,
     _SPA_TYPE_OBJECT_LAST,            /**< not part of ABI */
 
     /* vendor extensions */
@@ -122,6 +132,47 @@ struct spa_type_info {
     const struct spa_type_info *values;
 };
 
+SPA_API_TYPE bool spa_type_is_a(const char *type, const char *parent)
+{
+    return type != NULL && parent != NULL && strncmp(type, parent, strlen(parent)) == 0;
+}
+
+SPA_API_TYPE const char *spa_type_short_name(const char *name)
+{
+    const char *h;
+    if ((h = strrchr(name, ':')) != NULL)
+        name = h + 1;
+    return name;
+}
+
+SPA_API_TYPE uint32_t spa_type_from_short_name(const char *name,
+        const struct spa_type_info *info, uint32_t unknown)
+{
+    int i;
+    for (i = 0; info[i].name; i++) {
+        if (spa_streq(name, spa_type_short_name(info[i].name)))
+            return info[i].type;
+    }
+    return unknown;
+}
+SPA_API_TYPE const char * spa_type_to_name(uint32_t type,
+        const struct spa_type_info *info, const char *unknown)
+{
+    int i;
+    for (i = 0; info[i].name; i++) {
+        if (info[i].type == type)
+            return info[i].name;
+    }
+    return unknown;
+}
+
+SPA_API_TYPE const char * spa_type_to_short_name(uint32_t type,
+        const struct spa_type_info *info, const char *unknown)
+{
+    const char *n = spa_type_to_name(type, info, unknown);
+    return n ? spa_type_short_name(n) : NULL;
+}
+
 /**
  * \}
  */
diff -pruN 24.0.1+9-1/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp 24.0.2+12-1/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp
--- 24.0.1+9-1/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -47,6 +47,8 @@ extern "C" {
 #define MIDIIN_CHECK_ERROR
 #endif
 
+#include <inttypes.h>
+
 /*
  * Callback from the MIDI device for all messages.
  */
@@ -55,8 +57,8 @@ void CALLBACK MIDI_IN_PutMessage( HMIDII
 
     MidiDeviceHandle* handle = (MidiDeviceHandle*) dwInstance;
 
-    TRACE3("> MIDI_IN_PutMessage, hMidiIn: %x, wMsg: %x, dwInstance: %x\n", hMidiIn, wMsg, dwInstance);
-    TRACE2("                      dwParam1: %x, dwParam2: %x\n", dwParam1, dwParam2);
+    TRACE3("> MIDI_IN_PutMessage, hMidiIn: 0x%" PRIxPTR ", wMsg: %x, dwInstance: 0x%" PRIxPTR "\n", (uintptr_t)hMidiIn, wMsg, (uintptr_t)dwInstance);
+    TRACE2("                      dwParam1: 0x%" PRIxPTR ", dwParam2: 0x%" PRIxPTR "\n", (uintptr_t)dwParam1, (uintptr_t)dwParam2);
 
     switch(wMsg) {
 
@@ -70,8 +72,8 @@ void CALLBACK MIDI_IN_PutMessage( HMIDII
 
     case MIM_MOREDATA:
     case MIM_DATA:
-        TRACE3("  MIDI_IN_PutMessage: MIM_MOREDATA or MIM_DATA. status=%x  data1=%x  data2=%x\n",
-               dwParam1 & 0xFF, (dwParam1 & 0xFF00)>>8, (dwParam1 & 0xFF0000)>>16);
+        TRACE3("  MIDI_IN_PutMessage: MIM_MOREDATA or MIM_DATA. status=%x data1=%x data2=%x\n",
+               (int)(dwParam1 & 0xFF), (int)((dwParam1 & 0xFF00)>>8), (int)((dwParam1 & 0xFF0000)>>16));
         if (handle!=NULL && handle->queue!=NULL && handle->platformData) {
             MIDI_QueueAddShort(handle->queue,
                                // queue stores packedMsg in big endian
diff -pruN 24.0.1+9-1/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c 24.0.2+12-1/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c
--- 24.0.1+9-1/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -251,7 +251,7 @@ void printInfo(PortInfo* info) {
     TRACE5(" PortInfo %p: handle=%p, mixerIndex=%d, dstLineCount=%d, dstLines=%p, ", info, (void*) info->handle, info->mixerIndex, info->dstLineCount, info->dstLines);
     TRACE5("srcLineCount=%d, srcLines=%p, targetPortCount=%d, sourcePortCount=%d, ports=%p, ", info->srcLineCount, info->srcLines, info->targetPortCount, info->sourcePortCount, info->ports);
     TRACE3("maxControlCount=%d, usedControlIDs=%d, controlIDs=%p \n", info->maxControlCount, info->usedControlIDs, info->controlIDs);
-    TRACE2("usedMuxData=%d, muxData=%p, controlIDs=%p \n", info->usedMuxData, info->muxData);
+    TRACE3("usedMuxData=%d, muxData=%p, controlIDs=%p \n", info->usedMuxData, info->muxData, info->controlIDs);
 }
 
 #endif // USE_TRACE
diff -pruN 24.0.1+9-1/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java 24.0.2+12-1/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java
--- 24.0.1+9-1/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -26,6 +26,7 @@
 package jdk.internal.net.http;
 
 import java.net.InetSocketAddress;
+import java.net.http.HttpClient;
 import java.util.Arrays;
 import java.util.ArrayDeque;
 import java.util.List;
@@ -75,7 +76,7 @@ abstract class AbstractAsyncSSLConnectio
                                ServerName serverName, int port,
                                String[] alpn) {
         super(addr, client);
-        this.sniServerNames = formSNIServerNames(serverName);
+        this.sniServerNames = formSNIServerNames(serverName, client);
         SSLContext context = client.theSSLContext();
         sslParameters = createSSLParameters(client, this.sniServerNames, alpn);
         Log.logParams(sslParameters);
@@ -102,6 +103,20 @@ abstract class AbstractAsyncSSLConnectio
         return false;
     }
 
+    /**
+     * Returns the {@link SSLParameters} to be used by the {@link SSLEngine} for this connection.
+     * <p>
+     * The returned {@code SSLParameters} will have its {@link SNIServerName}s set to the given
+     * {@code sniServerNames}. If {@code alpn} is non-null then the returned {@code SSLParameters}
+     * will have its {@linkplain SSLParameters#getApplicationProtocols() application layer protocols}
+     * set to this value. All other parameters in the returned {@code SSLParameters} will be
+     * copied over from {@link HttpClient#sslParameters()} of the given {@code client}.
+     *
+     * @param client         the HttpClient
+     * @param sniServerNames the SNIServerName(s)
+     * @param alpn           the application layer protocols
+     * @return the SSLParameters to be set on the SSLEngine used by this connection.
+     */
     private static SSLParameters createSSLParameters(HttpClientImpl client,
                                                      List<SNIServerName> sniServerNames,
                                                      String[] alpn) {
@@ -132,22 +147,39 @@ abstract class AbstractAsyncSSLConnectio
         return sslParameters;
     }
 
-    private static List<SNIServerName> formSNIServerNames(final ServerName serverName) {
-        if (serverName == null) {
-            return List.of();
-        }
-        if (!serverName.isLiteral()) {
-            String name = serverName.name();
-            if (name != null && name.length() > 0) {
+    /**
+     * Returns a list of {@link SNIServerName}s that are expected to be used to
+     * configure the {@link SSLEngine} used by this connection.
+     * <p>
+     * The given {@code serverName} is given preference, and if it is not null and
+     * is not an IP address literal, then the returned list will contain only one
+     * {@code SNIServerName} formed out of the {@code serverName}. If {@code serverName}
+     * is null or is an IP address literal then the {@code SNIServerName}(s)
+     * configured through {@link HttpClient#sslParameters()} will be returned. If none have
+     * been configured, then an empty list is returned.
+     *
+     * @param serverName the {@link ServerName}, typically computed based on the request URI
+     * @param client     the {@code HttpClient}
+     * @return a list of {@code SNIServerName}s to be used by the {@code SSLEngine}
+     *         of this connection.
+     */
+    private static List<SNIServerName> formSNIServerNames(final ServerName serverName,
+                                                          final HttpClientImpl client) {
+        if (serverName != null && !serverName.isLiteral()) {
+            final String name = serverName.name();
+            if (name != null && !name.isEmpty()) {
                 return List.of(new SNIHostName(name));
             }
         }
-        return List.of();
+        // fallback on any SNIServerName(s) configured through HttpClient.sslParameters()
+        final SSLParameters clientSSLParams = client.sslParameters();
+        final List<SNIServerName> clientConfigured = clientSSLParams.getServerNames();
+        return clientConfigured != null ? clientConfigured : List.of();
     }
 
-    private static SSLEngine createEngine(SSLContext context, String serverName, int port,
+    private static SSLEngine createEngine(SSLContext context, String peerHost, int port,
                                           SSLParameters sslParameters) {
-        SSLEngine engine = context.createSSLEngine(serverName, port);
+        SSLEngine engine = context.createSSLEngine(peerHost, port);
         engine.setUseClientMode(true);
 
         engine.setSSLParameters(sslParameters);
diff -pruN 24.0.1+9-1/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java 24.0.2+12-1/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java
--- 24.0.1+9-1/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java	2025-06-27 08:03:14.000000000 +0000
@@ -1884,3 +1884,4 @@ final class HttpClientImpl extends HttpC
     }
 
 }
+
diff -pruN 24.0.1+9-1/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java 24.0.2+12-1/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java
--- 24.0.1+9-1/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -39,16 +39,17 @@ import java.util.Optional;
 import java.net.http.HttpClient;
 import java.net.http.HttpHeaders;
 import java.net.http.HttpRequest;
+import java.util.function.BiPredicate;
 
 import jdk.internal.net.http.common.Alpns;
 import jdk.internal.net.http.common.HttpHeadersBuilder;
 import jdk.internal.net.http.common.Utils;
 import jdk.internal.net.http.websocket.WebSocketRequest;
 
-import static java.net.Authenticator.RequestorType.PROXY;
 import static java.net.Authenticator.RequestorType.SERVER;
 import static jdk.internal.net.http.common.Utils.ALLOWED_HEADERS;
 import static jdk.internal.net.http.common.Utils.ProxyHeaders;
+import static jdk.internal.net.http.common.Utils.copyProxy;
 
 public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
 
@@ -127,15 +128,7 @@ public class HttpRequestImpl extends Htt
             this.systemHeadersBuilder.setHeader("User-Agent", USER_AGENT);
         }
         this.uri = requestURI;
-        if (isWebSocket) {
-            // WebSocket determines and sets the proxy itself
-            this.proxy = ((HttpRequestImpl) request).proxy;
-        } else {
-            if (ps != null)
-                this.proxy = retrieveProxy(ps, uri);
-            else
-                this.proxy = null;
-        }
+        this.proxy = retrieveProxy(request, ps, uri);
         this.expectContinue = request.expectContinue();
         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
         this.requestPublisher = request.bodyPublisher().orElse(null);
@@ -156,7 +149,11 @@ public class HttpRequestImpl extends Htt
                                                             String method,
                                                             HttpRequestImpl other,
                                                             boolean mayHaveBody) {
-        return new HttpRequestImpl(uri, method, other, mayHaveBody);
+        if (uri.getScheme().equalsIgnoreCase(other.uri.getScheme()) &&
+                uri.getRawAuthority().equals(other.uri.getRawAuthority())) {
+            return new HttpRequestImpl(uri, method, other, mayHaveBody, Optional.empty());
+        }
+        return new HttpRequestImpl(uri, method, other, mayHaveBody, Optional.of(Utils.ALLOWED_REDIRECT_HEADERS));
     }
 
     /** Returns a new instance suitable for authentication. */
@@ -176,9 +173,19 @@ public class HttpRequestImpl extends Htt
                             String method,
                             HttpRequestImpl other,
                             boolean mayHaveBody) {
+        this(uri, method, other, mayHaveBody, Optional.empty());
+    }
+
+    private HttpRequestImpl(URI uri,
+                            String method,
+                            HttpRequestImpl other,
+                            boolean mayHaveBody,
+                            Optional<BiPredicate<String, String>> redirectHeadersFilter) {
         assert method == null || Utils.isValidName(method);
-        this.method = method == null? "GET" : method;
-        this.userHeaders = other.userHeaders;
+        this.method = method == null ? "GET" : method;
+        HttpHeaders userHeaders = redirectHeadersFilter.isPresent() ?
+                HttpHeaders.of(other.userHeaders.map(), redirectHeadersFilter.get()) : other.userHeaders;
+        this.userHeaders = userHeaders;
         this.isWebSocket = other.isWebSocket;
         this.systemHeadersBuilder = new HttpHeadersBuilder();
         if (userHeaders.firstValue("User-Agent").isEmpty()) {
@@ -292,16 +299,27 @@ public class HttpRequestImpl extends Htt
     @Override
     public boolean expectContinue() { return expectContinue; }
 
-    /** Retrieves the proxy, from the given ProxySelector, if there is one. */
-    private static Proxy retrieveProxy(ProxySelector ps, URI uri) {
-        Proxy proxy = null;
-        List<Proxy> pl = ps.select(uri);
-        if (!pl.isEmpty()) {
-            Proxy p = pl.get(0);
-            if (p.type() == Proxy.Type.HTTP)
-                proxy = p;
+    /** Retrieves a copy of the proxy either from the given {@link HttpRequest} or {@link ProxySelector}, if there is one. */
+    private static Proxy retrieveProxy(HttpRequest request, ProxySelector ps, URI uri) {
+
+        // WebSocket determines and sets the proxy itself
+        if (request instanceof HttpRequestImpl requestImpl && requestImpl.isWebSocket) {
+            return requestImpl.proxy;
+        }
+
+        // Try to find a matching one from the `ProxySelector`
+        if (ps != null) {
+            List<Proxy> pl = ps.select(uri);
+            if (!pl.isEmpty()) {
+                Proxy p = pl.getFirst();
+                if (p.type() == Proxy.Type.HTTP) {
+                    return copyProxy(p);
+                }
+            }
         }
-        return proxy;
+
+        return null;
+
     }
 
     InetSocketAddress proxy() {
@@ -317,7 +335,7 @@ public class HttpRequestImpl extends Htt
     @Override
     public void setProxy(Proxy proxy) {
         assert isWebSocket;
-        this.proxy = proxy;
+        this.proxy = copyProxy(proxy);
     }
 
     @Override
@@ -408,3 +426,4 @@ public class HttpRequestImpl extends Htt
         }
     }
 }
+
diff -pruN 24.0.1+9-1/src/java.net.http/share/classes/jdk/internal/net/http/WindowUpdateSender.java 24.0.2+12-1/src/java.net.http/share/classes/jdk/internal/net/http/WindowUpdateSender.java
--- 24.0.1+9-1/src/java.net.http/share/classes/jdk/internal/net/http/WindowUpdateSender.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.net.http/share/classes/jdk/internal/net/http/WindowUpdateSender.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -117,18 +117,24 @@ abstract class WindowUpdateSender {
      *             the caller wants to buffer.
      */
     boolean canBufferUnprocessedBytes(int len) {
-        return !checkWindowSizeExceeded(unprocessed.addAndGet(len));
+        long buffered, processed;
+        // get received before unprocessed in order to avoid counting
+        // unprocessed bytes that might get unbuffered asynchronously
+        // twice.
+        processed = received.get();
+        buffered = unprocessed.addAndGet(len);
+        return !checkWindowSizeExceeded(processed, buffered);
     }
 
     // adds the provided amount to the amount of already
-    // received and processed bytes and checks whether the
+    // processed and processed bytes and checks whether the
     // flow control window is exceeded. If so, take
     // corrective actions and return true.
-    private boolean checkWindowSizeExceeded(long len) {
+    private boolean checkWindowSizeExceeded(long processed, long len) {
         // because windowSize is bound by Integer.MAX_VALUE
         // we will never reach the point where received.get() + len
         // could overflow
-        long rcv = received.get() + len;
+        long rcv = processed + len;
         return rcv > windowSize && windowSizeExceeded(rcv);
     }
 
@@ -143,6 +149,7 @@ abstract class WindowUpdateSender {
      * @param delta the amount of processed bytes to release
      */
     void processed(int delta) {
+        assert delta >= 0 : delta;
         long rest = unprocessed.addAndGet(-delta);
         assert rest >= 0;
         update(delta);
@@ -166,6 +173,7 @@ abstract class WindowUpdateSender {
      * @return the amount of remaining unprocessed bytes
      */
     long released(int delta) {
+        assert delta >= 0 : delta;
         long rest = unprocessed.addAndGet(-delta);
         assert rest >= 0;
         return rest;
@@ -195,7 +203,7 @@ abstract class WindowUpdateSender {
             try {
                 int tosend = (int)Math.min(received.get(), Integer.MAX_VALUE);
                 if (tosend > limit) {
-                    received.getAndAdd(-tosend);
+                    received.addAndGet(-tosend);
                     sendWindowUpdate(tosend);
                 }
             } finally {
diff -pruN 24.0.1+9-1/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java 24.0.2+12-1/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java
--- 24.0.1+9-1/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -38,6 +38,7 @@ import java.io.UncheckedIOException;
 import java.lang.System.Logger.Level;
 import java.net.ConnectException;
 import java.net.InetSocketAddress;
+import java.net.Proxy;
 import java.net.URI;
 import java.net.http.HttpHeaders;
 import java.net.http.HttpTimeoutException;
@@ -77,7 +78,6 @@ import sun.net.www.HeaderParser;
 
 import static java.lang.String.format;
 import static java.nio.charset.StandardCharsets.US_ASCII;
-import static java.util.stream.Collectors.joining;
 import static java.net.Authenticator.RequestorType.PROXY;
 import static java.net.Authenticator.RequestorType.SERVER;
 
@@ -187,6 +187,18 @@ public final class Utils {
     public static final BiPredicate<String, String>
             ALLOWED_HEADERS = (header, unused) -> !DISALLOWED_HEADERS_SET.contains(header);
 
+    private static final Set<String> DISALLOWED_REDIRECT_HEADERS_SET = getDisallowedRedirectHeaders();
+
+    private static Set<String> getDisallowedRedirectHeaders() {
+        Set<String> headers = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+        headers.addAll(Set.of("Authorization", "Cookie", "Origin", "Referer", "Host"));
+
+        return Collections.unmodifiableSet(headers);
+    }
+
+    public static final BiPredicate<String, String>
+            ALLOWED_REDIRECT_HEADERS = (header, _) -> !DISALLOWED_REDIRECT_HEADERS_SET.contains(header);
+
     public static final BiPredicate<String, String> VALIDATE_USER_HEADER =
             (name, value) -> {
                 assert name != null : "null header name";
@@ -308,6 +320,17 @@ public final class Utils {
                       : ! PROXY_AUTH_DISABLED_SCHEMES.isEmpty();
     }
 
+    /**
+     * Creates a new {@link Proxy} instance for the given proxy iff it is
+     * neither null, {@link Proxy#NO_PROXY Proxy.NO_PROXY}, nor already a
+     * {@code Proxy} instance.
+     */
+    public static Proxy copyProxy(Proxy proxy) {
+        return proxy == null || proxy.getClass() == Proxy.class
+                ? proxy
+                : new Proxy(proxy.type(), proxy.address());
+    }
+
     // WebSocket connection Upgrade headers
     private static final String HEADER_CONNECTION = "Connection";
     private static final String HEADER_UPGRADE    = "Upgrade";
@@ -1134,3 +1157,4 @@ public final class Utils {
         return sb.toString();
     }
 }
+
diff -pruN 24.0.1+9-1/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java 24.0.2+12-1/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java
--- 24.0.1+9-1/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -59,6 +59,7 @@ import java.util.TreeSet;
 import java.util.concurrent.CompletableFuture;
 
 import static java.lang.String.format;
+import static jdk.internal.net.http.common.Utils.copyProxy;
 import static jdk.internal.net.http.common.Utils.isValidName;
 import static jdk.internal.net.http.common.Utils.stringOf;
 
@@ -363,7 +364,8 @@ public class OpeningHandshake {
         if (proxy.type() != Proxy.Type.HTTP) {
             return null;
         }
-        return proxy;
+        return copyProxy(proxy);
     }
 
 }
+
diff -pruN 24.0.1+9-1/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java 24.0.2+12-1/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java
--- 24.0.1+9-1/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -57,7 +57,7 @@ import org.xml.sax.XMLReader;
  * @author G. Todd Miller
  * @author Morten Jorgensen
  * @author John Howard (johnh@schemasoft.com)
- * @LastModified: Dec 2024
+ * @LastModified: Feb 2025
  */
 public final class XSLTC {
 
@@ -734,7 +734,6 @@ public final class XSLTC {
      */
     public void setPackageName(String packageName) {
         _packageName = Objects.requireNonNull(packageName);
-        if (_className != null) setClassName(_className);
     }
 
     /**
diff -pruN 24.0.1+9-1/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java 24.0.2+12-1/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java
--- 24.0.1+9-1/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -87,7 +87,7 @@ import org.xml.sax.XMLReader;
  * @author G. Todd Miller
  * @author Morten Jorgensen
  * @author Santiago Pericas-Geertsen
- * @LastModified: Dec 2024
+ * @LastModified: Feb 2025
  */
 public class TransformerFactoryImpl
     extends SAXTransformerFactory implements SourceLoader
@@ -999,9 +999,6 @@ public class TransformerFactoryImpl
         // Set the attributes for translet generation
         int outputType = XSLTC.BYTEARRAY_OUTPUT;
         if (_generateTranslet || _autoTranslet) {
-            // Set the translet name
-            xsltc.setClassName(getTransletBaseName(source));
-
             if (_destinationDirectory != null)
                 xsltc.setDestDirectory(_destinationDirectory);
             else {
@@ -1015,8 +1012,11 @@ public class TransformerFactoryImpl
                 }
             }
 
+            // set package name
             if (_packageName != null)
                 xsltc.setPackageName(_packageName);
+            // Set the translet name
+            xsltc.setClassName(getTransletBaseName(source));
 
             if (_jarFileName != null) {
                 xsltc.setJarFileName(_jarFileName);
diff -pruN 24.0.1+9-1/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java 24.0.2+12-1/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java
--- 24.0.1+9-1/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2022, 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
@@ -83,7 +83,7 @@ public class BasicTypeDataBase implement
   public Type lookupType(String cTypeName, boolean throwException) {
     Type type = nameToTypeMap.get(cTypeName);
     if (type == null && throwException) {
-      throw new RuntimeException("No type named \"" + cTypeName + "\" in database");
+      throw new RuntimeException("No type named \"" + cTypeName + "\" present in type database");
     }
     return type;
   }
diff -pruN 24.0.1+9-1/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_de.java 24.0.2+12-1/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_de.java
--- 24.0.1+9-1/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_de.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_de.java	2025-06-27 08:03:14.000000000 +0000
@@ -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
@@ -173,12 +173,9 @@ public class Resources_de extends java.u
         {"with.algparams.weak", "%1$s mit %2$s (schwach)"},
         {"with.disabled", "%s (deaktiviert)"},
         {"with.algparams.disabled", "%1$s mit %2$s (deaktiviert)"},
-        {"key.bit", "%d-Bit-Schl\u00FCssel"},
-        {"key.bit.weak", "%d-Bit-Schl\u00FCssel (schwach)"},
-        {"key.bit.eccurve.weak", "%1$d-Bit-%2$s-Schl\u00FCssel (schwach)"},
-        {"key.bit.disabled", "%d-Bit-Schl\u00FCssel (deaktiviert)"},
-        {"key.bit.eccurve.disabled", "%1$d-Bit-%2$s-Schl\u00FCssel (deaktiviert)"},
-        {"unknown.size", "unbekannte Gr\u00F6\u00DFe"},
+        {"key.bit", "%s-Schl\u00FCssel"},
+        {"key.bit.weak", "%s Schl\u00FCssel (schwach)"},
+        {"key.bit.disabled", "%s Schl\u00FCssel (deaktiviert)"},
         {"nonexistent.entries.found", "Diese JAR-Datei enth\u00E4lt signierte Eintr\u00E4ge f\u00FCr Dateien, die nicht vorhanden sind. Weitere Details finden Sie in der Verbose-Ausgabe (-verbose)."},
         {"external.file.attributes.detected", "POSIX-Dateiberechtigung und/oder Symlink-Attribute erkannt. Diese Attribute werden bei der Signatur ignoriert und sind nicht durch die Signatur gesch\u00FCtzt."},
 
@@ -295,10 +292,12 @@ public class Resources_de extends java.u
                 "Der %1$s-Digestalgorithmus gilt als Sicherheitsrisiko. Dieser Algorithmus wird in einem zuk\u00FCnftigen Update deaktiviert."},
         {"The.signature.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.",
                 "Der %1$s-Signaturalgorithmus gilt als Sicherheitsrisiko. Dieser Algorithmus wird in einem zuk\u00FCnftigen Update deaktiviert."},
-        {"The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk..This.key.size.will.be.disabled.in.a.future.update.",
-                "Der %1$s-Signaturschl\u00FCssel hat eine Schl\u00FCsselgr\u00F6\u00DFe von %2$d. Das gilt als Sicherheitsrisiko. Diese Schl\u00FCsselgr\u00F6\u00DFe wird in einem zuk\u00FCnftigen Update deaktiviert."},
-        {"The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk.and.is.disabled.",
-                "Der %1$s-Signaturschl\u00FCssel hat eine Schl\u00FCsselgr\u00F6\u00DFe von %2$d. Das gilt als Sicherheitsrisiko und ist deaktiviert."},
+        {"size.bit.alg",
+                "%1$d-Bit %2$s"},
+        {"The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.",
+                "Der %s Signaturschl\u00FCssel wird als Sicherheitsrisiko betrachtet. Wird in einem zuk\u00FCnftigen Update deaktiviert."},
+        {"The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.",
+                "Der %s Signaturschl\u00FCssel wird als Sicherheitsrisiko betrachtet und ist deaktiviert."},
         {"This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1",
                  "Diese JAR-Datei enth\u00E4lt Eintr\u00E4ge, deren Zertifikatskette ung\u00FCltig ist. Grund: %s"},
         {"This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1",
diff -pruN 24.0.1+9-1/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_ja.java 24.0.2+12-1/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_ja.java
--- 24.0.1+9-1/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_ja.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_ja.java	2025-06-27 08:03:14.000000000 +0000
@@ -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
@@ -173,12 +173,9 @@ public class Resources_ja extends java.u
         {"with.algparams.weak", "%2$s\u3092\u4F7F\u7528\u3057\u305F%1$s (\u5F31)"},
         {"with.disabled", "%s (\u7121\u52B9)"},
         {"with.algparams.disabled", "%2$s\u3092\u4F7F\u7528\u3057\u305F%1$s (\u7121\u52B9)"},
-        {"key.bit", "%d\u30D3\u30C3\u30C8\u30FB\u30AD\u30FC"},
-        {"key.bit.weak", "%d\u30D3\u30C3\u30C8\u30FB\u30AD\u30FC(\u5F31)"},
-        {"key.bit.eccurve.weak", "%1$d\u30D3\u30C3\u30C8%2$s\u30AD\u30FC(\u5F31)"},
-        {"key.bit.disabled", "%d\u30D3\u30C3\u30C8\u30FB\u30AD\u30FC (\u7121\u52B9)"},
-        {"key.bit.eccurve.disabled", "%1$d\u30D3\u30C3\u30C8%2$s\u30AD\u30FC(\u7121\u52B9)"},
-        {"unknown.size", "\u4E0D\u660E\u30B5\u30A4\u30BA"},
+        {"key.bit", "%s\u30AD\u30FC"},
+        {"key.bit.weak", "%s\u30AD\u30FC(\u5F31\u3044)"},
+        {"key.bit.disabled", "%s\u30AD\u30FC(\u7121\u52B9)"},
         {"nonexistent.entries.found", "\u3053\u306Ejar\u306B\u306F\u3001\u5B58\u5728\u3057\u306A\u3044\u30D5\u30A1\u30A4\u30EB\u306E\u7F72\u540D\u6E08\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u307E\u3059\u3002\u8A73\u7D30\u306F\u3001-verbose\u51FA\u529B\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002"},
         {"external.file.attributes.detected", "POSIX\u30D5\u30A1\u30A4\u30EB\u6A29\u9650\u307E\u305F\u306Fsymlink(\u3042\u308B\u3044\u306F\u305D\u306E\u4E21\u65B9)\u306E\u5C5E\u6027\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F\u3002\u7F72\u540D\u4E2D\u306F\u3053\u308C\u3089\u306E\u5C5E\u6027\u306F\u7121\u8996\u3055\u308C\u3001\u7F72\u540D\u306B\u3088\u3063\u3066\u4FDD\u8B77\u3055\u308C\u307E\u305B\u3093\u3002"},
 
@@ -295,10 +292,12 @@ public class Resources_ja extends java.u
                 "%1$s\u30C0\u30A4\u30B8\u30A7\u30B9\u30C8\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u306F\u3001\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u307E\u3059\u3002\u3053\u306E\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u306F\u5C06\u6765\u306E\u66F4\u65B0\u3067\u7121\u52B9\u5316\u3055\u308C\u307E\u3059\u3002"},
         {"The.signature.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.",
                 "%1$s\u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u306F\u3001\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u307E\u3059\u3002\u3053\u306E\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u306F\u5C06\u6765\u306E\u66F4\u65B0\u3067\u7121\u52B9\u5316\u3055\u308C\u307E\u3059\u3002"},
-        {"The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk..This.key.size.will.be.disabled.in.a.future.update.",
-                "%1$s\u7F72\u540D\u30AD\u30FC\u306B\u306F%2$d\u306E\u30AD\u30FC\u30FB\u30B5\u30A4\u30BA\u304C\u3042\u308A\u3001\u3053\u308C\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u307E\u3059\u3002\u3053\u306E\u30AD\u30FC\u30FB\u30B5\u30A4\u30BA\u306F\u5C06\u6765\u306E\u66F4\u65B0\u3067\u7121\u52B9\u5316\u3055\u308C\u307E\u3059\u3002"},
-        {"The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk.and.is.disabled.",
-                "%1$s\u7F72\u540D\u30AD\u30FC\u306B\u306F%2$d\u306E\u30AD\u30FC\u30FB\u30B5\u30A4\u30BA\u304C\u3042\u308A\u3001\u3053\u308C\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u307E\u3059\u3002"},
+        {"size.bit.alg",
+                "%1$d\u30D3\u30C3\u30C8%2$s"},
+        {"The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.",
+                "%s\u7F72\u540D\u30AD\u30FC\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u307E\u3059\u3002\u4ECA\u5F8C\u306E\u66F4\u65B0\u3067\u306F\u7121\u52B9\u306B\u306A\u308A\u307E\u3059\u3002"},
+        {"The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.",
+                "%s\u7F72\u540D\u30AD\u30FC\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u3001\u7121\u52B9\u306B\u306A\u3063\u3066\u3044\u307E\u3059\u3002"},
         {"This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1",
                  "\u3053\u306Ejar\u306B\u306F\u3001\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u304C\u7121\u52B9\u306A\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002\u7406\u7531: %s"},
         {"This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1",
diff -pruN 24.0.1+9-1/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java 24.0.2+12-1/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java
--- 24.0.1+9-1/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java	2025-06-27 08:03:14.000000000 +0000
@@ -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
@@ -173,12 +173,9 @@ public class Resources_zh_CN extends jav
         {"with.algparams.weak", "%1$s \u4F7F\u7528 %2$s\uFF08\u5F31\uFF09"},
         {"with.disabled", "%s\uFF08\u7981\u7528\uFF09"},
         {"with.algparams.disabled", "%1$s \u4F7F\u7528 %2$s\uFF08\u7981\u7528\uFF09"},
-        {"key.bit", "%d \u4F4D\u5BC6\u94A5"},
-        {"key.bit.weak", "%d \u4F4D\u5BC6\u94A5 (\u5F31)"},
-        {"key.bit.eccurve.weak", "%1$d \u4F4D %2$s \u5BC6\u94A5 (\u5F31)"},
-        {"key.bit.disabled", "%d \u4F4D\u5BC6\u94A5\uFF08\u7981\u7528\uFF09"},
-        {"key.bit.eccurve.disabled", "%1$d \u4F4D %2$s \u5BC6\u94A5\uFF08\u7981\u7528\uFF09"},
-        {"unknown.size", "\u672A\u77E5\u5927\u5C0F"},
+        {"key.bit", "%s \u5BC6\u94A5"},
+        {"key.bit.weak", "%s \u5BC6\u94A5\uFF08\u5F31\uFF09"},
+        {"key.bit.disabled", "%s \u5BC6\u94A5\uFF08\u5DF2\u7981\u7528\uFF09"},
         {"nonexistent.entries.found", "\u6B64 jar \u7684\u6587\u4EF6\u5305\u542B\u4E0D\u5B58\u5728\u7684\u7B7E\u540D\u6761\u76EE\u3002\u6709\u5173\u66F4\u591A\u8BE6\u7EC6\u4FE1\u606F\uFF0C\u8BF7\u53C2\u89C1 -verbose \u8F93\u51FA\u3002"},
         {"external.file.attributes.detected", "\u68C0\u6D4B\u5230 POSIX \u6587\u4EF6\u6743\u9650\u548C/\u6216 symlink \u5C5E\u6027\u3002\u8FD9\u4E9B\u5C5E\u6027\u5728\u8FDB\u884C\u7B7E\u540D\u65F6\u4F1A\u88AB\u5FFD\u7565\uFF0C\u4E0D\u53D7\u8BE5\u7B7E\u540D\u7684\u4FDD\u62A4\u3002"},
 
@@ -295,10 +292,12 @@ public class Resources_zh_CN extends jav
                 "%1$s \u6458\u8981\u7B97\u6CD5\u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\u3002\u6B64\u7B97\u6CD5\u5C06\u5728\u672A\u6765\u7684\u66F4\u65B0\u4E2D\u88AB\u7981\u7528\u3002"},
         {"The.signature.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.",
                 "%1$s \u7B7E\u540D\u7B97\u6CD5\u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\u3002\u6B64\u7B97\u6CD5\u5C06\u5728\u672A\u6765\u7684\u66F4\u65B0\u4E2D\u88AB\u7981\u7528\u3002"},
-        {"The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk..This.key.size.will.be.disabled.in.a.future.update.",
-                "%1$s \u7B7E\u540D\u5BC6\u94A5\u7684\u5BC6\u94A5\u5927\u5C0F %2$d \u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\u3002\u6B64\u5BC6\u94A5\u5927\u5C0F\u5C06\u5728\u672A\u6765\u7684\u66F4\u65B0\u4E2D\u88AB\u7981\u7528\u3002"},
-        {"The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk.and.is.disabled.",
-                "%1$s \u7B7E\u540D\u5BC6\u94A5\u7684\u5BC6\u94A5\u5927\u5C0F %2$d \u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\u800C\u4E14\u88AB\u7981\u7528\u3002"},
+        {"size.bit.alg",
+                "%1$d \u4F4D %2$s"},
+        {"The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.",
+                "%s \u7B7E\u540D\u5BC6\u94A5\u88AB\u89C6\u4E3A\u5B89\u5168\u98CE\u9669\u3002\u5728\u5C06\u6765\u7684\u66F4\u65B0\u4E2D\u5C06\u7981\u7528\u5B83\u3002"},
+        {"The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.",
+                "%s \u7B7E\u540D\u5BC6\u94A5\u88AB\u89C6\u4E3A\u5B89\u5168\u98CE\u9669\u5E76\u88AB\u7981\u7528\u3002"},
         {"This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1",
                  "\u6B64 jar \u5305\u542B\u5176\u8BC1\u4E66\u94FE\u65E0\u6548\u7684\u6761\u76EE\u3002\u539F\u56E0: %s"},
         {"This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1",
diff -pruN 24.0.1+9-1/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JRTArchive.java 24.0.2+12-1/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JRTArchive.java
--- 24.0.1+9-1/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JRTArchive.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JRTArchive.java	2025-06-27 08:03:14.000000000 +0000
@@ -45,6 +45,7 @@ import java.util.HexFormat;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -76,6 +77,7 @@ public class JRTArchive implements Archi
     private final Map<String, ResourceDiff> resDiff;
     private final boolean errorOnModifiedFile;
     private final TaskHelper taskHelper;
+    private final Set<String> upgradeableFiles;
 
     /**
      * JRTArchive constructor
@@ -86,12 +88,15 @@ public class JRTArchive implements Archi
      *        install aborts the link.
      * @param perModDiff The lib/modules (a.k.a jimage) diff for this module,
      *                   possibly an empty list if there are no differences.
+     * @param taskHelper The task helper instance.
+     * @param upgradeableFiles The set of files that are allowed for upgrades.
      */
     JRTArchive(String module,
                Path path,
                boolean errorOnModifiedFile,
                List<ResourceDiff> perModDiff,
-               TaskHelper taskHelper) {
+               TaskHelper taskHelper,
+               Set<String> upgradeableFiles) {
         this.module = module;
         this.path = path;
         this.ref = ModuleFinder.ofSystem()
@@ -105,6 +110,7 @@ public class JRTArchive implements Archi
         this.resDiff = Objects.requireNonNull(perModDiff).stream()
                             .collect(Collectors.toMap(ResourceDiff::getName, Function.identity()));
         this.taskHelper = taskHelper;
+        this.upgradeableFiles = upgradeableFiles;
     }
 
     @Override
@@ -217,7 +223,8 @@ public class JRTArchive implements Archi
 
                         // Read from the base JDK image.
                         Path path = BASE.resolve(m.resPath);
-                        if (shaSumMismatch(path, m.hashOrTarget, m.symlink)) {
+                        if (!isUpgradeableFile(m.resPath) &&
+                                shaSumMismatch(path, m.hashOrTarget, m.symlink)) {
                             if (errorOnModifiedFile) {
                                 String msg = taskHelper.getMessage("err.runtime.link.modified.file", path.toString());
                                 IOException cause = new IOException(msg);
@@ -239,6 +246,17 @@ public class JRTArchive implements Archi
         }
     }
 
+    /**
+     * Certain files in a module are considered upgradeable. That is,
+     * their hash sums aren't checked.
+     *
+     * @param resPath The resource path of the file to check for upgradeability.
+     * @return {@code true} if the file is upgradeable. {@code false} otherwise.
+     */
+    private boolean isUpgradeableFile(String resPath) {
+        return upgradeableFiles.contains(resPath);
+    }
+
     static boolean shaSumMismatch(Path res, String expectedSha, boolean isSymlink) {
         if (isSymlink) {
             return false;
diff -pruN 24.0.1+9-1/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/LinkableRuntimeImage.java 24.0.2+12-1/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/LinkableRuntimeImage.java
--- 24.0.1+9-1/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/LinkableRuntimeImage.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/LinkableRuntimeImage.java	2025-06-27 08:03:14.000000000 +0000
@@ -28,7 +28,10 @@ package jdk.tools.jlink.internal;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Path;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Scanner;
+import java.util.Set;
 
 import jdk.tools.jlink.internal.runtimelink.ResourceDiff;
 
@@ -42,6 +45,9 @@ public class LinkableRuntimeImage {
     public static final String RESPATH_PATTERN = "jdk/tools/jlink/internal/runtimelink/fs_%s_files";
     // The diff files per module for supporting linking from the run-time image
     public static final String DIFF_PATTERN = "jdk/tools/jlink/internal/runtimelink/diff_%s";
+    // meta data for upgradable files
+    private static final String UPGRADEABLE_FILES_PATTERN = "jdk/tools/jlink/internal/runtimelink/upgrade_files_%s.conf";
+    private static final Module JDK_JLINK_MOD = LinkableRuntimeImage.class.getModule();
 
     /**
      * In order to be able to show whether or not a runtime is capable of
@@ -62,7 +68,38 @@ public class LinkableRuntimeImage {
 
     private static InputStream getDiffInputStream(String module) throws IOException {
         String resourceName = String.format(DIFF_PATTERN, module);
-        return LinkableRuntimeImage.class.getModule().getResourceAsStream(resourceName);
+        return JDK_JLINK_MOD.getResourceAsStream(resourceName);
+    }
+
+    private static Set<String> upgradeableFiles(String module) {
+        String resourceName = String.format(UPGRADEABLE_FILES_PATTERN, module);
+        InputStream filesIn = null;
+        try {
+            filesIn = JDK_JLINK_MOD.getResourceAsStream(resourceName);
+        } catch (IOException e) {
+            throw new AssertionError("Unexpected IO error getting res stream");
+        }
+        if (filesIn == null) {
+            // no upgradeable files
+            return Set.of();
+        }
+        Set<String> upgradeableFiles = new HashSet<>();
+        final InputStream in = filesIn;
+        try (in;
+             Scanner scanner = new Scanner(filesIn)) {
+            while (scanner.hasNextLine()) {
+                String line = scanner.nextLine();
+                if (line.trim().startsWith("#")) {
+                    // Skip comments
+                    continue;
+                }
+                upgradeableFiles.add(line);
+            }
+        } catch (IOException e) {
+            throw new AssertionError("Failure to retrieve upgradeable files for " +
+                                     "module " + module, e);
+        }
+        return upgradeableFiles;
     }
 
     public static Archive newArchive(String module,
@@ -81,7 +118,13 @@ public class LinkableRuntimeImage {
             throw new AssertionError("Failure to retrieve resource diff for " +
                                      "module " + module, e);
         }
-        return new JRTArchive(module, path, !ignoreModifiedRuntime, perModuleDiff, taskHelper);
+        Set<String> upgradeableFiles = upgradeableFiles(module);
+        return new JRTArchive(module,
+                              path,
+                              !ignoreModifiedRuntime,
+                              perModuleDiff,
+                              taskHelper,
+                              upgradeableFiles);
     }
 
 
diff -pruN 24.0.1+9-1/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/upgrade_files_java.base.conf 24.0.2+12-1/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/upgrade_files_java.base.conf
--- 24.0.1+9-1/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/upgrade_files_java.base.conf	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/upgrade_files_java.base.conf	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,4 @@
+# Configuration for resource paths of files allowed to be
+# upgraded (in java.base)
+lib/security/cacerts
+lib/tzdb.dat
diff -pruN 24.0.1+9-1/src/jdk.jpackage/share/classes/jdk/jpackage/internal/JLinkBundlerHelper.java 24.0.2+12-1/src/jdk.jpackage/share/classes/jdk/jpackage/internal/JLinkBundlerHelper.java
--- 24.0.1+9-1/src/jdk.jpackage/share/classes/jdk/jpackage/internal/JLinkBundlerHelper.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/jdk.jpackage/share/classes/jdk/jpackage/internal/JLinkBundlerHelper.java	2025-06-27 08:03:14.000000000 +0000
@@ -47,6 +47,7 @@ import java.util.regex.Matcher;
 import java.util.spi.ToolProvider;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
+
 import jdk.internal.module.ModulePath;
 
 
@@ -99,8 +100,10 @@ final class JLinkBundlerHelper {
 
         ModuleFinder finder = createModuleFinder(paths);
 
+        // Don't perform service bindings by default as outlined by JEP 343
+        // and JEP 392
         return Configuration.empty()
-                .resolveAndBind(finder, ModuleFinder.of(), roots)
+                .resolve(finder, ModuleFinder.of(), roots)
                 .modules()
                 .stream()
                 .map(ResolvedModule::name)
diff -pruN 24.0.1+9-1/src/jdk.management/macosx/native/libmanagement_ext/UnixOperatingSystem.c 24.0.2+12-1/src/jdk.management/macosx/native/libmanagement_ext/UnixOperatingSystem.c
--- 24.0.1+9-1/src/jdk.management/macosx/native/libmanagement_ext/UnixOperatingSystem.c	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/src/jdk.management/macosx/native/libmanagement_ext/UnixOperatingSystem.c	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2020, 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
@@ -63,6 +63,9 @@ Java_com_sun_management_internal_Operati
 
     jlong used_delta  = used - last_used;
     jlong total_delta = total - last_total;
+    if (total_delta == 0) {
+        return 0;
+    }
 
     jdouble cpu = (jdouble) used_delta / total_delta;
 
diff -pruN 24.0.1+9-1/test/hotspot/gtest/runtime/test_cgroupSubsystem_linux.cpp 24.0.2+12-1/test/hotspot/gtest/runtime/test_cgroupSubsystem_linux.cpp
--- 24.0.1+9-1/test/hotspot/gtest/runtime/test_cgroupSubsystem_linux.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/gtest/runtime/test_cgroupSubsystem_linux.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -27,6 +27,7 @@
 
 #include "runtime/os.hpp"
 #include "cgroupSubsystem_linux.hpp"
+#include "cgroupUtil_linux.hpp"
 #include "cgroupV1Subsystem_linux.hpp"
 #include "cgroupV2Subsystem_linux.hpp"
 #include "unittest.hpp"
@@ -434,9 +435,16 @@ TEST(cgroupTest, set_cgroupv1_subsystem_
     "/user.slice/user-1000.slice/user@1000.service", // cgroup_path
     "/sys/fs/cgroup/mem"                             // expected_path
   };
-  int length = 2;
+  TestCase container_moving_cgroup = {
+    "/sys/fs/cgroup/cpu,cpuacct",                                            // mount_path
+    "/system.slice/garden.service/garden/good/2f57368b-0eda-4e52-64d8-af5c", // root_path
+    "/system.slice/garden.service/garden/bad/2f57368b-0eda-4e52-64d8-af5c",  // cgroup_path
+    "/sys/fs/cgroup/cpu,cpuacct"                                             // expected_path
+  };
+  int length = 3;
   TestCase* testCases[] = { &host,
-                            &container_engine };
+                            &container_engine,
+                            &container_moving_cgroup };
   for (int i = 0; i < length; i++) {
     CgroupV1Controller* ctrl = new CgroupV1Controller( (char*)testCases[i]->root_path,
                                                        (char*)testCases[i]->mount_path,
@@ -446,6 +454,72 @@ TEST(cgroupTest, set_cgroupv1_subsystem_
   }
 }
 
+TEST(cgroupTest, set_cgroupv1_subsystem_path_adjusted) {
+  TestCase memory = {
+    "/sys/fs/cgroup/memory", // mount_path
+    "/",                     // root_path
+    "../test1",              // cgroup_path
+    "/sys/fs/cgroup/memory"  // expected_path
+  };
+  TestCase cpu = {
+    "/sys/fs/cgroup/cpu", // mount_path
+    "/",                  // root_path
+    "../../test2",        // cgroup_path
+    "/sys/fs/cgroup/cpu"  // expected_path
+  };
+  CgroupCpuController* ccc = new CgroupV1CpuController(CgroupV1Controller((char*)cpu.root_path,
+                                                                          (char*)cpu.mount_path,
+                                                                          true /* read-only mount */));
+  ccc->set_subsystem_path((char*)cpu.cgroup_path);
+  EXPECT_TRUE(ccc->needs_hierarchy_adjustment());
+
+  CgroupUtil::adjust_controller(ccc);
+  ASSERT_STREQ(cpu.expected_path, ccc->subsystem_path());
+  EXPECT_FALSE(ccc->needs_hierarchy_adjustment());
+
+  CgroupMemoryController* cmc = new CgroupV1MemoryController(CgroupV1Controller((char*)memory.root_path,
+                                                                                (char*)memory.mount_path,
+                                                                                true /* read-only mount */));
+  cmc->set_subsystem_path((char*)memory.cgroup_path);
+  EXPECT_TRUE(cmc->needs_hierarchy_adjustment());
+
+  CgroupUtil::adjust_controller(cmc);
+  ASSERT_STREQ(memory.expected_path, cmc->subsystem_path());
+  EXPECT_FALSE(cmc->needs_hierarchy_adjustment());
+}
+
+TEST(cgroupTest, set_cgroupv2_subsystem_path_adjusted) {
+  TestCase memory = {
+    "/sys/fs/cgroup", // mount_path
+    "/",              // root_path
+    "../test1",       // cgroup_path
+    "/sys/fs/cgroup"  // expected_path
+  };
+  TestCase cpu = {
+    "/sys/fs/cgroup", // mount_path
+    "/",              // root_path
+    "../../test2",    // cgroup_path
+    "/sys/fs/cgroup"  // expected_path
+  };
+  CgroupCpuController* ccc = new CgroupV2CpuController(CgroupV2Controller((char*)cpu.mount_path,
+                                                                          (char*)cpu.cgroup_path,
+                                                                          true /* read-only mount */));
+  EXPECT_TRUE(ccc->needs_hierarchy_adjustment());
+
+  CgroupUtil::adjust_controller(ccc);
+  ASSERT_STREQ(cpu.expected_path, ccc->subsystem_path());
+  EXPECT_FALSE(ccc->needs_hierarchy_adjustment());
+
+  CgroupMemoryController* cmc = new CgroupV2MemoryController(CgroupV2Controller((char*)memory.mount_path,
+                                                                                (char*)memory.cgroup_path,
+                                                                                true /* read-only mount */));
+  EXPECT_TRUE(cmc->needs_hierarchy_adjustment());
+
+  CgroupUtil::adjust_controller(cmc);
+  ASSERT_STREQ(memory.expected_path, cmc->subsystem_path());
+  EXPECT_FALSE(cmc->needs_hierarchy_adjustment());
+}
+
 TEST(cgroupTest, set_cgroupv2_subsystem_path) {
   TestCase at_mount_root = {
     "/sys/fs/cgroup",       // mount_path
diff -pruN 24.0.1+9-1/test/hotspot/gtest/runtime/test_os_linux.cpp 24.0.2+12-1/test/hotspot/gtest/runtime/test_os_linux.cpp
--- 24.0.1+9-1/test/hotspot/gtest/runtime/test_os_linux.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/gtest/runtime/test_os_linux.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -445,26 +445,28 @@ TEST_VM(os_linux, decoder_get_source_inf
 #endif // clang
 
 #ifdef __GLIBC__
+#ifndef ADDRESS_SANITIZER
 TEST_VM(os_linux, glibc_mallinfo_wrapper) {
   // Very basic test. Call it. That proves that resolution and invocation works.
   os::Linux::glibc_mallinfo mi;
   bool did_wrap = false;
 
-  os::Linux::get_mallinfo(&mi, &did_wrap);
-
   void* p = os::malloc(2 * K, mtTest);
   ASSERT_NOT_NULL(p);
 
+  os::Linux::get_mallinfo(&mi, &did_wrap);
+
   // We should see total allocation values > 0
   ASSERT_GE((mi.uordblks + mi.hblkhd), 2 * K);
 
-  // These values also should exceed some reasonable size.
+  // These values also should less than some reasonable size.
   ASSERT_LT(mi.fordblks, 2 * G);
   ASSERT_LT(mi.uordblks, 2 * G);
   ASSERT_LT(mi.hblkhd, 2 * G);
 
   os::free(p);
 }
+#endif // ADDRESS_SANITIZER
 #endif // __GLIBC__
 
 #endif // LINUX
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/ProblemList-Virtual.txt 24.0.2+12-1/test/hotspot/jtreg/ProblemList-Virtual.txt
--- 24.0.1+9-1/test/hotspot/jtreg/ProblemList-Virtual.txt	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/ProblemList-Virtual.txt	2025-06-27 08:03:14.000000000 +0000
@@ -103,7 +103,9 @@ gc/g1/TestMixedGCLiveThreshold.java#25pe
 
 gc/arguments/TestNewSizeThreadIncrease.java 0000000 generic-all
 gc/g1/TestSkipRebuildRemsetPhase.java 0000000 generic-all
+runtime/classFileParserBug/TestEmptyBootstrapMethodsAttr.java JDK-8346442 generic-all
 runtime/ErrorHandling/MachCodeFramesInErrorFile.java 0000000 generic-all
+runtime/logging/LoaderConstraintsTest.java JDK-8346442 generic-all
 runtime/Thread/AsyncExceptionOnMonitorEnter.java 0000000 generic-all
 runtime/Thread/StopAtExit.java 0000000 generic-all
 runtime/handshake/HandshakeWalkStackTest.java 0000000 generic-all
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/ProblemList.txt 24.0.2+12-1/test/hotspot/jtreg/ProblemList.txt
--- 24.0.1+9-1/test/hotspot/jtreg/ProblemList.txt	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/ProblemList.txt	2025-06-27 08:03:14.000000000 +0000
@@ -190,3 +190,6 @@ vmTestbase/nsk/jdwp/ThreadReference/Forc
 vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi005/TestDescription.java 8076494 windows-x64
 
 vmTestbase/nsk/monitoring/ThreadMXBean/findMonitorDeadlockedThreads/find006/TestDescription.java 8310144 macosx-aarch64
+
+# Mechanically added:
+containers/docker/TestMemoryWithSubgroups.java 8352926 linux-x64
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndHeapDump.java 24.0.2+12-1/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndHeapDump.java
--- 24.0.1+9-1/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndHeapDump.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndHeapDump.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 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
@@ -54,7 +54,7 @@ public class TestReduceAllocationAndHeap
                 HeapDumper.class.getName()
             };
 
-            ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(dumperArgs);
+            ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(dumperArgs);
             Process p = pb.start();
             OutputAnalyzer out = new OutputAnalyzer(p);
 
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndPointerComparisons.java 24.0.2+12-1/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndPointerComparisons.java
--- 24.0.1+9-1/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndPointerComparisons.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndPointerComparisons.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8347718
+ * @summary Check that Reduce Allocation Merges correctly handle "NE" pointer comparisons.
+ * @requires vm.flagless & vm.compiler2.enabled & vm.opt.final.EliminateAllocations
+ * @run main/othervm -XX:CompileCommand=compileonly,*TestReduceAllocationAndPointerComparisons*::*
+ *                   -XX:CompileCommand=dontinline,*TestReduceAllocationAndPointerComparisons*::*
+ *                   -XX:-TieredCompilation -Xcomp -server
+ *                   compiler.c2.TestReduceAllocationAndPointerComparisons
+ * @run main compiler.c2.TestReduceAllocationAndPointerComparisons
+ */
+
+package compiler.c2;
+
+public class TestReduceAllocationAndPointerComparisons {
+    public static void main(String[] args) {
+        for (int i=0; i<50000; i++) {
+            if (test(true) == false) {
+                throw new RuntimeException("Unexpected result.");
+            }
+        }
+    }
+
+    public static boolean test(boolean b) {
+        MyClass obj = new MyClass();
+
+        for (int i = 0; i < 100_000; ++i) { }
+
+        obj = b ? obj : new MyClass();
+        obj = b ? obj : new MyClass();
+
+        if (obj == null) {
+            return false;
+        }
+
+        return b;
+    }
+
+    static class MyClass {
+    }
+}
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/compiler/calls/NativeCalls.java 24.0.2+12-1/test/hotspot/jtreg/compiler/calls/NativeCalls.java
--- 24.0.1+9-1/test/hotspot/jtreg/compiler/calls/NativeCalls.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/compiler/calls/NativeCalls.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
  * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -104,7 +105,7 @@ public class NativeCalls {
             ArrayList<String> command = new ArrayList<String>(v.options);
             command.addAll(baseOptions);
             command.add(v.compile);
-            ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(command);
+            ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(command);
             OutputAnalyzer analyzer = new OutputAnalyzer(pb.start());
             analyzer.shouldHaveExitValue(0);
             System.out.println(analyzer.getOutput());
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/compiler/codecache/CheckCodeCacheInfo.java 24.0.2+12-1/test/hotspot/jtreg/compiler/codecache/CheckCodeCacheInfo.java
--- 24.0.1+9-1/test/hotspot/jtreg/compiler/codecache/CheckCodeCacheInfo.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/compiler/codecache/CheckCodeCacheInfo.java	2025-06-27 08:03:14.000000000 +0000
@@ -56,9 +56,14 @@ public class CheckCodeCacheInfo {
                        + pair
                        + "Non-nmethod blobs:\\n"
                        + " #\\d+ runtime = " + entry
+                       + " #\\d+ upcall = " + entry
                        + " #\\d+ uncommon trap = " + entry
                        + " #\\d+ deoptimization = " + entry
+                       + " #\\d+ exception = " + entry
+                       + " #\\d+ safepoint = " + entry
                        + " #\\d+ adapter = " + entry
+                       + " #\\d+ mh_adapter = " + entry
+                       + " #\\d+ vtable = " + entry
                        + " #\\d+ buffer blob = " + entry
                        + " #\\d+ other = " + entry;
     }
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/compiler/debug/TestStress.java 24.0.2+12-1/test/hotspot/jtreg/compiler/debug/TestStress.java
--- 24.0.1+9-1/test/hotspot/jtreg/compiler/debug/TestStress.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/compiler/debug/TestStress.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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,6 +32,7 @@ import jdk.test.lib.Asserts;
  * @key stress randomness
  * @bug 8252219 8256535 8317349
  * @requires vm.debug == true & vm.compiler2.enabled
+ * @requires vm.flagless
  * @summary Tests that stress compilations with the same seed yield the same
  *          IGVN, CCP, and macro expansion traces.
  * @library /test/lib /
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/compiler/inlining/TestDuplicatedLateInliningOutput.java 24.0.2+12-1/test/hotspot/jtreg/compiler/inlining/TestDuplicatedLateInliningOutput.java
--- 24.0.1+9-1/test/hotspot/jtreg/compiler/inlining/TestDuplicatedLateInliningOutput.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/compiler/inlining/TestDuplicatedLateInliningOutput.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2023, Red Hat and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -27,6 +28,7 @@
  * @summary late inlining output shouldn't produce both failure and success messages
  * @library /test/lib
  * @requires vm.compiler2.enabled
+ * @requires vm.flagless
  * @run driver compiler.inlining.TestDuplicatedLateInliningOutput
  */
 
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/compiler/intrinsics/TestContinuationPinningAndEA.java 24.0.2+12-1/test/hotspot/jtreg/compiler/intrinsics/TestContinuationPinningAndEA.java
--- 24.0.1+9-1/test/hotspot/jtreg/compiler/intrinsics/TestContinuationPinningAndEA.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/compiler/intrinsics/TestContinuationPinningAndEA.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8347997
+ * @summary Test that Continuation.pin() and unpin() intrinsics work with EA.
+ * @modules java.base/jdk.internal.vm
+ * @run main TestContinuationPinningAndEA
+ */
+
+import jdk.internal.vm.Continuation;
+
+public class TestContinuationPinningAndEA {
+
+    static class FailsEA {
+        final Object o;
+
+        public FailsEA() throws Throwable {
+            o = new Object();
+            Continuation.pin();
+            Continuation.unpin();
+        }
+    }
+
+    static class Crashes {
+        final Object o;
+
+        public Crashes() throws Throwable {
+            Continuation.pin();
+            Continuation.unpin();
+            o = new Object();
+        }
+    }
+
+    static void test_FailsEA() throws Throwable {
+        for (int i = 0; i < 10_000; ++i) {
+            new FailsEA();
+        }
+    }
+
+    static void test_Crashes() throws Throwable {
+        for (int i = 0; i < 10_000; ++i) {
+            new Crashes();
+        }
+    }
+
+    public static void main(String[] args) throws Throwable {
+        int iterations = 100;
+        for (int i = 0; i < iterations; ++i) {
+            test_FailsEA();
+        }
+        for (int i = 0; i < iterations; ++i) {
+            test_Crashes();
+        }
+    }
+}
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/compiler/jsr292/MHDeoptTest.java 24.0.2+12-1/test/hotspot/jtreg/compiler/jsr292/MHDeoptTest.java
--- 24.0.1+9-1/test/hotspot/jtreg/compiler/jsr292/MHDeoptTest.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/compiler/jsr292/MHDeoptTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.jsr292;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
+
+/*
+ * @test
+ * @bug 8336042
+ * @library /test/lib /
+ *
+ * @run main/bootclasspath/othervm -Xbatch -XX:-TieredCompilation compiler.jsr292.MHDeoptTest
+ *
+ */
+public class MHDeoptTest {
+
+    static int xx = 0;
+
+    public static void main(String[] args) throws Throwable {
+        MethodHandle mh1 = MethodHandles.lookup().findStatic(MHDeoptTest.class, "body1", MethodType.methodType(int.class));
+        MethodHandle mh2 = MethodHandles.lookup().findStatic(MHDeoptTest.class, "body2", MethodType.methodType(int.class));
+        MethodHandle[] arr = new MethodHandle[] {mh2, mh1};
+
+        for (MethodHandle mh : arr) {
+            for (int i = 1; i < 50_000; i++) {
+                xx = i;
+                mainLink(mh);
+            }
+        }
+
+    }
+
+    static int mainLink(MethodHandle mh) throws Throwable {
+        return (int)mh.invokeExact();
+    }
+
+    static int cnt = 1000;
+
+    static int body1() {
+        int limit = 0x7fff;
+        // uncommon trap
+        if (xx == limit) {
+            // OSR
+            for (int i = 0; i < 50_000; i++) {
+            }
+            ++cnt;
+            ++xx;
+        }
+        if (xx == limit + 1) {
+            return cnt + 1;
+        }
+        return cnt;
+    }
+
+    static int body2() {
+        int limit = 0x7fff;
+        int dummy = 0;
+        // uncommon trap
+        if (xx == limit) {
+            // OSR
+            for (int i = 0; i < 50_000; i++) {
+            }
+            ++cnt;
+            ++xx;
+        }
+        if (xx == limit + 1) {
+            return cnt + 1;
+        }
+        return cnt;
+    }
+
+}
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/compiler/predicates/assertion/TestLoadPinnedAboveAssertionPredicatesAndUsingStore.java 24.0.2+12-1/test/hotspot/jtreg/compiler/predicates/assertion/TestLoadPinnedAboveAssertionPredicatesAndUsingStore.java
--- 24.0.1+9-1/test/hotspot/jtreg/compiler/predicates/assertion/TestLoadPinnedAboveAssertionPredicatesAndUsingStore.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/compiler/predicates/assertion/TestLoadPinnedAboveAssertionPredicatesAndUsingStore.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @bug 8347018
+ * @summary Test that stores cloned with clone_up_backedge_goo() are not pinned above Assertion Predicates on which a
+ *          load node is pinned at which will later fail in scheduling.
+ * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,*TestLoadPinnedAboveAssertionPredicatesAndUsingStore::test
+ *                   compiler.predicates.assertion.TestLoadPinnedAboveAssertionPredicatesAndUsingStore
+ */
+
+package compiler.predicates.assertion;
+
+public class TestLoadPinnedAboveAssertionPredicatesAndUsingStore {
+    static int iFld;
+    static int iArr[] = new int[100];
+
+    static void test() {
+        int i = 63;
+        do {
+            iArr[1] = 34;
+            iArr[i] += iFld;
+            for (int j = i; j < 1; j++) {
+            }
+        } while (--i > 0);
+    }
+
+    public static void main(String[] strArr) {
+        for (int i = 0; i < 10000; i++) {
+            test();
+        }
+    }
+}
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java 24.0.2+12-1/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java
--- 24.0.1+9-1/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2022, 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 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
@@ -23,6 +24,7 @@
 
 /**
 * @test
+* @bug 8297172 8331993 8349637
 * @key randomness
 * @summary Test vectorization of numberOfTrailingZeros/numberOfLeadingZeros for Long
 * @requires vm.compiler2.enabled
@@ -30,16 +32,20 @@
 *           (os.simpleArch == "aarch64" & vm.cpu.features ~= ".*sve.*") |
 *           (os.simpleArch == "riscv64" & vm.cpu.features ~= ".*zvbb.*")
 * @library /test/lib /
+* @modules jdk.incubator.vector
 * @run driver compiler.vectorization.TestNumberOfContinuousZeros
 */
 
 package compiler.vectorization;
 
+import jdk.incubator.vector.*;
 import compiler.lib.ir_framework.*;
 import java.util.Random;
 import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
 
 public class TestNumberOfContinuousZeros {
+    private static final int[] SPECIAL = { 0x01FFFFFF, 0x03FFFFFE, 0x07FFFFFC, 0x0FFFFFF8, 0x1FFFFFF0, 0x3FFFFFE0, 0xFFFFFFFF };
     private long[] inputLong;
     private int[] outputLong;
     private int[] inputInt;
@@ -47,8 +53,8 @@ public class TestNumberOfContinuousZeros
     private static final int LEN = 1024;
     private Random rng;
 
-    public static void main(String args[]) {
-        TestFramework.run();
+    public static void main(String[] args) {
+        TestFramework.runWithFlags("--add-modules=jdk.incubator.vector");
     }
 
     public TestNumberOfContinuousZeros() {
@@ -56,7 +62,7 @@ public class TestNumberOfContinuousZeros
         outputLong = new int[LEN];
         inputInt = new int[LEN];
         outputInt = new int[LEN];
-        rng = new Random(42);
+        rng = Utils.getRandomInstance();
         for (int i = 0; i < LEN; ++i) {
             inputLong[i] = rng.nextLong();
             inputInt[i] = rng.nextInt();
@@ -119,5 +125,80 @@ public class TestNumberOfContinuousZeros
             Asserts.assertEquals(outputInt[i], Integer.numberOfLeadingZeros(inputInt[i]));
         }
     }
+
+    @Setup
+    static Object[] setupSpecialIntArray() {
+        int[] res = new int[LEN];
+
+        for (int i = 0; i < LEN; i++) {
+            res[i] = SPECIAL[i % SPECIAL.length];
+        }
+
+        return new Object[] { res };
+    }
+
+    @Test
+    @IR(counts = {IRNode.COUNT_LEADING_ZEROS_VI, "> 0"})
+    @Arguments(setup = "setupSpecialIntArray")
+    public Object[] testSpecialIntLeadingZeros(int[] ints) {
+        int[] res = new int[LEN];
+
+        for (int i = 0; i < LEN; ++i) {
+            res[i] = Integer.numberOfLeadingZeros(ints[i]);
+        }
+
+        return new Object[] { ints, res };
+    }
+
+    @Check(test = "testSpecialIntLeadingZeros")
+    public void checkSpecialIntLeadingZeros(Object[] vals) {
+        int[] in = (int[]) vals[0];
+        int[] out = (int[]) vals[1];
+
+        for (int i = 0; i < LEN; ++i) {
+            int value = Integer.numberOfLeadingZeros(in[i]);
+
+            if (out[i] != value) {
+                throw new IllegalStateException("Expected lzcnt(" + in[i] + ") to be " + value + " but got " + out[i]);
+            }
+        }
+    }
+
+    private static final VectorSpecies<Integer> SPECIES = IntVector.SPECIES_PREFERRED;
+
+    @Test
+    @IR(counts = {IRNode.COUNT_LEADING_ZEROS_VI, "> 0"})
+    @Arguments(setup = "setupSpecialIntArray")
+    public Object[] checkSpecialIntLeadingZerosVector(int[] ints) {
+        int[] res = new int[LEN];
+
+        for (int i = 0; i < ints.length; i += SPECIES.length()) {
+            IntVector av = IntVector.fromArray(SPECIES, ints, i);
+            av.lanewise(VectorOperators.LEADING_ZEROS_COUNT).intoArray(res, i);
+        }
+
+        return new Object[] { ints, res };
+    }
+
+    @Check(test = "checkSpecialIntLeadingZerosVector")
+    public void checkSpecialIntLeadingZerosVector(Object[] vals) {
+        int[] ints = (int[]) vals[0];
+        int[] res = (int[]) vals[1];
+
+        // Verification
+
+        int[] check = new int[LEN];
+
+        for (int i = 0; i < ints.length; i += SPECIES.length()) {
+            IntVector av = IntVector.fromArray(SPECIES, ints, i);
+            av.lanewise(VectorOperators.LEADING_ZEROS_COUNT).intoArray(check, i);
+        }
+
+        for (int i = 0; i < LEN; i++) {
+            if (res[i] != check[i]) {
+                throw new IllegalStateException("Expected " + check[i] + " but got " + res[i]);
+            }
+        }
+    }
 }
 
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/compiler/vectorization/TestVectorZeroCount.java 24.0.2+12-1/test/hotspot/jtreg/compiler/vectorization/TestVectorZeroCount.java
--- 24.0.1+9-1/test/hotspot/jtreg/compiler/vectorization/TestVectorZeroCount.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/compiler/vectorization/TestVectorZeroCount.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8349637
+ * @summary Ensure that vectorization of numberOfLeadingZeros and numberOfTrailingZeros outputs correct values
+ * @library /test/lib /
+ * @run main/othervm compiler.vectorization.TestVectorZeroCount
+ */
+
+package compiler.vectorization;
+
+import java.util.Random;
+
+import jdk.test.lib.Utils;
+
+public class TestVectorZeroCount {
+    private static final int SIZE = 1024;
+    private static final Random RANDOM = Utils.getRandomInstance();
+
+    private static final int[] INT_VALUES = new int[SIZE];
+    private static final int[] INT_EXPECTED_LEADING = new int[SIZE];
+    private static final int[] INT_RESULT_LEADING = new int[SIZE];
+    private static final int[] INT_EXPECTED_TRAILING = new int[SIZE];
+    private static final int[] INT_RESULT_TRAILING = new int[SIZE];
+
+    private static final long[] LONG_VALUES = new long[SIZE];
+    private static final long[] LONG_EXPECTED_LEADING = new long[SIZE];
+    private static final long[] LONG_RESULT_LEADING = new long[SIZE];
+    private static final long[] LONG_EXPECTED_TRAILING = new long[SIZE];
+    private static final long[] LONG_RESULT_TRAILING = new long[SIZE];
+
+    private static final int INT_START_INDEX  = Integer.MIN_VALUE;
+    private static final int INT_END_INDEX    = Integer.MAX_VALUE;
+    private static final int LONG_START_INDEX = 0;
+    private static final int LONG_END_INDEX   = 100_000_000;
+
+    private static int intCounter;
+    private static int longCounter;
+
+    public static boolean testInt() {
+        boolean done = false;
+
+        // Non-vectorized loop as baseline (not vectorized because source array is initialized)
+        for (int i = 0; i < SIZE; ++i) {
+            INT_VALUES[i] = intCounter++;
+            if (intCounter == INT_END_INDEX) {
+                done = true;
+            }
+            INT_EXPECTED_LEADING[i] = Integer.numberOfLeadingZeros(INT_VALUES[i]);
+            INT_EXPECTED_TRAILING[i] = Integer.numberOfTrailingZeros(INT_VALUES[i]);
+        }
+        // Vectorized loop
+        for (int i = 0; i < SIZE; ++i) {
+            INT_RESULT_LEADING[i] = Integer.numberOfLeadingZeros(INT_VALUES[i]);
+        }
+        for (int i = 0; i < SIZE; ++i) {
+            INT_RESULT_TRAILING[i] = Integer.numberOfTrailingZeros(INT_VALUES[i]);
+        }
+
+        // Compare results
+        for (int i = 0; i < SIZE; ++i) {
+            if (INT_RESULT_LEADING[i] != INT_EXPECTED_LEADING[i]) {
+                throw new RuntimeException("Unexpected result for Integer.numberOfLeadingZeros(" + INT_VALUES[i] + "): " + INT_RESULT_LEADING[i] + ", expected " + INT_EXPECTED_LEADING[i]);
+            }
+            if (INT_RESULT_TRAILING[i] != INT_EXPECTED_TRAILING[i]) {
+                throw new RuntimeException("Unexpected result for Integer.numberOfTrailingZeros(" + INT_VALUES[i] + "): " + INT_RESULT_TRAILING[i] + ", expected " + INT_EXPECTED_TRAILING[i]);
+            }
+        }
+        return done;
+    }
+
+    public static boolean testLong() {
+        boolean done = false;
+
+        // Non-vectorized loop as baseline (not vectorized because source array is initialized)
+        for (int i = 0; i < SIZE; ++i) {
+            // Use random values because the long range is too large to iterate over it
+            LONG_VALUES[i] = RANDOM.nextLong();
+            if (longCounter++ == LONG_END_INDEX) {
+                done = true;
+            }
+            LONG_EXPECTED_LEADING[i] = Long.numberOfLeadingZeros(LONG_VALUES[i]);
+            LONG_EXPECTED_TRAILING[i] = Long.numberOfTrailingZeros(LONG_VALUES[i]);
+        }
+        // Vectorized loop
+        for (int i = 0; i < SIZE; ++i) {
+            LONG_RESULT_LEADING[i] = Long.numberOfLeadingZeros(LONG_VALUES[i]);
+        }
+        for (int i = 0; i < SIZE; ++i) {
+            LONG_RESULT_TRAILING[i] = Long.numberOfTrailingZeros(LONG_VALUES[i]);
+        }
+
+        // Compare results
+        for (int i = 0; i < SIZE; ++i) {
+            if (LONG_RESULT_LEADING[i] != LONG_EXPECTED_LEADING[i]) {
+                throw new RuntimeException("Unexpected result for Long.numberOfLeadingZeros(" + LONG_VALUES[i] + "): " + LONG_RESULT_LEADING[i] + ", expected " + LONG_EXPECTED_LEADING[i]);
+            }
+            if (LONG_RESULT_TRAILING[i] != LONG_EXPECTED_TRAILING[i]) {
+                throw new RuntimeException("Unexpected result for Long.numberOfTrailingZeros(" + LONG_VALUES[i] + "): " + LONG_RESULT_TRAILING[i] + ", expected " + LONG_EXPECTED_TRAILING[i]);
+            }
+        }
+        return done;
+    }
+
+    public static void main(String[] args) {
+        // Run twice to make sure compiled code is used from the beginning
+        for (int i = 0; i < 2; ++i) {
+            intCounter = INT_START_INDEX;
+            longCounter = LONG_START_INDEX;
+            while (!testLong()) ;
+            while (!testInt()) ;
+        }
+    }
+}
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java 24.0.2+12-1/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java
--- 24.0.1+9-1/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2025, BELLSOFT. 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.test.lib.Container;
+import jdk.test.lib.containers.docker.Common;
+import jdk.test.lib.containers.docker.DockerTestUtils;
+import jdk.test.lib.containers.docker.DockerRunOptions;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import jdk.internal.platform.Metrics;
+
+import java.util.ArrayList;
+
+import jtreg.SkippedException;
+
+/*
+ * @test
+ * @bug 8343191
+ * @requires os.family == "linux"
+ * @modules java.base/jdk.internal.platform
+ * @library /test/lib
+ * @build jdk.test.whitebox.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar whitebox.jar jdk.test.whitebox.WhiteBox
+ * @run main TestMemoryWithSubgroups
+ */
+public class TestMemoryWithSubgroups {
+
+    private static final String imageName = Common.imageName("subgroup");
+
+    static String getEngineInfo(String format) throws Exception {
+        return DockerTestUtils.execute(Container.ENGINE_COMMAND, "info", "-f", format)
+            .getStdout();
+    }
+
+    static boolean isRootless() throws Exception {
+        // Docker and Podman have different INFO structures.
+        // The node path for Podman is .Host.Security.Rootless, that also holds for
+        // Podman emulating Docker CLI. The node path for Docker is .SecurityOptions.
+        return (getEngineInfo("{{.Host.Security.Rootless}}").contains("true") ||
+                getEngineInfo("{{.SecurityOptions}}").contains("name=rootless"));
+    }
+
+    public static void main(String[] args) throws Exception {
+        Metrics metrics = Metrics.systemMetrics();
+        if (metrics == null) {
+            System.out.println("Cgroup not configured.");
+            return;
+        }
+        if (!DockerTestUtils.canTestDocker()) {
+            System.out.println("Unable to run docker tests.");
+            return;
+        }
+        if (isRootless()) {
+            throw new SkippedException("Test skipped in rootless mode");
+        }
+        Common.prepareWhiteBox();
+        DockerTestUtils.buildJdkContainerImage(imageName);
+
+        if ("cgroupv1".equals(metrics.getProvider())) {
+            try {
+                testMemoryLimitSubgroupV1("200m", "100m", "104857600", false);
+                testMemoryLimitSubgroupV1("1g", "500m", "524288000", false);
+                testMemoryLimitSubgroupV1("200m", "100m", "104857600", true);
+                testMemoryLimitSubgroupV1("1g", "500m", "524288000", true);
+            } finally {
+                DockerTestUtils.removeDockerImage(imageName);
+            }
+        } else if ("cgroupv2".equals(metrics.getProvider())) {
+            try {
+                testMemoryLimitSubgroupV2("200m", "100m", "104857600", false);
+                testMemoryLimitSubgroupV2("1g", "500m", "524288000", false);
+                testMemoryLimitSubgroupV2("200m", "100m", "104857600", true);
+                testMemoryLimitSubgroupV2("1g", "500m", "524288000", true);
+            } finally {
+                DockerTestUtils.removeDockerImage(imageName);
+            }
+        } else {
+            throw new SkippedException("Metrics are from neither cgroup v1 nor v2, skipped for now.");
+        }
+    }
+
+    private static void testMemoryLimitSubgroupV1(String containerMemorySize, String valueToSet, String expectedValue, boolean privateNamespace)
+            throws Exception {
+
+        Common.logNewTestCase("Cgroup V1 subgroup memory limit: " + valueToSet);
+
+        DockerRunOptions opts = new DockerRunOptions(imageName, "sh", "-c");
+        opts.javaOpts = new ArrayList<>();
+        opts.appendTestJavaOptions = false;
+        opts.addDockerOpts("--privileged")
+            .addDockerOpts("--cgroupns=" + (privateNamespace ? "private" : "host"))
+            .addDockerOpts("--memory", containerMemorySize);
+        opts.addClassOptions("mkdir -p /sys/fs/cgroup/memory/test ; " +
+            "echo " + valueToSet + " > /sys/fs/cgroup/memory/test/memory.limit_in_bytes ; " +
+            "echo $$ > /sys/fs/cgroup/memory/test/cgroup.procs ; " +
+            "/jdk/bin/java -Xlog:os+container=trace -version");
+
+        Common.run(opts)
+            .shouldMatch("Lowest limit was:.*" + expectedValue);
+    }
+
+    private static void testMemoryLimitSubgroupV2(String containerMemorySize, String valueToSet, String expectedValue, boolean privateNamespace)
+            throws Exception {
+
+        Common.logNewTestCase("Cgroup V2 subgroup memory limit: " + valueToSet);
+
+        DockerRunOptions opts = new DockerRunOptions(imageName, "sh", "-c");
+        opts.javaOpts = new ArrayList<>();
+        opts.appendTestJavaOptions = false;
+        opts.addDockerOpts("--privileged")
+            .addDockerOpts("--cgroupns=" + (privateNamespace ? "private" : "host"))
+            .addDockerOpts("--memory", containerMemorySize);
+        opts.addClassOptions("mkdir -p /sys/fs/cgroup/memory/test ; " +
+            "echo $$ > /sys/fs/cgroup/memory/test/cgroup.procs ; " +
+            "echo '+memory' > /sys/fs/cgroup/cgroup.subtree_control ; " +
+            "echo '+memory' > /sys/fs/cgroup/memory/cgroup.subtree_control ; " +
+            "echo " + valueToSet + " > /sys/fs/cgroup/memory/test/memory.max ; " +
+            "/jdk/bin/java -Xlog:os+container=trace -version");
+
+        Common.run(opts)
+            .shouldMatch("Lowest limit was:.*" + expectedValue);
+    }
+}
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/containers/systemd/SystemdMemoryAwarenessTest.java 24.0.2+12-1/test/hotspot/jtreg/containers/systemd/SystemdMemoryAwarenessTest.java
--- 24.0.1+9-1/test/hotspot/jtreg/containers/systemd/SystemdMemoryAwarenessTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/containers/systemd/SystemdMemoryAwarenessTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Red Hat, Inc.
+ * Copyright (c) 2024, 2025, Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,14 +68,14 @@ public class SystemdMemoryAwarenessTest
 
         OutputAnalyzer out = SystemdTestUtils.buildAndRunSystemdJava(opts);
         out.shouldHaveExitValue(0)
-           .shouldContain("Hello Systemd")
-           .shouldContain(String.format("Memory Limit is: %d", (expectedMemLimit * MB)));
+           .shouldContain("Hello Systemd");
         try {
+            out.shouldContain(String.format("Memory Limit is: %d", (expectedMemLimit * MB)));
             out.shouldContain("OSContainer::active_processor_count: " + coreLimit);
         } catch (RuntimeException e) {
-            // CPU delegation needs to be enabled when run as user on cg v2
+            // CPU/memory delegation needs to be enabled when run as user on cg v2
             if (SystemdTestUtils.RUN_AS_USER) {
-                String hint = "When run as user on cg v2 cpu delegation needs to be configured!";
+                String hint = "When run as user on cg v2 cpu/memory delegation needs to be configured!";
                 throw new SkippedException(hint);
             }
             throw e;
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/gc/epsilon/TestDieDefault.java 24.0.2+12-1/test/hotspot/jtreg/gc/epsilon/TestDieDefault.java
--- 24.0.1+9-1/test/hotspot/jtreg/gc/epsilon/TestDieDefault.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/gc/epsilon/TestDieDefault.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2017, 2025, Red Hat, Inc. 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
@@ -37,13 +37,13 @@ import jdk.test.lib.process.ProcessTools
 public class TestDieDefault {
 
   public static void passWith(String... args) throws Exception {
-    OutputAnalyzer out = ProcessTools.executeLimitedTestJava(args);
+    OutputAnalyzer out = ProcessTools.executeTestJava(args);
     out.shouldNotContain("OutOfMemoryError");
     out.shouldHaveExitValue(0);
   }
 
   public static void failWith(String... args) throws Exception {
-    OutputAnalyzer out = ProcessTools.executeLimitedTestJava(args);
+    OutputAnalyzer out = ProcessTools.executeTestJava(args);
     out.shouldContain("OutOfMemoryError");
     if (out.getExitValue() == 0) {
       throw new IllegalStateException("Should have failed with non-zero exit code");
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/gc/epsilon/TestDieWithHeapDump.java 24.0.2+12-1/test/hotspot/jtreg/gc/epsilon/TestDieWithHeapDump.java
--- 24.0.1+9-1/test/hotspot/jtreg/gc/epsilon/TestDieWithHeapDump.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/gc/epsilon/TestDieWithHeapDump.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2017, 2025, Red Hat, Inc. 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
@@ -38,13 +38,13 @@ import jdk.test.lib.process.ProcessTools
 public class TestDieWithHeapDump {
 
   public static void passWith(String... args) throws Exception {
-    OutputAnalyzer out = ProcessTools.executeLimitedTestJava(args);
+    OutputAnalyzer out = ProcessTools.executeTestJava(args);
     out.shouldNotContain("OutOfMemoryError");
     out.shouldHaveExitValue(0);
   }
 
   public static void failWith(String... args) throws Exception {
-    ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(args);
+    ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(args);
     Process p = pb.start();
     OutputAnalyzer out = new OutputAnalyzer(p);
     out.shouldContain("OutOfMemoryError");
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/gc/epsilon/TestDieWithOnError.java 24.0.2+12-1/test/hotspot/jtreg/gc/epsilon/TestDieWithOnError.java
--- 24.0.1+9-1/test/hotspot/jtreg/gc/epsilon/TestDieWithOnError.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/gc/epsilon/TestDieWithOnError.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2017, 2025, Red Hat, Inc. 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
@@ -39,14 +39,14 @@ public class TestDieWithOnError {
   static String ON_ERR_MSG = "Epsilon error handler message";
 
   public static void passWith(String... args) throws Exception {
-    OutputAnalyzer out = ProcessTools.executeLimitedTestJava(args);
+    OutputAnalyzer out = ProcessTools.executeTestJava(args);
     out.shouldNotContain("OutOfMemoryError");
     out.stdoutShouldNotMatch("^" + ON_ERR_MSG);
     out.shouldHaveExitValue(0);
   }
 
   public static void failWith(String... args) throws Exception {
-    OutputAnalyzer out = ProcessTools.executeLimitedTestJava(args);
+    OutputAnalyzer out = ProcessTools.executeTestJava(args);
     out.shouldContain("OutOfMemoryError");
     if (out.getExitValue() == 0) {
       throw new IllegalStateException("Should have failed with non-zero exit code");
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedEvacEmpty.java 24.0.2+12-1/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedEvacEmpty.java
--- 24.0.1+9-1/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedEvacEmpty.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedEvacEmpty.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8351921 8352508
+ * @summary Test that pinned regions with no Java references into them
+ *          do not make the garbage collector reclaim that region.
+ *          This test simulates this behavior using Whitebox methods
+ *          to pin a Java object in a region with no other pinnable objects and
+*           lose the reference to it before the garbage collection.
+ * @requires vm.gc.G1
+ * @requires vm.debug
+ * @library /test/lib /
+ * @modules java.management
+ * @build jdk.test.whitebox.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC
+ *      -Xbootclasspath/a:. -Xlog:gc=debug,gc+ergo+cset=trace,gc+phases=debug -XX:G1HeapRegionSize=1m -Xms30m  gc.g1.pinnedobjs.TestPinnedEvacEmpty regular
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC
+ *      -Xbootclasspath/a:. -Xlog:gc=debug,gc+ergo+cset=trace,gc+phases=debug -XX:G1HeapRegionSize=1m -Xms30m  gc.g1.pinnedobjs.TestPinnedEvacEmpty humongous
+ */
+
+package gc.g1.pinnedobjs;
+
+import gc.testlibrary.Helpers;
+
+import jdk.test.lib.Asserts;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.whitebox.WhiteBox;
+
+public class TestPinnedEvacEmpty {
+
+    private static final WhiteBox wb = WhiteBox.getWhiteBox();
+
+    private static final int objSize = (int)wb.getObjectSize(new Object());
+
+    private static Object allocHumongous() {
+        final int M = 1024 * 1024;
+        // The target object to pin. Since it is humongous, it will always be in its
+        // own regions.
+        return new int[M];
+    }
+
+    private static Object allocRegular() {
+        // How many j.l.Object should we allocate when creating garbage.
+        final int numAllocations = 1024 * 1024 * 3 / objSize;
+
+        // Allocate garbage so that the target object will be in a new region.
+        for (int i = 0; i < numAllocations; i++) {
+          Object z = new Object();
+        }
+        int[] o = new int[100];  // The target object to pin.
+        // Further allocate garbage so that any additional allocations of potentially
+        // pinned objects can not be allocated in the same region as the target object.
+        for (int i = 0; i < numAllocations; i++) {
+          Object z = new Object();
+        }
+
+        Asserts.assertTrue(!wb.isObjectInOldGen(o), "should not be in old gen already");
+        return o;
+    }
+
+    public static void main(String[] args) throws Exception {
+        System.out.println("Testing " + args[0] + " objects...");
+
+        // Remove garbage from VM initialization.
+        wb.fullGC();
+
+        // Allocate target object according to arguments.
+        Object o = args[0].equals("regular") ? allocRegular() : allocHumongous();
+
+        // Pin the object.
+        wb.pinObject(o);
+
+        // And forget the (Java) reference to the int array. After this, the garbage
+        // collection should find a completely empty pinned region. The collector
+        // must not collect/free it.
+        o = null;
+
+        // Full collection should not crash the VM in case of "empty" pinned regions.
+        wb.fullGC();
+
+        // Do a young garbage collection to zap the data in the pinned region. This test
+        // achieves that by executing a concurrent cycle that both performs both a young
+        // garbage collection as well as checks that errorneous reclamation does not occur
+        // in the Remark pause.
+        wb.g1RunConcurrentGC();
+        System.out.println("Done");
+    }
+}
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/gc/stress/TestStressG1Uncommit.java 24.0.2+12-1/test/hotspot/jtreg/gc/stress/TestStressG1Uncommit.java
--- 24.0.1+9-1/test/hotspot/jtreg/gc/stress/TestStressG1Uncommit.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/gc/stress/TestStressG1Uncommit.java	2025-06-27 08:03:14.000000000 +0000
@@ -57,6 +57,7 @@ public class TestStressG1Uncommit {
         Collections.addAll(options,
             "-Xlog:gc,gc+heap+region=debug",
             "-XX:+UseG1GC",
+            "-Xmx1g",
             StressUncommit.class.getName()
         );
         OutputAnalyzer output = ProcessTools.executeLimitedTestJava(options);
@@ -79,9 +80,9 @@ class StressUncommit {
         // Leave 20% head room to try to avoid Full GCs.
         long allocationSize = (long) (Runtime.getRuntime().maxMemory() * 0.8);
 
-        // Figure out suitable number of workers (~1 per gig).
-        int gigsOfAllocation = (int) Math.ceil((double) allocationSize / G);
-        int numWorkers = Math.min(gigsOfAllocation, Runtime.getRuntime().availableProcessors());
+        // Figure out suitable number of workers (~1 per 100M).
+        int allocationChunks = (int) Math.ceil((double) allocationSize / (100 * M));
+        int numWorkers = Math.min(allocationChunks, Runtime.getRuntime().availableProcessors());
         long workerAllocation = allocationSize / numWorkers;
 
         log("Using " + numWorkers + " workers, each allocating: ~" + (workerAllocation / M) + "M");
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java 24.0.2+12-1/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java
--- 24.0.1+9-1/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java	2025-06-27 08:03:14.000000000 +0000
@@ -85,15 +85,8 @@ public class CompressedCPUSpecificClassS
             output.shouldContain(tryReserveFor16bitMoveIntoQ3);
         } else if (Platform.isRISCV64()) {
             output.shouldContain(tryReserveForUnscaled); // unconditionally
-            if (CDS) {
-                output.shouldNotContain(tryReserveForZeroBased);
-                // bits 32..44
-                output.shouldContain("reserve_between (range [0x0000000100000000-0x0000100000000000)");
-            } else {
-                output.shouldContain(tryReserveForZeroBased);
-                // bits 32..44, but not lower than zero-based limit
-                output.shouldContain("reserve_between (range [0x0000000800000000-0x0000100000000000)");
-            }
+            // bits 32..44
+            output.shouldContain("reserve_between (range [0x0000000100000000-0x0000100000000000)");
             // bits 44..64
             output.shouldContain("reserve_between (range [0x0000100000000000-0xffffffffffffffff)");
         } else if (Platform.isS390x()) {
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java 24.0.2+12-1/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java
--- 24.0.1+9-1/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java	2025-06-27 08:03:14.000000000 +0000
@@ -108,17 +108,16 @@ public class Compiler {
 
     private static void preloadClasses(String className, long id,
             ConstantPool constantPool) {
-        try {
-            for (int i = 0, n = constantPool.getSize(); i < n; ++i) {
-                try {
+        for (int i = 0, n = constantPool.getSize(); i < n; ++i) {
+            try {
+                if (constantPool.getTagAt(i) == ConstantPool.Tag.CLASS) {
                     constantPool.getClassAt(i);
-                } catch (IllegalArgumentException ignore) {
                 }
+            } catch (Throwable t) {
+                CompileTheWorld.OUT.println(String.format("[%d]\t%s\tWARNING preloading failed : %s",
+                        id, className, t));
+                t.printStackTrace(CompileTheWorld.ERR);
             }
-        } catch (Throwable t) {
-            CompileTheWorld.OUT.println(String.format("[%d]\t%s\tWARNING preloading failed : %s",
-                    id, className, t));
-            t.printStackTrace(CompileTheWorld.ERR);
         }
     }
 
diff -pruN 24.0.1+9-1/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/sampling/SP05/sp05t003/sp05t003.cpp 24.0.2+12-1/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/sampling/SP05/sp05t003/sp05t003.cpp
--- 24.0.1+9-1/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/sampling/SP05/sp05t003/sp05t003.cpp	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/sampling/SP05/sp05t003/sp05t003.cpp	2025-06-27 08:03:14.000000000 +0000
@@ -74,6 +74,7 @@ static volatile int eventsEnd   = 0;
 /* testcase(s) */
 static int prepare();
 static int checkThreads(const char* kind);
+static int waitSuspended(const char* kind);
 static int resumeThreads(const char* kind);
 static int clean();
 
@@ -125,7 +126,7 @@ agentProc(jvmtiEnv* jvmti, JNIEnv* agent
                 nsk_jvmti_setFailStatus();
             }
 
-            /* check if all threads suspended on THREAD_START events */
+            /* check if all THREAD_START events are generated */
             if (eventsStart != THREADS_COUNT) {
                 NSK_COMPLAIN2("Unexpected number of THREAD_START events:\n"
                              "#   received: %d\n"
@@ -133,6 +134,11 @@ agentProc(jvmtiEnv* jvmti, JNIEnv* agent
                              eventsStart, THREADS_COUNT);
             }
 
+            /* wait until all threads are suspended */
+            if (!NSK_VERIFY(waitSuspended("starting"))) {
+                return;
+            }
+
             NSK_DISPLAY0("Testcase #1: check threads on THREAD_START\n");
             if (!NSK_VERIFY(checkThreads("starting")))
                 return;
@@ -175,7 +181,7 @@ agentProc(jvmtiEnv* jvmti, JNIEnv* agent
                 nsk_jvmti_setFailStatus();
             }
 
-            /* check ia all threads suspended on THREAD_END event */
+            /* check if all THREAD_END event are generated */
             if (eventsEnd != THREADS_COUNT) {
                 NSK_COMPLAIN2("Unexpected number of THREAD_END events:\n"
                              "#   received: %d\n"
@@ -183,6 +189,11 @@ agentProc(jvmtiEnv* jvmti, JNIEnv* agent
                              eventsEnd, THREADS_COUNT);
             }
 
+            /* wait until all threads are suspended */
+            if (!NSK_VERIFY(waitSuspended("finishing"))) {
+                return;
+            }
+
             NSK_DISPLAY0("Testcase #2: check threads on THREAD_END\n");
             if (!NSK_VERIFY(checkThreads("finishing")))
                 return;
@@ -210,6 +221,31 @@ agentProc(jvmtiEnv* jvmti, JNIEnv* agent
 
 /* ============================================================================= */
 
+static int waitSuspended(const char* kind) {
+    NSK_DISPLAY1("Wait for %s threads to be suspended\n", kind);
+    for (int i = 0; i < THREADS_COUNT; i++) {
+        for (int j = 0; j * TIMEOUT_DELTA < timeout; j++) {
+            jint state = 0;
+            if (!NSK_JVMTI_VERIFY(jvmti->GetThreadState(threadsList[i], &state))) {
+                nsk_jvmti_setFailStatus();
+                break;
+            }
+            if ((state & JVMTI_THREAD_STATE_ALIVE) == 0) {
+                NSK_COMPLAIN3("%s thread %s is not alive: %x\n", kind, threadsName[i], (int)state);
+                nsk_jvmti_setFailStatus();
+                break;
+            }
+            if ((state & JVMTI_THREAD_STATE_SUSPENDED) != 0) {
+                NSK_DISPLAY2("  OK: %s thread %s is suspended\n", kind, threadsName[i]);
+                break;
+            }
+            NSK_DISPLAY2("  %s thread %s is not suspended, waiting\n", kind, threadsName[i]);
+            nsk_jvmti_sleep(TIMEOUT_DELTA);
+        }
+    }
+    return NSK_TRUE;  // continue execution
+}
+
 /**
  * Resume all threads in given state.
  */
diff -pruN 24.0.1+9-1/test/jaxp/javax/xml/jaxp/libs/jaxp/library/JUnitTestUtil.java 24.0.2+12-1/test/jaxp/javax/xml/jaxp/libs/jaxp/library/JUnitTestUtil.java
--- 24.0.1+9-1/test/jaxp/javax/xml/jaxp/libs/jaxp/library/JUnitTestUtil.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/jaxp/javax/xml/jaxp/libs/jaxp/library/JUnitTestUtil.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jaxp.library;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import jdk.test.lib.Platform;
+
+public class JUnitTestUtil {
+    public static final String CLS_DIR = System.getProperty("test.classes");
+    public static final String SRC_DIR = System.getProperty("test.src");
+
+    /**
+     * Returns the System identifier (URI) of the source.
+     * @param path the path to the source
+     * @return the System identifier
+     */
+    public static String getSystemId(String path) {
+        if (path == null) return null;
+        String xmlSysId = "file://" + path;
+        if (Platform.isWindows()) {
+            path = path.replace('\\', '/');
+            xmlSysId = "file:///" + path;
+        }
+        return xmlSysId;
+    }
+
+    /**
+     * Copies a file.
+     * @param src the path of the source file
+     * @param target the path of the target file
+     * @throws Exception if the process fails
+     */
+    public static void copyFile(String src, String target) throws Exception {
+        try {
+            Files.copy(Path.of(src), Path.of(target), StandardCopyOption.REPLACE_EXISTING);
+        } catch (IOException x) {
+            throw new Exception(x.getMessage());
+        }
+    }
+}
diff -pruN 24.0.1+9-1/test/jaxp/javax/xml/jaxp/unittest/transform/PropertiesTest.java 24.0.2+12-1/test/jaxp/javax/xml/jaxp/unittest/transform/PropertiesTest.java
--- 24.0.1+9-1/test/jaxp/javax/xml/jaxp/unittest/transform/PropertiesTest.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/jaxp/javax/xml/jaxp/unittest/transform/PropertiesTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package transform;
+
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamSource;
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.stream.Stream;
+import jaxp.library.JUnitTestUtil;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/*
+ * @test
+ * @bug 8344925
+ * @summary Transformer properties tests
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest /test/lib
+ * @run junit/othervm transform.PropertiesTest
+ */
+public class PropertiesTest {
+    private static final String USER_DIR = System.getProperty("user.dir");
+    private static final String TEST_DIR = System.getProperty("test.src");
+    // Test parameters:
+    // generate-translet: indicates whether to generate translet
+    // translet-name: the name of the translet
+    // package-name: the package name
+    // destination-directory: the destination
+    // expected: the class path
+    private static Stream<Arguments> testData() {
+        String destination = JUnitTestUtil.CLS_DIR + "/testdir";
+        return Stream.of(
+                Arguments.of(true, "MyTranslet", "org.myorg", destination, "/org/myorg/MyTranslet.class"),
+                Arguments.of(false, "Translet", "not.generate", destination, "/not/generate/Translet.class"),
+                // translet named after the stylesheet
+                Arguments.of(true, null, "org.myorg", destination, "/org/myorg/transform.class"),
+                // default package name die.verwandlung since JDK 9
+                Arguments.of(true, "MyTranslet", null, destination, "/die/verwandlung/MyTranslet.class"),
+                Arguments.of(true, "MyTranslet", "org.myorg", null, "/org/myorg/MyTranslet.class")
+                );
+    }
+
+    @BeforeAll
+    public static void setup() throws Exception {
+        // so that the translet is generated under test.classes
+        JUnitTestUtil.copyFile(JUnitTestUtil.SRC_DIR + "/transform.xsl", JUnitTestUtil.CLS_DIR + "/transform.xsl");
+    }
+
+    @ParameterizedTest
+    @MethodSource("testData")
+    public void test(boolean generateTranslet, String name, String packageName,
+                     String destination, String expected)
+            throws Exception {
+        TransformerFactory tf = TransformerFactory.newInstance();
+
+        tf.setAttribute("generate-translet", generateTranslet);
+        if (name != null) tf.setAttribute("translet-name", name);
+        if (packageName != null) tf.setAttribute("package-name", packageName);
+        if (destination != null) tf.setAttribute("destination-directory", destination);
+
+        String xslFile = JUnitTestUtil.CLS_DIR + "/transform.xsl";
+        String xslSysId = JUnitTestUtil.getSystemId(xslFile);
+        StreamSource xsl = new StreamSource(xslSysId);
+        tf.newTemplates(xsl);
+
+        String path = (destination != null) ? destination + expected : new File(xslFile).getParent() + expected;
+
+        if (generateTranslet) {
+            assertTrue(Files.exists(Path.of(path)), "Translet is expected at " + expected);
+        } else {
+            assertTrue(Files.notExists(Path.of(path)), "Translet is not to be generated.");
+        }
+    }
+}
diff -pruN 24.0.1+9-1/test/jdk/ProblemList.txt 24.0.2+12-1/test/jdk/ProblemList.txt
--- 24.0.1+9-1/test/jdk/ProblemList.txt	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/ProblemList.txt	2025-06-27 08:03:14.000000000 +0000
@@ -468,7 +468,6 @@ java/awt/Window/MainKeyWindowTest/TestMa
 java/awt/Robot/Delay/InterruptOfDelay.java 8265986 macosx-all
 java/awt/Robot/InfiniteLoopException.java 8342638 windows-all,linux-all
 java/awt/MenuBar/TestNoScreenMenuBar.java 8265987 macosx-all
-java/awt/Robot/ScreenCaptureRobotTest.java 8344581 macosx-all
 
 java/awt/Graphics2D/DrawString/DrawRotatedStringUsingRotatedFont.java 8266283 generic-all
 java/awt/Graphics2D/DrawString/RotTransText.java 8316878 linux-all
@@ -499,7 +498,6 @@ java/awt/image/multiresolution/MultiReso
 
 # Wayland related
 
-java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java 8280991 linux-x64
 java/awt/FullScreen/SetFullScreenTest.java 8332155 linux-x64
 
 ############################################################################
@@ -564,8 +562,6 @@ javax/management/remote/mandatory/connec
 
 # jdk_net
 
-java/net/DatagramSocket/DatagramSocketExample.java              8308807 aix-ppc64
-java/net/DatagramSocket/DatagramSocketMulticasting.java         8308807 aix-ppc64
 
 java/net/MulticastSocket/B6427403.java                          8308807 aix-ppc64
 java/net/MulticastSocket/IPMulticastIF.java                     8308807 aix-ppc64
@@ -821,3 +817,13 @@ java/awt/Checkbox/CheckboxBoxSizeTest.ja
 java/awt/Checkbox/CheckboxIndicatorSizeTest.java 8340870 windows-all
 java/awt/Checkbox/CheckboxNullLabelTest.java 8340870 windows-all
 java/awt/dnd/WinMoveFileToShellTest.java 8341665 windows-all
+
+# Mechanically added:
+jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java 8352926 linux-x64
+jdk/jfr/api/consumer/streaming/TestJVMExit.java 8344671 macosx-aarch64
+jdk/jfr/api/consumer/streaming/TestJVMCrash.java 8344671 macosx-aarch64
+jdk/jfr/api/consumer/streaming/TestOutOfProcessMigration.java 8344671 macosx-aarch64
+javax/sound/midi/Sequencer/MetaCallback.java 8299218 macosx-aarch64
+java/net/DatagramSocket/DatagramSocketExample.java 8144003,8308807 aix-ppc64,macosx-aarch64
+java/net/DatagramSocket/DatagramSocketMulticasting.java 8144003,8308807 aix-ppc64,macosx-aarch64
+javax/sound/sampled/Clip/OpenNonIntegralNumberOfSampleframes.java 8334549 linux-aarch64,linux-x64
diff -pruN 24.0.1+9-1/test/jdk/com/sun/net/httpserver/bugs/B6361557.java 24.0.2+12-1/test/jdk/com/sun/net/httpserver/bugs/B6361557.java
--- 24.0.1+9-1/test/jdk/com/sun/net/httpserver/bugs/B6361557.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/com/sun/net/httpserver/bugs/B6361557.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -65,7 +65,7 @@ public class B6361557 {
     }
 
     final static String request = "GET /test/foo.html HTTP/1.1\r\nContent-length: 0\r\n\r\n";
-    final static ByteBuffer requestBuf = ByteBuffer.allocate(64).put(request.getBytes());
+    final static ByteBuffer requestBuf = ByteBuffer.wrap(request.getBytes());
 
     public static void main (String[] args) throws Exception {
         Handler handler = new Handler();
diff -pruN 24.0.1+9-1/test/jdk/com/sun/security/auth/callback/TextCallbackHandler/Default.java 24.0.2+12-1/test/jdk/com/sun/security/auth/callback/TextCallbackHandler/Default.java
--- 24.0.1+9-1/test/jdk/com/sun/security/auth/callback/TextCallbackHandler/Default.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/com/sun/security/auth/callback/TextCallbackHandler/Default.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @library /test/lib /java/security/testlibrary
+ * @library /test/lib
  * @bug 4470717
  * @summary fix default handling and other misc
  * @run main/othervm Default
@@ -34,6 +34,7 @@ import jdk.test.lib.Asserts;
 
 import javax.security.auth.callback.*;
 import java.io.*;
+import jdk.test.lib.security.HumanInputStream;
 
 public class Default {
     public static void main(String args[]) throws Exception {
diff -pruN 24.0.1+9-1/test/jdk/com/sun/security/auth/callback/TextCallbackHandler/Password.java 24.0.2+12-1/test/jdk/com/sun/security/auth/callback/TextCallbackHandler/Password.java
--- 24.0.1+9-1/test/jdk/com/sun/security/auth/callback/TextCallbackHandler/Password.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/com/sun/security/auth/callback/TextCallbackHandler/Password.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -25,35 +25,118 @@
  * @test
  * @bug 6825240 6829785
  * @summary Password.readPassword() echos the input when System.Console is null
- * @run main/manual Password
- */
-
-/*
- * This scenario cannot be automated because util/Password.java verifies the given input stream is
- * equal to the initialSystemIn. This prevents the test from providing a custom input stream.
- *
- *  Steps to run the test:
- *  1) Compile the class using the JDK version being tested: '<JdkBin>/javac Password.java'
- *  2) Run the test using the JDK version being tested: '<JdkBin>/java -cp . Password'
- *  3) Type in the first password, it should not be visible in the console
- *  4) Type in the second password, it should be visible in the console
- *  5) The final output line displays the entered passwords, both should be visible
+ * @library /test/lib
+ * @run main/manual/othervm Password
  */
 
 import com.sun.security.auth.callback.TextCallbackHandler;
+
+
 import javax.security.auth.callback.*;
+import javax.swing.*;
+
+import jdk.test.lib.UIBuilder;
+
+import java.util.Arrays;
 
 public class Password {
-   public static void main(String args[]) throws Exception {
-        TextCallbackHandler h = new TextCallbackHandler();
-        PasswordCallback nc = new PasswordCallback("Invisible: ", false);
-        PasswordCallback nc2 = new PasswordCallback("Visible: ", true);
 
-        System.out.println("Two passwords will be prompted for. The first one " +
-                "should have echo off, the second one on. Otherwise, this test fails");
-        Callback[] callbacks = { nc, nc2 };
+    private static final int TIMEOUT_MS = 240000;
+    private volatile boolean failed = false;
+    private volatile boolean aborted = false;
+    private Thread currentThread = null;
+
+    public static void password() throws Exception {
+
+        TextCallbackHandler h = new TextCallbackHandler();
+        PasswordCallback nc =
+                new PasswordCallback("Please input something, your input should be VISIBLE: ", true);
+        PasswordCallback nc2 =
+                new PasswordCallback("Please input something again, your input should be INVISIBLE: ", false);
+        Callback[] callbacks = {nc, nc2};
         h.handle(callbacks);
         System.out.println("You input " + new String(nc.getPassword()) +
                 " and " + new String(nc2.getPassword()));
-   }
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (Arrays.asList(args).contains("--password")) {
+            password();
+        } else {
+            final String instructions = String.format("%s/bin/java -cp \"%s\" Password --password",
+                    System.getProperty("java.home").replace("\\","/"),
+                    System.getProperty("java.class.path").replace("\\","/")
+            );
+
+            boolean testFailed = new Password().validate(
+                    "Please copy and execute the following script in the terminal / Windows Command Prompt window. " +
+                            "Two passwords will be prompted for.\n" +
+                            "Enter something at each prompt and press Enter/Return.\n" +
+                            "If the first input is visible and the second is invisible, this test PASSES. Otherwise, this test FAILS.\n" +
+                            "Once the test is complete please select whether the test has passed.\n",
+                    instructions);
+
+            if (testFailed) {
+                throw new RuntimeException("Test has failed");
+            }
+        }
+    }
+
+    public boolean validate(String instruction, String message) {
+        failed = false;
+        currentThread = Thread.currentThread();
+        final JDialog dialog = new UIBuilder.DialogBuilder()
+                .setTitle("Password")
+                .setInstruction(instruction)
+                .setMessage(message)
+                .setPassAction(e -> pass())
+                .setFailAction(e -> fail())
+                .setCloseAction(this::abort)
+                .build();
+
+        SwingUtilities.invokeLater(() -> {
+            try {
+                dialog.setVisible(true);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        });
+
+        try {
+            Thread.sleep(TIMEOUT_MS);
+            //Timed out, so fail the test
+            throw new RuntimeException(
+                    "Timed out after " + TIMEOUT_MS / 1000 + " seconds");
+        } catch (final InterruptedException e) {
+            if (aborted) {
+                throw new RuntimeException("TEST ABORTED");
+            }
+
+            if (failed) {
+                System.out.println("TEST FAILED");
+                System.out.println(message);
+            } else {
+                System.out.println("TEST PASSED");
+            }
+        } finally {
+            dialog.dispose();
+        }
+
+        return failed;
+    }
+
+    public void pass() {
+        failed = false;
+        currentThread.interrupt();
+    }
+
+    public void fail() {
+        failed = true;
+        currentThread.interrupt();
+    }
+
+    public void abort() {
+        aborted = true;
+        currentThread.interrupt();
+    }
 }
diff -pruN 24.0.1+9-1/test/jdk/java/awt/Desktop/MailTest.java 24.0.2+12-1/test/jdk/java/awt/Desktop/MailTest.java
--- 24.0.1+9-1/test/jdk/java/awt/Desktop/MailTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/awt/Desktop/MailTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -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
@@ -21,21 +21,23 @@
  * questions.
  */
 
+import java.awt.Desktop;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import javax.swing.JPanel;
+
+import jtreg.SkippedException;
+
 /*
  * @test
  * @bug 6255196
  * @summary Verifies the function of methods mail() and mail(java.net.URI uri).
- * @library /java/awt/regtesthelpers
- * @build PassFailJFrame
+ * @library /java/awt/regtesthelpers /test/lib
+ * @build PassFailJFrame jtreg.SkippedException
  * @run main/manual MailTest
  */
 
-import java.awt.Desktop;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.net.URI;
-import javax.swing.JPanel;
-
 public class MailTest extends JPanel {
 
     static final String INSTRUCTIONS = """
@@ -48,18 +50,7 @@ public class MailTest extends JPanel {
             """;
 
     private MailTest() {
-        if (!Desktop.isDesktopSupported()) {
-            PassFailJFrame.log("Class java.awt.Desktop is not supported on " +
-                    "current platform. Farther testing will not be performed");
-            PassFailJFrame.forcePass();
-        }
-
         Desktop desktop = Desktop.getDesktop();
-        if (!desktop.isSupported(Desktop.Action.MAIL)) {
-            PassFailJFrame.log("Action.MAIL is not supported.");
-            PassFailJFrame.forcePass();
-        }
-
         /*
          * Part 1: launch the mail composing window without a mailto URI.
          */
@@ -103,6 +94,15 @@ public class MailTest extends JPanel {
 
     public static void main(String[] args) throws InterruptedException,
             InvocationTargetException {
+        if (!Desktop.isDesktopSupported()) {
+            throw new SkippedException("Class java.awt.Desktop is not supported " +
+                    "on current platform. Further testing will not be performed");
+        }
+
+        if (!Desktop.getDesktop().isSupported(Desktop.Action.MAIL)) {
+            throw new SkippedException("Action.MAIL is not supported.");
+        }
+
         PassFailJFrame.builder()
                 .title("Mail Test")
                 .splitUI(MailTest::new)
diff -pruN 24.0.1+9-1/test/jdk/java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java 24.0.2+12-1/test/jdk/java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java
--- 24.0.1+9-1/test/jdk/java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -52,6 +52,10 @@ public final class FullscreenWindowProps
                 super.paint(g);
                 g.setColor(Color.GREEN);
                 g.fillRect(0, 0, getWidth(), getHeight());
+                g.setColor(Color.RED);
+                DisplayMode displayMode =
+                        getGraphicsConfiguration().getDevice().getDisplayMode();
+                g.drawString(displayMode.toString(), 100, 100);
             }
         };
         try {
diff -pruN 24.0.1+9-1/test/jdk/java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java 24.0.2+12-1/test/jdk/java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java
--- 24.0.1+9-1/test/jdk/java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -26,6 +26,8 @@
  * @bug 6646411
  * @summary Tests that full screen window and its children receive resize
             event when display mode changes
+ * @library /test/lib
+ * @build   jdk.test.lib.Platform jtreg.SkippedException
  * @run main/othervm NoResizeEventOnDMChangeTest
  * @run main/othervm -Dsun.java2d.d3d=false NoResizeEventOnDMChangeTest
  */
@@ -44,9 +46,21 @@ import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
+import java.io.BufferedReader;
+import java.io.IOException;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import jdk.test.lib.Platform;
+import jtreg.SkippedException;
 
 public class NoResizeEventOnDMChangeTest {
+
     public static void main(String[] args) {
+        if (Platform.isOnWayland() && !isFixDelivered()) {
+            throw new SkippedException("Test skipped because fix was not" +
+                    "delivered in current GnomeShell version");
+        }
+
         final GraphicsDevice gd = GraphicsEnvironment.
             getLocalGraphicsEnvironment().getDefaultScreenDevice();
 
@@ -231,4 +245,34 @@ public class NoResizeEventOnDMChangeTest
             return dmChanges;
         }
     }
+
+    private static boolean isFixDelivered() {
+        try {
+            Process process =
+                    new ProcessBuilder("/usr/bin/gnome-shell", "--version")
+                            .start();
+
+            try (BufferedReader reader = process.inputReader()) {
+                if (process.waitFor(2, SECONDS) &&  process.exitValue() == 0) {
+                    String line = reader.readLine();
+                    if (line != null) {
+                        System.out.println("Gnome shell version: " + line);
+                        String[] versionComponents = line
+                                .replaceAll("[^\\d.]", "")
+                                .split("\\.");
+
+                        if (versionComponents.length >= 1) {
+                            return Integer.parseInt(versionComponents[0]) > 42;
+                        }
+                    }
+                }
+            }
+        } catch (IOException
+                 | InterruptedException
+                 | IllegalThreadStateException
+                 | NumberFormatException ignored) {
+        }
+
+        return false;
+    }
 }
diff -pruN 24.0.1+9-1/test/jdk/java/awt/List/ItemEventTest/ItemEventTest.java 24.0.2+12-1/test/jdk/java/awt/List/ItemEventTest/ItemEventTest.java
--- 24.0.1+9-1/test/jdk/java/awt/List/ItemEventTest/ItemEventTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/awt/List/ItemEventTest/ItemEventTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -27,8 +27,13 @@
  * @bug 8033936 8172510
  * @summary Verify that correct ItemEvent is received while selection &
  *          deselection of multi select List items.
+ * @library /test/lib
+ * @build jdk.test.lib.Platform
+ * @run main ItemEventTest
  */
 
+// Pass -save to the test to enable screenshots at each select/deselect
+
 import java.awt.AWTException;
 import java.awt.Event;
 import java.awt.FlowLayout;
@@ -37,26 +42,30 @@ import java.awt.List;
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.Robot;
-import java.awt.event.KeyEvent;
 import java.awt.event.InputEvent;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
+import java.awt.event.KeyEvent;
+import java.awt.image.RenderedImage;
+import java.io.File;
+import java.io.IOException;
 
-public class ItemEventTest extends Frame
-{
-    List list;
-    final String expectedSelectionOrder;
-    StringBuilder actualSelectionOrder;
-    Robot robot;
+import javax.imageio.ImageIO;
 
-    public ItemEventTest()
-    {
-        try {
-            robot = new Robot();
-        } catch(AWTException e) {
-            throw new RuntimeException(e.getMessage());
-        }
-        expectedSelectionOrder = "01230123";
+import jdk.test.lib.Platform;
+
+public final class ItemEventTest extends Frame {
+    private static final String expectedSelectionOrder = "01230123";
+
+    private static boolean saveScreenshots;
+
+    private final StringBuffer actualSelectionOrder
+            = new StringBuffer(expectedSelectionOrder.length());
+
+    private final List list;
+    private final Robot robot;
+
+    private ItemEventTest() throws AWTException {
+        robot = new Robot();
+        robot.setAutoWaitForIdle(true);
 
         list = new List(4, true);
         list.add("0");
@@ -65,71 +74,76 @@ public class ItemEventTest extends Frame
         list.add("3");
 
         add(list);
+
         setSize(400,400);
         setLayout(new FlowLayout());
         pack();
+        setLocationRelativeTo(null);
         setVisible(true);
         robot.waitForIdle();
     }
 
     @Override
+    @SuppressWarnings("deprecation")
     public boolean handleEvent(Event e) {
-        if (e.target instanceof List) {
-            if (e.id == Event.LIST_DESELECT || e.id == Event.LIST_SELECT) {
-                actualSelectionOrder.append(e.arg);
-            }
+        if ((e.target instanceof List)
+            && (e.id == Event.LIST_DESELECT
+                || e.id == Event.LIST_SELECT)) {
+            logEvent("handleEvent: ", e.arg);
         }
         return true;
     }
 
-    void testHandleEvent() {
+    private void logEvent(String method, Object listItem) {
+        actualSelectionOrder.append(listItem);
+        System.out.println(method + listItem);
+    }
+
+    private void testHandleEvent() {
         // When no ItemListener is added to List, parent's handleEvent is
         // called with ItemEvent.
         performTest();
     }
 
-    void testItemListener() {
-        list.addItemListener(new ItemListener() {
-            @Override
-            public void itemStateChanged(ItemEvent ie) {
-                actualSelectionOrder.append(ie.getItem());
-            }
-        });
+    private void testItemListener() {
+        list.addItemListener(ie
+                -> logEvent("testItemListener: ", ie.getItem()));
         performTest();
     }
 
-    void performTest() {
-        actualSelectionOrder = new StringBuilder();
-        Point loc = list.getLocationOnScreen();
-        Rectangle rect = list.getBounds();
-        int dY = rect.height / list.getItemCount();
-        loc = new Point(loc.x + 10, loc.y + 5);
-
-        String osName = System.getProperty("os.name");
-        boolean isMac = osName.contains("Mac") || osName.contains("mac");
-        if(isMac) {
+    private void performTest() {
+        actualSelectionOrder.setLength(0);
+
+        final Rectangle rect = getListBoundsOnScreen();
+        final int dY = rect.height / list.getItemCount();
+        final Point loc = new Point(rect.x + rect.width / 2,
+                                    rect.y + dY / 2);
+
+        if (Platform.isOSX()) {
             robot.keyPress(KeyEvent.VK_META);
-            robot.waitForIdle();
         }
 
         // First loop to select & Second loop to deselect the list items.
         for (int j = 0; j < 2; ++j) {
             for (int i = 0; i < list.getItemCount(); ++i) {
                 robot.mouseMove(loc.x, loc.y + i * dY);
+                robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+                robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
                 robot.waitForIdle();
-                robot.mousePress(InputEvent.BUTTON1_MASK);
-                robot.waitForIdle();
-                robot.mouseRelease(InputEvent.BUTTON1_MASK);
-                robot.waitForIdle();
+
+                if (saveScreenshots) {
+                    saveImage(robot.createScreenCapture(rect));
+                }
             }
         }
 
-        if(isMac) {
+        if (Platform.isOSX()) {
             robot.keyRelease(KeyEvent.VK_META);
         }
 
-        if (!expectedSelectionOrder.equals(actualSelectionOrder.toString())) {
-            dispose();
+        if (!expectedSelectionOrder.contentEquals(actualSelectionOrder)) {
+            saveImage(robot.createScreenCapture(rect));
+
             throw new RuntimeException("ItemEvent for selection & deselection"
                 + " of multi select List's item is not correct"
                 + " Expected : " + expectedSelectionOrder
@@ -137,10 +151,32 @@ public class ItemEventTest extends Frame
         }
     }
 
-    public static void main(String args[]) {
-       ItemEventTest test = new ItemEventTest();
-       test.testHandleEvent();
-       test.testItemListener();
-       test.dispose();
+    private Rectangle getListBoundsOnScreen() {
+        return new Rectangle(list.getLocationOnScreen(),
+                             list.getSize());
+    }
+
+    private static int imageNo = 0;
+
+    private static void saveImage(RenderedImage image) {
+        try {
+            ImageIO.write(image,
+                          "png",
+                          new File(String.format("image-%02d.png",
+                                                 ++imageNo)));
+        } catch (IOException ignored) {
+        }
+    }
+
+    public static void main(String[] args) throws AWTException {
+        saveScreenshots = args.length > 0 && "-save".equals(args[0]);
+
+        ItemEventTest test = new ItemEventTest();
+        try {
+            test.testHandleEvent();
+            test.testItemListener();
+        } finally {
+            test.dispose();
+        }
     }
 }
diff -pruN 24.0.1+9-1/test/jdk/java/awt/Robot/ScreenCaptureRobotTest.java 24.0.2+12-1/test/jdk/java/awt/Robot/ScreenCaptureRobotTest.java
--- 24.0.1+9-1/test/jdk/java/awt/Robot/ScreenCaptureRobotTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/awt/Robot/ScreenCaptureRobotTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -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
@@ -44,6 +44,17 @@ import javax.imageio.ImageIO;
  * @bug 8342098
  * @summary Verify that the image captured from the screen using a Robot
  * and the source image are same.
+ * @requires os.family == "mac"
+ * @run main/othervm ScreenCaptureRobotTest
+ */
+
+/*
+ * @test
+ * @key headful
+ * @bug 8342098
+ * @summary Verify that the image captured from the screen using a Robot
+ * and the source image are same.
+ * @requires os.family != "mac"
  * @run main/othervm -Dsun.java2d.uiScale=1 ScreenCaptureRobotTest
  */
 public class ScreenCaptureRobotTest {
@@ -96,6 +107,7 @@ public class ScreenCaptureRobotTest {
 
     private static void doTest() throws Exception {
         Robot robot = new Robot();
+        robot.mouseMove(0, 0);
         robot.waitForIdle();
         robot.delay(500);
 
diff -pruN 24.0.1+9-1/test/jdk/java/awt/TrayIcon/ActionCommand/ActionCommand.java 24.0.2+12-1/test/jdk/java/awt/TrayIcon/ActionCommand/ActionCommand.java
--- 24.0.1+9-1/test/jdk/java/awt/TrayIcon/ActionCommand/ActionCommand.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/awt/TrayIcon/ActionCommand/ActionCommand.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -21,7 +21,14 @@
  * questions.
  */
 
-import java.awt.*;
+import jdk.test.lib.Platform;
+import jtreg.SkippedException;
+
+import java.awt.AWTException;
+import java.awt.EventQueue;
+import java.awt.Point;
+import java.awt.SystemTray;
+import java.awt.TrayIcon;
 import java.awt.image.BufferedImage;
 
 /*
@@ -30,12 +37,18 @@ import java.awt.image.BufferedImage;
  * @summary Check the return value of the getActionCommand method
  *          of the ActionEvent triggered when TrayIcon is double clicked
  *          (single clicked, on Mac)
- * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
  * @modules java.desktop/java.awt:open
- * @library /lib/client ../
- * @library /java/awt/patchlib
- * @build java.desktop/java.awt.Helper
- * @build ExtendedRobot SystemTrayIconHelper
+ * @library
+ *          /java/awt/patchlib
+ *          /java/awt/TrayIcon
+ *          /lib/client
+ *          /test/lib
+ * @build
+ *          java.desktop/java.awt.Helper
+ *          jdk.test.lib.Platform
+ *          jtreg.SkippedException
+ *          ExtendedRobot
+ *          SystemTrayIconHelper
  * @run main ActionCommand
  */
 
@@ -44,32 +57,38 @@ public class ActionCommand {
     TrayIcon icon;
     ExtendedRobot robot;
 
-    boolean actionPerformed = false;
-    Object actionLock = new Object();
-    String actionCommand = null;
+    volatile boolean actionPerformed = false;
+    volatile String actionCommand = null;
+    final Object actionLock = new Object();
+
     static boolean isMacOS = false;
 
     public static void main(String[] args) throws Exception {
-        if (! SystemTray.isSupported()) {
-            System.out.println("SystemTray not supported on the platform under test. " +
-                    "Marking the test passed");
-        } else {
-            if (System.getProperty("os.name").toLowerCase().startsWith("win")) {
-                System.err.println("Test can fail if the icon hides to a tray icons pool " +
-                        "in Windows 7, which is behavior by default.\n" +
-                        "Set \"Right mouse click\" -> \"Customize notification icons\" -> " +
-                        "\"Always show all icons and notifications on the taskbar\" true to " +
-                        "avoid this problem. Or change behavior only for Java SE tray icon " +
-                        "and rerun test.");
-            } else  if (System.getProperty("os.name").toLowerCase().startsWith("mac")){
-                isMacOS = true;
-            } else if (SystemTrayIconHelper.isOel7orLater()) {
-                System.out.println("OEL 7 doesn't support double click in " +
-                        "systray. Skipped");
-                return;
-            }
-            new ActionCommand().doTest();
+        if (Platform.isOnWayland()) {
+            // The current robot implementation does not support
+            // clicking in the system tray area.
+            throw new SkippedException("Skipped on Wayland");
+        }
+
+        if (!SystemTray.isSupported()) {
+            throw new SkippedException("SystemTray is not supported on this platform.");
+        }
+
+        if (Platform.isWindows()) {
+            System.err.println("Test can fail if the icon hides to a tray icons pool " +
+                    "in Windows 7, which is behavior by default.\n" +
+                    "Set \"Right mouse click\" -> \"Customize notification icons\" -> " +
+                    "\"Always show all icons and notifications on the taskbar\" true to " +
+                    "avoid this problem. Or change behavior only for Java SE tray icon " +
+                    "and rerun test.");
+        } else if (Platform.isOSX()){
+            isMacOS = true;
+        } else if (SystemTrayIconHelper.isOel7orLater()) {
+            System.out.println("OEL 7 doesn't support double click in " +
+                    "systray. Skipped");
+            throw new SkippedException("Skipped on OEL 7+");
         }
+        new ActionCommand().doTest();
     }
 
     void doTest() throws Exception {
@@ -95,7 +114,7 @@ public class ActionCommand {
 
             icon.setActionCommand("Sample Command");
 
-            if (! "Sample Command".equals(icon.getActionCommand()))
+            if (!"Sample Command".equals(icon.getActionCommand()))
                 throw new RuntimeException("FAIL: getActionCommand did not return the correct value. " +
                         icon.getActionCommand() + " Expected: Sample Command");
 
@@ -117,7 +136,7 @@ public class ActionCommand {
         actionPerformed = false;
         SystemTrayIconHelper.doubleClick(robot);
 
-        if (! actionPerformed) {
+        if (!actionPerformed) {
             synchronized (actionLock) {
                 try {
                     actionLock.wait(3000);
@@ -125,7 +144,7 @@ public class ActionCommand {
                 }
             }
         }
-        if (! actionPerformed) {
+        if (!actionPerformed) {
             throw new RuntimeException("FAIL: ActionEvent not triggered when TrayIcon is "+(isMacOS? "" : "double ")+"clicked");
         } else if (! "Sample Command".equals(actionCommand)) {
             throw new RuntimeException("FAIL: ActionEvent.getActionCommand did not return the correct " +
@@ -140,7 +159,7 @@ public class ActionCommand {
             }
         });
 
-        robot.mouseMove(0, 0);
+        robot.mouseMove(100, 0);
         robot.waitForIdle();
         robot.mouseMove(iconPosition.x, iconPosition.y);
         robot.waitForIdle();
@@ -149,7 +168,7 @@ public class ActionCommand {
         actionCommand = null;
         SystemTrayIconHelper.doubleClick(robot);
 
-        if (! actionPerformed) {
+        if (!actionPerformed) {
             synchronized (actionLock) {
                 try {
                     actionLock.wait(3000);
@@ -157,7 +176,7 @@ public class ActionCommand {
                 }
             }
         }
-        if (! actionPerformed) {
+        if (!actionPerformed) {
             throw new RuntimeException("FAIL: ActionEvent not triggered when ActionCommand set to " +
                     "null and then TrayIcon is "+(isMacOS? "" : "double ")+ "clicked");
         } else if (actionCommand != null) {
diff -pruN 24.0.1+9-1/test/jdk/java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java 24.0.2+12-1/test/jdk/java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java
--- 24.0.1+9-1/test/jdk/java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -21,6 +21,9 @@
  * questions.
  */
 
+import jdk.test.lib.Platform;
+import jtreg.SkippedException;
+
 import java.awt.EventQueue;
 import java.awt.Point;
 import java.awt.SystemTray;
@@ -37,10 +40,17 @@ import java.awt.image.BufferedImage;
  *          or single clicked with button 3 on Mac OS X
  *          or single clicked with button 1 on rest.
  * @modules java.desktop/java.awt:open
- * @library /java/awt/patchlib
- * @library /lib/client ../
- * @build java.desktop/java.awt.Helper
- * @build ExtendedRobot SystemTrayIconHelper
+ * @library
+ *          /java/awt/patchlib
+ *          /java/awt/TrayIcon
+ *          /lib/client
+ *          /test/lib
+ * @build
+ *          java.desktop/java.awt.Helper
+ *          jdk.test.lib.Platform
+ *          jtreg.SkippedException
+ *          ExtendedRobot
+ *          SystemTrayIconHelper
  * @run main TrayIconMouseTest
  */
 
@@ -48,16 +58,18 @@ public class TrayIconMouseTest {
 
     TrayIcon icon;
     ExtendedRobot robot;
-    boolean actionPerformed = false;
-    Object actionLock = new Object();
+
+    volatile boolean actionPerformed = false;
+    final Object actionLock = new Object();
+
     static boolean isMacOS = false;
     static boolean isWinOS = false;
     static boolean isOelOS = false;
     String caption = "Sample Icon";
     int[] buttonTypes = {
-        InputEvent.BUTTON1_MASK,
-        InputEvent.BUTTON2_MASK,
-        InputEvent.BUTTON3_MASK
+        InputEvent.BUTTON1_DOWN_MASK,
+        InputEvent.BUTTON2_DOWN_MASK,
+        InputEvent.BUTTON3_DOWN_MASK
     };
     String[] buttonNames = {
         "BUTTON1",
@@ -66,20 +78,24 @@ public class TrayIconMouseTest {
     };
 
     public static void main(String[] args) throws Exception {
+        if (Platform.isOnWayland()) {
+            // The current robot implementation does not support
+            // clicking in the system tray area.
+            throw new SkippedException("Skipped on Wayland");
+        }
+
         if (!SystemTray.isSupported()) {
-            System.out.println("SystemTray not supported on the platform "
-                    + "under test. Marking the test passed");
+            throw new SkippedException("SystemTray is not supported on this platform.");
+        }
+
+        if (Platform.isOSX()) {
+            isMacOS = true;
+        } else if (Platform.isWindows()) {
+            isWinOS = true;
         } else {
-            String osName = System.getProperty("os.name").toLowerCase();
-            if (osName.startsWith("mac")) {
-                isMacOS = true;
-            } else if (osName.startsWith("win")) {
-                isWinOS = true;
-            } else {
-                isOelOS = SystemTrayIconHelper.isOel7orLater();
-            }
-            new TrayIconMouseTest().doTest();
+            isOelOS = SystemTrayIconHelper.isOel7orLater();
         }
+        new TrayIconMouseTest().doTest();
     }
 
     TrayIconMouseTest() throws Exception {
diff -pruN 24.0.1+9-1/test/jdk/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupClickTest.java 24.0.2+12-1/test/jdk/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupClickTest.java
--- 24.0.1+9-1/test/jdk/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupClickTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupClickTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -20,14 +20,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+import jdk.test.lib.Platform;
+import jtreg.SkippedException;
+
 import java.awt.TrayIcon;
 import java.awt.SystemTray;
 import java.awt.EventQueue;
 import java.awt.Point;
 import java.awt.AWTException;
 import java.awt.event.MouseEvent;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.awt.event.InputEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.image.BufferedImage;
@@ -37,12 +38,18 @@ import java.awt.image.BufferedImage;
  * @key headful
  * @summary Check if a action performed event is received when TrayIcon display
  *          message is clicked on.
- * @author Shashidhara Veerabhadraiah (shashidhara.veerabhadraiah@oracle.com)
  * @modules java.desktop/java.awt:open
- * @library /java/awt/patchlib
- * @library /lib/client ../
- * @build java.desktop/java.awt.Helper
- * @build ExtendedRobot SystemTrayIconHelper
+ * @library
+ *          /java/awt/patchlib
+ *          /java/awt/TrayIcon
+ *          /lib/client
+ *          /test/lib
+ * @build
+ *          java.desktop/java.awt.Helper
+ *          jdk.test.lib.Platform
+ *          jtreg.SkippedException
+ *          ExtendedRobot
+ *          SystemTrayIconHelper
  * @run main TrayIconPopupClickTest
  */
 
@@ -50,22 +57,29 @@ public class TrayIconPopupClickTest {
 
     TrayIcon icon;
     ExtendedRobot robot;
-    boolean actionPerformed = false;
+    volatile boolean actionPerformed = false;
 
     public static void main(String[] args) throws Exception {
+        if (Platform.isOnWayland()) {
+            // The current robot implementation does not support
+            // clicking in the system tray area.
+            throw new SkippedException("Skipped on Wayland");
+        }
+
         if (!SystemTray.isSupported()) {
-            System.out.println("SystemTray not supported on the platform under test. " +
-                    "Marking the test passed");
-        } else {
-            if (System.getProperty("os.name").toLowerCase().startsWith("win"))
-                System.err.println("Test can fail if the icon hides to a tray icons pool " +
-                        "in Windows 7/10, which is behavior by default.\n" +
-                        "Set \"Right mouse click\" -> \"Customize notification icons\" -> " +
-                        "\"Always show all icons and notifications on the taskbar\" true " +
-                        "to avoid this problem. Or change behavior only for Java SE " +
-                        "tray icon.");
-            new TrayIconPopupClickTest().doTest();
+            throw new SkippedException("SystemTray is not supported on this platform.");
+        }
+
+        if (Platform.isWindows()) {
+            System.err.println("Test can fail if the icon hides to a tray icons pool " +
+                    "in Windows 7/10, which is behavior by default.\n" +
+                    "Set \"Right mouse click\" -> \"Customize notification icons\" -> " +
+                    "\"Always show all icons and notifications on the taskbar\" true " +
+                    "to avoid this problem. Or change behavior only for Java SE " +
+                    "tray icon.");
         }
+
+        new TrayIconPopupClickTest().doTest();
     }
 
     TrayIconPopupClickTest() throws Exception {
@@ -89,33 +103,26 @@ public class TrayIconPopupClickTest {
             throw new RuntimeException(e);
         }
 
-        icon.getActionCommand();
-        icon.addActionListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                actionPerformed = true;
-            }
-        });
+        icon.addActionListener(e -> actionPerformed = true);
     }
 
     void doTest() throws Exception {
-
         Point iconPosition = SystemTrayIconHelper.getTrayIconLocation(icon);
         if (iconPosition == null)
             throw new RuntimeException("Unable to find the icon location!");
 
         robot.mouseMove(iconPosition.x, iconPosition.y);
         robot.waitForIdle();
-        robot.mousePress(InputEvent.BUTTON1_MASK);
+        robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
         robot.delay(50);
-        robot.mouseRelease(InputEvent.BUTTON1_MASK);
+        robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
         robot.delay(50);
 
         robot.mouseMove(iconPosition.x, iconPosition.y + 10);
         robot.waitForIdle();
-        robot.mousePress(InputEvent.BUTTON1_MASK);
+        robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
         robot.delay(50);
-        robot.mouseRelease(InputEvent.BUTTON1_MASK);
+        robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
         robot.delay(50);
 
         if (!actionPerformed)
diff -pruN 24.0.1+9-1/test/jdk/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java 24.0.2+12-1/test/jdk/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java
--- 24.0.1+9-1/test/jdk/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -20,8 +20,22 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-import java.awt.*;
-import java.awt.event.*;
+
+import jdk.test.lib.Platform;
+import jtreg.SkippedException;
+
+import java.awt.AWTException;
+import java.awt.Dialog;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.MenuItem;
+import java.awt.Point;
+import java.awt.PopupMenu;
+import java.awt.SystemTray;
+import java.awt.TrayIcon;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
 import java.awt.image.BufferedImage;
 
 /*
@@ -29,12 +43,18 @@ import java.awt.image.BufferedImage;
  * @key headful
  * @summary Check if a JPopupMenu can be displayed when TrayIcon is
  *          right clicked. It uses a JWindow as the parent of the JPopupMenu
- * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
  * @modules java.desktop/java.awt:open
- * @library /java/awt/patchlib
- * @library /lib/client ../
- * @build java.desktop/java.awt.Helper
- * @build ExtendedRobot SystemTrayIconHelper
+ * @library
+ *          /java/awt/patchlib
+ *          /java/awt/TrayIcon
+ *          /lib/client
+ *          /test/lib
+ * @build
+ *          java.desktop/java.awt.Helper
+ *          jdk.test.lib.Platform
+ *          jtreg.SkippedException
+ *          ExtendedRobot
+ *          SystemTrayIconHelper
  * @run main TrayIconPopupTest
  */
 
@@ -43,27 +63,34 @@ public class TrayIconPopupTest {
     TrayIcon icon;
     ExtendedRobot robot;
 
-    boolean actionPerformed = false;
-    Object actionLock = new Object();
+    volatile boolean actionPerformed = false;
+    final Object actionLock = new Object();
+
     static final int ATTEMPTS = 10;
 
     PopupMenu popup;
     Dialog window;
 
     public static void main(String[] args) throws Exception {
+        if (Platform.isOnWayland()) {
+            // The current robot implementation does not support
+            // clicking in the system tray area.
+            throw new SkippedException("Skipped on Wayland");
+        }
+
         if (!SystemTray.isSupported()) {
-            System.out.println("SystemTray not supported on the platform under test. " +
-                    "Marking the test passed");
-        } else {
-            if (System.getProperty("os.name").toLowerCase().startsWith("win"))
-                System.err.println("Test can fail if the icon hides to a tray icons pool " +
-                        "in Windows 7, which is behavior by default.\n" +
-                        "Set \"Right mouse click\" -> \"Customize notification icons\" -> " +
-                        "\"Always show all icons and notifications on the taskbar\" true " +
-                        "to avoid this problem. Or change behavior only for Java SE " +
-                        "tray icon.");
-            new TrayIconPopupTest().doTest();
+            throw new SkippedException("SystemTray is not supported on this platform.");
+        }
+
+        if (Platform.isWindows()) {
+            System.err.println("Test can fail if the icon hides to a tray icons pool " +
+                    "in Windows 7, which is behavior by default.\n" +
+                    "Set \"Right mouse click\" -> \"Customize notification icons\" -> " +
+                    "\"Always show all icons and notifications on the taskbar\" true " +
+                    "to avoid this problem. Or change behavior only for Java SE " +
+                    "tray icon.");
         }
+        new TrayIconPopupTest().doTest();
     }
 
     TrayIconPopupTest() throws Exception {
@@ -128,15 +155,15 @@ public class TrayIconPopupTest {
 
         robot.mouseMove(iconPosition.x, iconPosition.y);
         robot.waitForIdle();
-        robot.mousePress(InputEvent.BUTTON3_MASK);
+        robot.mousePress(InputEvent.BUTTON3_DOWN_MASK);
         robot.delay(50);
-        robot.mouseRelease(InputEvent.BUTTON3_MASK);
+        robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK);
         robot.delay(6000);
 
         robot.mouseMove(window.getLocation().x + 10, window.getLocation().y + 10);
-        robot.mousePress(InputEvent.BUTTON3_MASK);
+        robot.mousePress(InputEvent.BUTTON3_DOWN_MASK);
         robot.delay(50);
-        robot.mouseRelease(InputEvent.BUTTON3_MASK);
+        robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK);
 
         int attempts = 0;
         while (!actionPerformed && attempts++ < ATTEMPTS) {
diff -pruN 24.0.1+9-1/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/ValidateICCHeaderData.java 24.0.2+12-1/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/ValidateICCHeaderData.java
--- 24.0.1+9-1/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/ValidateICCHeaderData.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/ValidateICCHeaderData.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8337703
+ * @summary To verify if ICC_Profile's setData() and getInstance() methods
+ *          validate header data and throw IAE for invalid values.
+ * @run main ValidateICCHeaderData
+ */
+
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_Profile;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+
+public class ValidateICCHeaderData {
+    private static ICC_Profile profile;
+
+    private static final boolean DEBUG = false;
+    private static final int VALID_HEADER_SIZE = 128;
+    private static final int HEADER_TAG = ICC_Profile.icSigHead;
+    private static final int PROFILE_CLASS_START_INDEX = ICC_Profile.icHdrDeviceClass;
+    private static final int COLOR_SPACE_START_INDEX = ICC_Profile.icHdrColorSpace;
+    private static final int RENDER_INTENT_START_INDEX = ICC_Profile.icHdrRenderingIntent;
+    private static final int PCS_START_INDEX = ICC_Profile.icHdrPcs;
+
+    private static final int[] VALID_PROFILE_CLASS = new int[] {
+            ICC_Profile.icSigInputClass, ICC_Profile.icSigDisplayClass,
+            ICC_Profile.icSigOutputClass, ICC_Profile.icSigLinkClass,
+            ICC_Profile.icSigAbstractClass, ICC_Profile.icSigColorSpaceClass,
+            ICC_Profile.icSigNamedColorClass
+    };
+
+    private static final int[] VALID_COLOR_SPACE = new int[] {
+            ICC_Profile.icSigXYZData, ICC_Profile.icSigLabData,
+            ICC_Profile.icSigLuvData, ICC_Profile.icSigYCbCrData,
+            ICC_Profile.icSigYxyData, ICC_Profile.icSigRgbData,
+            ICC_Profile.icSigGrayData, ICC_Profile.icSigHsvData,
+            ICC_Profile.icSigHlsData, ICC_Profile.icSigCmykData,
+            ICC_Profile.icSigSpace2CLR, ICC_Profile.icSigSpace3CLR,
+            ICC_Profile.icSigSpace4CLR, ICC_Profile.icSigSpace5CLR,
+            ICC_Profile.icSigSpace6CLR, ICC_Profile.icSigSpace7CLR,
+            ICC_Profile.icSigSpace8CLR, ICC_Profile.icSigSpace9CLR,
+            ICC_Profile.icSigSpaceACLR, ICC_Profile.icSigSpaceBCLR,
+            ICC_Profile.icSigSpaceCCLR, ICC_Profile.icSigSpaceDCLR,
+            ICC_Profile.icSigSpaceECLR, ICC_Profile.icSigSpaceFCLR,
+            ICC_Profile.icSigCmyData
+    };
+
+    private static final int[] VALID_RENDER_INTENT = new int[] {
+            ICC_Profile.icPerceptual, ICC_Profile.icMediaRelativeColorimetric,
+            ICC_Profile.icSaturation, ICC_Profile.icAbsoluteColorimetric
+    };
+
+    private static void createCopyOfBuiltInProfile() {
+        ICC_Profile builtInProfile = ICC_Profile.getInstance(ColorSpace.CS_sRGB);
+        //copy of SRGB BuiltIn Profile that can be modified
+        //using ICC_Profile.setData()
+        profile = ICC_Profile.getInstance(builtInProfile.getData());
+    }
+
+    public static void main(String[] args) throws Exception {
+        createCopyOfBuiltInProfile();
+
+        System.out.println("CASE 1: Testing VALID Profile Classes ...");
+        testValidHeaderData(VALID_PROFILE_CLASS, PROFILE_CLASS_START_INDEX, 4);
+        System.out.println("CASE 1: Passed \n");
+
+        // PCS field validation for Profile class != DEVICE_LINK
+        System.out.println("CASE 2: Testing VALID PCS Type"
+                           + " for Profile class != DEVICE_LINK ...");
+        testValidHeaderData(new int[] {ICC_Profile.icSigXYZData, ICC_Profile.icSigLabData},
+                PCS_START_INDEX, 4);
+        System.out.println("CASE 2: Passed \n");
+
+        System.out.println("CASE 3: Testing INVALID PCS Type"
+                           + " for Profile class != DEVICE_LINK ...");
+        testInvalidHeaderData(ICC_Profile.icSigCmykData, PCS_START_INDEX, 4);
+        System.out.println("CASE 3: Passed \n");
+
+        System.out.println("CASE 4: Testing DEVICE LINK PROFILE CLASS ...");
+        testValidHeaderData(new int[] {ICC_Profile.icSigLinkClass},
+                PROFILE_CLASS_START_INDEX, 4);
+        //to check if instantiating BufferedImage with
+        //ICC_Profile device class = CLASS_DEVICELINK does not throw IAE.
+        BufferedImage img = new BufferedImage(100, 100,
+                                              BufferedImage.TYPE_3BYTE_BGR);
+        System.out.println("CASE 4: Passed \n");
+
+        // PCS field validation for Profile class == DEVICE_LINK
+        System.out.println("CASE 5: Testing VALID PCS Type"
+                           + " for Profile class == DEVICE_LINK ...");
+        testValidHeaderData(VALID_COLOR_SPACE, PCS_START_INDEX, 4);
+        System.out.println("CASE 5: Passed \n");
+
+        System.out.println("CASE 6: Testing INVALID PCS Type"
+                           + " for Profile class == DEVICE_LINK ...");
+        //original icSigLabData = 0x4C616220
+        int invalidSigLabData = 0x4C616221;
+        testInvalidHeaderData(invalidSigLabData, PCS_START_INDEX, 4);
+        System.out.println("CASE 6: Passed \n");
+
+        System.out.println("CASE 7: Testing VALID Color Spaces ...");
+        testValidHeaderData(VALID_COLOR_SPACE, COLOR_SPACE_START_INDEX, 4);
+        System.out.println("CASE 7: Passed \n");
+
+        System.out.println("CASE 8: Testing VALID Rendering Intent ...");
+        testValidHeaderData(VALID_RENDER_INTENT, RENDER_INTENT_START_INDEX, 4);
+        System.out.println("CASE 8: Passed \n");
+
+        System.out.println("CASE 9: Testing INVALID Profile Class ...");
+        //original icSigInputClass = 0x73636E72
+        int invalidSigInputClass = 0x73636E70;
+        testInvalidHeaderData(invalidSigInputClass, PROFILE_CLASS_START_INDEX, 4);
+        System.out.println("CASE 9: Passed \n");
+
+        System.out.println("CASE 10: Testing INVALID Color Space ...");
+        //original icSigXYZData = 0x58595A20
+        int invalidSigXYZData = 0x58595A21;
+        testInvalidHeaderData(invalidSigXYZData, COLOR_SPACE_START_INDEX, 4);
+        System.out.println("CASE 10: Passed \n");
+
+        System.out.println("CASE 11: Testing INVALID Rendering Intent ...");
+        //valid rendering intent values are 0-3
+        int invalidRenderIntent = 5;
+        testInvalidHeaderData(invalidRenderIntent, RENDER_INTENT_START_INDEX, 4);
+        System.out.println("CASE 11: Passed \n");
+
+        System.out.println("CASE 12: Testing INVALID Header Size ...");
+        testInvalidHeaderSize();
+        System.out.println("CASE 12: Passed \n");
+
+        System.out.println("CASE 13: Testing ICC_Profile.getInstance(..)"
+                           + " with VALID profile data ...");
+        testProfileCreation(true);
+        System.out.println("CASE 13: Passed \n");
+
+        System.out.println("CASE 14: Testing ICC_Profile.getInstance(..)"
+                           + " with INVALID profile data ...");
+        testProfileCreation(false);
+        System.out.println("CASE 14: Passed \n");
+
+        System.out.println("CASE 15: Testing Deserialization of ICC_Profile ...");
+        testDeserialization();
+        System.out.println("CASE 15: Passed \n");
+
+        System.out.println("Successfully completed testing all 15 cases. Test Passed !!");
+    }
+
+    private static void testValidHeaderData(int[] validData, int startIndex,
+                                            int fieldLength) {
+        for (int value : validData) {
+            setTag(value, startIndex, fieldLength);
+        }
+    }
+
+    private static void testInvalidHeaderData(int invalidData, int startIndex,
+                                              int fieldLength) {
+        try {
+            setTag(invalidData, startIndex, fieldLength);
+            throw new RuntimeException("Test Failed ! Expected IAE NOT thrown");
+        } catch (IllegalArgumentException iae) {
+            System.out.println("Expected IAE thrown: " + iae.getMessage());
+        }
+    }
+
+    private static void setTag(int value, int startIndex, int fieldLength) {
+        byte[] byteArray;
+        if (startIndex == RENDER_INTENT_START_INDEX) {
+            byteArray = ByteBuffer.allocate(4).putInt(value).array();
+        } else {
+            BigInteger big = BigInteger.valueOf(value);
+            byteArray = (big.toByteArray());
+        }
+
+        if (DEBUG) {
+            System.out.print("Byte Array : ");
+            for (int i = 0; i < byteArray.length; i++) {
+                System.out.print(byteArray[i] + " ");
+            }
+            System.out.println("\n");
+        }
+
+        byte[] iccProfileHeaderData = profile.getData(HEADER_TAG);
+        System.arraycopy(byteArray, 0, iccProfileHeaderData, startIndex, fieldLength);
+        profile.setData(HEADER_TAG, iccProfileHeaderData);
+    }
+
+    private static void testProfileCreation(boolean validCase) {
+        ICC_Profile builtInProfile = ICC_Profile.getInstance(ColorSpace.CS_GRAY);
+        byte[] profileData = builtInProfile.getData();
+
+        int validDeviceClass = ICC_Profile.icSigInputClass;
+        BigInteger big = BigInteger.valueOf(validDeviceClass);
+        //valid case set device class to 0x73636E72 (icSigInputClass)
+        //invalid case set device class to 0x00000000
+        byte[] field = validCase ? big.toByteArray()
+                                 : ByteBuffer.allocate(4).putInt(0).array();
+        System.arraycopy(field, 0, profileData, PROFILE_CLASS_START_INDEX, 4);
+
+        try {
+            ICC_Profile.getInstance(profileData);
+            if (!validCase) {
+                throw new RuntimeException("Test Failed ! Expected IAE NOT thrown");
+            }
+        } catch (IllegalArgumentException iae) {
+            if (!validCase) {
+                System.out.println("Expected IAE thrown: " + iae.getMessage());
+            } else {
+                throw new RuntimeException("Unexpected IAE thrown");
+            }
+        }
+    }
+
+    private static void testInvalidHeaderSize() {
+        byte[] iccProfileHeaderData = profile.getData(HEADER_TAG);
+        byte[] invalidHeaderSize = new byte[VALID_HEADER_SIZE - 1];
+        System.arraycopy(iccProfileHeaderData, 0,
+                invalidHeaderSize, 0, invalidHeaderSize.length);
+        try {
+            profile.setData(HEADER_TAG, invalidHeaderSize);
+            throw new RuntimeException("Test Failed ! Expected IAE NOT thrown");
+        } catch (IllegalArgumentException iae) {
+            System.out.println("Expected IAE thrown: " + iae.getMessage());
+        }
+    }
+
+    private static void testDeserialization() throws IOException {
+        //invalidSRGB.icc is serialized on older version of JDK
+        //Upon deserialization, the invalid profile is expected to throw IAE
+        try {
+            ICC_Profile.getInstance("./invalidSRGB.icc");
+            throw new RuntimeException("Test Failed ! Expected IAE NOT thrown");
+        } catch (IllegalArgumentException iae) {
+            System.out.println("Expected IAE thrown: " + iae.getMessage());
+        }
+    }
+}
Binary files 24.0.1+9-1/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/invalidSRGB.icc and 24.0.2+12-1/test/jdk/java/awt/color/ICC_Profile/ValidateICCHeaderData/invalidSRGB.icc differ
diff -pruN 24.0.1+9-1/test/jdk/java/awt/print/Dialog/PaperSizeError.java 24.0.2+12-1/test/jdk/java/awt/print/Dialog/PaperSizeError.java
--- 24.0.1+9-1/test/jdk/java/awt/print/Dialog/PaperSizeError.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/awt/print/Dialog/PaperSizeError.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2024, 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
@@ -23,16 +23,22 @@
 
 /**
  * @test
- * @bug 6360339
+ * @bug 6360339 8343224
  * @key printer
  * @summary Test for fp error in paper size calculations.
  * @run main/manual PaperSizeError
  */
 
-import java.awt.print.*;
-import javax.print.*;
-import javax.print.attribute.*;
-import javax.print.attribute.standard.*;
+import javax.print.PrintService;
+import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.PrintRequestAttributeSet;
+import javax.print.attribute.Size2DSyntax;
+import javax.print.attribute.standard.MediaSize;
+import javax.print.attribute.standard.MediaSizeName;
+import javax.print.attribute.standard.OrientationRequested;
+import java.awt.print.PageFormat;
+import java.awt.print.Paper;
+import java.awt.print.PrinterJob;
 
 public class PaperSizeError {
 
diff -pruN 24.0.1+9-1/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java 24.0.2+12-1/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java
--- 24.0.1+9-1/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java	2025-06-27 08:03:14.000000000 +0000
@@ -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.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -359,7 +359,7 @@ public final class PassFailJFrame {
      * the default values of {@value #ROWS} and {@value #COLUMNS}
      * for rows and columns.
      * <p>
-     * See {@link #PassFailJFrame(String,String,long,int,int,boolean)} for
+     * See {@link #PassFailJFrame(String,String,long,int,int)} for
      * more details.
      *
      * @param instructions the instructions for the tester
@@ -382,7 +382,7 @@ public final class PassFailJFrame {
      * and the default values of {@value #ROWS} and {@value #COLUMNS}
      * for rows and columns.
      * <p>
-     * See {@link #PassFailJFrame(String,String,long,int,int,boolean)} for
+     * See {@link #PassFailJFrame(String,String,long,int,int)} for
      * more details.
      *
      * @param instructions the instructions for the tester
@@ -404,9 +404,8 @@ public final class PassFailJFrame {
      * with the given title, instructions and timeout as well as
      * the default values of {@value #ROWS} and {@value #COLUMNS}
      * for rows and columns.
-     * The screenshot feature is not enabled, if you use this constructor.
      * <p>
-     * See {@link #PassFailJFrame(String,String,long,int,int,boolean)} for
+     * See {@link #PassFailJFrame(String,String,long,int,int)} for
      * more details.
      *
      * @param title        the title of the instruction frame
@@ -427,38 +426,8 @@ public final class PassFailJFrame {
     /**
      * Constructs a frame which displays test instructions and
      * the <i>Pass</i> / <i>Fail</i> buttons
-     * with the given title, instructions, timeout, number of rows and columns.
-     * The screenshot feature is not enabled, if you use this constructor.
-     * <p>
-     * See {@link #PassFailJFrame(String,String,long,int,int,boolean)} for
-     * more details.
-     *
-     * @param title        the title of the instruction frame
-     * @param instructions the instructions for the tester
-     * @param testTimeOut  the test timeout in minutes
-     * @param rows         the number of rows for the text component
-     *                     which displays test instructions
-     * @param columns      the number of columns for the text component
-     *                     which displays test instructions
-     *
-     * @throws InterruptedException if the current thread is interrupted
-     *              while waiting for EDT to finish creating UI components
-     * @throws InvocationTargetException if an exception is thrown while
-     *              creating UI components on EDT
-     */
-    public PassFailJFrame(String title, String instructions,
-                          long testTimeOut,
-                          int rows, int columns)
-            throws InterruptedException, InvocationTargetException {
-        this(title, instructions, testTimeOut, rows, columns, false);
-    }
-
-    /**
-     * Constructs a frame which displays test instructions and
-     * the <i>Pass</i> / <i>Fail</i> buttons
      * as well as supporting UI components with the given title, instructions,
-     * timeout, number of rows and columns,
-     * and screen capture functionality.
+     * timeout, number of rows and columns.
      * All the UI components are created on the EDT, so it is safe to call
      * the constructor on the main thread.
      * <p>
@@ -483,12 +452,6 @@ public final class PassFailJFrame {
      * the size of a text component which displays the instructions.
      * The preferred size of the instructions is calculated by
      * creating {@code new JTextArea(rows, columns)}.
-     * <p>
-     * If you enable screenshots by setting the {@code screenCapture}
-     * parameter to {@code true}, a <i>Screenshot</i> button is added.
-     * Clicking the <i>Screenshot</i> button takes screenshots of
-     * all the monitors or all the windows registered with
-     * {@code PassFailJFrame}.
      *
      * @param title        the title of the instruction frame
      * @param instructions the instructions for the tester
@@ -497,8 +460,6 @@ public final class PassFailJFrame {
      *                     which displays test instructions
      * @param columns      the number of columns for the text component
      *                     which displays test instructions
-     * @param screenCapture if set to {@code true}, enables screen capture
-     *                      functionality
      *
      * @throws InterruptedException if the current thread is interrupted
      *              while waiting for EDT to finish creating UI components
@@ -510,13 +471,11 @@ public final class PassFailJFrame {
      */
     public PassFailJFrame(String title, String instructions,
                           long testTimeOut,
-                          int rows, int columns,
-                          boolean screenCapture)
+                          int rows, int columns)
             throws InterruptedException, InvocationTargetException {
         invokeOnEDT(() -> createUI(title, instructions,
                                    testTimeOut,
-                                   rows, columns,
-                                   screenCapture));
+                                   rows, columns));
     }
 
     /**
@@ -613,8 +572,7 @@ public final class PassFailJFrame {
     }
 
     private static void createUI(String title, String instructions,
-                                 long testTimeOut, int rows, int columns,
-                                 boolean enableScreenCapture) {
+                                 long testTimeOut, int rows, int columns) {
         frame = new JFrame(title);
         frame.setLayout(new BorderLayout());
 
@@ -623,7 +581,7 @@ public final class PassFailJFrame {
         frame.add(createInstructionUIPanel(instructions,
                                            testTimeOut,
                                            rows, columns,
-                                           enableScreenCapture,
+                                           false,
                                            false, 0),
                   BorderLayout.CENTER);
         frame.pack();
@@ -675,6 +633,8 @@ public final class PassFailJFrame {
                               ? configureHTML(instructions, rows, columns)
                               : configurePlainText(instructions, rows, columns);
         text.setEditable(false);
+        text.setBorder(createTextBorder());
+        text.setCaretPosition(0);
 
         JPanel textPanel = new JPanel(new BorderLayout());
         textPanel.setBorder(createEmptyBorder(GAP, 0, GAP, 0));
@@ -729,7 +689,6 @@ public final class PassFailJFrame {
         JTextArea text = new JTextArea(instructions, rows, columns);
         text.setLineWrap(true);
         text.setWrapStyleWord(true);
-        text.setBorder(createTextBorder());
         return text;
     }
 
@@ -743,10 +702,10 @@ public final class PassFailJFrame {
 
         HTMLEditorKit kit = (HTMLEditorKit) text.getEditorKit();
         StyleSheet styles = kit.getStyleSheet();
-        // Reduce the default margins
-        styles.addRule("ol, ul { margin-left-ltr: 20; margin-left-rtl: 20 }");
-        // Make the size of code blocks the same as other text
-        styles.addRule("code { font-size: inherit }");
+        // Reduce the list default margins
+        styles.addRule("ol, ul { margin-left-ltr: 30; margin-left-rtl: 30 }");
+        // Make the size of code (and other elements) the same as other text
+        styles.addRule("code, kbd, samp, pre { font-size: inherit }");
 
         return text;
     }
@@ -1829,8 +1788,20 @@ public final class PassFailJFrame {
 
         public PassFailJFrame build() throws InterruptedException,
                 InvocationTargetException {
-            validate();
-            return new PassFailJFrame(this);
+            try {
+                validate();
+                return new PassFailJFrame(this);
+            } catch (final Throwable t) {
+                // Dispose of all the windows, including those that may not
+                // be registered with PassFailJFrame to allow AWT to shut down
+                try {
+                    invokeOnEDT(() -> Arrays.stream(Window.getWindows())
+                                            .forEach(Window::dispose));
+                } catch (Throwable edt) {
+                    t.addSuppressed(edt);
+                }
+                throw t;
+            }
         }
 
         /**
diff -pruN 24.0.1+9-1/test/jdk/java/io/File/createTempFile/SpecialTempFile.java 24.0.2+12-1/test/jdk/java/io/File/createTempFile/SpecialTempFile.java
--- 24.0.1+9-1/test/jdk/java/io/File/createTempFile/SpecialTempFile.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/io/File/createTempFile/SpecialTempFile.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -36,10 +36,15 @@ import java.nio.file.Path;
 
 import jdk.internal.util.OperatingSystem;
 import jdk.internal.util.OSVersion;
+import jdk.internal.util.StaticProperty;
 
 public class SpecialTempFile {
+    //
+    // If exceptionExpected == null, then any IOException thrown by
+    // File.createTempFile is ignored.
+    //
     private static void test(String name, String[] prefix, String[] suffix,
-                             boolean exceptionExpected) throws IOException
+                             Boolean exceptionExpected) throws IOException
     {
         if (prefix == null || suffix == null
             || prefix.length != suffix.length)
@@ -66,19 +71,21 @@ public class SpecialTempFile {
                     f = File.createTempFile(prefix[i], suffix[i],
                         tempDir.toFile());
                 } catch (IOException e) {
-                    if (exceptionExpected) {
-                        if (e.getMessage().startsWith(exceptionMsg))
-                            exceptionThrown = true;
-                        else
-                            System.out.println("Wrong error message:" +
-                                               e.getMessage());
-                    } else {
-                        throw e;
+                    if (exceptionExpected != null) {
+                        if (exceptionExpected) {
+                            if (e.getMessage().startsWith(exceptionMsg))
+                                exceptionThrown = true;
+                            else
+                                System.out.println("Wrong error message:" +
+                                                   e.getMessage());
+                        } else {
+                            throw e;
+                        }
+
+                        if (exceptionExpected && (!exceptionThrown || f != null))
+                            throw new RuntimeException("IOException expected");
                     }
                 }
-
-                if (exceptionExpected && (!exceptionThrown || f != null))
-                    throw new RuntimeException("IOException is expected");
             }
         }
     }
@@ -107,9 +114,12 @@ public class SpecialTempFile {
         // Test JDK-8013827
         String[] resvPre = { "LPT1.package.zip", "com7.4.package.zip" };
         String[] resvSuf = { ".temp", ".temp" };
-        boolean exceptionExpected =
-            !(System.getProperty("os.name").endsWith("11") ||
-              new OSVersion(10, 0).compareTo(OSVersion.current()) > 0);
-        test("ReservedName", resvPre, resvSuf, exceptionExpected);
+
+        System.out.println("OS name:    " + StaticProperty.osName() + "\n" +
+                           "OS version: " + OSVersion.current());
+
+        // Here the test is for whether File.createTempFile hangs, so whether
+        // an exception is thrown is ignored: expectedException == null
+        test("ReservedName", resvPre, resvSuf, null);
     }
 }
diff -pruN 24.0.1+9-1/test/jdk/java/lang/Thread/ThreadSleepEvent.java 24.0.2+12-1/test/jdk/java/lang/Thread/ThreadSleepEvent.java
--- 24.0.1+9-1/test/jdk/java/lang/Thread/ThreadSleepEvent.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/lang/Thread/ThreadSleepEvent.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 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
@@ -24,6 +24,7 @@
 /**
  * @test
  * @summary Test that Thread.sleep emits a JFR jdk.ThreadSleep event
+ * @requires vm.hasJFR
  * @modules jdk.jfr
  * @run junit ThreadSleepEvent
  */
diff -pruN 24.0.1+9-1/test/jdk/java/lang/Thread/virtual/JfrEvents.java 24.0.2+12-1/test/jdk/java/lang/Thread/virtual/JfrEvents.java
--- 24.0.1+9-1/test/jdk/java/lang/Thread/virtual/JfrEvents.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/lang/Thread/virtual/JfrEvents.java	2025-06-27 08:03:14.000000000 +0000
@@ -24,7 +24,7 @@
 /**
  * @test
  * @summary Basic test for JFR jdk.VirtualThreadXXX events
- * @requires vm.continuations
+ * @requires vm.continuations & vm.hasJFR
  * @modules jdk.jfr java.base/java.lang:+open jdk.management
  * @library /test/lib
  * @run junit/othervm --enable-native-access=ALL-UNNAMED JfrEvents
diff -pruN 24.0.1+9-1/test/jdk/java/lang/Thread/virtual/ThreadPollOnYield.java 24.0.2+12-1/test/jdk/java/lang/Thread/virtual/ThreadPollOnYield.java
--- 24.0.1+9-1/test/jdk/java/lang/Thread/virtual/ThreadPollOnYield.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/lang/Thread/virtual/ThreadPollOnYield.java	2025-06-27 08:03:14.000000000 +0000
@@ -40,13 +40,16 @@
  */
 
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.CountDownLatch;
 
 import jdk.test.lib.thread.VThreadPinner;
 import org.junit.jupiter.api.Test;
 import static org.junit.jupiter.api.Assertions.*;
 
 class ThreadPollOnYield {
+    private static final CountDownLatch started = new CountDownLatch(1);
     static void foo(AtomicBoolean done) {
+        started.countDown();
         while (!done.get()) {
             Thread.yield();
         }
@@ -58,7 +61,7 @@ class ThreadPollOnYield {
         var vthread = Thread.ofVirtual().start(() -> {
             VThreadPinner.runPinned(() -> foo(done));
         });
-        Thread.sleep(5000);
+        started.await();
         done.set(true);
         vthread.join();
 
diff -pruN 24.0.1+9-1/test/jdk/java/net/DatagramSocket/InterruptibleDatagramSocket.java 24.0.2+12-1/test/jdk/java/net/DatagramSocket/InterruptibleDatagramSocket.java
--- 24.0.1+9-1/test/jdk/java/net/DatagramSocket/InterruptibleDatagramSocket.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/DatagramSocket/InterruptibleDatagramSocket.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 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
@@ -37,6 +37,7 @@ import static java.lang.Thread.sleep;
  * @test
  * @summary Check interrupt mechanism for DatagramSocket,
  *      MulticastSocket, and DatagramSocketAdaptor
+ * @library /test/lib
  * @run main InterruptibleDatagramSocket
  */
 
@@ -97,6 +98,10 @@ public class InterruptibleDatagramSocket
     }
 
     public static void main(String[] args) throws Exception {
+        if (Thread.currentThread().isVirtual()) {
+            throw new jtreg.SkippedException(
+                    "skipping test execution - main thread is a virtual thread");
+        }
         try (DatagramSocket s = new DatagramSocket()) {
             System.out.println("Testing interrupt of DatagramSocket receive " +
                     "on endpoint " + s.getLocalSocketAddress());
diff -pruN 24.0.1+9-1/test/jdk/java/net/InetAddress/IsReachableViaLoopbackTest.java 24.0.2+12-1/test/jdk/java/net/InetAddress/IsReachableViaLoopbackTest.java
--- 24.0.1+9-1/test/jdk/java/net/InetAddress/IsReachableViaLoopbackTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/InetAddress/IsReachableViaLoopbackTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -21,22 +21,24 @@
  * questions.
  */
 
-import java.io.*;
-import java.net.*;
-import java.util.*;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
 
 /**
  * @test
  * @bug 8135305
  * @key intermittent
+ * @library /test/lib
  * @summary ensure we can't ping external hosts via loopback if
+ * @run main IsReachableViaLoopbackTest
  */
 
 public class IsReachableViaLoopbackTest {
     public static void main(String[] args) {
         try {
-            InetAddress addr = InetAddress.getByName("localhost");
-            InetAddress remoteAddr = InetAddress.getByName("bugs.openjdk.org");
+            InetAddress addr = InetAddress.getLoopbackAddress();
+            InetAddress remoteAddr = InetAddress.getByName("23.197.138.208");  // use literal address to avoid DNS checks
             if (!addr.isReachable(10000))
                 throw new RuntimeException("Localhost should always be reachable");
             NetworkInterface inf = NetworkInterface.getByInetAddress(addr);
@@ -54,7 +56,6 @@ public class IsReachableViaLoopbackTest
             } else {
                 System.out.println("inf == null");
             }
-
         } catch (IOException e) {
             throw new RuntimeException("Unexpected exception:" + e);
         }
diff -pruN 24.0.1+9-1/test/jdk/java/net/InetAddress/getOriginalHostName.java 24.0.2+12-1/test/jdk/java/net/InetAddress/getOriginalHostName.java
--- 24.0.1+9-1/test/jdk/java/net/InetAddress/getOriginalHostName.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/InetAddress/getOriginalHostName.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -41,7 +41,9 @@ public class getOriginalHostName {
     public static void main(String[] args) throws Exception {
         final String HOST = "dummyserver.java.net";
         InetAddress ia = null;
-        ia = InetAddress.getByName(HOST);
+        ia = getInetAddress(HOST);
+        if (ia != null) testInetAddress(ia, HOST);
+        ia = InetAddress.getByAddress(HOST, new byte[] { 1, 2, 3, 4});
         testInetAddress(ia, HOST);
         ia = InetAddress.getByName("255.255.255.0");
         testInetAddress(ia, null);
@@ -53,6 +55,14 @@ public class getOriginalHostName {
         testInetAddress(ia, ia.getHostName());
     }
 
+    private static InetAddress getInetAddress(String host) {
+        try {
+            return InetAddress.getByName(host);
+        } catch (java.net.UnknownHostException uhe) {
+            System.out.println("Skipping " + host + " due to " + uhe);
+            return null;
+        }
+    }
 
     private static void testInetAddress(InetAddress ia, String expected)
         throws Exception {
diff -pruN 24.0.1+9-1/test/jdk/java/net/httpclient/AbstractConnectTimeoutHandshake.java 24.0.2+12-1/test/jdk/java/net/httpclient/AbstractConnectTimeoutHandshake.java
--- 24.0.1+9-1/test/jdk/java/net/httpclient/AbstractConnectTimeoutHandshake.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/httpclient/AbstractConnectTimeoutHandshake.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -44,10 +44,11 @@ import java.net.http.HttpRequest;
 import java.net.http.HttpRequest.BodyPublishers;
 import java.net.http.HttpResponse;
 import java.net.http.HttpResponse.BodyHandlers;
+
+import jdk.test.lib.net.URIBuilder;
 import org.testng.annotations.AfterTest;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.DataProvider;
-import static java.lang.String.format;
 import static java.lang.System.out;
 import static java.net.http.HttpClient.Builder.NO_PROXY;
 import static java.net.http.HttpClient.Version.HTTP_1_1;
@@ -56,7 +57,7 @@ import static java.time.Duration.*;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 import static org.testng.Assert.fail;
 
-public abstract class AbstractConnectTimeoutHandshake {
+abstract class AbstractConnectTimeoutHandshake {
 
     // The number of iterations each testXXXClient performs.
     static final int TIMES = 2;
@@ -197,15 +198,15 @@ public abstract class AbstractConnectTim
 
     // -- Infrastructure
 
-    static String serverAuthority(Server server) {
-        return InetAddress.getLoopbackAddress().getHostName() + ":"
-                + server.getPort();
-    }
-
     @BeforeTest
     public void setup() throws Exception {
         server = new Server();
-        httpsURI = URI.create("https://" + serverAuthority(server) + "/foo");
+        httpsURI = URIBuilder.newBuilder()
+                .scheme("https")
+                .loopback()
+                .port(server.getPort())
+                .path("/foo")
+                .build();
         out.println("HTTPS URI: " + httpsURI);
     }
 
diff -pruN 24.0.1+9-1/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeAsync.java 24.0.2+12-1/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeAsync.java
--- 24.0.1+9-1/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeAsync.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeAsync.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -29,6 +29,8 @@ import org.testng.annotations.Test;
  * @test
  * @summary Tests connection timeouts during SSL handshake
  * @bug 8208391
+ * @library /test/lib
+ * @build AbstractConnectTimeoutHandshake
  * @run testng/othervm ConnectTimeoutHandshakeAsync
  */
 
diff -pruN 24.0.1+9-1/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeSync.java 24.0.2+12-1/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeSync.java
--- 24.0.1+9-1/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeSync.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/httpclient/ConnectTimeoutHandshakeSync.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -29,6 +29,8 @@ import org.testng.annotations.Test;
  * @test
  * @summary Tests connection timeouts during SSL handshake
  * @bug 8208391
+ * @library /test/lib
+ * @build AbstractConnectTimeoutHandshake
  * @run testng/othervm ConnectTimeoutHandshakeSync
  */
 
diff -pruN 24.0.1+9-1/test/jdk/java/net/httpclient/DigestEchoClient.java 24.0.2+12-1/test/jdk/java/net/httpclient/DigestEchoClient.java
--- 24.0.1+9-1/test/jdk/java/net/httpclient/DigestEchoClient.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/httpclient/DigestEchoClient.java	2025-06-27 08:03:14.000000000 +0000
@@ -260,8 +260,9 @@ public class DigestEchoClient {
         }
         try {
             for (DigestEchoServer.HttpAuthType authType : types) {
-                // The test server does not support PROXY305 properly
-                if (authType == DigestEchoServer.HttpAuthType.PROXY305) continue;
+                // The test server does not support PROXY305 or SERVER307 properly
+                if (authType == DigestEchoServer.HttpAuthType.PROXY305 ||
+                    authType == DigestEchoServer.HttpAuthType.SERVER307) continue;
                 EnumSet<DigestEchoServer.HttpAuthSchemeType> basics =
                         EnumSet.of(DigestEchoServer.HttpAuthSchemeType.BASICSERVER,
                                 DigestEchoServer.HttpAuthSchemeType.BASIC);
diff -pruN 24.0.1+9-1/test/jdk/java/net/httpclient/HeadTest.java 24.0.2+12-1/test/jdk/java/net/httpclient/HeadTest.java
--- 24.0.1+9-1/test/jdk/java/net/httpclient/HeadTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/httpclient/HeadTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -86,22 +86,21 @@ public class HeadTest implements HttpSer
     @DataProvider(name = "positive")
     public Object[][] positive() {
         return new Object[][] {
+                // HTTP/1.1
                 { httpURI, "GET", HTTP_NOT_MODIFIED, HTTP_1_1  },
                 { httpsURI, "GET", HTTP_NOT_MODIFIED, HTTP_1_1  },
-                { httpURI, "GET", HTTP_NOT_MODIFIED, HttpClient.Version.HTTP_2  },
-                { httpsURI, "GET", HTTP_NOT_MODIFIED, HttpClient.Version.HTTP_2  },
                 { httpURI, "HEAD", HTTP_OK, HTTP_1_1  },
                 { httpsURI, "HEAD", HTTP_OK, HTTP_1_1  },
-                { httpURI, "HEAD", HTTP_OK, HttpClient.Version.HTTP_2  },
-                { httpsURI, "HEAD", HTTP_OK, HttpClient.Version.HTTP_2  },
                 { httpURI + "transfer/", "GET", HTTP_NOT_MODIFIED, HTTP_1_1  },
                 { httpsURI + "transfer/", "GET", HTTP_NOT_MODIFIED, HTTP_1_1  },
-                { httpURI + "transfer/", "GET", HTTP_NOT_MODIFIED, HttpClient.Version.HTTP_2  },
-                { httpsURI + "transfer/", "GET", HTTP_NOT_MODIFIED, HttpClient.Version.HTTP_2  },
                 { httpURI + "transfer/", "HEAD", HTTP_OK, HTTP_1_1  },
                 { httpsURI + "transfer/", "HEAD", HTTP_OK, HTTP_1_1  },
-                { httpURI + "transfer/", "HEAD", HTTP_OK, HttpClient.Version.HTTP_2  },
-                { httpsURI + "transfer/", "HEAD", HTTP_OK, HttpClient.Version.HTTP_2  }
+                // HTTP/2
+                { http2URI, "GET", HTTP_NOT_MODIFIED, HttpClient.Version.HTTP_2  },
+                { https2URI, "GET", HTTP_NOT_MODIFIED, HttpClient.Version.HTTP_2  },
+                { http2URI, "HEAD", HTTP_OK, HttpClient.Version.HTTP_2  },
+                { https2URI, "HEAD", HTTP_OK, HttpClient.Version.HTTP_2  },
+                // HTTP2 forbids transfer-encoding
         };
     }
 
@@ -112,17 +111,13 @@ public class HeadTest implements HttpSer
         URI uri = URI.create(uriString);
         HttpRequest.Builder requestBuilder = HttpRequest
                 .newBuilder(uri)
+                .version(version)
                 .method(method, HttpRequest.BodyPublishers.noBody());
-        if (version != null) {
-            requestBuilder.version(version);
-        }
         doTest(requestBuilder.build(), expResp);
         // repeat the test this time by building the request using convenience
         // GET and HEAD methods
-        requestBuilder = HttpRequest.newBuilder(uri);
-        if (version != null) {
-            requestBuilder.version(version);
-        }
+        requestBuilder = HttpRequest.newBuilder(uri)
+                .version(version);
         switch (method) {
             case "GET" -> requestBuilder.GET();
             case "HEAD" -> requestBuilder.HEAD();
@@ -146,6 +141,7 @@ public class HeadTest implements HttpSer
         assertEquals(response.statusCode(), expResp);
         assertEquals(response.body(), "");
         assertEquals(response.headers().firstValue("Content-length").get(), CONTENT_LEN);
+        assertEquals(response.version(), request.version().get());
     }
 
     // -- Infrastructure
@@ -168,7 +164,7 @@ public class HeadTest implements HttpSer
         http2TestServer = HttpTestServer.create(HTTP_2);
         http2TestServer.addHandler(new HeadHandler(), "/");
         http2URI = "http://" + http2TestServer.serverAuthority() + "/";
-        https2TestServer = HttpTestServer.create(HTTP_2, SSLContext.getDefault());
+        https2TestServer = HttpTestServer.create(HTTP_2, sslContext);
         https2TestServer.addHandler(new HeadHandler(), "/");
         https2URI = "https://" + https2TestServer.serverAuthority() + "/";
 
diff -pruN 24.0.1+9-1/test/jdk/java/net/httpclient/Http1ChunkedTest.java 24.0.2+12-1/test/jdk/java/net/httpclient/Http1ChunkedTest.java
--- 24.0.1+9-1/test/jdk/java/net/httpclient/Http1ChunkedTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/httpclient/Http1ChunkedTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -97,7 +97,7 @@ public class Http1ChunkedTest {
                         }
                     }
                     if (!received) {
-                        System.out.printf("%s: Unexpected headers received: dropping request.%n");
+                        System.out.printf("%s: Unexpected headers received: dropping request.%n", name);
                         continue;
                     }
                     OutputStream os = serverConn.getOutputStream();
diff -pruN 24.0.1+9-1/test/jdk/java/net/httpclient/HttpClientSNITest.java 24.0.2+12-1/test/jdk/java/net/httpclient/HttpClientSNITest.java
--- 24.0.1+9-1/test/jdk/java/net/httpclient/HttpClientSNITest.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/httpclient/HttpClientSNITest.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.util.List;
+
+import javax.net.ssl.SNIHostName;
+import javax.net.ssl.SNIMatcher;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+
+import com.sun.net.httpserver.HttpsConfigurator;
+import com.sun.net.httpserver.HttpsParameters;
+import com.sun.net.httpserver.HttpsServer;
+import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestExchange;
+import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestHandler;
+import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestServer;
+import jdk.httpclient.test.lib.common.ServerNameMatcher;
+import jdk.test.lib.net.SimpleSSLContext;
+import jdk.test.lib.net.URIBuilder;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import static java.nio.charset.StandardCharsets.US_ASCII;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/*
+ * @test
+ * @bug 8346705
+ * @summary verify the behaviour of java.net.http.HttpClient
+ *          when sending a Server Name Indication in the TLS
+ *          connections that it establishes for the requests
+ * @library /test/lib /test/jdk/java/net/httpclient/lib
+ * @build jdk.httpclient.test.lib.common.HttpServerAdapters
+ *        jdk.test.lib.net.SimpleSSLContext
+ *        jdk.test.lib.net.URIBuilder
+ * @run junit HttpClientSNITest
+ */
+public class HttpClientSNITest {
+    private static final String RESP_BODY_TEXT = "hello world";
+
+    private static final class Handler implements HttpTestHandler {
+
+        @Override
+        public void handle(final HttpTestExchange exch) throws IOException {
+            System.out.println("handling request " + exch.getRequestURI());
+            final byte[] respBody = RESP_BODY_TEXT.getBytes(US_ASCII);
+            exch.sendResponseHeaders(200, respBody.length);
+            try (final OutputStream os = exch.getResponseBody()) {
+                os.write(respBody);
+            }
+        }
+    }
+
+    /*
+     * Creates and configures a HTTPS server with a SNIMatcher that
+     * expects a specific SNI name to be sent by the connection client.
+     * The test uses a HttpClient to issue a couple of requests with the URI having
+     * a IP address literal as the host. For one of the request, the HttpClient
+     * is configured with specific ServerName(s) through HttpClient.sslParameters()
+     * and for the other request, it isn't.
+     * The test then verifies that for such requests with a IP address literal as the host,
+     * the HttpClient sends across the ServerName(s) if any has been configured on the client.
+     */
+    @ParameterizedTest
+    @ValueSource(booleans = {false, true})
+    void testRequestToIPLiteralHost(final boolean sniConfiguredOnClient) throws Exception {
+        final SSLContext sslContext = new SimpleSSLContext().get();
+        assertNotNull(sslContext, "could not create a SSLContext");
+        final String expectedSNI = "non-dns-resolvable.foo.bar.localhost";
+        final ServerNameMatcher matcher = new ServerNameMatcher(expectedSNI);
+        final HttpTestServer server = createServer(matcher, sslContext);
+        try {
+            final HttpClient.Builder builder = HttpClient.newBuilder().sslContext(sslContext);
+            if (sniConfiguredOnClient) {
+                final SSLParameters clientConfiguredSSLParams = new SSLParameters();
+                clientConfiguredSSLParams.setServerNames(List.of(new SNIHostName(expectedSNI)));
+                builder.sslParameters(clientConfiguredSSLParams);
+            }
+            try (final HttpClient client = builder.build()) {
+                final String ipLiteral = InetAddress.getLoopbackAddress().getHostAddress();
+                final URI reqURI = URIBuilder.newBuilder()
+                        .host(ipLiteral)
+                        .port(server.getAddress().getPort())
+                        .scheme("https")
+                        .path("/")
+                        .build();
+                final HttpRequest req = HttpRequest.newBuilder(reqURI).build();
+                System.out.println("issuing request " + reqURI);
+                final HttpResponse<String> resp = client.send(req, BodyHandlers.ofString(US_ASCII));
+                assertEquals(200, resp.statusCode(), "unexpected response status code");
+                assertEquals(RESP_BODY_TEXT, resp.body(), "unexpected response body");
+                if (sniConfiguredOnClient) {
+                    assertTrue(matcher.wasInvoked(), "SNIMatcher wasn't invoked on the server");
+                } else {
+                    assertFalse(matcher.wasInvoked(), "SNIMatcher was unexpectedly invoked" +
+                            " on the server");
+                }
+            }
+        } finally {
+            System.out.println("stopping server " + server.getAddress());
+            server.stop();
+        }
+    }
+
+    /*
+     * Creates and configures a HTTPS server with a SNIMatcher that
+     * expects a specific SNI name to be sent by the connection client.
+     * The test uses a HttpClient to issue a couple of requests with the URI having
+     * a hostname (i.e. not a IP address literal) as the host. For one of the request,
+     * the HttpClient is configured with specific ServerName(s) through
+     * HttpClient.sslParameters() and for the other request, it isn't.
+     * The test then verifies that for such requests with a hostname
+     * (i.e. not a IP address literal) in the request URI,
+     * the HttpClient never sends ServerName(s) that may have been configured on the
+     * client and instead it sends the hostname (from the request URI) as the ServerName
+     * for each of the request.
+     */
+    @ParameterizedTest
+    @ValueSource(booleans = {false, true})
+    void testRequestResolvedHostName(final boolean sniConfiguredOnClient) throws Exception {
+        final SSLContext sslContext = new SimpleSSLContext().get();
+        assertNotNull(sslContext, "could not create a SSLContext");
+        final String resolvedHostName = InetAddress.getLoopbackAddress().getHostName();
+        final String expectedSNI = resolvedHostName;
+        final ServerNameMatcher matcher = new ServerNameMatcher(expectedSNI);
+        final HttpTestServer server = createServer(matcher, sslContext);
+        try {
+            final HttpClient.Builder builder = HttpClient.newBuilder().sslContext(sslContext);
+            if (sniConfiguredOnClient) {
+                final SSLParameters clientConfiguredSSLParams = new SSLParameters();
+                clientConfiguredSSLParams.setServerNames(List.of(new SNIHostName("does-not-matter")));
+                builder.sslParameters(clientConfiguredSSLParams);
+            }
+            try (final HttpClient client = builder.build()) {
+                final URI reqURI = URIBuilder.newBuilder()
+                        .host(resolvedHostName)
+                        .port(server.getAddress().getPort())
+                        .scheme("https")
+                        .path("/")
+                        .build();
+                final HttpRequest req = HttpRequest.newBuilder(reqURI).build();
+                System.out.println("issuing request " + reqURI);
+                final HttpResponse<String> resp = client.send(req, BodyHandlers.ofString(US_ASCII));
+                assertEquals(200, resp.statusCode(), "unexpected response status code");
+                assertEquals(RESP_BODY_TEXT, resp.body(), "unexpected response body");
+                assertTrue(matcher.wasInvoked(), "SNIMatcher wasn't invoked on the server");
+            }
+        } finally {
+            System.out.println("stopping server " + server.getAddress());
+            server.stop();
+        }
+    }
+
+    /*
+     * Creates a HttpsServer configured to use the given SNIMatcher
+     */
+    private static HttpTestServer createServer(final SNIMatcher matcher,
+                                               final SSLContext sslContext) throws Exception {
+        final InetSocketAddress addr = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
+        final int backlog = 0;
+        final HttpsServer httpsServer = HttpsServer.create(addr, backlog);
+        final HttpsConfigurator configurator = new HttpsConfigurator(sslContext) {
+            @Override
+            public void configure(final HttpsParameters params) {
+                final SSLParameters sslParameters = sslContext.getDefaultSSLParameters();
+                // add the SNIMatcher
+                sslParameters.setSNIMatchers(List.of(matcher));
+                params.setSSLParameters(sslParameters);
+                System.out.println("configured HttpsServer with SNIMatcher: " + matcher);
+            }
+        };
+        httpsServer.setHttpsConfigurator(configurator);
+        final HttpTestServer server = HttpTestServer.of(httpsServer);
+        server.addHandler(new Handler(), "/");
+        server.start();
+        System.out.println("server started at " + server.getAddress());
+        return server;
+    }
+}
diff -pruN 24.0.1+9-1/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java 24.0.2+12-1/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java
--- 24.0.1+9-1/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 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
@@ -34,6 +34,7 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InterruptedIOException;
 import java.io.OutputStream;
 import java.net.ProtocolException;
 import java.net.URI;
@@ -335,7 +336,9 @@ public class StreamFlowControlTest {
                             // to wait for the connection window
                             fct.conn.obtainConnectionWindow(resp.length);
                         } catch (InterruptedException ie) {
-                            // ignore and continue...
+                            var ioe = new InterruptedIOException(ie.toString());
+                            ioe.initCause(ie);
+                            throw ioe;
                         }
                     }
                     try {
@@ -344,6 +347,7 @@ public class StreamFlowControlTest {
                         if (t instanceof FCHttp2TestExchange fct) {
                             fct.conn.updateConnectionWindow(resp.length);
                         }
+                        throw x;
                     }
                 }
             } finally {
diff -pruN 24.0.1+9-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java 24.0.2+12-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java
--- 24.0.1+9-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -239,7 +239,7 @@ public interface HttpServerAdapters {
         public abstract OutputStream  getResponseBody();
         public abstract HttpTestRequestHeaders getRequestHeaders();
         public abstract HttpTestResponseHeaders getResponseHeaders();
-        public abstract void sendResponseHeaders(int code, int contentLength) throws IOException;
+        public abstract void sendResponseHeaders(int code, long contentLength) throws IOException;
         public abstract URI getRequestURI();
         public abstract String getRequestMethod();
         public abstract void close();
@@ -292,7 +292,7 @@ public interface HttpServerAdapters {
                 return HttpTestResponseHeaders.of(exchange.getResponseHeaders());
             }
             @Override
-            public void sendResponseHeaders(int code, int contentLength) throws IOException {
+            public void sendResponseHeaders(int code, long contentLength) throws IOException {
                 if (contentLength == 0) contentLength = -1;
                 else if (contentLength < 0) contentLength = 0;
                 exchange.sendResponseHeaders(code, contentLength);
@@ -355,7 +355,7 @@ public interface HttpServerAdapters {
                 return HttpTestResponseHeaders.of(exchange.getResponseHeaders());
             }
             @Override
-            public void sendResponseHeaders(int code, int contentLength) throws IOException {
+            public void sendResponseHeaders(int code, long contentLength) throws IOException {
                 if (contentLength == 0) contentLength = -1;
                 else if (contentLength < 0) contentLength = 0;
                 exchange.sendResponseHeaders(code, contentLength);
diff -pruN 24.0.1+9-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/ServerNameMatcher.java 24.0.2+12-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/ServerNameMatcher.java
--- 24.0.1+9-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/ServerNameMatcher.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/ServerNameMatcher.java	2025-06-27 08:03:14.000000000 +0000
@@ -58,6 +58,7 @@ public class ServerNameMatcher extends S
     private final Logger debug;
     private final boolean attemptDNSResolution;
     private final Set<String> recognizedSNINames;
+    private volatile boolean invoked;
 
     /**
      * Creates a ServerNameMatcher which recognizes the passed {@code recognizedSNIName}
@@ -97,6 +98,7 @@ public class ServerNameMatcher extends S
      */
     @Override
     public boolean matches(final SNIServerName clientRequestedSNI) {
+        this.invoked = true;
         Objects.requireNonNull(clientRequestedSNI);
         if (!SNIHostName.class.isInstance(clientRequestedSNI)) {
             if (debug.on()) {
@@ -128,6 +130,14 @@ public class ServerNameMatcher extends S
         return false;
     }
 
+    /**
+     * @return true if the {@link #matches(SNIServerName)} method of this SNIMatcher instance
+     * was invoked at least once, false otherwise.
+     */
+    public boolean wasInvoked() {
+        return this.invoked;
+    }
+
     private boolean matchesAfterDNSResolution(final String clientRequestedSNI) {
         final InetAddress clientRequestedAddr;
         try {
diff -pruN 24.0.1+9-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/BodyOutputStream.java 24.0.2+12-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/BodyOutputStream.java
--- 24.0.1+9-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/BodyOutputStream.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/BodyOutputStream.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -63,22 +63,28 @@ public class BodyOutputStream extends Ou
     }
 
     void waitForWindow(int demand) throws InterruptedException {
-        // first wait for the connection window
-        conn.obtainConnectionWindow(demand);
-        // now wait for the stream window
+        //  first wait for the stream window
         waitForStreamWindow(demand);
+        // now wait for the connection window
+        conn.obtainConnectionWindow(demand);
     }
 
-    public void waitForStreamWindow(int demand) throws InterruptedException {
-        synchronized (this) {
-            while (demand > 0) {
-                int n = Math.min(demand, window);
-                demand -= n;
-                window -= n;
-                if (demand > 0) {
-                    wait();
+    public void waitForStreamWindow(int amount) throws InterruptedException {
+        int demand = amount;
+        try {
+            synchronized (this) {
+                while (amount > 0) {
+                    int n = Math.min(amount, window);
+                    amount -= n;
+                    window -= n;
+                    if (amount > 0) {
+                        wait();
+                    }
                 }
             }
+        } catch (Throwable t) {
+            window += (demand - amount);
+            throw t;
         }
     }
 
diff -pruN 24.0.1+9-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServerConnection.java 24.0.2+12-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServerConnection.java
--- 24.0.1+9-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServerConnection.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServerConnection.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -171,7 +171,7 @@ public class Http2TestServerConnection {
                               Properties properties)
         throws IOException
     {
-        System.err.println("TestServer: New connection from " + socket);
+        System.err.println(server.name + ": New connection from " + socket);
 
         if (socket instanceof SSLSocket) {
             SSLSocket sslSocket = (SSLSocket)socket;
@@ -218,10 +218,10 @@ public class Http2TestServerConnection {
             String prop = properties.getProperty(propPrefix + key);
             if (prop != null) {
                 try {
-                    System.err.println("TestServer: setting " + key + " property to: " +
+                    System.err.println(server.name + ": setting " + key + " property to: " +
                         prop);
                     int num = Integer.parseInt(numS);
-                    System.err.println("TestServer: num = " + num);
+                    System.err.println(server.name + ": num = " + num);
                     s.setParameter(num, Integer.parseInt(prop));
                 } catch (NumberFormatException e) {/* ignore errors */}
             }
@@ -269,7 +269,7 @@ public class Http2TestServerConnection {
         }
         final GoAwayFrame frame = new GoAwayFrame(maxProcessedStreamId, error);
         outputQ.put(frame);
-        System.err.println("Sending GOAWAY frame " + frame + " from server connection " + this);
+        System.err.println(server.name + ": Sending GOAWAY frame " + frame + " from server connection " + this);
     }
 
     /**
@@ -285,7 +285,7 @@ public class Http2TestServerConnection {
      */
     void handlePing(PingFrame ping) throws IOException {
         if (ping.streamid() != 0) {
-            System.err.println("Invalid ping received");
+            System.err.println(server.name + ": Invalid ping received");
             close(ErrorFrame.PROTOCOL_ERROR);
             return;
         }
@@ -293,7 +293,7 @@ public class Http2TestServerConnection {
             // did we send a Ping?
             PingRequest request = getNextRequest();
             if (request == null) {
-                System.err.println("Invalid ping ACK received");
+                System.err.println(server.name + ": Invalid ping ACK received");
                 close(ErrorFrame.PROTOCOL_ERROR);
                 return;
             } else if (!Arrays.equals(request.pingData, ping.getData())) {
@@ -356,7 +356,7 @@ public class Http2TestServerConnection {
         if (stopping)
             return;
         stopping = true;
-        System.err.printf("Server connection to %s stopping. %d streams\n",
+        System.err.printf(server.name + ": Server connection to %s stopping. %d streams\n",
             socket.getRemoteSocketAddress().toString(), streams.size());
         streams.forEach((i, q) -> {
             q.orderlyClose();
@@ -376,16 +376,20 @@ public class Http2TestServerConnection {
         byte[] bytes = new byte[len];
         int n = is.readNBytes(bytes, 0, len);
         if (Arrays.compare(clientPreface, bytes) != 0) {
-            System.err.printf("Invalid preface: read %d/%d bytes%n", n, len);
-            throw new IOException("Invalid preface: " +
-                    new String(bytes, 0, len, ISO_8859_1));
+            String msg = String.format("Invalid preface: read %s/%s bytes", n, len);
+            System.err.println(server.name + ": " + msg);
+            throw new IOException(msg +": \"" +
+                    new String(bytes, 0, n, ISO_8859_1)
+                            .replace("\r", "\\r")
+                            .replace("\n", "\\n")
+                    + "\"");
         }
     }
 
     Http1InitialRequest doUpgrade(Http1InitialRequest upgrade) throws IOException {
         String h2c = getHeader(upgrade.headers, "Upgrade");
         if (h2c == null || !h2c.equals("h2c")) {
-            System.err.println("Server:HEADERS: " + upgrade);
+            System.err.println(server.name + ":HEADERS: " + upgrade);
             throw new IOException("Bad upgrade 1 " + h2c);
         }
 
@@ -457,7 +461,7 @@ public class Http2TestServerConnection {
                     socket.close();
                     return;
                 } else {
-                    System.err.println("Server:HEADERS: " + upgrade);
+                    System.err.println(server.name + ":HEADERS: " + upgrade);
                     throw new IOException("Bad upgrade 1 " + h2c);
                 }
             }
@@ -556,7 +560,7 @@ public class Http2TestServerConnection {
             outputQ.put(frame);
             return;
         } else if (f instanceof GoAwayFrame) {
-            System.err.println("Closing: "+ f.toString());
+            System.err.println(server.name + ": Closing connection: "+ f.toString());
             close(ErrorFrame.NO_ERROR);
         } else if (f instanceof PingFrame) {
             handlePing((PingFrame)f);
@@ -649,7 +653,7 @@ public class Http2TestServerConnection {
         // skip processing the request if configured to do so
         final String connKey = connectionKey();
         if (!shouldProcessNewHTTPRequest(connKey)) {
-            System.err.println("Rejecting primordial stream 1 and sending GOAWAY" +
+            System.err.println(server.name + ": Rejecting primordial stream 1 and sending GOAWAY" +
                     " on server connection " + connKey + ", for request: " + path);
             sendGoAway(ErrorFrame.NO_ERROR);
             return;
@@ -726,7 +730,7 @@ public class Http2TestServerConnection {
         final String connKey = connectionKey();
         final String path = headers.firstValue(":path").orElse("");
         if (!shouldProcessNewHTTPRequest(connKey)) {
-            System.err.println("Rejecting stream " + streamid
+            System.err.println(server.name + ": Rejecting stream " + streamid
                     + " and sending GOAWAY on server connection "
                     + connKey + ", for request: " + path);
             sendGoAway(ErrorFrame.NO_ERROR);
@@ -764,17 +768,17 @@ public class Http2TestServerConnection {
         //System.out.println("scheme = " + scheme);
         String authority = headers.firstValue(":authority").orElse("");
         //System.out.println("authority = " + authority);
-        System.err.printf("TestServer: %s %s\n", method, path);
+        System.err.printf(server.name + ": %s %s\n", method, path);
         int winsize = clientSettings.getParameter(
                 SettingsFrame.INITIAL_WINDOW_SIZE);
         //System.err.println ("Stream window size = " + winsize);
 
         final InputStream bis;
         if (endStreamReceived && queue.size() == 0) {
-            System.err.println("Server: got END_STREAM for stream " + streamid);
+            System.err.println(server.name + ": got END_STREAM for stream " + streamid);
             bis = NullInputStream.INSTANCE;
         } else {
-            System.err.println("Server: creating input stream for stream " + streamid);
+            System.err.println(server.name + ": creating input stream for stream " + streamid);
             bis = new BodyInputStream(queue, streamid, this);
         }
         try (bis;
@@ -802,7 +806,7 @@ public class Http2TestServerConnection {
                 if (bos.closed) {
                     Queue q = streams.get(streamid);
                     if (q != null && (q.isClosed() || q.isClosing())) {
-                        System.err.println("TestServer: Stream " + streamid + " closed: " + closed);
+                        System.err.println(server.name + ": Stream " + streamid + " closed: " + closed);
                         return;
                     }
                 }
@@ -812,7 +816,7 @@ public class Http2TestServerConnection {
             // everything happens in the exchange from here. Hopefully will
             // return though.
         } catch (Throwable e) {
-            System.err.println("TestServer: handleRequest exception: " + e);
+            System.err.println(server.name + ": handleRequest exception: " + e);
             e.printStackTrace();
             close(-1);
         }
@@ -844,7 +848,7 @@ public class Http2TestServerConnection {
             while (!stopping) {
                 Http2Frame frame = readFrameImpl();
                 if (frame == null) {
-                    System.err.println("EOF reached on connection " + connectionKey()
+                    System.err.println(server.name + ": EOF reached on connection " + connectionKey()
                             + ", will no longer accept incoming frames");
                     closeIncoming();
                     return;
@@ -865,7 +869,7 @@ public class Http2TestServerConnection {
                     Queue q = streams.get(stream);
                     if (frame.type() == HeadersFrame.TYPE) {
                         if (q != null) {
-                            System.err.println("HEADERS frame for existing stream! Error.");
+                            System.err.println(server.name + ": HEADERS frame for existing stream! Error.");
                             // TODO: close connection
                             continue;
                         } else {
@@ -874,7 +878,8 @@ public class Http2TestServerConnection {
                             // if we already sent a goaway, then don't create new streams with
                             // higher stream ids.
                             if (finalProcessedStreamId != -1 && streamId > finalProcessedStreamId) {
-                                System.err.println(connectionKey() + " resetting stream " + streamId
+                                System.err.println(server.name + ": " + connectionKey()
+                                        + " resetting stream " + streamId
                                         + " as REFUSED_STREAM");
                                 final ResetFrame rst = new ResetFrame(streamId, REFUSED_STREAM);
                                 outputQ.put(rst);
@@ -884,7 +889,7 @@ public class Http2TestServerConnection {
                         }
                     } else {
                         if (q == null && !pushStreams.contains(stream)) {
-                            System.err.printf("Non Headers frame received with"+
+                            System.err.printf(server.name + ": Non Headers frame received with"+
                                     " non existing stream (%d) ", frame.streamid());
                             System.err.println(frame);
                             continue;
@@ -914,21 +919,21 @@ public class Http2TestServerConnection {
                             } else if (isClientStreamId(stream) && stream < next) {
                                 // We may receive a reset on a client stream that has already
                                 // been closed. Just ignore it.
-                                System.err.println("TestServer: received ResetFrame on closed stream: " + stream);
+                                System.err.println(server.name + ": received ResetFrame on closed stream: " + stream);
                                 System.err.println(frame);
                             } else if (isServerStreamId(stream) && stream < nextPush) {
                                 // We may receive a reset on a push stream that has already
                                 // been closed. Just ignore it.
-                                System.err.println("TestServer: received ResetFrame on closed push stream: " + stream);
+                                System.err.println(server.name + ": received ResetFrame on closed push stream: " + stream);
                                 System.err.println(frame);
                             } else {
-                                System.err.println("TestServer: Unexpected frame on: " + stream);
+                                System.err.println(server.name + ": Unexpected frame on: " + stream);
                                 System.err.println(frame);
                                 throw new IOException("Unexpected frame");
                             }
                         } else {
                             if (!q.putIfOpen(frame)) {
-                                System.err.printf("Stream %s is closed: dropping %s%n",
+                                System.err.printf(server.name + ": Stream %s is closed: dropping %s%n",
                                         stream, frame);
                             }
                         }
@@ -937,7 +942,7 @@ public class Http2TestServerConnection {
             }
         } catch (Throwable e) {
             if (!stopping) {
-                System.err.println("Http server reader thread shutdown");
+                System.err.println(server.name + ": Http server reader thread shutdown");
                 e.printStackTrace();
             }
             close(ErrorFrame.PROTOCOL_ERROR);
@@ -1078,7 +1083,7 @@ public class Http2TestServerConnection {
                                 : new ContinuationFrame(rh.streamid(), flags, list);
                         if (Log.headers()) {
                             // avoid too much chatter: log only if Log.headers() is enabled
-                            System.err.println("TestServer writing " + hf);
+                            System.err.println(server.name + ": writing " + hf);
                         }
                         writeFrame(hf);
                         cont++;
@@ -1088,7 +1093,7 @@ public class Http2TestServerConnection {
                 } else
                     writeFrame(frame);
             }
-            System.err.println("TestServer: Connection writer stopping");
+            System.err.println(server.name + ": Connection writer stopping " + connectionKey());
         } catch (Throwable e) {
             e.printStackTrace();
             /*close();
@@ -1140,7 +1145,7 @@ public class Http2TestServerConnection {
 
                 ii.transferTo(oo);
             } catch (Throwable ex) {
-                System.err.printf("TestServer: pushing response error: %s\n",
+                System.err.printf(server.name + ": pushing response error: %s\n",
                         ex.toString());
             } finally {
                 closeIgnore(ii);
@@ -1303,7 +1308,7 @@ public class Http2TestServerConnection {
             }
             return new Http1InitialRequest(headers, buf);
         } catch (IOException e) {
-            System.err.println("TestServer: headers read: [ " + headers + " ]");
+            System.err.println(server.name + ": headers read: [ " + headers + " ]");
             throw e;
         }
     }
@@ -1335,7 +1340,7 @@ public class Http2TestServerConnection {
     }
 
     private void unexpectedFrame(Http2Frame frame) {
-        System.err.println("OOPS. Unexpected");
+        System.err.println(server.name + ": OOPS. Unexpected");
         assert false;
     }
 
@@ -1375,19 +1380,41 @@ public class Http2TestServerConnection {
      * @param amount
      */
     public synchronized void obtainConnectionWindow(int amount) throws InterruptedException {
-        while (amount > 0) {
-            int n = Math.min(amount, sendWindow);
-            amount -= n;
-            sendWindow -= n;
-            if (amount > 0)
-                wait();
+        int demand = amount;
+        try {
+            int waited = 0;
+            while (amount > 0) {
+                int n = Math.min(amount, sendWindow);
+                amount -= n;
+                sendWindow -= n;
+                if (amount > 0) {
+                    // Do not include this print line on a version that does not have
+                    // JDK-8337395
+                    System.err.printf("%s: blocked waiting for %s connection window, obtained %s%n",
+                            server.name, amount, demand - amount);
+                    waited++;
+                    wait();
+                }
+            }
+            if (waited > 0) {
+                // Do not backport this print line on a version that does not have
+                // JDK-8337395
+                System.err.printf("%s: obtained %s connection window, remaining %s%n",
+                        server.name, demand, sendWindow);
+            }
+            assert amount == 0;
+        } catch (Throwable t) {
+            sendWindow += (demand - amount);
+            throw t;
         }
     }
 
     public void updateConnectionWindow(int amount) {
-        System.out.printf("sendWindow (window=%s, amount=%s) is now: %s%n",
-                sendWindow, amount, sendWindow + amount);
         synchronized (this) {
+            // Do not backport this print line on a version that does not have
+            // JDK-8337395
+            System.err.printf(server.name + ": update sendWindow (window=%s, amount=%s) is now: %s%n",
+                    sendWindow, amount, sendWindow + amount);
             sendWindow += amount;
             notifyAll();
         }
diff -pruN 24.0.1+9-1/test/jdk/java/net/httpclient/offline/FixedResponseHttpClient.java 24.0.2+12-1/test/jdk/java/net/httpclient/offline/FixedResponseHttpClient.java
--- 24.0.1+9-1/test/jdk/java/net/httpclient/offline/FixedResponseHttpClient.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/httpclient/offline/FixedResponseHttpClient.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -209,8 +209,11 @@ public class FixedResponseHttpClient ext
         if (obp.isPresent()) {
             ConsumingSubscriber subscriber = new ConsumingSubscriber();
             obp.get().subscribe(subscriber);
+            // wait for our subscriber to be completed and get the
+            // list of ByteBuffers it received.
+            var buffers = subscriber.getBuffers().join();
             if (responseBodyBytes == ECHO_SENTINAL) {
-                responseBody = subscriber.buffers;
+                responseBody = buffers;
             }
         }
 
@@ -246,6 +249,13 @@ public class FixedResponseHttpClient ext
      */
     private static class ConsumingSubscriber implements Flow.Subscriber<ByteBuffer> {
         final List<ByteBuffer> buffers = Collections.synchronizedList(new ArrayList<>());
+        // A CompletableFuture that will be completed with a list of ByteBuffers that the
+        // ConsumingSubscriber has consumed.
+        final CompletableFuture<List<ByteBuffer>> consumed = new CompletableFuture<>();
+
+        public final CompletableFuture<List<ByteBuffer>> getBuffers() {
+            return consumed;
+        }
 
         @Override
         public void onSubscribe(Flow.Subscription subscription) {
@@ -256,9 +266,9 @@ public class FixedResponseHttpClient ext
             buffers.add(item.duplicate());
         }
 
-        @Override public void onError(Throwable throwable) { assert false : "Unexpected"; }
+        @Override public void onError(Throwable throwable) { consumed.completeExceptionally(throwable); }
 
-        @Override public void onComplete() { /* do nothing */ }
+        @Override public void onComplete() { consumed.complete(buffers.stream().toList()); }
     }
 
     @Override
diff -pruN 24.0.1+9-1/test/jdk/java/net/ipv6tests/TcpTest.java 24.0.2+12-1/test/jdk/java/net/ipv6tests/TcpTest.java
--- 24.0.1+9-1/test/jdk/java/net/ipv6tests/TcpTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/ipv6tests/TcpTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2021, 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
@@ -36,6 +36,7 @@
 
 import java.net.*;
 import java.io.*;
+import java.util.concurrent.TimeUnit;
 
 public class TcpTest extends Tests {
     static ServerSocket server, server1, server2;
@@ -193,13 +194,14 @@ public class TcpTest extends Tests {
         server = new ServerSocket (0);
         server.setSoTimeout (5000);
         int port = server.getLocalPort();
-        long t1 = System.currentTimeMillis();
+        long t1 = System.nanoTime();
         try {
             server.accept ();
             throw new RuntimeException ("accept should not have returned");
         } catch (SocketTimeoutException e) {}
-        t1 = System.currentTimeMillis() - t1;
-        checkTime (t1, 5000);
+        t1 = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t1);
+        final long expectedTime = TimeUnit.SECONDS.toMillis(5);
+        checkIfTimeOut(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t1), expectedTime);
 
         c1 = new Socket ();
         c1.connect (new InetSocketAddress (ia4addr, port), 1000);
diff -pruN 24.0.1+9-1/test/jdk/java/net/ipv6tests/Tests.java 24.0.2+12-1/test/jdk/java/net/ipv6tests/Tests.java
--- 24.0.1+9-1/test/jdk/java/net/ipv6tests/Tests.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/ipv6tests/Tests.java	2025-06-27 08:03:14.000000000 +0000
@@ -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
@@ -151,19 +151,14 @@ public class Tests {
         }
     }
 
-    /* check the time got is within 50% of the time expected */
-    public static void checkTime (long got, long expected) {
-        checkTime(got, expected, expected);
-    }
 
-    /* check the time got is between start and end, given 50% tolerance */
-    public static void checkTime(long got, long start, long end) {
-        dprintln("checkTime: got = " + got + " start = " + start + " end = " + end);
-        long upper = end + (end / 2);
-        long lower = start - (start / 2);
-        if (got > upper || got < lower) {
-            throw new RuntimeException("checkTime failed: got " + got
-                    + ", expected between " + start + " and " + end);
+    /* check the timeout breached lower bound time rule */
+    public static void checkIfTimeOut(long got, long expected) {
+        dprintln("checkIfTimeOut: got = " + got + " lower bound = " + expected);
+
+        if (got < expected) {
+            throw new RuntimeException("checkIfTimeOut failed: got " + got
+                    + ", expected at least " + expected );
         }
     }
 
diff -pruN 24.0.1+9-1/test/jdk/java/net/ipv6tests/UdpTest.java 24.0.2+12-1/test/jdk/java/net/ipv6tests/UdpTest.java
--- 24.0.1+9-1/test/jdk/java/net/ipv6tests/UdpTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/net/ipv6tests/UdpTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2019, 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
@@ -41,6 +41,7 @@ import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.PortUnreachableException;
 import java.net.SocketTimeoutException;
+import java.util.concurrent.TimeUnit;
 
 public class UdpTest extends Tests {
     static DatagramSocket c3, s1, s2, s3;
@@ -138,26 +139,27 @@ public class UdpTest extends Tests {
         s1 = new DatagramSocket ();
         s2 = new DatagramSocket ();
         s1.setSoTimeout (4000);
-        long t1 = System.currentTimeMillis();
+        long t1 = System.nanoTime();
         try {
             s1.receive (new DatagramPacket (new byte [128], 128));
             throw new Exception ("expected receive timeout ");
         } catch (SocketTimeoutException e) {
         }
-        checkTime (System.currentTimeMillis() - t1, 4000);
+        final long expectedTime = TimeUnit.SECONDS.toMillis(4);
+        checkIfTimeOut(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t1), expectedTime);
 
         /* check data can be exchanged now */
 
         simpleDataExchange (s1, ia6addr, s2, ia4addr);
 
         /* double check timeout still works */
-        t1 = System.currentTimeMillis();
+        t1 = System.nanoTime();
         try {
             s1.receive (new DatagramPacket (new byte [128], 128));
             throw new Exception ("expected receive timeout ");
         } catch (SocketTimeoutException e) {
         }
-        checkTime (System.currentTimeMillis() - t1, 4000);
+        checkIfTimeOut(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t1), expectedTime);
 
         /* check receive works after a delay < timeout */
 
@@ -174,9 +176,10 @@ public class UdpTest extends Tests {
                 } catch (Exception e) {}
             }
         });
-        t1 = System.currentTimeMillis();
+        t1 = System.nanoTime();
         s1.receive (new DatagramPacket (new byte [128], 128));
-        checkTime (System.currentTimeMillis() - t1, 2000, 10000);
+        final long startTime = TimeUnit.SECONDS.toMillis(2);
+        checkIfTimeOut(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t1), startTime);
         s1.close ();
         s2.close ();
         System.out.println ("Test2: OK");
diff -pruN 24.0.1+9-1/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java 24.0.2+12-1/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java
--- 24.0.1+9-1/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 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
@@ -47,6 +47,7 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.function.Executable;
 import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assumptions.*;
 
 public class InterruptibleOrNot {
     // DatagramChannel implementation class
@@ -98,6 +99,7 @@ public class InterruptibleOrNot {
      */
     @Test
     public void testInterruptBeforeUninterruptibleReceive() throws Exception {
+        assumeFalse(Thread.currentThread().isVirtual());
         try (DatagramChannel dc = boundDatagramChannel(false)) {
             ByteBuffer buf = ByteBuffer.allocate(100);
             onReceive(() -> {
diff -pruN 24.0.1+9-1/test/jdk/java/nio/channels/FileChannel/LoopingTruncate.java 24.0.2+12-1/test/jdk/java/nio/channels/FileChannel/LoopingTruncate.java
--- 24.0.1+9-1/test/jdk/java/nio/channels/FileChannel/LoopingTruncate.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/nio/channels/FileChannel/LoopingTruncate.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -21,7 +21,7 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 8137121 8137230
  * @summary (fc) Infinite loop FileChannel.truncate
@@ -31,12 +31,12 @@
  */
 
 import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
 import java.nio.channels.ClosedByInterruptException;
+import java.nio.channels.FileChannel;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import static java.nio.file.StandardOpenOption.*;
 import java.util.concurrent.TimeUnit;
+import static java.nio.file.StandardOpenOption.*;
 import static jdk.test.lib.Utils.adjustTimeout;
 
 public class LoopingTruncate {
@@ -48,7 +48,10 @@ public class LoopingTruncate {
     static long TIMEOUT = adjustTimeout(20_000);
 
     public static void main(String[] args) throws Throwable {
-        Path path = Files.createTempFile("LoopingTruncate.tmp", null);
+        // Intentionally opting out from the default `java.io.tmpdir`.
+        // It occasionally lacks the sufficient disk space this test needs.
+        Path pathDir = Path.of(System.getProperty("user.dir"));
+        Path path = Files.createTempFile(pathDir, "LoopingTruncate.tmp", null);
         try (FileChannel fc = FileChannel.open(path, CREATE, WRITE)) {
             fc.position(FATEFUL_SIZE + 1L);
             System.out.println("  Writing large file...");
diff -pruN 24.0.1+9-1/test/jdk/java/nio/file/Files/probeContentType/Basic.java 24.0.2+12-1/test/jdk/java/nio/file/Files/probeContentType/Basic.java
--- 24.0.1+9-1/test/jdk/java/nio/file/Files/probeContentType/Basic.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/nio/file/Files/probeContentType/Basic.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -39,7 +39,7 @@ import java.util.List;
 import java.util.stream.Stream;
 
 import jdk.internal.util.OperatingSystem;
-import jdk.internal.util.OSVersion;
+import jdk.internal.util.StaticProperty;
 
 /**
  * Uses Files.probeContentType to probe html file, custom file type, and minimal
@@ -83,7 +83,7 @@ public class Basic {
         if (!expected.equals(actual)) {
             if (!OperatingSystem.isWindows()) {
                 Path userMimeTypes =
-                    Path.of(System.getProperty("user.home"), ".mime.types");
+                    Path.of(StaticProperty.userHome(), ".mime.types");
                 checkMimeTypesFile(userMimeTypes);
 
                 Path etcMimeTypes = Path.of("/etc/mime.types");
@@ -188,17 +188,8 @@ public class Basic {
         exTypes.add(new ExType("xlsx", List.of("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")));
         exTypes.add(new ExType("wasm", List.of("application/wasm")));
 
-        // extensions with content type that differs on Windows 11+
-        if (OperatingSystem.isWindows() &&
-            (System.getProperty("os.name").endsWith("11") ||
-                new OSVersion(10, 0).compareTo(OSVersion.current()) > 0)) {
-            System.out.println("Windows 11+ detected: using different types");
-            exTypes.add(new ExType("bz2", List.of("application/bz2", "application/x-bzip2", "application/x-bzip", "application/x-compressed")));
-            exTypes.add(new ExType("csv", List.of("text/csv", "application/vnd.ms-excel")));
-            exTypes.add(new ExType("rar", List.of("application/rar", "application/vnd.rar", "application/x-rar", "application/x-rar-compressed", "application/x-compressed")));
-            exTypes.add(new ExType("rtf", List.of("application/rtf", "text/rtf", "application/msword")));
-            exTypes.add(new ExType("7z", List.of("application/x-7z-compressed", "application/x-compressed")));
-        } else {
+        // extensions with consistent content type on Unix (but not on Windows)
+        if (!OperatingSystem.isWindows()) {
             exTypes.add(new ExType("bz2", List.of("application/bz2", "application/x-bzip2", "application/x-bzip")));
             exTypes.add(new ExType("csv", List.of("text/csv")));
             exTypes.add(new ExType("rar", List.of("application/rar", "application/vnd.rar", "application/x-rar", "application/x-rar-compressed")));
diff -pruN 24.0.1+9-1/test/jdk/java/security/KeyFactory/Failover.java 24.0.2+12-1/test/jdk/java/security/KeyFactory/Failover.java
--- 24.0.1+9-1/test/jdk/java/security/KeyFactory/Failover.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/KeyFactory/Failover.java	2025-06-27 08:03:14.000000000 +0000
@@ -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
@@ -24,7 +24,7 @@
 /**
  * @test
  * @bug 4894125 7054918 8130181
- * @library ../testlibrary /test/lib
+ * @library /test/lib
  * @summary test that failover for KeyFactory works
  * @author Andreas Sterbenz
  */
@@ -32,8 +32,8 @@
 import java.util.*;
 
 import java.security.*;
-import java.security.interfaces.*;
 import java.security.spec.*;
+import jdk.test.lib.security.ProvidersSnapshot;
 import jdk.test.lib.security.SecurityUtils;
 
 public class Failover {
diff -pruN 24.0.1+9-1/test/jdk/java/security/KeyPairGenerator/Failover.java 24.0.2+12-1/test/jdk/java/security/KeyPairGenerator/Failover.java
--- 24.0.1+9-1/test/jdk/java/security/KeyPairGenerator/Failover.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/KeyPairGenerator/Failover.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, 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
@@ -24,7 +24,7 @@
 /**
  * @test
  * @bug 4894125 7054918 8130181
- * @library ../testlibrary
+ * @library /test/lib
  * @summary test that failover for KeyPairGenerator works
  * @author Andreas Sterbenz
  */
@@ -32,8 +32,8 @@
 import java.util.*;
 
 import java.security.*;
-import java.security.interfaces.*;
 import java.security.spec.*;
+import jdk.test.lib.security.ProvidersSnapshot;
 
 public class Failover {
 
diff -pruN 24.0.1+9-1/test/jdk/java/security/Provider/ChangeProviders.java 24.0.2+12-1/test/jdk/java/security/Provider/ChangeProviders.java
--- 24.0.1+9-1/test/jdk/java/security/Provider/ChangeProviders.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/Provider/ChangeProviders.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2023, 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
@@ -24,14 +24,13 @@
 /*
  * @test
  * @bug 4856968 7054918 8130181 8175874
- * @library ../testlibrary
+ * @library /test/lib
  * @summary make sure add/insert/removeProvider() work correctly
  * @author Andreas Sterbenz
  */
 
-import java.util.*;
-
 import java.security.*;
+import jdk.test.lib.security.ProvidersSnapshot;
 
 public class ChangeProviders extends Provider {
 
diff -pruN 24.0.1+9-1/test/jdk/java/security/Provider/GetInstance.java 24.0.2+12-1/test/jdk/java/security/Provider/GetInstance.java
--- 24.0.1+9-1/test/jdk/java/security/Provider/GetInstance.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/Provider/GetInstance.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, 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
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 4856968 7054918 8130181
- * @library ../testlibrary
+ * @library /test/lib
  * @summary make sure getInstance() works correctly, including failover
  *   and delayed provider selection for Signatures
  * @author Andreas Sterbenz
@@ -34,6 +34,7 @@ import java.util.*;
 
 import java.security.*;
 import java.security.cert.*;
+import jdk.test.lib.security.ProvidersSnapshot;
 
 public class GetInstance {
 
diff -pruN 24.0.1+9-1/test/jdk/java/security/Provider/GetServiceRace.java 24.0.2+12-1/test/jdk/java/security/Provider/GetServiceRace.java
--- 24.0.1+9-1/test/jdk/java/security/Provider/GetServiceRace.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/Provider/GetServiceRace.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 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
@@ -24,7 +24,6 @@
 /*
  * @test
  * @bug 8231387
- * @library ../testlibrary
  * @summary make sure getService() avoids a race
  * @author Tianmin Shi
  */
diff -pruN 24.0.1+9-1/test/jdk/java/security/Provider/RemoveProvider.java 24.0.2+12-1/test/jdk/java/security/Provider/RemoveProvider.java
--- 24.0.1+9-1/test/jdk/java/security/Provider/RemoveProvider.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/Provider/RemoveProvider.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -24,13 +24,14 @@
 /*
  * @test
  * @bug 4190873 7054918 8130181
- * @library ../testlibrary
+ * @library /test/lib
  * @summary Make sure provider instance can be removed from list of registered
  * providers, and "entrySet", "keySet", and "values" methods don't loop
  * indefinitely.
  */
 import java.security.*;
 import java.util.*;
+import jdk.test.lib.security.ProvidersSnapshot;
 
 public class RemoveProvider {
 
diff -pruN 24.0.1+9-1/test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.java 24.0.2+12-1/test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.java
--- 24.0.1+9-1/test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -21,7 +21,14 @@
  * questions.
  */
 
-// See bug 5094825 / ClassLoadDeadlock.sh
+/*
+* @test
+* @bug 5094825
+* @summary verify no deadlock if crypto provider in other classloader is used to verify signed jars
+* @library ./Deadlock.jar
+* @compile provider/HashProvider.java
+* @run main/othervm/timeout=30 ClassLoaderDeadlock
+*/
 
 import java.net.*;
 
diff -pruN 24.0.1+9-1/test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh 24.0.2+12-1/test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh
--- 24.0.1+9-1/test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh	1970-01-01 00:00:00.000000000 +0000
@@ -1,106 +0,0 @@
-#
-# Copyright (c) 2004, 2024, 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
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 5094825
-# @summary verify no deadlock if crypto provider in other classloader is used to verify signed jars
-#
-# @run shell/timeout=30 ClassLoaderDeadlock.sh
-
-# set a few environment variables so that the shell-script can run stand-alone
-# in the source directory
-if [ "${TESTSRC}" = "" ] ; then
-   TESTSRC="."
-fi
-
-if [ "${TESTCLASSES}" = "" ] ; then
-   TESTCLASSES="."
-fi
-
-if [ "${TESTJAVA}" = "" ] ; then
-   echo "TESTJAVA not set.  Test cannot execute."
-   echo "FAILED!!!"
-   exit 1
-fi
-
-if [ "${COMPILEJAVA}" = "" ]; then
-   COMPILEJAVA="${TESTJAVA}"
-fi
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
-  Linux )
-    PATHSEP=":"
-    FILESEP="/"
-    ;;
-  Darwin )
-    PATHSEP=":"
-    FILESEP="/"
-    ;;
-  AIX )
-    PATHSEP=":"
-    FILESEP="/"
-    ;;
-  CYGWIN* )
-    PATHSEP=";"
-    FILESEP="/"
-    ;;
-  Windows* )
-    PATHSEP=";"
-    FILESEP="\\"
-    ;;
-  * )
-    echo "Unrecognized system!"
-    exit 1;
-    ;;
-esac
-
-cd ${TESTCLASSES}${FILESEP}
-if [ ! -d provider ] ; then
-    mkdir provider
-fi
-
-# compile the test program
-${COMPILEJAVA}${FILESEP}bin${FILESEP}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
-        -d ${TESTCLASSES}${FILESEP} \
-        ${TESTSRC}${FILESEP}ClassLoaderDeadlock.java
-
-${COMPILEJAVA}${FILESEP}bin${FILESEP}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
-        -d ${TESTCLASSES}${FILESEP}provider${FILESEP} \
-        ${TESTSRC}${FILESEP}provider${FILESEP}HashProvider.java
-
-# run the test
-${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} ${TESTJAVAOPTS} \
-        -classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar" \
-	-Djava.awt.headless=true \
-        ClassLoaderDeadlock
-
-STATUS=$?
-
-# clean up
-rm -f 'ClassLoaderDeadlock.class' 'ClassLoaderDeadlock$1.class' \
-'ClassLoaderDeadlock$DelayClassLoader.class' \
-provider${FILESEP}HashProvider.class
-
-exit $STATUS
diff -pruN 24.0.1+9-1/test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.java 24.0.2+12-1/test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.java
--- 24.0.1+9-1/test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 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
@@ -21,8 +21,13 @@
  * questions.
  */
 
-
-// see Deadlock.sh
+/*
+ * @test
+ * @bug 4944382
+ * @summary make sure we do not deadlock loading signed JAR with getInstance()
+ * @library ./Deadlock.jar
+ * @run main/othervm/timeout=30 Deadlock
+ */
 
 import java.security.*;
 
diff -pruN 24.0.1+9-1/test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.sh 24.0.2+12-1/test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.sh
--- 24.0.1+9-1/test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.sh	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.sh	1970-01-01 00:00:00.000000000 +0000
@@ -1,66 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2003, 2024, 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
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-
-# @test
-# @bug 4944382
-# @summary make sure we do not deadlock loading signed JAR with getInstance()
-# @author Andreas Sterbenz
-# @build Deadlock
-# @run shell/timeout=30 Deadlock.sh
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
-  Linux )
-    PATHSEP=":"
-    FILESEP="/"
-    ;;
-  Darwin )
-    PATHSEP=":"
-    FILESEP="/"
-    ;;
-  AIX )
-    PATHSEP=":"
-    FILESEP="/"
-    ;;
-  CYGWIN* )
-    PATHSEP=";"
-    FILESEP="/"
-    ;;
-  Windows* )
-    PATHSEP=";"
-    FILESEP="\\"
-    ;;
-  * )
-    echo "Unrecognized system!"
-    exit 1;
-    ;;
-esac
-
-JAVA="${TESTJAVA}${FILESEP}bin${FILESEP}java"
-
-${JAVA} ${TESTVMOPTS} ${TESTJAVAOPTS} -cp "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar" Deadlock
-
diff -pruN 24.0.1+9-1/test/jdk/java/security/Security/NoInstalledProviders.java 24.0.2+12-1/test/jdk/java/security/Security/NoInstalledProviders.java
--- 24.0.1+9-1/test/jdk/java/security/Security/NoInstalledProviders.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/Security/NoInstalledProviders.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -24,12 +24,13 @@
 /*
  * @test
  * @bug 4273454 7054918 7052537
- * @library ../testlibrary
+ * @library /test/lib
  * @summary Make sure getProviders(filter) doesn't throw NPE
  * @run main/othervm NoInstalledProviders
  */
 
 import java.security.*;
+import jdk.test.lib.security.ProvidersSnapshot;
 
 public class NoInstalledProviders {
 
diff -pruN 24.0.1+9-1/test/jdk/java/security/Security/SynchronizedAccess.java 24.0.2+12-1/test/jdk/java/security/Security/SynchronizedAccess.java
--- 24.0.1+9-1/test/jdk/java/security/Security/SynchronizedAccess.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/Security/SynchronizedAccess.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -24,13 +24,14 @@
 /*
  * @test
  * @bug 4162583 7054918 8130181 8028127
- * @library /test/lib ../testlibrary
+ * @library /test/lib
  * @summary Make sure Provider api implementations are synchronized properly
  */
 
 import java.security.*;
 
 import jdk.test.lib.Asserts;
+import jdk.test.lib.security.ProvidersSnapshot;
 
 public class SynchronizedAccess {
 
diff -pruN 24.0.1+9-1/test/jdk/java/security/Security/removing/RemoveProviders.java 24.0.2+12-1/test/jdk/java/security/Security/removing/RemoveProviders.java
--- 24.0.1+9-1/test/jdk/java/security/Security/removing/RemoveProviders.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/Security/removing/RemoveProviders.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, 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
@@ -24,7 +24,7 @@
 /**
  * @test
  * @bug 4963416 7054918
- * @library ../../testlibrary
+ * @library /test/lib
  * @summary make sure removeProvider() always works correctly
  * @author Andreas Sterbenz
  */
@@ -32,6 +32,7 @@
 import java.util.*;
 
 import java.security.*;
+import jdk.test.lib.security.ProvidersSnapshot;
 
 public class RemoveProviders {
 
diff -pruN 24.0.1+9-1/test/jdk/java/security/cert/CertPathValidator/OCSP/GetAndPostTests.java 24.0.2+12-1/test/jdk/java/security/cert/CertPathValidator/OCSP/GetAndPostTests.java
--- 24.0.1+9-1/test/jdk/java/security/cert/CertPathValidator/OCSP/GetAndPostTests.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/cert/CertPathValidator/OCSP/GetAndPostTests.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -25,8 +25,7 @@
  * @test
  * @bug 8179503 8328638
  * @summary Java should support GET OCSP calls
- * @library /javax/net/ssl/templates /java/security/testlibrary
- * @build SimpleOCSPServer
+ * @library /javax/net/ssl/templates /test/lib
  * @modules java.base/sun.security.util
  *          java.base/sun.security.provider.certpath
  *          java.base/sun.security.x509
@@ -64,7 +63,7 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
-import sun.security.testlibrary.SimpleOCSPServer;
+import jdk.test.lib.security.SimpleOCSPServer;
 import sun.security.util.DerOutputStream;
 import sun.security.util.DerValue;
 import sun.security.util.ObjectIdentifier;
diff -pruN 24.0.1+9-1/test/jdk/java/security/cert/CertPathValidator/OCSP/OCSPTimeout.java 24.0.2+12-1/test/jdk/java/security/cert/CertPathValidator/OCSP/OCSPTimeout.java
--- 24.0.1+9-1/test/jdk/java/security/cert/CertPathValidator/OCSP/OCSPTimeout.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/cert/CertPathValidator/OCSP/OCSPTimeout.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 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
@@ -34,8 +34,7 @@
  * @modules java.base/sun.security.x509
  *          java.base/sun.security.provider.certpath
  *          java.base/sun.security.util
- * @library ../../../../../java/security/testlibrary
- * @build CertificateBuilder SimpleOCSPServer
+ * @library /test/lib
  * @run main/othervm -Djava.security.debug=certpath OCSPTimeout 1000 true
  * @run main/othervm -Djava.security.debug=certpath
  *      -Dcom.sun.security.ocsp.readtimeout=5 OCSPTimeout 1000 true
@@ -59,8 +58,8 @@ import java.util.*;
 import java.security.cert.*;
 import java.util.concurrent.TimeUnit;
 
-import sun.security.testlibrary.SimpleOCSPServer;
-import sun.security.testlibrary.CertificateBuilder;
+import jdk.test.lib.security.SimpleOCSPServer;
+import jdk.test.lib.security.CertificateBuilder;
 
 import static java.security.cert.PKIXRevocationChecker.Option.*;
 
@@ -84,7 +83,7 @@ public class OCSPTimeout {
 
     public static void main(String[] args) throws Exception {
         int ocspTimeout = 15000;
-        boolean expected = false;
+        boolean expected;
 
         createPKI();
 
@@ -195,7 +194,6 @@ public class OCSPTimeout {
         rootOcsp = new SimpleOCSPServer(rootKeystore, passwd, ROOT_ALIAS, null);
         rootOcsp.enableLog(debug);
         rootOcsp.setNextUpdateInterval(3600);
-        rootOcsp.setDisableContentLength(true);
         rootOcsp.start();
 
         // Wait 60 seconds for server ready
diff -pruN 24.0.1+9-1/test/jdk/java/security/cert/CertPathValidator/crlDP/CheckAllCRLs.java 24.0.2+12-1/test/jdk/java/security/cert/CertPathValidator/crlDP/CheckAllCRLs.java
--- 24.0.1+9-1/test/jdk/java/security/cert/CertPathValidator/crlDP/CheckAllCRLs.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/cert/CertPathValidator/crlDP/CheckAllCRLs.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 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
@@ -26,7 +26,6 @@ import java.nio.file.Path;
 import java.math.BigInteger;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
-import java.security.PublicKey;
 import java.security.cert.CertificateFactory;
 import java.security.cert.CertPath;
 import java.security.cert.CertPathValidator;
@@ -54,7 +53,7 @@ import sun.security.x509.X500Name;
 import sun.security.x509.X509CRLEntryImpl;
 import sun.security.x509.X509CRLImpl;
 import static sun.security.x509.X509CRLImpl.TBSCertList;
-import sun.security.testlibrary.CertificateBuilder;
+import jdk.test.lib.security.CertificateBuilder;
 
 /*
  * @test
@@ -65,8 +64,7 @@ import sun.security.testlibrary.Certific
  *          fresh or stale.
  * @modules java.base/sun.security.x509
  *          java.base/sun.security.util
- * @library ../../../../../java/security/testlibrary
- * @build CertificateBuilder CheckAllCRLs
+ * @library /test/lib
  * @run main/othervm -Dcom.sun.security.enableCRLDP=true CheckAllCRLs
  */
 public class CheckAllCRLs {
diff -pruN 24.0.1+9-1/test/jdk/java/security/cert/CertPathValidator/trustAnchor/ValWithAnchorByName.java 24.0.2+12-1/test/jdk/java/security/cert/CertPathValidator/trustAnchor/ValWithAnchorByName.java
--- 24.0.1+9-1/test/jdk/java/security/cert/CertPathValidator/trustAnchor/ValWithAnchorByName.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/cert/CertPathValidator/trustAnchor/ValWithAnchorByName.java	2025-06-27 08:03:14.000000000 +0000
@@ -52,8 +52,8 @@ public class ValWithAnchorByName {
 
     // The following certificates and OCSP responses were captured from
     // a test run that used certificates and responses generated by
-    // sun.security.testlibrary.CertificateBuilder and
-    // sun.security.testlibrary.SimpleOCSPServer.
+    // jdk.test.lib.security.CertificateBuilder and
+    // jdk.test.lib.security.SimpleOCSPServer.
 
     // Subject: CN=SSLCertificate, O=SomeCompany
     // Issuer: CN=Intermediate CA Cert, O=SomeCompany
diff -pruN 24.0.1+9-1/test/jdk/java/security/testlibrary/CertificateBuilder.java 24.0.2+12-1/test/jdk/java/security/testlibrary/CertificateBuilder.java
--- 24.0.1+9-1/test/jdk/java/security/testlibrary/CertificateBuilder.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/testlibrary/CertificateBuilder.java	1970-01-01 00:00:00.000000000 +0000
@@ -1,583 +0,0 @@
-/*
- * Copyright (c) 2015, 2024, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.testlibrary;
-
-import java.io.*;
-import java.util.*;
-import java.security.*;
-import java.security.cert.X509Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.Extension;
-import java.time.temporal.ChronoUnit;
-import java.time.Instant;
-import javax.security.auth.x500.X500Principal;
-import java.math.BigInteger;
-
-import sun.security.util.DerOutputStream;
-import sun.security.util.DerValue;
-import sun.security.util.ObjectIdentifier;
-import sun.security.util.SignatureUtil;
-import sun.security.x509.AccessDescription;
-import sun.security.x509.AlgorithmId;
-import sun.security.x509.AuthorityInfoAccessExtension;
-import sun.security.x509.AuthorityKeyIdentifierExtension;
-import sun.security.x509.SubjectKeyIdentifierExtension;
-import sun.security.x509.BasicConstraintsExtension;
-import sun.security.x509.CertificateSerialNumber;
-import sun.security.x509.ExtendedKeyUsageExtension;
-import sun.security.x509.DNSName;
-import sun.security.x509.GeneralName;
-import sun.security.x509.GeneralNames;
-import sun.security.x509.KeyUsageExtension;
-import sun.security.x509.SerialNumber;
-import sun.security.x509.SubjectAlternativeNameExtension;
-import sun.security.x509.URIName;
-import sun.security.x509.KeyIdentifier;
-
-/**
- * Helper class that builds and signs X.509 certificates.
- *
- * A CertificateBuilder is created with a default constructor, and then
- * uses additional public methods to set the public key, desired validity
- * dates, serial number and extensions.  It is expected that the caller will
- * have generated the necessary key pairs prior to using a CertificateBuilder
- * to generate certificates.
- *
- * The following methods are mandatory before calling build():
- * <UL>
- * <LI>{@link #setSubjectName(java.lang.String)}
- * <LI>{@link #setPublicKey(java.security.PublicKey)}
- * <LI>{@link #setNotBefore(java.util.Date)} and
- * {@link #setNotAfter(java.util.Date)}, or
- * {@link #setValidity(java.util.Date, java.util.Date)}
- * <LI>{@link #setSerialNumber(java.math.BigInteger)}
- * </UL><BR>
- *
- * Additionally, the caller can either provide a {@link List} of
- * {@link Extension} objects, or use the helper classes to add specific
- * extension types.
- *
- * When all required and desired parameters are set, the
- * {@link #build(java.security.cert.X509Certificate, java.security.PrivateKey,
- * java.lang.String)} method can be used to create the {@link X509Certificate}
- * object.
- *
- * Multiple certificates may be cut from the same settings using subsequent
- * calls to the build method.  Settings may be cleared using the
- * {@link #reset()} method.
- */
-public class CertificateBuilder {
-    private final CertificateFactory factory;
-
-    private X500Principal subjectName = null;
-    private BigInteger serialNumber = null;
-    private PublicKey publicKey = null;
-    private Date notBefore = null;
-    private Date notAfter = null;
-    private final Map<String, Extension> extensions = new HashMap<>();
-    private byte[] tbsCertBytes;
-    private byte[] signatureBytes;
-
-    /**
-     * Default constructor for a {@code CertificateBuilder} object.
-     *
-     * @throws CertificateException if the underlying {@link CertificateFactory}
-     * cannot be instantiated.
-     */
-    public CertificateBuilder() throws CertificateException {
-        factory = CertificateFactory.getInstance("X.509");
-    }
-
-    /**
-     * Set the subject name for the certificate.
-     *
-     * @param name An {@link X500Principal} to be used as the subject name
-     * on this certificate.
-     */
-    public CertificateBuilder setSubjectName(X500Principal name) {
-        subjectName = name;
-        return this;
-    }
-
-    /**
-     * Set the subject name for the certificate.
-     *
-     * @param name The subject name in RFC 2253 format
-     */
-    public CertificateBuilder setSubjectName(String name) {
-        subjectName = new X500Principal(name);
-        return this;
-    }
-
-    /**
-     * Set the public key for this certificate.
-     *
-     * @param pubKey The {@link PublicKey} to be used on this certificate.
-     */
-    public CertificateBuilder setPublicKey(PublicKey pubKey) {
-        publicKey = Objects.requireNonNull(pubKey, "Caught null public key");
-        return this;
-    }
-
-    /**
-     * Set the NotBefore date on the certificate.
-     *
-     * @param nbDate A {@link Date} object specifying the start of the
-     * certificate validity period.
-     */
-    public CertificateBuilder setNotBefore(Date nbDate) {
-        Objects.requireNonNull(nbDate, "Caught null notBefore date");
-        notBefore = (Date)nbDate.clone();
-        return this;
-    }
-
-    /**
-     * Set the NotAfter date on the certificate.
-     *
-     * @param naDate A {@link Date} object specifying the end of the
-     * certificate validity period.
-     */
-    public CertificateBuilder setNotAfter(Date naDate) {
-        Objects.requireNonNull(naDate, "Caught null notAfter date");
-        notAfter = (Date)naDate.clone();
-        return this;
-    }
-
-    /**
-     * Set the validity period for the certificate
-     *
-     * @param nbDate A {@link Date} object specifying the start of the
-     * certificate validity period.
-     * @param naDate A {@link Date} object specifying the end of the
-     * certificate validity period.
-     */
-    public CertificateBuilder setValidity(Date nbDate, Date naDate) {
-        return setNotBefore(nbDate).setNotAfter(naDate);
-    }
-
-    /**
-     * Set the serial number on the certificate.
-     *
-     * @param serial A serial number in {@link BigInteger} form.
-     */
-    public CertificateBuilder setSerialNumber(BigInteger serial) {
-        Objects.requireNonNull(serial, "Caught null serial number");
-        serialNumber = serial;
-        return this;
-    }
-
-
-    /**
-     * Add a single extension to the certificate.
-     *
-     * @param ext The extension to be added.
-     */
-    public CertificateBuilder addExtension(Extension ext) {
-        Objects.requireNonNull(ext, "Caught null extension");
-        extensions.put(ext.getId(), ext);
-        return this;
-    }
-
-    /**
-     * Add multiple extensions contained in a {@code List}.
-     *
-     * @param extList The {@link List} of extensions to be added to
-     * the certificate.
-     */
-    public CertificateBuilder addExtensions(List<Extension> extList) {
-        Objects.requireNonNull(extList, "Caught null extension list");
-        for (Extension ext : extList) {
-            extensions.put(ext.getId(), ext);
-        }
-        return this;
-    }
-
-    /**
-     * Helper method to add DNSName types for the SAN extension
-     *
-     * @param dnsNames A {@code List} of names to add as DNSName types
-     *
-     * @throws IOException if an encoding error occurs.
-     */
-    public CertificateBuilder addSubjectAltNameDNSExt(List<String> dnsNames)
-            throws IOException {
-        if (!dnsNames.isEmpty()) {
-            GeneralNames gNames = new GeneralNames();
-            for (String name : dnsNames) {
-                gNames.add(new GeneralName(new DNSName(name)));
-            }
-            addExtension(new SubjectAlternativeNameExtension(false,
-                    gNames));
-        }
-        return this;
-    }
-
-    /**
-     * Helper method to add one or more OCSP URIs to the Authority Info Access
-     * certificate extension.  Location strings can be in two forms:
-     * 1) Just a URI by itself: This will be treated as using the OCSP
-     *    access description (legacy behavior).
-     * 2) An access description name (case-insensitive) followed by a
-     *    pipe (|) and the URI (e.g. OCSP|http://ocsp.company.com/revcheck).
-     * Current description names are OCSP and CAISSUER. Others may be
-     * added later.
-     *
-     * @param locations A list of one or more access descriptor URIs as strings
-     *
-     * @throws IOException if an encoding error occurs.
-     */
-    public CertificateBuilder addAIAExt(List<String> locations)
-            throws IOException {
-        if (!locations.isEmpty()) {
-            List<AccessDescription> acDescList = new ArrayList<>();
-            for (String loc : locations) {
-                String[] tokens = loc.split("\\|", 2);
-                ObjectIdentifier adObj;
-                String uriLoc;
-                if (tokens.length == 1) {
-                    // Legacy form, assume OCSP
-                    adObj = AccessDescription.Ad_OCSP_Id;
-                    uriLoc = tokens[0];
-                } else {
-                    switch (tokens[0].toUpperCase()) {
-                        case "OCSP":
-                            adObj = AccessDescription.Ad_OCSP_Id;
-                            break;
-                        case "CAISSUER":
-                            adObj = AccessDescription.Ad_CAISSUERS_Id;
-                            break;
-                        default:
-                            throw new IOException("Unknown AD: " + tokens[0]);
-                    }
-                    uriLoc = tokens[1];
-                }
-                acDescList.add(new AccessDescription(adObj,
-                        new GeneralName(new URIName(uriLoc))));
-            }
-            addExtension(new AuthorityInfoAccessExtension(acDescList));
-        }
-        return this;
-    }
-
-
-    /**
-     * Set a Key Usage extension for the certificate.  The extension will
-     * be marked critical.
-     *
-     * @param bitSettings Boolean array for all nine bit settings in the order
-     * documented in RFC 5280 section 4.2.1.3.
-     *
-     * @throws IOException if an encoding error occurs.
-     */
-    public CertificateBuilder addKeyUsageExt(boolean[] bitSettings)
-            throws IOException {
-        return addExtension(new KeyUsageExtension(bitSettings));
-    }
-
-    /**
-     * Set the Basic Constraints Extension for a certificate.
-     *
-     * @param crit {@code true} if critical, {@code false} otherwise
-     * @param isCA {@code true} if the extension will be on a CA certificate,
-     * {@code false} otherwise
-     * @param maxPathLen The maximum path length issued by this CA.  Values
-     * less than zero will omit this field from the resulting extension and
-     * no path length constraint will be asserted.
-     *
-     * @throws IOException if an encoding error occurs.
-     */
-    public CertificateBuilder addBasicConstraintsExt(boolean crit, boolean isCA,
-            int maxPathLen) throws IOException {
-        return addExtension(new BasicConstraintsExtension(crit, isCA,
-                maxPathLen));
-    }
-
-    /**
-     * Add the Authority Key Identifier extension.
-     *
-     * @param authorityCert The certificate of the issuing authority.
-     *
-     * @throws IOException if an encoding error occurs.
-     */
-    public CertificateBuilder addAuthorityKeyIdExt(X509Certificate authorityCert)
-            throws IOException {
-        return addAuthorityKeyIdExt(authorityCert.getPublicKey());
-    }
-
-    /**
-     * Add the Authority Key Identifier extension.
-     *
-     * @param authorityKey The public key of the issuing authority.
-     *
-     * @throws IOException if an encoding error occurs.
-     */
-    public CertificateBuilder addAuthorityKeyIdExt(PublicKey authorityKey)
-            throws IOException {
-        KeyIdentifier kid = new KeyIdentifier(authorityKey);
-        return addExtension(new AuthorityKeyIdentifierExtension(kid,
-                null, null));
-    }
-
-    /**
-     * Add the Subject Key Identifier extension.
-     *
-     * @param subjectKey The public key to be used in the resulting certificate
-     *
-     * @throws IOException if an encoding error occurs.
-     */
-    public CertificateBuilder addSubjectKeyIdExt(PublicKey subjectKey)
-            throws IOException {
-        byte[] keyIdBytes = new KeyIdentifier(subjectKey).getIdentifier();
-        return addExtension(new SubjectKeyIdentifierExtension(keyIdBytes));
-    }
-
-    /**
-     * Add the Extended Key Usage extension.
-     *
-     * @param ekuOids A {@link List} of object identifiers in string form.
-     *
-     * @throws IOException if an encoding error occurs.
-     */
-    public CertificateBuilder addExtendedKeyUsageExt(List<String> ekuOids)
-            throws IOException {
-        if (!ekuOids.isEmpty()) {
-            Vector<ObjectIdentifier> oidVector = new Vector<>();
-            for (String oid : ekuOids) {
-                oidVector.add(ObjectIdentifier.of(oid));
-            }
-            addExtension(new ExtendedKeyUsageExtension(oidVector));
-        }
-        return this;
-    }
-
-    /**
-     * Clear all settings and return the {@code CertificateBuilder} to
-     * its default state.
-     */
-    public CertificateBuilder reset() {
-        extensions.clear();
-        subjectName = null;
-        notBefore = null;
-        notAfter = null;
-        serialNumber = null;
-        publicKey = null;
-        signatureBytes = null;
-        tbsCertBytes = null;
-        return this;
-    }
-
-    /**
-     * Build the certificate.
-     *
-     * @param issuerCert The certificate of the issuing authority, or
-     * {@code null} if the resulting certificate is self-signed.
-     * @param issuerKey The private key of the issuing authority
-     * @param algName The signature algorithm name
-     *
-     * @return The resulting {@link X509Certificate}
-     *
-     * @throws IOException if an encoding error occurs.
-     * @throws CertificateException If the certificate cannot be generated
-     * by the underlying {@link CertificateFactory}
-     * @throws NoSuchAlgorithmException If an invalid signature algorithm
-     * is provided.
-     */
-    public X509Certificate build(X509Certificate issuerCert,
-            PrivateKey issuerKey, String algName)
-            throws IOException, CertificateException, NoSuchAlgorithmException {
-        // TODO: add some basic checks (key usage, basic constraints maybe)
-
-        byte[] encodedCert = encodeTopLevel(issuerCert, issuerKey, algName);
-        ByteArrayInputStream bais = new ByteArrayInputStream(encodedCert);
-        return (X509Certificate)factory.generateCertificate(bais);
-    }
-
-    /**
-     * Encode the contents of the outer-most ASN.1 SEQUENCE:
-     *
-     * <PRE>
-     *  Certificate  ::=  SEQUENCE  {
-     *      tbsCertificate       TBSCertificate,
-     *      signatureAlgorithm   AlgorithmIdentifier,
-     *      signatureValue       BIT STRING  }
-     * </PRE>
-     *
-     * @param issuerCert The certificate of the issuing authority, or
-     * {@code null} if the resulting certificate is self-signed.
-     * @param issuerKey The private key of the issuing authority
-     * @param algName The signature algorithm object
-     *
-     * @return The DER-encoded X.509 certificate
-     *
-     * @throws CertificateException If an error occurs during the
-     * signing process.
-     * @throws IOException if an encoding error occurs.
-     */
-    private byte[] encodeTopLevel(X509Certificate issuerCert,
-            PrivateKey issuerKey, String algName)
-            throws CertificateException, IOException, NoSuchAlgorithmException {
-
-        AlgorithmId signAlg = AlgorithmId.get(algName);
-        DerOutputStream outerSeq = new DerOutputStream();
-        DerOutputStream topLevelItems = new DerOutputStream();
-
-        try {
-            Signature sig = SignatureUtil.fromKey(signAlg.getName(), issuerKey, (Provider)null);
-            // Rewrite signAlg, RSASSA-PSS needs some parameters.
-            signAlg = SignatureUtil.fromSignature(sig, issuerKey);
-            tbsCertBytes = encodeTbsCert(issuerCert, signAlg);
-            sig.update(tbsCertBytes);
-            signatureBytes = sig.sign();
-        } catch (GeneralSecurityException ge) {
-            throw new CertificateException(ge);
-        }
-        topLevelItems.write(tbsCertBytes);
-        signAlg.encode(topLevelItems);
-        topLevelItems.putBitString(signatureBytes);
-        outerSeq.write(DerValue.tag_Sequence, topLevelItems);
-
-        return outerSeq.toByteArray();
-    }
-
-    /**
-     * Encode the bytes for the TBSCertificate structure:
-     * <PRE>
-     *  TBSCertificate  ::=  SEQUENCE  {
-     *      version         [0]  EXPLICIT Version DEFAULT v1,
-     *      serialNumber         CertificateSerialNumber,
-     *      signature            AlgorithmIdentifier,
-     *      issuer               Name,
-     *      validity             Validity,
-     *      subject              Name,
-     *      subjectPublicKeyInfo SubjectPublicKeyInfo,
-     *      issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
-     *                        -- If present, version MUST be v2 or v3
-     *      subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
-     *                        -- If present, version MUST be v2 or v3
-     *      extensions      [3]  EXPLICIT Extensions OPTIONAL
-     *                        -- If present, version MUST be v3
-     *      }
-     *
-     * @param issuerCert The certificate of the issuing authority, or
-     * {@code null} if the resulting certificate is self-signed.
-     * @param signAlg The signature algorithm object
-     *
-     * @return The DER-encoded bytes for the TBSCertificate structure
-     *
-     * @throws IOException if an encoding error occurs.
-     */
-    private byte[] encodeTbsCert(X509Certificate issuerCert,
-            AlgorithmId signAlg) throws IOException {
-        DerOutputStream tbsCertSeq = new DerOutputStream();
-        DerOutputStream tbsCertItems = new DerOutputStream();
-
-        // If extensions exist then it needs to be v3, otherwise
-        // we can make it v1 and omit the version field as v1 is the default.
-        if (!extensions.isEmpty()) {
-            byte[] v3int = {0x02, 0x01, 0x02};
-            tbsCertItems.write(DerValue.createTag(DerValue.TAG_CONTEXT, true,
-                    (byte) 0), v3int);
-        }
-
-        // Serial Number
-        CertificateSerialNumber sn = (serialNumber != null) ?
-            new CertificateSerialNumber(serialNumber) :
-            CertificateSerialNumber.newRandom64bit(new SecureRandom());
-        sn.encode(tbsCertItems);
-
-        // Algorithm ID
-        signAlg.encode(tbsCertItems);
-
-        // Issuer Name
-        if (issuerCert != null) {
-            tbsCertItems.write(
-                    issuerCert.getSubjectX500Principal().getEncoded());
-        } else {
-            // Self-signed
-            tbsCertItems.write(subjectName.getEncoded());
-        }
-
-        // Validity period (set as UTCTime)
-        DerOutputStream valSeq = new DerOutputStream();
-        Instant now = Instant.now();
-        Date startDate = (notBefore != null) ? notBefore : Date.from(now);
-        valSeq.putUTCTime(startDate);
-        Date endDate = (notAfter != null) ? notAfter :
-            Date.from(now.plus(90, ChronoUnit.DAYS));
-        valSeq.putUTCTime(endDate);
-        tbsCertItems.write(DerValue.tag_Sequence, valSeq);
-
-        // Subject Name
-        tbsCertItems.write(subjectName.getEncoded());
-
-        // SubjectPublicKeyInfo
-        tbsCertItems.write(publicKey.getEncoded());
-
-        // Encode any extensions in the builder
-        encodeExtensions(tbsCertItems);
-
-        // Wrap it all up in a SEQUENCE and return the bytes
-        tbsCertSeq.write(DerValue.tag_Sequence, tbsCertItems);
-        return tbsCertSeq.toByteArray();
-    }
-
-    /**
-     * Encode the extensions segment for an X.509 Certificate:
-     *
-     * <PRE>
-     *  Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
-     *
-     *  Extension  ::=  SEQUENCE  {
-     *      extnID      OBJECT IDENTIFIER,
-     *      critical    BOOLEAN DEFAULT FALSE,
-     *      extnValue   OCTET STRING
-     *                  -- contains the DER encoding of an ASN.1 value
-     *                  -- corresponding to the extension type identified
-     *                  -- by extnID
-     *      }
-     * </PRE>
-     *
-     * @param tbsStream The {@code DerOutputStream} that holds the
-     * TBSCertificate contents.
-     *
-     * @throws IOException if an encoding error occurs.
-     */
-    private void encodeExtensions(DerOutputStream tbsStream)
-            throws IOException {
-
-        if (extensions.isEmpty()) {
-            return;
-        }
-        DerOutputStream extSequence = new DerOutputStream();
-        DerOutputStream extItems = new DerOutputStream();
-
-        for (Extension ext : extensions.values()) {
-            ext.encode(extItems);
-        }
-        extSequence.write(DerValue.tag_Sequence, extItems);
-        tbsStream.write(DerValue.createTag(DerValue.TAG_CONTEXT, true,
-                (byte)3), extSequence);
-    }
-}
diff -pruN 24.0.1+9-1/test/jdk/java/security/testlibrary/HumanInputStream.java 24.0.2+12-1/test/jdk/java/security/testlibrary/HumanInputStream.java
--- 24.0.1+9-1/test/jdk/java/security/testlibrary/HumanInputStream.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/testlibrary/HumanInputStream.java	1970-01-01 00:00:00.000000000 +0000
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2024, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-
-/**
- * HumanInputStream tries to act like a human sitting in front of a computer
- * terminal typing on the keyboard while a program is running.
- * <p>
- * The program may call InputStream.read() and BufferedReader.readLine() in
- * various places. a call to B.readLine() will try to buffer as much input as
- * possible. Thus, a trivial InputStream will find it impossible to feed
- * anything to I.read() after a B.readLine() call.
- * <p>
- * This is why HumanInputStream was created, which will only send a single line
- * to B.readLine(), no more, no less, and the next I.read() can have a chance
- * to read the exact character right after "\n".
- *
- */
-
-public class HumanInputStream extends InputStream {
-    byte[] src;
-    int pos;
-    int length;
-    boolean inLine;
-    int stopIt;
-
-    public HumanInputStream(String input) {
-        src = input.getBytes();
-        pos = 0;
-        length = src.length;
-        stopIt = 0;
-        inLine = false;
-    }
-
-    // the trick: when called through read(byte[], int, int),
-    // return -1 twice after "\n"
-
-    @Override public int read() throws IOException {
-        int re;
-        if(pos < length) {
-            re = src[pos];
-            if(inLine) {
-                if(stopIt > 0) {
-                    stopIt--;
-                    re = -1;
-                } else {
-                    if(re == '\n') {
-                        stopIt = 2;
-                    }
-                    pos++;
-                }
-            } else {
-                pos++;
-            }
-        } else {
-            re = -1; //throws new IOException("NO MORE TO READ");
-        }
-        return re;
-    }
-    @Override public int read(byte[] buffer, int offset, int len) {
-        inLine = true;
-        try {
-            return super.read(buffer, offset, len);
-        } catch(Exception e) {
-            throw new RuntimeException("HumanInputStream error");
-        } finally {
-            inLine = false;
-        }
-    }
-    @Override public int available() {
-        if (pos < length) return 1;
-        return 0;
-    }
-
-    // test part
-    static void assertTrue(boolean bool) {
-        if (!bool)
-            throw new RuntimeException();
-    }
-
-    public static void test() throws Exception {
-        class Tester {
-            HumanInputStream is;
-            BufferedReader reader;
-            Tester(String s) {
-                is = new HumanInputStream(s);
-                reader = new BufferedReader(new InputStreamReader(is));
-            }
-
-            // three kinds of test method
-            // 1. read byte by byte from InputStream
-            void testStreamReadOnce(int expection) throws Exception {
-                assertTrue(is.read() == expection);
-            }
-            void testStreamReadMany(String expectation) throws Exception {
-                char[] keys = expectation.toCharArray();
-                for (char key : keys) {
-                    assertTrue(is.read() == key);
-                }
-            }
-            // 2. read a line with a newly created Reader
-            void testReaderReadline(String expectation) throws Exception {
-                String s = new BufferedReader(new InputStreamReader(is)).readLine();
-                if(s == null) assertTrue(expectation == null);
-                else assertTrue(s.equals(expectation));
-            }
-            // 3. read a line with the old Reader
-            void testReaderReadline2(String expectation) throws Exception  {
-                String s = reader.readLine();
-                if(s == null) assertTrue(expectation == null);
-                else assertTrue(s.equals(expectation));
-            }
-        }
-
-        Tester test;
-
-        test = new Tester("111\n222\n\n444\n\n");
-        test.testReaderReadline("111");
-        test.testReaderReadline("222");
-        test.testReaderReadline("");
-        test.testReaderReadline("444");
-        test.testReaderReadline("");
-        test.testReaderReadline(null);
-
-        test = new Tester("111\n222\n\n444\n\n");
-        test.testReaderReadline2("111");
-        test.testReaderReadline2("222");
-        test.testReaderReadline2("");
-        test.testReaderReadline2("444");
-        test.testReaderReadline2("");
-        test.testReaderReadline2(null);
-
-        test = new Tester("111\n222\n\n444\n\n");
-        test.testReaderReadline2("111");
-        test.testReaderReadline("222");
-        test.testReaderReadline2("");
-        test.testReaderReadline2("444");
-        test.testReaderReadline("");
-        test.testReaderReadline2(null);
-
-        test = new Tester("1\n2");
-        test.testStreamReadMany("1\n2");
-        test.testStreamReadOnce(-1);
-
-        test = new Tester("12\n234");
-        test.testStreamReadOnce('1');
-        test.testReaderReadline("2");
-        test.testStreamReadOnce('2');
-        test.testReaderReadline2("34");
-        test.testReaderReadline2(null);
-
-        test = new Tester("changeit\n");
-        test.testStreamReadMany("changeit\n");
-        test.testReaderReadline(null);
-
-        test = new Tester("changeit\nName\nCountry\nYes\n");
-        test.testStreamReadMany("changeit\n");
-        test.testReaderReadline("Name");
-        test.testReaderReadline("Country");
-        test.testReaderReadline("Yes");
-        test.testReaderReadline(null);
-
-        test = new Tester("Me\nHere\n");
-        test.testReaderReadline2("Me");
-        test.testReaderReadline2("Here");
-    }
-}
diff -pruN 24.0.1+9-1/test/jdk/java/security/testlibrary/Providers.java 24.0.2+12-1/test/jdk/java/security/testlibrary/Providers.java
--- 24.0.1+9-1/test/jdk/java/security/testlibrary/Providers.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/testlibrary/Providers.java	1970-01-01 00:00:00.000000000 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2011, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.security.Provider;
-import java.security.Security;
-
-public class Providers {
-    public static void setAt(Provider p, int pos) throws Exception {
-        if (Security.getProvider(p.getName()) != null) {
-            Security.removeProvider(p.getName());
-        }
-        if (Security.insertProviderAt(p, pos) == -1) {
-            throw new Exception("cannot setAt");
-        }
-    }
-}
diff -pruN 24.0.1+9-1/test/jdk/java/security/testlibrary/ProvidersSnapshot.java 24.0.2+12-1/test/jdk/java/security/testlibrary/ProvidersSnapshot.java
--- 24.0.1+9-1/test/jdk/java/security/testlibrary/ProvidersSnapshot.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/testlibrary/ProvidersSnapshot.java	1970-01-01 00:00:00.000000000 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2011, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.security.Provider;
-import java.security.Security;
-
-public class ProvidersSnapshot {
-
-    private Provider[] oldProviders;
-
-    private ProvidersSnapshot() {
-        oldProviders = Security.getProviders();
-    }
-
-    public static ProvidersSnapshot create() {
-        return new ProvidersSnapshot();
-    }
-
-    public void restore() {
-        Provider[] newProviders = Security.getProviders();
-        for (Provider p: newProviders) {
-            Security.removeProvider(p.getName());
-        }
-        for (Provider p: oldProviders) {
-            Security.addProvider(p);
-        }
-    }
-}
diff -pruN 24.0.1+9-1/test/jdk/java/security/testlibrary/SimpleOCSPServer.java 24.0.2+12-1/test/jdk/java/security/testlibrary/SimpleOCSPServer.java
--- 24.0.1+9-1/test/jdk/java/security/testlibrary/SimpleOCSPServer.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/security/testlibrary/SimpleOCSPServer.java	1970-01-01 00:00:00.000000000 +0000
@@ -1,1694 +0,0 @@
-/*
- * Copyright (c) 2015, 2024, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.testlibrary;
-
-import java.io.*;
-import java.net.*;
-import java.security.*;
-import java.security.cert.CRLReason;
-import java.security.cert.X509Certificate;
-import java.security.cert.Extension;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateEncodingException;
-import java.security.Signature;
-import java.util.*;
-import java.util.concurrent.*;
-import java.text.SimpleDateFormat;
-import java.math.BigInteger;
-
-import sun.security.x509.*;
-import sun.security.x509.PKIXExtensions;
-import sun.security.provider.certpath.ResponderId;
-import sun.security.provider.certpath.CertId;
-import sun.security.provider.certpath.OCSPResponse;
-import sun.security.provider.certpath.OCSPResponse.ResponseStatus;
-import sun.security.util.*;
-
-
-/**
- * This is a simple OCSP server designed to listen and respond to incoming
- * requests.
- */
-public class SimpleOCSPServer {
-    private final Debug debug = Debug.getInstance("oserv");
-    private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID =
-            ObjectIdentifier.of(KnownOIDs.OCSPBasicResponse);
-
-    private static final SimpleDateFormat utcDateFmt =
-            new SimpleDateFormat("MMM dd yyyy, HH:mm:ss z");
-
-    static final int FREE_PORT = 0;
-
-    // CertStatus values
-    public static enum CertStatus {
-        CERT_STATUS_GOOD,
-        CERT_STATUS_REVOKED,
-        CERT_STATUS_UNKNOWN,
-    }
-
-    // Fields used for the networking portion of the responder
-    private ServerSocket servSocket;
-    private InetAddress listenAddress;
-    private int listenPort;
-
-    // Keystore information (certs, keys, etc.)
-    private KeyStore keystore;
-    private X509Certificate issuerCert;
-    private X509Certificate signerCert;
-    private PrivateKey signerKey;
-
-    // Fields used for the operational portions of the server
-    private boolean logEnabled = false;
-    private ExecutorService threadPool;
-    private volatile boolean started = false;
-    private CountDownLatch serverReady = new CountDownLatch(1);
-    private volatile boolean receivedShutdown = false;
-    private volatile boolean acceptConnections = true;
-    private volatile long delayMsec = 0;
-    private boolean omitContentLength = false;
-
-    // Fields used in the generation of responses
-    private long nextUpdateInterval = -1;
-    private Date nextUpdate = null;
-    private ResponderId respId;
-    private AlgorithmId sigAlgId;
-    private Map<CertId, CertStatusInfo> statusDb =
-            Collections.synchronizedMap(new HashMap<>());
-
-    /**
-     * Construct a SimpleOCSPServer using keystore, password, and alias
-     * parameters.
-     *
-     * @param ks the keystore to be used
-     * @param password the password to access key material in the keystore
-     * @param issuerAlias the alias of the issuer certificate
-     * @param signerAlias the alias of the signer certificate and key.  A
-     * value of {@code null} means that the {@code issuerAlias} will be used
-     * to look up the signer key.
-     *
-     * @throws GeneralSecurityException if there are problems accessing the
-     * keystore or finding objects within the keystore.
-     * @throws IOException if a {@code ResponderId} cannot be generated from
-     * the signer certificate.
-     */
-    public SimpleOCSPServer(KeyStore ks, String password, String issuerAlias,
-            String signerAlias) throws GeneralSecurityException, IOException {
-        this(null, FREE_PORT, ks, password, issuerAlias, signerAlias);
-    }
-
-    /**
-     * Construct a SimpleOCSPServer using specific network parameters,
-     * keystore, password, and alias.
-     *
-     * @param addr the address to bind the server to.  A value of {@code null}
-     * means the server will bind to all interfaces.
-     * @param port the port to listen on.  A value of {@code 0} will mean that
-     * the server will randomly pick an open ephemeral port to bind to.
-     * @param ks the keystore to be used
-     * @param password the password to access key material in the keystore
-     * @param issuerAlias the alias of the issuer certificate
-     * @param signerAlias the alias of the signer certificate and key.  A
-     * value of {@code null} means that the {@code issuerAlias} will be used
-     * to look up the signer key.
-     *
-     * @throws GeneralSecurityException if there are problems accessing the
-     * keystore or finding objects within the keystore.
-     * @throws IOException if a {@code ResponderId} cannot be generated from
-     * the signer certificate.
-     */
-    public SimpleOCSPServer(InetAddress addr, int port, KeyStore ks,
-            String password, String issuerAlias, String signerAlias)
-            throws GeneralSecurityException, IOException {
-        Objects.requireNonNull(ks, "Null keystore provided");
-        Objects.requireNonNull(issuerAlias, "Null issuerName provided");
-
-        utcDateFmt.setTimeZone(TimeZone.getTimeZone("GMT"));
-
-        keystore = ks;
-        issuerCert = (X509Certificate)ks.getCertificate(issuerAlias);
-        if (issuerCert == null) {
-            throw new IllegalArgumentException("Certificate for alias " +
-                    issuerAlias + " not found");
-        }
-
-        if (signerAlias != null) {
-            signerCert = (X509Certificate)ks.getCertificate(signerAlias);
-            if (signerCert == null) {
-                throw new IllegalArgumentException("Certificate for alias " +
-                    signerAlias + " not found");
-            }
-            signerKey = (PrivateKey)ks.getKey(signerAlias,
-                    password.toCharArray());
-            if (signerKey == null) {
-                throw new IllegalArgumentException("PrivateKey for alias " +
-                    signerAlias + " not found");
-            }
-        } else {
-            signerCert = issuerCert;
-            signerKey = (PrivateKey)ks.getKey(issuerAlias,
-                    password.toCharArray());
-            if (signerKey == null) {
-                throw new IllegalArgumentException("PrivateKey for alias " +
-                    issuerAlias + " not found");
-            }
-        }
-        sigAlgId = AlgorithmId.get(SignatureUtil.getDefaultSigAlgForKey(signerKey));
-        respId = new ResponderId(signerCert.getSubjectX500Principal());
-        listenAddress = addr;
-        listenPort = port;
-    }
-
-    /**
-     * Start the server.  The server will bind to the specified network
-     * address and begin listening for incoming connections.
-     *
-     * @throws IOException if any number of things go wonky.
-     */
-    public synchronized void start() throws IOException {
-        // You cannot start the server twice.
-        if (started) {
-            log("Server has already been started");
-            return;
-        } else {
-            started = true;
-        }
-
-        // Create and start the thread pool
-        threadPool = Executors.newFixedThreadPool(32, new ThreadFactory() {
-            @Override
-            public Thread newThread(Runnable r) {
-                Thread t = Executors.defaultThreadFactory().newThread(r);
-                t.setDaemon(true);
-                return t;
-            }
-        });
-
-        threadPool.submit(new Runnable() {
-            @Override
-            public void run() {
-                try (ServerSocket sSock = new ServerSocket()) {
-                    servSocket = sSock;
-                    servSocket.setReuseAddress(true);
-                    servSocket.setSoTimeout(500);
-                    servSocket.bind(new InetSocketAddress(listenAddress,
-                            listenPort), 128);
-                    log("Listening on " + servSocket.getLocalSocketAddress());
-
-                    // Update the listenPort with the new port number.  If
-                    // the server is restarted, it will bind to the same
-                    // port rather than picking a new one.
-                    listenPort = servSocket.getLocalPort();
-
-                    // Decrement the latch, allowing any waiting entities
-                    // to proceed with their requests.
-                    serverReady.countDown();
-
-                    // Main dispatch loop
-                    while (!receivedShutdown) {
-                        try {
-                            Socket newConnection = servSocket.accept();
-                            if (!acceptConnections) {
-                                try {
-                                    log("Reject connection");
-                                    newConnection.close();
-                                } catch (IOException e) {
-                                    // ignore
-                                }
-                                continue;
-                            }
-                            threadPool.submit(new OcspHandler(newConnection));
-                        } catch (SocketTimeoutException timeout) {
-                            // Nothing to do here.  If receivedShutdown
-                            // has changed to true then the loop will
-                            // exit on its own.
-                        } catch (IOException ioe) {
-                            // Something bad happened, log and force a shutdown
-                            log("Unexpected Exception: " + ioe);
-                            stop();
-                        }
-                    }
-
-                    log("Shutting down...");
-                    threadPool.shutdown();
-                } catch (IOException ioe) {
-                    err(ioe);
-                } finally {
-                    // Reset state variables so the server can be restarted
-                    receivedShutdown = false;
-                    started = false;
-                    serverReady = new CountDownLatch(1);
-                }
-            }
-        });
-    }
-
-    /**
-     * Make the OCSP server reject incoming connections.
-     */
-    public synchronized void rejectConnections() {
-        log("Reject OCSP connections");
-        acceptConnections = false;
-    }
-
-    /**
-     * Make the OCSP server accept incoming connections.
-     */
-    public synchronized void acceptConnections() {
-        log("Accept OCSP connections");
-        acceptConnections = true;
-    }
-
-
-    /**
-     * Stop the OCSP server.
-     */
-    public synchronized void stop() {
-        if (started) {
-            receivedShutdown = true;
-            started = false;
-            log("Received shutdown notification");
-        }
-    }
-
-    public synchronized void shutdownNow() {
-        stop();
-        if (threadPool != null) {
-            threadPool.shutdownNow();
-        }
-    }
-
-    /**
-     * Print {@code SimpleOCSPServer} operating parameters.
-     *
-     * @return the {@code SimpleOCSPServer} operating parameters in
-     * {@code String} form.
-     */
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("OCSP Server:\n");
-        sb.append("----------------------------------------------\n");
-        sb.append("issuer: ").append(issuerCert.getSubjectX500Principal()).
-                append("\n");
-        sb.append("signer: ").append(signerCert.getSubjectX500Principal()).
-                append("\n");
-        sb.append("ResponderId: ").append(respId).append("\n");
-        sb.append("----------------------------------------------");
-
-        return sb.toString();
-    }
-
-    /**
-     * Helpful debug routine to hex dump byte arrays.
-     *
-     * @param data the array of bytes to dump to stdout.
-     *
-     * @return the hexdump of the byte array
-     */
-    private static String dumpHexBytes(byte[] data) {
-        return dumpHexBytes(data, data.length, 16, "\n", " ");
-    }
-
-    /**
-     *
-     * @param data the array of bytes to dump to stdout
-     * @param dataLen the length of the data to be displayed
-     * @param itemsPerLine the number of bytes to display per line
-     * if the {@code lineDelim} character is blank then all bytes will be
-     * printed on a single line.
-     * @param lineDelim the delimiter between lines
-     * @param itemDelim the delimiter between bytes
-     *
-     * @return The hexdump of the byte array
-     */
-    private static String dumpHexBytes(byte[] data, int dataLen,
-            int itemsPerLine, String lineDelim, String itemDelim) {
-        StringBuilder sb = new StringBuilder();
-        if (data != null) {
-            for (int i = 0; i < dataLen; i++) {
-                if (i % itemsPerLine == 0 && i != 0) {
-                    sb.append(lineDelim);
-                }
-                sb.append(String.format("%02X", data[i])).append(itemDelim);
-            }
-        }
-
-        return sb.toString();
-    }
-
-    /**
-     * Enable or disable the logging feature.
-     *
-     * @param enable {@code true} to enable logging, {@code false} to
-     * disable it.  The setting must be activated before the server calls
-     * its start method.  Any calls after that have no effect.
-     */
-    public void enableLog(boolean enable) {
-        if (!started) {
-            logEnabled = enable;
-        }
-    }
-
-    /**
-     * Sets the nextUpdate interval.  Intervals will be calculated relative
-     * to the server startup time.  When first set, the nextUpdate date is
-     * calculated based on the current time plus the interval.  After that,
-     * calls to getNextUpdate() will return this date if it is still
-     * later than current time.  If not, the Date will be updated to the
-     * next interval that is later than current time.  This value must be set
-     * before the server has had its start method called.  Calls made after
-     * the server has been started have no effect.
-     *
-     * @param interval the recurring time interval in seconds used to
-     * calculate nextUpdate times.   A value less than or equal to 0 will
-     * disable the nextUpdate feature.
-     */
-    public synchronized void setNextUpdateInterval(long interval) {
-        if (!started) {
-            if (interval <= 0) {
-                nextUpdateInterval = -1;
-                nextUpdate = null;
-                log("nexUpdate support has been disabled");
-            } else {
-                nextUpdateInterval = interval * 1000;
-                nextUpdate = new Date(System.currentTimeMillis() +
-                        nextUpdateInterval);
-                log("nextUpdate set to " + nextUpdate);
-            }
-        }
-    }
-
-    /**
-     * Return the nextUpdate {@code Date} object for this server.  If the
-     * nextUpdate date has already passed, set a new nextUpdate based on
-     * the nextUpdate interval and return that date.
-     *
-     * @return a {@code Date} object set to the nextUpdate field for OCSP
-     * responses.
-     */
-    private synchronized Date getNextUpdate() {
-        if (nextUpdate != null && nextUpdate.before(new Date())) {
-            long nuEpochTime = nextUpdate.getTime();
-            long currentTime = System.currentTimeMillis();
-
-            // Keep adding nextUpdate intervals until you reach a date
-            // that is later than current time.
-            while (currentTime >= nuEpochTime) {
-                nuEpochTime += nextUpdateInterval;
-            }
-
-            // Set the nextUpdate for future threads
-            nextUpdate = new Date(nuEpochTime);
-            log("nextUpdate updated to new value: " + nextUpdate);
-        }
-        return nextUpdate;
-    }
-
-    /**
-     * Add entries into the responder's status database.
-     *
-     * @param newEntries a map of {@code CertStatusInfo} objects, keyed on
-     * their serial number (as a {@code BigInteger}).  All serial numbers
-     * are assumed to have come from this responder's issuer certificate.
-     *
-     * @throws IOException if a CertId cannot be generated.
-     */
-    public void updateStatusDb(Map<BigInteger, CertStatusInfo> newEntries)
-            throws IOException {
-         if (newEntries != null) {
-            for (BigInteger serial : newEntries.keySet()) {
-                CertStatusInfo info = newEntries.get(serial);
-                if (info != null) {
-                    CertId cid = new CertId(issuerCert,
-                            new SerialNumber(serial));
-                    statusDb.put(cid, info);
-                    log("Added entry for serial " + serial + "(" +
-                            info.getType() + ")");
-                }
-            }
-        }
-    }
-
-    /**
-     * Check the status database for revocation information on one or more
-     * certificates.
-     *
-     * @param reqList the list of {@code LocalSingleRequest} objects taken
-     * from the incoming OCSP request.
-     *
-     * @return a {@code Map} of {@code CertStatusInfo} objects keyed by their
-     * {@code CertId} values, for each single request passed in.  Those
-     * CertIds not found in the statusDb will have returned List members with
-     * a status of UNKNOWN.
-     */
-    private Map<CertId, CertStatusInfo> checkStatusDb(
-            List<LocalOcspRequest.LocalSingleRequest> reqList) {
-        // TODO figure out what, if anything to do with request extensions
-        Map<CertId, CertStatusInfo> returnMap = new HashMap<>();
-
-        for (LocalOcspRequest.LocalSingleRequest req : reqList) {
-            CertId cid = req.getCertId();
-            CertStatusInfo info = statusDb.get(cid);
-            if (info != null) {
-                log("Status for SN " + cid.getSerialNumber() + ": " +
-                        info.getType());
-                returnMap.put(cid, info);
-            } else {
-                log("Status for SN " + cid.getSerialNumber() +
-                        " not found, using CERT_STATUS_UNKNOWN");
-                returnMap.put(cid,
-                        new CertStatusInfo(CertStatus.CERT_STATUS_UNKNOWN));
-            }
-        }
-
-        return Collections.unmodifiableMap(returnMap);
-    }
-
-    /**
-     * Set the digital signature algorithm used to sign OCSP responses.
-     *
-     * @param algName The algorithm name
-     *
-     * @throws NoSuchAlgorithmException if the algorithm name is invalid.
-     */
-    public void setSignatureAlgorithm(String algName)
-            throws NoSuchAlgorithmException {
-        if (!started) {
-            sigAlgId = AlgorithmId.get(algName);
-            log("Signature algorithm set to " + sigAlgId.getName());
-        }
-    }
-
-    /**
-     * Get the port the OCSP server is running on.
-     *
-     * @return the port that the OCSP server is running on, or -1 if the
-     * server has not yet been bound to a port.
-     */
-    public int getPort() {
-        if (serverReady.getCount() == 0) {
-            InetSocketAddress inetSock =
-                    (InetSocketAddress)servSocket.getLocalSocketAddress();
-            return inetSock.getPort();
-        } else {
-            return -1;
-        }
-    }
-
-    /**
-     * Allow SimpleOCSPServer consumers to wait for the server to be in
-     * the ready state before sending requests.
-     *
-     * @param timeout the length of time to wait for the server to be ready
-     * @param unit the unit of time applied to the timeout parameter
-     *
-     * @return true if the server enters the ready state, false if the
-     *      timeout period elapses while the caller is waiting for the server
-     *      to become ready.
-     *
-     * @throws InterruptedException if the current thread is interrupted.
-     */
-    public boolean awaitServerReady(long timeout, TimeUnit unit)
-            throws InterruptedException {
-        return serverReady.await(timeout, unit);
-    }
-
-    /**
-     * Set a delay between the reception of the request and production of
-     * the response.
-     *
-     * @param delayMillis the number of milliseconds to wait before acting
-     * on the incoming request.
-     */
-    public void setDelay(long delayMillis) {
-        delayMsec = delayMillis > 0 ? delayMillis : 0;
-        if (delayMsec > 0) {
-            log("OCSP latency set to " + delayMsec + " milliseconds.");
-        } else {
-            log("OCSP latency disabled");
-        }
-    }
-
-    /**
-     * Setting to control whether HTTP responses have the Content-Length
-     * field asserted or not.
-     *
-     * @param isDisabled true if the Content-Length field should not be
-     *        asserted, false otherwise.
-     */
-    public void setDisableContentLength(boolean isDisabled) {
-        if (!started) {
-            omitContentLength = isDisabled;
-            log("Response Content-Length field " +
-                    (isDisabled ? "disabled" : "enabled"));
-        }
-    }
-
-    /**
-     * Log a message to stdout.
-     *
-     * @param message the message to log
-     */
-    private synchronized void log(String message) {
-        if (logEnabled || debug != null) {
-            System.out.println("[" + Thread.currentThread().getName() + "][" +
-                    System.currentTimeMillis() + "]: " + message);
-        }
-    }
-
-    /**
-     * Log an error message on the stderr stream.
-     *
-     * @param message the message to log
-     */
-    private static synchronized void err(String message) {
-        System.err.println("[" + Thread.currentThread().getName() + "]: " +
-                message);
-    }
-
-    /**
-     * Log exception information on the stderr stream.
-     *
-     * @param exc the exception to dump information about
-     */
-    private static synchronized void err(Throwable exc) {
-        System.out.print("[" + Thread.currentThread().getName() +
-                "]: Exception: ");
-        exc.printStackTrace(System.out);
-    }
-
-    /**
-     * The {@code CertStatusInfo} class defines an object used to return
-     * information from the internal status database.  The data in this
-     * object may be used to construct OCSP responses.
-     */
-    public static class CertStatusInfo {
-        private CertStatus certStatusType;
-        private CRLReason reason;
-        private Date revocationTime;
-
-        /**
-         * Create a Certificate status object by providing the status only.
-         * If the status is {@code REVOKED} then current time is assumed
-         * for the revocation time.
-         *
-         * @param statType the status for this entry.
-         */
-        public CertStatusInfo(CertStatus statType) {
-            this(statType, null, null);
-        }
-
-        /**
-         * Create a CertStatusInfo providing both type and revocation date
-         * (if applicable).
-         *
-         * @param statType the status for this entry.
-         * @param revDate if applicable, the date that revocation took place.
-         * A value of {@code null} indicates that current time should be used.
-         * If the value of {@code statType} is not {@code CERT_STATUS_REVOKED},
-         * then the {@code revDate} parameter is ignored.
-         */
-        public CertStatusInfo(CertStatus statType, Date revDate) {
-            this(statType, revDate, null);
-        }
-
-        /**
-         * Create a CertStatusInfo providing type, revocation date
-         * (if applicable) and revocation reason.
-         *
-         * @param statType the status for this entry.
-         * @param revDate if applicable, the date that revocation took place.
-         * A value of {@code null} indicates that current time should be used.
-         * If the value of {@code statType} is not {@code CERT_STATUS_REVOKED},
-         * then the {@code revDate} parameter is ignored.
-         * @param revReason the reason the certificate was revoked.  A value of
-         * {@code null} means that no reason was provided.
-         */
-        public CertStatusInfo(CertStatus statType, Date revDate,
-                CRLReason revReason) {
-            Objects.requireNonNull(statType, "Cert Status must be non-null");
-            certStatusType = statType;
-            switch (statType) {
-                case CERT_STATUS_GOOD:
-                case CERT_STATUS_UNKNOWN:
-                    revocationTime = null;
-                    break;
-                case CERT_STATUS_REVOKED:
-                    revocationTime = revDate != null ? (Date)revDate.clone() :
-                            new Date();
-                    break;
-                default:
-                    throw new IllegalArgumentException("Unknown status type: " +
-                            statType);
-            }
-        }
-
-        /**
-         * Get the cert status type
-         *
-         * @return the status applied to this object (e.g.
-         * {@code CERT_STATUS_GOOD}, {@code CERT_STATUS_UNKNOWN}, etc.)
-         */
-        public CertStatus getType() {
-            return certStatusType;
-        }
-
-        /**
-         * Get the revocation time (if applicable).
-         *
-         * @return the revocation time as a {@code Date} object, or
-         * {@code null} if not applicable (i.e. if the certificate hasn't been
-         * revoked).
-         */
-        public Date getRevocationTime() {
-            return (revocationTime != null ? (Date)revocationTime.clone() :
-                    null);
-        }
-
-        /**
-         * Get the revocation reason.
-         *
-         * @return the revocation reason, or {@code null} if one was not
-         * provided.
-         */
-        public CRLReason getRevocationReason() {
-            return reason;
-        }
-    }
-
-    /**
-     * Runnable task that handles incoming OCSP Requests and returns
-     * responses.
-     */
-    private class OcspHandler implements Runnable {
-        private final boolean USE_GET =
-            !System.getProperty("com.sun.security.ocsp.useget", "").equals("false");
-
-        private final Socket sock;
-        InetSocketAddress peerSockAddr;
-
-        /**
-         * Construct an {@code OcspHandler}.
-         *
-         * @param incomingSocket the socket the server created on accept()
-         */
-        private OcspHandler(Socket incomingSocket) {
-            sock = incomingSocket;
-        }
-
-        /**
-         * Run the OCSP Request parser and construct a response to be sent
-         * back to the client.
-         */
-        @Override
-        public void run() {
-            // If we have implemented a delay to simulate network latency
-            // wait out the delay here before any other processing.
-            try {
-                if (delayMsec > 0) {
-                    log("Delaying response for " + delayMsec + " milliseconds.");
-                    Thread.sleep(delayMsec);
-                }
-            } catch (InterruptedException ie) {
-                // Just log the interrupted sleep
-                log("Delay of " + delayMsec + " milliseconds was interrupted");
-            }
-
-            try (Socket ocspSocket = sock;
-                    InputStream in = ocspSocket.getInputStream();
-                    OutputStream out = ocspSocket.getOutputStream()) {
-                peerSockAddr =
-                        (InetSocketAddress)ocspSocket.getRemoteSocketAddress();
-
-                // Read in the first line which will be the request line.
-                // This will be tokenized so we know if we are dealing with
-                // a GET or POST.
-                String[] headerTokens = readLine(in).split(" ");
-                LocalOcspRequest ocspReq = null;
-                LocalOcspResponse ocspResp = null;
-                ResponseStatus respStat = ResponseStatus.INTERNAL_ERROR;
-                try {
-                    if (headerTokens[0] != null) {
-                        log("Received incoming HTTP " + headerTokens[0] +
-                                " from " + peerSockAddr);
-                        switch (headerTokens[0].toUpperCase()) {
-                            case "POST":
-                                ocspReq = parseHttpOcspPost(in);
-                                break;
-                            case "GET":
-                                ocspReq = parseHttpOcspGet(headerTokens, in);
-                                break;
-                            default:
-                                respStat = ResponseStatus.MALFORMED_REQUEST;
-                                throw new IOException("Not a GET or POST");
-                        }
-                    } else {
-                        respStat = ResponseStatus.MALFORMED_REQUEST;
-                        throw new IOException("Unable to get HTTP method");
-                    }
-
-                    if (ocspReq != null) {
-                        log(ocspReq.toString());
-                        // Get responses for all CertIds in the request
-                        Map<CertId, CertStatusInfo> statusMap =
-                                checkStatusDb(ocspReq.getRequests());
-                        if (statusMap.isEmpty()) {
-                            respStat = ResponseStatus.UNAUTHORIZED;
-                        } else {
-                            ocspResp = new LocalOcspResponse(
-                                    ResponseStatus.SUCCESSFUL, statusMap,
-                                    ocspReq.getExtensions());
-                        }
-                    } else {
-                        respStat = ResponseStatus.MALFORMED_REQUEST;
-                        throw new IOException("Found null request");
-                    }
-                } catch (IOException | RuntimeException exc) {
-                    err(exc);
-                }
-                if (ocspResp == null) {
-                    ocspResp = new LocalOcspResponse(respStat);
-                }
-                sendResponse(out, ocspResp);
-                out.flush();
-
-                log("Closing " + ocspSocket);
-            } catch (IOException | CertificateException exc) {
-                err(exc);
-            }
-        }
-
-        /**
-         * Send an OCSP response on an {@code OutputStream}.
-         *
-         * @param out the {@code OutputStream} on which to send the response.
-         * @param resp the OCSP response to send.
-         *
-         * @throws IOException if an encoding error occurs.
-         */
-        public void sendResponse(OutputStream out, LocalOcspResponse resp)
-                throws IOException {
-            StringBuilder sb = new StringBuilder();
-
-            byte[] respBytes;
-            try {
-                respBytes = resp.getBytes();
-            } catch (RuntimeException re) {
-                err(re);
-                return;
-            }
-
-            sb.append("HTTP/1.0 200 OK\r\n");
-            sb.append("Content-Type: application/ocsp-response\r\n");
-            if (!omitContentLength) {
-                sb.append("Content-Length: ").append(respBytes.length).
-                        append("\r\n");
-            }
-            sb.append("\r\n");
-
-            out.write(sb.toString().getBytes("UTF-8"));
-            out.write(respBytes);
-            log(resp.toString());
-        }
-
-        /**
-         * Parse the incoming HTTP POST of an OCSP Request.
-         *
-         * @param inStream the input stream from the socket bound to this
-         * {@code OcspHandler}.
-         *
-         * @return the OCSP Request as a {@code LocalOcspRequest}
-         *
-         * @throws IOException if there are network related issues or problems
-         * occur during parsing of the OCSP request.
-         * @throws CertificateException if one or more of the certificates in
-         * the OCSP request cannot be read/parsed.
-         */
-        private LocalOcspRequest parseHttpOcspPost(InputStream inStream)
-                throws IOException, CertificateException {
-            boolean endOfHeader = false;
-            boolean properContentType = false;
-            int length = -1;
-
-            while (!endOfHeader) {
-                String[] lineTokens = readLine(inStream).split(" ");
-                if (lineTokens[0].isEmpty()) {
-                    endOfHeader = true;
-                } else if (lineTokens[0].equalsIgnoreCase("Content-Type:")) {
-                    if (lineTokens[1] == null ||
-                            !lineTokens[1].equals(
-                                    "application/ocsp-request")) {
-                        log("Unknown Content-Type: " +
-                                (lineTokens[1] != null ?
-                                        lineTokens[1] : "<NULL>"));
-                        return null;
-                    } else {
-                        properContentType = true;
-                        log("Content-Type = " + lineTokens[1]);
-                    }
-                } else if (lineTokens[0].equalsIgnoreCase("Content-Length:")) {
-                    if (lineTokens[1] != null) {
-                        length = Integer.parseInt(lineTokens[1]);
-                        log("Content-Length = " + length);
-                    }
-                }
-            }
-
-            // Okay, make sure we got what we needed from the header, then
-            // read the remaining OCSP Request bytes
-            if (properContentType && length >= 0) {
-                if (USE_GET && length <= 255) {
-                    // Received a small POST request. Check that our client code properly
-                    // handled the relevant flag. We expect small GET requests, unless
-                    // explicitly disabled.
-                    throw new IOException("Should have received small GET, not POST.");
-                }
-                byte[] ocspBytes = new byte[length];
-                inStream.read(ocspBytes);
-                return new LocalOcspRequest(ocspBytes);
-            } else {
-                return null;
-            }
-        }
-
-        /**
-         * Parse the incoming HTTP GET of an OCSP Request.
-         *
-         * @param headerTokens the individual String tokens from the first
-         * line of the HTTP GET.
-         * @param inStream the input stream from the socket bound to this
-         * {@code OcspHandler}.
-         *
-         * @return the OCSP Request as a {@code LocalOcspRequest}
-         *
-         * @throws IOException if there are network related issues or problems
-         * occur during parsing of the OCSP request.
-         * @throws CertificateException if one or more of the certificates in
-         * the OCSP request cannot be read/parsed.
-         */
-        private LocalOcspRequest parseHttpOcspGet(String[] headerTokens,
-                InputStream inStream) throws IOException, CertificateException {
-            // Display the whole request
-            StringBuilder sb = new StringBuilder("OCSP GET REQUEST\n");
-            for (String hTok : headerTokens) {
-                sb.append(hTok).append("\n");
-            }
-            log(sb.toString());
-
-            // Before we process the remainder of the GET URL, we should drain
-            // the InputStream of any other header data.  We (for now) won't
-            // use it, but will display the contents if logging is enabled.
-            boolean endOfHeader = false;
-            while (!endOfHeader) {
-                String[] lineTokens = readLine(inStream).split(":", 2);
-                // We expect to see a type and value pair delimited by a colon.
-                if (lineTokens[0].isEmpty()) {
-                    endOfHeader = true;
-                } else if (lineTokens.length == 2) {
-                    log(String.format("ReqHdr: %s: %s", lineTokens[0].trim(),
-                            lineTokens[1].trim()));
-                } else {
-                    // A colon wasn't found and token 0 should be the whole line
-                    log("ReqHdr: " + lineTokens[0].trim());
-                }
-            }
-
-            // We have already established headerTokens[0] to be "GET".
-            // We should have the URL-encoded base64 representation of the
-            // OCSP request in headerTokens[1].  We need to strip any leading
-            // "/" off before decoding.
-            return new LocalOcspRequest(Base64.getMimeDecoder().decode(
-                    URLDecoder.decode(headerTokens[1].replaceAll("/", ""),
-                            "UTF-8")));
-        }
-
-        /**
-         * Read a line of text that is CRLF-delimited.
-         *
-         * @param is the {@code InputStream} tied to the socket
-         * for this {@code OcspHandler}
-         *
-         * @return a {@code String} consisting of the line of text
-         * read from the stream with the CRLF stripped.
-         *
-         * @throws IOException if any I/O error occurs.
-         */
-        private String readLine(InputStream is) throws IOException {
-            PushbackInputStream pbis = new PushbackInputStream(is);
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
-            boolean done = false;
-            while (!done) {
-                byte b = (byte)pbis.read();
-                if (b == '\r') {
-                    byte bNext = (byte)pbis.read();
-                    if (bNext == '\n' || bNext == -1) {
-                        done = true;
-                    } else {
-                        pbis.unread(bNext);
-                        bos.write(b);
-                    }
-                } else if (b == -1) {
-                    done = true;
-                } else {
-                    bos.write(b);
-                }
-            }
-
-            return new String(bos.toByteArray(), "UTF-8");
-        }
-    }
-
-
-    /**
-     * Simple nested class to handle OCSP requests without making
-     * changes to sun.security.provider.certpath.OCSPRequest
-     */
-    public class LocalOcspRequest {
-
-        private byte[] nonce;
-        private byte[] signature = null;
-        private AlgorithmId algId = null;
-        private int version = 0;
-        private GeneralName requestorName = null;
-        private Map<String, Extension> extensions = Collections.emptyMap();
-        private final List<LocalSingleRequest> requestList = new ArrayList<>();
-        private final List<X509Certificate> certificates = new ArrayList<>();
-
-        /**
-         * Construct a {@code LocalOcspRequest} from its DER encoding.
-         *
-         * @param requestBytes the DER-encoded bytes
-         *
-         * @throws IOException if decoding errors occur
-         * @throws CertificateException if certificates are found in the
-         * OCSP request and they do not parse correctly.
-         */
-        private LocalOcspRequest(byte[] requestBytes) throws IOException,
-                CertificateException {
-            Objects.requireNonNull(requestBytes, "Received null input");
-
-            // Display the DER encoding before parsing
-            log("Local OCSP Request Constructor, parsing bytes:\n" +
-                    dumpHexBytes(requestBytes));
-
-            DerInputStream dis = new DerInputStream(requestBytes);
-
-            // Parse the top-level structure, it should have no more than
-            // two elements.
-            DerValue[] topStructs = dis.getSequence(2);
-            for (DerValue dv : topStructs) {
-                if (dv.tag == DerValue.tag_Sequence) {
-                    parseTbsRequest(dv);
-                } else if (dv.isContextSpecific((byte)0)) {
-                    parseSignature(dv);
-                } else {
-                    throw new IOException("Unknown tag at top level: " +
-                            dv.tag);
-                }
-            }
-        }
-
-        /**
-         * Parse the signature block from an OCSP request
-         *
-         * @param sigSequence a {@code DerValue} containing the signature
-         * block at the outer sequence datum.
-         *
-         * @throws IOException if any non-certificate-based parsing errors occur
-         * @throws CertificateException if certificates are found in the
-         * OCSP request and they do not parse correctly.
-         */
-        private void parseSignature(DerValue sigSequence)
-                throws IOException, CertificateException {
-            DerValue[] sigItems = sigSequence.data.getSequence(3);
-            if (sigItems.length != 3) {
-                throw new IOException("Invalid number of signature items: " +
-                        "expected 3, got " + sigItems.length);
-            }
-
-            algId = AlgorithmId.parse(sigItems[0]);
-            signature = sigItems[1].getBitString();
-
-            if (sigItems[2].isContextSpecific((byte)0)) {
-                DerValue[] certDerItems = sigItems[2].data.getSequence(4);
-                int i = 0;
-                for (DerValue dv : certDerItems) {
-                    X509Certificate xc = new X509CertImpl(dv);
-                    certificates.add(xc);
-                }
-            } else {
-                throw new IOException("Invalid tag in signature block: " +
-                    sigItems[2].tag);
-            }
-        }
-
-        /**
-         * Parse the to-be-signed request data
-         *
-         * @param tbsReqSeq a {@code DerValue} object containing the to-be-
-         * signed OCSP request at the outermost SEQUENCE tag.
-         * @throws IOException if any parsing errors occur
-         */
-        private void parseTbsRequest(DerValue tbsReqSeq) throws IOException {
-            while (tbsReqSeq.data.available() > 0) {
-                DerValue dv = tbsReqSeq.data.getDerValue();
-                if (dv.isContextSpecific((byte)0)) {
-                    // The version was explicitly called out
-                    version = dv.data.getInteger();
-                } else if (dv.isContextSpecific((byte)1)) {
-                    // A GeneralName was provided
-                    requestorName = new GeneralName(dv.data.getDerValue());
-                } else if (dv.isContextSpecific((byte)2)) {
-                    // Parse the extensions
-                    DerValue[] extItems = dv.data.getSequence(2);
-                    extensions = parseExtensions(extItems);
-                } else if (dv.tag == DerValue.tag_Sequence) {
-                    while (dv.data.available() > 0) {
-                        requestList.add(new LocalSingleRequest(dv.data));
-                    }
-                }
-            }
-        }
-
-        /**
-         * Parse a SEQUENCE of extensions.  This routine is used both
-         * at the overall request level and down at the singleRequest layer.
-         *
-         * @param extDerItems an array of {@code DerValue} items, each one
-         * consisting of a DER-encoded extension.
-         *
-         * @return a {@code Map} of zero or more extensions,
-         * keyed by its object identifier in {@code String} form.
-         *
-         * @throws IOException if any parsing errors occur.
-         */
-        private Map<String, Extension> parseExtensions(DerValue[] extDerItems)
-                throws IOException {
-            Map<String, Extension> extMap = new HashMap<>();
-
-            if (extDerItems != null && extDerItems.length != 0) {
-                for (DerValue extDerVal : extDerItems) {
-                    sun.security.x509.Extension ext =
-                            new sun.security.x509.Extension(extDerVal);
-                    extMap.put(ext.getId(), ext);
-                }
-            }
-
-            return extMap;
-        }
-
-        /**
-         * Return the list of single request objects in this OCSP request.
-         *
-         * @return an unmodifiable {@code List} of zero or more requests.
-         */
-        private List<LocalSingleRequest> getRequests() {
-            return Collections.unmodifiableList(requestList);
-        }
-
-        /**
-         * Return the list of X.509 Certificates in this OCSP request.
-         *
-         * @return an unmodifiable {@code List} of zero or more
-         * {@cpde X509Certificate} objects.
-         */
-        private List<X509Certificate> getCertificates() {
-            return Collections.unmodifiableList(certificates);
-        }
-
-        /**
-         * Return the map of OCSP request extensions.
-         *
-         * @return an unmodifiable {@code Map} of zero or more
-         * {@code Extension} objects, keyed by their object identifiers
-         * in {@code String} form.
-         */
-        private Map<String, Extension> getExtensions() {
-            return Collections.unmodifiableMap(extensions);
-        }
-
-        /**
-         * Display the {@code LocalOcspRequest} in human readable form.
-         *
-         * @return a {@code String} representation of the
-         * {@code LocalOcspRequest}
-         */
-        @Override
-        public String toString() {
-            StringBuilder sb = new StringBuilder();
-
-            sb.append(String.format("OCSP Request: Version %d (0x%X)",
-                    version + 1, version)).append("\n");
-            if (requestorName != null) {
-                sb.append("Requestor Name: ").append(requestorName).
-                        append("\n");
-            }
-
-            int requestCtr = 0;
-            for (LocalSingleRequest lsr : requestList) {
-                sb.append("Request [").append(requestCtr++).append("]\n");
-                sb.append(lsr).append("\n");
-            }
-            if (!extensions.isEmpty()) {
-                sb.append("Extensions (").append(extensions.size()).
-                        append(")\n");
-                for (Extension ext : extensions.values()) {
-                    sb.append("\t").append(ext).append("\n");
-                }
-            }
-            if (signature != null) {
-                sb.append("Signature: ").append(algId).append("\n");
-                sb.append(dumpHexBytes(signature)).append("\n");
-                int certCtr = 0;
-                for (X509Certificate cert : certificates) {
-                    sb.append("Certificate [").append(certCtr++).append("]").
-                            append("\n");
-                    sb.append("\tSubject: ");
-                    sb.append(cert.getSubjectX500Principal()).append("\n");
-                    sb.append("\tIssuer: ");
-                    sb.append(cert.getIssuerX500Principal()).append("\n");
-                    sb.append("\tSerial: ").append(cert.getSerialNumber());
-                }
-            }
-
-            return sb.toString();
-        }
-
-        /**
-         * Inner class designed to handle the decoding/representation of
-         * single requests within a {@code LocalOcspRequest} object.
-         */
-        public class LocalSingleRequest {
-            private final CertId cid;
-            private Map<String, Extension> extensions = Collections.emptyMap();
-
-            private LocalSingleRequest(DerInputStream dis)
-                    throws IOException {
-                DerValue[] srItems = dis.getSequence(2);
-
-                // There should be 1, possibly 2 DerValue items
-                if (srItems.length == 1 || srItems.length == 2) {
-                    // The first parsable item should be the mandatory CertId
-                    cid = new CertId(srItems[0].data);
-                    if (srItems.length == 2) {
-                        if (srItems[1].isContextSpecific((byte)0)) {
-                            DerValue[] extDerItems = srItems[1].data.getSequence(2);
-                            extensions = parseExtensions(extDerItems);
-                        } else {
-                            throw new IOException("Illegal tag in Request " +
-                                    "extensions: " + srItems[1].tag);
-                        }
-                    }
-                } else {
-                    throw new IOException("Invalid number of items in " +
-                            "Request (" + srItems.length + ")");
-                }
-            }
-
-            /**
-             * Get the {@code CertId} for this single request.
-             *
-             * @return the {@code CertId} for this single request.
-             */
-            private CertId getCertId() {
-                return cid;
-            }
-
-            /**
-             * Return the map of single request extensions.
-             *
-             * @return an unmodifiable {@code Map} of zero or more
-             * {@code Extension} objects, keyed by their object identifiers
-             * in {@code String} form.
-             */
-            private Map<String, Extension> getExtensions() {
-                return Collections.unmodifiableMap(extensions);
-            }
-
-            /**
-             * Display the {@code LocalSingleRequest} in human readable form.
-             *
-             * @return a {@code String} representation of the
-             * {@code LocalSingleRequest}
-             */
-            @Override
-            public String toString() {
-                StringBuilder sb = new StringBuilder();
-                sb.append("CertId, Algorithm = ");
-                sb.append(cid.getHashAlgorithm()).append("\n");
-                sb.append("\tIssuer Name Hash: ");
-                byte[] cidHashBuf = cid.getIssuerNameHash();
-                sb.append(dumpHexBytes(cidHashBuf, cidHashBuf.length,
-                        256, "", ""));
-                sb.append("\n");
-                sb.append("\tIssuer Key Hash: ");
-                cidHashBuf = cid.getIssuerKeyHash();
-                sb.append(dumpHexBytes(cidHashBuf, cidHashBuf.length,
-                        256, "", ""));
-                sb.append("\n");
-                sb.append("\tSerial Number: ").append(cid.getSerialNumber());
-                if (!extensions.isEmpty()) {
-                    sb.append("Extensions (").append(extensions.size()).
-                            append(")\n");
-                    for (Extension ext : extensions.values()) {
-                        sb.append("\t").append(ext).append("\n");
-                    }
-                }
-
-                return sb.toString();
-            }
-        }
-    }
-
-    /**
-     * Simple nested class to handle OCSP requests without making
-     * changes to sun.security.provider.certpath.OCSPResponse
-     */
-    public class LocalOcspResponse {
-        private final int version = 0;
-        private final OCSPResponse.ResponseStatus responseStatus;
-        private final Map<CertId, CertStatusInfo> respItemMap;
-        private final Date producedAtDate;
-        private final List<LocalSingleResponse> singleResponseList =
-                new ArrayList<>();
-        private final Map<String, Extension> responseExtensions;
-        private byte[] signature;
-        private final List<X509Certificate> certificates;
-        private final byte[] encodedResponse;
-
-        /**
-         * Constructor for the generation of non-successful responses
-         *
-         * @param respStat the OCSP response status.
-         *
-         * @throws IOException if an error happens during encoding
-         * @throws NullPointerException if {@code respStat} is {@code null}
-         * or {@code respStat} is successful.
-         */
-        public LocalOcspResponse(OCSPResponse.ResponseStatus respStat)
-                throws IOException {
-            this(respStat, null, null);
-        }
-
-        /**
-         * Construct a response from a list of certificate
-         * status objects and extensions.
-         *
-         * @param respStat the status of the entire response
-         * @param itemMap a {@code Map} of {@code CertId} objects and their
-         * respective revocation statuses from the server's response DB.
-         * @param reqExtensions a {@code Map} of request extensions
-         *
-         * @throws IOException if an error happens during encoding
-         * @throws NullPointerException if {@code respStat} is {@code null}
-         * or {@code respStat} is successful, and a {@code null} {@code itemMap}
-         * has been provided.
-         */
-        public LocalOcspResponse(OCSPResponse.ResponseStatus respStat,
-                Map<CertId, CertStatusInfo> itemMap,
-                Map<String, Extension> reqExtensions) throws IOException {
-            responseStatus = Objects.requireNonNull(respStat,
-                    "Illegal null response status");
-            if (responseStatus == ResponseStatus.SUCCESSFUL) {
-                respItemMap = Objects.requireNonNull(itemMap,
-                        "SUCCESSFUL responses must have a response map");
-                producedAtDate = new Date();
-
-                // Turn the answerd from the response DB query into a list
-                // of single responses.
-                for (CertId id : itemMap.keySet()) {
-                    singleResponseList.add(
-                            new LocalSingleResponse(id, itemMap.get(id)));
-                }
-
-                responseExtensions = setResponseExtensions(reqExtensions);
-                certificates = new ArrayList<>();
-                if (signerCert != issuerCert) {
-                    certificates.add(signerCert);
-                }
-                certificates.add(issuerCert);
-            } else {
-                respItemMap = null;
-                producedAtDate = null;
-                responseExtensions = null;
-                certificates = null;
-            }
-            encodedResponse = this.getBytes();
-        }
-
-        /**
-         * Set the response extensions based on the request extensions
-         * that were received.  Right now, this is limited to the
-         * OCSP nonce extension.
-         *
-         * @param reqExts a {@code Map} of zero or more request extensions
-         *
-         * @return a {@code Map} of zero or more response extensions, keyed
-         * by the extension object identifier in {@code String} form.
-         */
-        private Map<String, Extension> setResponseExtensions(
-                Map<String, Extension> reqExts) {
-            Map<String, Extension> respExts = new HashMap<>();
-            String ocspNonceStr = PKIXExtensions.OCSPNonce_Id.toString();
-
-            if (reqExts != null) {
-                for (String id : reqExts.keySet()) {
-                    if (id.equals(ocspNonceStr)) {
-                        // We found a nonce, add it into the response extensions
-                        Extension ext = reqExts.get(id);
-                        if (ext != null) {
-                            respExts.put(id, ext);
-                            log("Added OCSP Nonce to response");
-                        } else {
-                            log("Error: Found nonce entry, but found null " +
-                                    "value.  Skipping");
-                        }
-                    }
-                }
-            }
-
-            return respExts;
-        }
-
-        /**
-         * Get the DER-encoded response bytes for this response
-         *
-         * @return a byte array containing the DER-encoded bytes for
-         * the response
-         *
-         * @throws IOException if any encoding errors occur
-         */
-        private byte[] getBytes() throws IOException {
-            DerOutputStream outerSeq = new DerOutputStream();
-            DerOutputStream responseStream = new DerOutputStream();
-            responseStream.putEnumerated(responseStatus.ordinal());
-            if (responseStatus == ResponseStatus.SUCCESSFUL &&
-                    respItemMap != null) {
-                encodeResponseBytes(responseStream);
-            }
-
-            // Commit the outermost sequence bytes
-            outerSeq.write(DerValue.tag_Sequence, responseStream);
-            return outerSeq.toByteArray();
-        }
-
-        private void encodeResponseBytes(DerOutputStream responseStream)
-                throws IOException {
-            DerOutputStream explicitZero = new DerOutputStream();
-            DerOutputStream respItemStream = new DerOutputStream();
-
-            respItemStream.putOID(OCSP_BASIC_RESPONSE_OID);
-
-            byte[] basicOcspBytes = encodeBasicOcspResponse();
-            respItemStream.putOctetString(basicOcspBytes);
-            explicitZero.write(DerValue.tag_Sequence, respItemStream);
-            responseStream.write(DerValue.createTag(DerValue.TAG_CONTEXT,
-                    true, (byte)0), explicitZero);
-        }
-
-        private byte[] encodeBasicOcspResponse() throws IOException {
-            DerOutputStream outerSeq = new DerOutputStream();
-            DerOutputStream basicORItemStream = new DerOutputStream();
-
-            // Encode the tbsResponse
-            byte[] tbsResponseBytes = encodeTbsResponse();
-            basicORItemStream.write(tbsResponseBytes);
-
-            try {
-                // Create the signature
-                Signature sig = SignatureUtil.fromKey(
-                        sigAlgId.getName(), signerKey, (Provider)null);
-                sig.update(tbsResponseBytes);
-                signature = sig.sign();
-                // Rewrite signAlg, RSASSA-PSS needs some parameters.
-                sigAlgId = SignatureUtil.fromSignature(sig, signerKey);
-                sigAlgId.encode(basicORItemStream);
-                basicORItemStream.putBitString(signature);
-            } catch (GeneralSecurityException exc) {
-                err(exc);
-                throw new IOException(exc);
-            }
-
-            // Add certificates
-            try {
-                DerOutputStream certStream = new DerOutputStream();
-                ArrayList<DerValue> certList = new ArrayList<>();
-                if (signerCert != issuerCert) {
-                    certList.add(new DerValue(signerCert.getEncoded()));
-                }
-                certList.add(new DerValue(issuerCert.getEncoded()));
-                DerValue[] dvals = new DerValue[certList.size()];
-                certStream.putSequence(certList.toArray(dvals));
-                basicORItemStream.write(DerValue.createTag(DerValue.TAG_CONTEXT,
-                        true, (byte)0), certStream);
-            } catch (CertificateEncodingException cex) {
-                err(cex);
-                throw new IOException(cex);
-            }
-
-            // Commit the outermost sequence bytes
-            outerSeq.write(DerValue.tag_Sequence, basicORItemStream);
-            return outerSeq.toByteArray();
-        }
-
-        private byte[] encodeTbsResponse() throws IOException {
-            DerOutputStream outerSeq = new DerOutputStream();
-            DerOutputStream tbsStream = new DerOutputStream();
-
-            // Note: We're not going explicitly assert the version
-            tbsStream.write(respId.getEncoded());
-            tbsStream.putGeneralizedTime(producedAtDate);
-
-            // Sequence of responses
-            encodeSingleResponses(tbsStream);
-
-            // TODO: add response extension support
-            encodeExtensions(tbsStream);
-
-            outerSeq.write(DerValue.tag_Sequence, tbsStream);
-            return outerSeq.toByteArray();
-        }
-
-        private void encodeSingleResponses(DerOutputStream tbsStream)
-                throws IOException {
-            DerValue[] srDerVals = new DerValue[singleResponseList.size()];
-            int srDvCtr = 0;
-
-            for (LocalSingleResponse lsr : singleResponseList) {
-                srDerVals[srDvCtr++] = new DerValue(lsr.getBytes());
-            }
-
-            tbsStream.putSequence(srDerVals);
-        }
-
-        private void encodeExtensions(DerOutputStream tbsStream)
-                throws IOException {
-            DerOutputStream extSequence = new DerOutputStream();
-            DerOutputStream extItems = new DerOutputStream();
-
-            for (Extension ext : responseExtensions.values()) {
-                ext.encode(extItems);
-            }
-            extSequence.write(DerValue.tag_Sequence, extItems);
-            tbsStream.write(DerValue.createTag(DerValue.TAG_CONTEXT, true,
-                    (byte)1), extSequence);
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder sb = new StringBuilder();
-
-            sb.append("OCSP Response: ").append(responseStatus).append("\n");
-            if (responseStatus == ResponseStatus.SUCCESSFUL) {
-                sb.append("Response Type: ").
-                        append(OCSP_BASIC_RESPONSE_OID.toString()).append("\n");
-                sb.append(String.format("Version: %d (0x%X)", version + 1,
-                        version)).append("\n");
-                sb.append("Responder Id: ").append(respId.toString()).
-                        append("\n");
-                sb.append("Produced At: ").
-                        append(utcDateFmt.format(producedAtDate)).append("\n");
-
-                int srCtr = 0;
-                for (LocalSingleResponse lsr : singleResponseList) {
-                    sb.append("SingleResponse [").append(srCtr++).append("]\n");
-                    sb.append(lsr);
-                }
-
-                if (!responseExtensions.isEmpty()) {
-                    sb.append("Extensions (").append(responseExtensions.size()).
-                            append(")\n");
-                    for (Extension ext : responseExtensions.values()) {
-                        sb.append("\t").append(ext).append("\n");
-                    }
-                } else {
-                    sb.append("\n");
-                }
-
-                if (signature != null) {
-                    sb.append("Signature: ").append(sigAlgId).append("\n");
-                    sb.append(dumpHexBytes(signature)).append("\n");
-                    int certCtr = 0;
-                    for (X509Certificate cert : certificates) {
-                        sb.append("Certificate [").append(certCtr++).append("]").
-                                append("\n");
-                        sb.append("\tSubject: ");
-                        sb.append(cert.getSubjectX500Principal()).append("\n");
-                        sb.append("\tIssuer: ");
-                        sb.append(cert.getIssuerX500Principal()).append("\n");
-                        sb.append("\tSerial: ").append(cert.getSerialNumber());
-                        sb.append("\n");
-                    }
-                }
-            }
-
-            return sb.toString();
-        }
-
-        private class LocalSingleResponse {
-            private final CertId certId;
-            private final CertStatusInfo csInfo;
-            private final Date thisUpdate;
-            private final Date lsrNextUpdate;
-            private final Map<String, Extension> singleExtensions;
-
-            public LocalSingleResponse(CertId cid, CertStatusInfo info) {
-                certId = Objects.requireNonNull(cid, "CertId must be non-null");
-                csInfo = Objects.requireNonNull(info,
-                        "CertStatusInfo must be non-null");
-
-                // For now, we'll keep things simple and make the thisUpdate
-                // field the same as the producedAt date.
-                thisUpdate = producedAtDate;
-                lsrNextUpdate = getNextUpdate();
-
-                // TODO Add extensions support
-                singleExtensions = Collections.emptyMap();
-            }
-
-            @Override
-            public String toString() {
-                StringBuilder sb = new StringBuilder();
-                sb.append("Certificate Status: ").append(csInfo.getType());
-                sb.append("\n");
-                if (csInfo.getType() == CertStatus.CERT_STATUS_REVOKED) {
-                    sb.append("Revocation Time: ");
-                    sb.append(utcDateFmt.format(csInfo.getRevocationTime()));
-                    sb.append("\n");
-                    if (csInfo.getRevocationReason() != null) {
-                        sb.append("Revocation Reason: ");
-                        sb.append(csInfo.getRevocationReason()).append("\n");
-                    }
-                }
-
-                sb.append("CertId, Algorithm = ");
-                sb.append(certId.getHashAlgorithm()).append("\n");
-                sb.append("\tIssuer Name Hash: ");
-                byte[] cidHashBuf = certId.getIssuerNameHash();
-                sb.append(dumpHexBytes(cidHashBuf, cidHashBuf.length,
-                        256, "", ""));
-                sb.append("\n");
-                sb.append("\tIssuer Key Hash: ");
-                cidHashBuf = certId.getIssuerKeyHash();
-                sb.append(dumpHexBytes(cidHashBuf, cidHashBuf.length,
-                        256, "", ""));
-                sb.append("\n");
-                sb.append("\tSerial Number: ").append(certId.getSerialNumber());
-                sb.append("\n");
-                sb.append("This Update: ");
-                sb.append(utcDateFmt.format(thisUpdate)).append("\n");
-                if (lsrNextUpdate != null) {
-                    sb.append("Next Update: ");
-                    sb.append(utcDateFmt.format(lsrNextUpdate)).append("\n");
-                }
-
-                if (!singleExtensions.isEmpty()) {
-                    sb.append("Extensions (").append(singleExtensions.size()).
-                            append(")\n");
-                    for (Extension ext : singleExtensions.values()) {
-                        sb.append("\t").append(ext).append("\n");
-                    }
-                }
-
-                return sb.toString();
-            }
-
-            public byte[] getBytes() throws IOException {
-                byte[] nullData = { };
-                DerOutputStream responseSeq = new DerOutputStream();
-                DerOutputStream srStream = new DerOutputStream();
-
-                // Encode the CertId
-                certId.encode(srStream);
-
-                // Next, encode the CertStatus field
-                CertStatus csiType = csInfo.getType();
-                switch (csiType) {
-                    case CERT_STATUS_GOOD:
-                        srStream.write(DerValue.createTag(DerValue.TAG_CONTEXT,
-                                false, (byte)0), nullData);
-                        break;
-                    case CERT_STATUS_REVOKED:
-                        DerOutputStream revInfo = new DerOutputStream();
-                        revInfo.putGeneralizedTime(csInfo.getRevocationTime());
-                        CRLReason revReason = csInfo.getRevocationReason();
-                        if (revReason != null) {
-                            byte[] revDer = new byte[3];
-                            revDer[0] = DerValue.tag_Enumerated;
-                            revDer[1] = 1;
-                            revDer[2] = (byte)revReason.ordinal();
-                            revInfo.write(DerValue.createTag(
-                                    DerValue.TAG_CONTEXT, true, (byte)0),
-                                    revDer);
-                        }
-                        srStream.write(DerValue.createTag(
-                                DerValue.TAG_CONTEXT, true, (byte)1),
-                                revInfo);
-                        break;
-                    case CERT_STATUS_UNKNOWN:
-                        srStream.write(DerValue.createTag(DerValue.TAG_CONTEXT,
-                                false, (byte)2), nullData);
-                        break;
-                    default:
-                        throw new IOException("Unknown CertStatus: " + csiType);
-                }
-
-                // Add the necessary dates
-                srStream.putGeneralizedTime(thisUpdate);
-                if (lsrNextUpdate != null) {
-                    DerOutputStream nuStream = new DerOutputStream();
-                    nuStream.putGeneralizedTime(lsrNextUpdate);
-                    srStream.write(DerValue.createTag(DerValue.TAG_CONTEXT,
-                            true, (byte)0), nuStream);
-                }
-
-                // TODO add singleResponse Extension support
-
-                // Add the single response to the response output stream
-                responseSeq.write(DerValue.tag_Sequence, srStream);
-                return responseSeq.toByteArray();
-            }
-        }
-    }
-}
diff -pruN 24.0.1+9-1/test/jdk/java/util/Currency/ISO4217-list-one.txt 24.0.2+12-1/test/jdk/java/util/Currency/ISO4217-list-one.txt
--- 24.0.1+9-1/test/jdk/java/util/Currency/ISO4217-list-one.txt	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/util/Currency/ISO4217-list-one.txt	2025-06-27 08:03:14.000000000 +0000
@@ -1,12 +1,12 @@
 #
 #
-# Amendments up until ISO 4217 AMENDMENT NUMBER 177
-#   (As of 20 June 2024)
+# Amendments up until ISO 4217 AMENDMENT NUMBER 179
+#   (As of 02 May 2025)
 #
 
 # Version
 FILEVERSION=3
-DATAVERSION=177
+DATAVERSION=179
 
 # ISO 4217 currency data
 AF	AFN	971	2
diff -pruN 24.0.1+9-1/test/jdk/java/util/Currency/ValidateISO4217.java 24.0.2+12-1/test/jdk/java/util/Currency/ValidateISO4217.java
--- 24.0.1+9-1/test/jdk/java/util/Currency/ValidateISO4217.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/util/Currency/ValidateISO4217.java	2025-06-27 08:03:14.000000000 +0000
@@ -26,6 +26,7 @@
  * @bug 4691089 4819436 4942982 5104960 6544471 6627549 7066203 7195759
  *      8039317 8074350 8074351 8145952 8187946 8193552 8202026 8204269
  *      8208746 8209775 8264792 8274658 8283277 8296239 8321480 8334653
+ *      8356096
  * @summary Validate ISO 4217 data for Currency class.
  * @modules java.base/java.util:open
  *          jdk.localedata
@@ -89,7 +90,7 @@ public class ValidateISO4217 {
             "ADP-AFA-ATS-AYM-AZM-BEF-BGL-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-"
                     + "DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-HRK-IEP-ITL-LTL-LUF-LVL-MGF-MRO-MTL-MXV-MZM-NLG-"
                     + "PTE-ROL-RUR-SDD-SIT-SLL-SKK-SRG-STD-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-VED-"
-                    + "XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-"
+                    + "XAD-XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-"
                     + "YUM-ZMK-ZWD-ZWL-ZWN-ZWR";
     private static final String[][] extraCodes = {
             /* Defined in ISO 4217 list, but don't have code and minor unit info. */
diff -pruN 24.0.1+9-1/test/jdk/java/util/TimeZone/TimeZoneData/VERSION 24.0.2+12-1/test/jdk/java/util/TimeZone/TimeZoneData/VERSION
--- 24.0.1+9-1/test/jdk/java/util/TimeZone/TimeZoneData/VERSION	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/util/TimeZone/TimeZoneData/VERSION	2025-06-27 08:03:14.000000000 +0000
@@ -1 +1 @@
-tzdata2025a
+tzdata2025b
diff -pruN 24.0.1+9-1/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java 24.0.2+12-1/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java
--- 24.0.1+9-1/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java	2025-06-27 08:03:14.000000000 +0000
@@ -39,6 +39,7 @@ import java.util.stream.Stream;
  * @bug 8066859
  * @summary Check that AQS-based locks, conditions, and CountDownLatches do not fail when encountering OOME
  * @requires vm.gc.G1
+ * @requires !(vm.graal.enabled & vm.compMode == "Xcomp")
  * @run main/othervm -XX:+UseG1GC -XX:-UseGCOverheadLimit -Xmx48M -XX:-UseTLAB OOMEInAQS
  */
 
diff -pruN 24.0.1+9-1/test/jdk/java/util/concurrent/locks/StampedLock/OOMEInStampedLock.java 24.0.2+12-1/test/jdk/java/util/concurrent/locks/StampedLock/OOMEInStampedLock.java
--- 24.0.1+9-1/test/jdk/java/util/concurrent/locks/StampedLock/OOMEInStampedLock.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/java/util/concurrent/locks/StampedLock/OOMEInStampedLock.java	2025-06-27 08:03:14.000000000 +0000
@@ -38,6 +38,7 @@ import java.util.stream.Stream;
  * @bug 8066859
  * @summary An adaptation of OOMEInAQS test for StampedLocks
  * @requires vm.gc.G1
+ * @requires !(vm.graal.enabled & vm.compMode == "Xcomp")
  * @run main/othervm -XX:+UseG1GC -XX:-UseGCOverheadLimit -Xmx48M -XX:-UseTLAB OOMEInStampedLock
  */
 
diff -pruN 24.0.1+9-1/test/jdk/javax/accessibility/TestJCheckBoxToggleAccessibility.java 24.0.2+12-1/test/jdk/javax/accessibility/TestJCheckBoxToggleAccessibility.java
--- 24.0.1+9-1/test/jdk/javax/accessibility/TestJCheckBoxToggleAccessibility.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/jdk/javax/accessibility/TestJCheckBoxToggleAccessibility.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.BorderLayout;
+import java.awt.GridLayout;
+
+import javax.swing.JCheckBox;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JToggleButton;
+
+/*
+ * @test
+ * @bug 8348936 8345728
+ * @summary Verifies that VoiceOver announces the untick state of CheckBox and
+ *          ToggleButton when space key is pressed. Also verifies that CheckBox
+ *          and ToggleButton untick state is magnified with Screen Magnifier.
+ * @requires os.family == "mac"
+ * @library /java/awt/regtesthelpers
+ * @build PassFailJFrame
+ * @run main/manual TestJCheckBoxToggleAccessibility
+ */
+
+public class TestJCheckBoxToggleAccessibility {
+    public static void main(String[] args) throws Exception {
+        String INSTRUCTIONS = """
+                <html><body>
+                <p><b>Testing with VoiceOver</b></p>
+
+                <ol>
+                  <li>Start the VoiceOver application
+                      (Press <kbd>Command</kbd> + <kbd>F5</kbd>)
+                  <li>Click on the <i>Frame with CheckBox and ToggleButton</i>
+                      window to move focus
+                  <li>Press <kbd>Spacebar</kbd>
+                  <li>VO should announce the checked state
+                  <li>Press <kbd>Spacebar</kbd> again
+                  <li>VO should announce the unchecked state
+                  <li>Press <kbd>Tab</kbd> to move focus to <i>ToggleButton</i>
+                  <li>Repeat steps 3 to 6 and listen the announcement
+                  <li>If announcements are incorrect, press <b>Fail</b>
+                  <li>Stop the VoiceOver application
+                      (Press <kbd>Command</kbd> + <kbd>F5</kbd> again)
+                </ol>
+
+                <p><b>Testing with Screen Magnifier</b></p>
+                <ol style="margin-bottom: 0">
+                  <li>Enable Screen magnifier on the Mac:
+                   <b>System Settings</b> -> <b>Accessibility</b> ->
+                   <b>Hover Text</b> -> Enable <b>Hover Text</b><br>
+                   Default Hover Text Activation Modifier is <kbd>Command</kbd> key
+                  <li>Move focus back to the test application and perform the following tests
+
+                  <ul style="margin-bottom: 0">
+                    <li>Test <i>CheckBox</i> states with Screen Magnifier
+                      <ol style="list-style-type: lower-alpha; margin-top: 0; margin-bottom: 0">
+                        <li>Click on <i>CheckBox</i> to select it
+                        <li>Press the <kbd>Command</kbd> key and
+                            hover mouse over <i>CheckBox</i>
+                        <li>CheckBox ticked state along with its label should be magnified
+                        <li>Keep the <kbd>Command</kbd> key pressed and
+                            click <i>CheckBox</i> to deselect it
+                        <li>CheckBox unticked state along with its label should be magnified
+                        <li>Release the <kbd>Command</kbd> key
+                        <li>If Screen Magnifier behaviour is incorrect, press <b>Fail</b>
+                      </ol>
+                    <li>Test <i>ToggleButton</i> states with Screen Magnifier
+                      <ol style="list-style-type: lower-alpha; margin-top: 0; margin-bottom: 0">
+                        <li>Click on <i>ToggleButton</i> to select it
+                        <li>Press the <kbd>Command</kbd> key and
+                            hover mouse over <i>ToggleButton</i>
+                        <li>Ticked state along with label should be magnified
+                        <li>Keep the <kbd>Command</kbd> button pressed and
+                            click <i>ToggleButton</i> to deselect it
+                        <li>Unticked state along with its label should be magnified
+                        <li>Release the <kbd>Command</kbd> key
+                        <li>If Screen Magnifier behaviour is incorrect, press <b>Fail</b>
+                      </ol>
+                  </ul>
+                  <li>Disable <b>Hover Text</b> (optionally) in the Settings
+                </ol>
+
+                <p>Press <b>Pass</b> if you are able to hear correct VoiceOver announcements and
+                able to see the correct screen magnifier behaviour.</p></body></html>""";
+
+        PassFailJFrame.builder()
+                .title("TestJCheckBoxToggleAccessibility Instruction")
+                .instructions(INSTRUCTIONS)
+                .columns(40)
+                .rows(25)
+                .testUI(TestJCheckBoxToggleAccessibility::createUI)
+                .testTimeOut(8)
+                .build()
+                .awaitAndCheck();
+    }
+
+    private static JFrame createUI() {
+        JFrame frame = new JFrame("A Frame with CheckBox and ToggleButton");
+        JCheckBox cb = new JCheckBox("CheckBox", false);
+        JToggleButton tb = new JToggleButton("ToggleButton");
+
+        JPanel p = new JPanel(new GridLayout(2, 1));
+        p.add(cb);
+        p.add(tb);
+        frame.getContentPane().add(p, BorderLayout.CENTER);
+        frame.setSize(400, 400);
+        return frame;
+    }
+}
diff -pruN 24.0.1+9-1/test/jdk/javax/accessibility/TestJSpinnerAccessibility.java 24.0.2+12-1/test/jdk/javax/accessibility/TestJSpinnerAccessibility.java
--- 24.0.1+9-1/test/jdk/javax/accessibility/TestJSpinnerAccessibility.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/jdk/javax/accessibility/TestJSpinnerAccessibility.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.BorderLayout;
+
+import javax.swing.JFrame;
+import javax.swing.JSpinner;
+import javax.swing.SpinnerModel;
+import javax.swing.SpinnerNumberModel;
+
+/*
+ * @test
+ * @bug 8286204
+ * @summary Verifies that VoiceOver announces the JSpinner's value correctly
+ * @requires os.family == "mac"
+ * @library /java/awt/regtesthelpers
+ * @build PassFailJFrame
+ * @run main/manual TestJSpinnerAccessibility
+ */
+
+public class TestJSpinnerAccessibility {
+    public static void main(String[] args) throws Exception {
+        String INSTRUCTIONS = """
+                Test UI contains a JSpinner with minimum value 0, maximum value 20
+                and current value 5. On press of up / down arrow, value will be
+                incremented / decremented by 1.
+
+                Follow these steps to test the behaviour:
+
+                1. Start the VoiceOver (Press Command + F5) application
+                2. Move focus on test window if it is not focused
+                3. Press Up / Down arrow to increase / decrease Spinner value
+                4. VO should announce correct values in terms of percentage
+                   (e.g. For JSpinner's value 10, VO should announce 50%)
+                5. Press Pass if you are able to hear correct announcements
+                   else Fail""";
+
+        PassFailJFrame.builder()
+                .title("TestJSpinnerAccessibility Instruction")
+                .instructions(INSTRUCTIONS)
+                .columns(40)
+                .testUI(TestJSpinnerAccessibility::createUI)
+                .build()
+                .awaitAndCheck();
+    }
+
+    private static JFrame createUI() {
+        JFrame frame = new JFrame("A Frame with JSpinner");
+        SpinnerModel spinnerModel = new SpinnerNumberModel(5, 0, 20, 1);
+        JSpinner spinner = new JSpinner(spinnerModel);
+        frame.getContentPane().add(spinner, BorderLayout.CENTER);
+        frame.setSize(200, 100);
+        return frame;
+    }
+}
diff -pruN 24.0.1+9-1/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpecException.java 24.0.2+12-1/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpecException.java
--- 24.0.1+9-1/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpecException.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKeySpecException.java	2025-06-27 08:03:14.000000000 +0000
@@ -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
@@ -24,19 +24,20 @@
 /**
  * @test
  * @bug 4508341 7055362
- * @library ../../../java/security/testlibrary
+ * @library /test/lib
  * @summary Test the error conditions of
  * EncryptedPrivateKeyInfo.getKeySpec(...) methods.
  * @author Valerie Peng
  * @run main/othervm -DcipherAlg=PBEWithMD5AndDES GetKeySpecException
  * @run main/othervm -DcipherAlg=PBEWithSHA1AndDESede GetKeySpecException
  */
+
 import java.security.*;
-import java.util.Arrays;
 import java.util.Vector;
 import java.security.spec.*;
 import javax.crypto.*;
 import javax.crypto.spec.*;
+import jdk.test.lib.security.ProvidersSnapshot;
 
 public class GetKeySpecException {
     private static String cipherAlg;
diff -pruN 24.0.1+9-1/test/jdk/javax/crypto/JceSecurity/SunJCE_BC_LoadOrdering.java 24.0.2+12-1/test/jdk/javax/crypto/JceSecurity/SunJCE_BC_LoadOrdering.java
--- 24.0.1+9-1/test/jdk/javax/crypto/JceSecurity/SunJCE_BC_LoadOrdering.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/javax/crypto/JceSecurity/SunJCE_BC_LoadOrdering.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 6377058 7055362
- * @library ../../../java/security/testlibrary
+ * @library /test/lib
  * @summary SunJCE depends on sun.security.provider.SignatureImpl
  * behaviour, BC can't load into 1st slot.
  * @author Brad R. Wetmore
@@ -33,7 +33,7 @@
 
 import java.security.*;
 import javax.crypto.*;
-import java.io.*;
+import jdk.test.lib.security.ProvidersSnapshot;
 
 public class SunJCE_BC_LoadOrdering {
 
diff -pruN 24.0.1+9-1/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java 24.0.2+12-1/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java
--- 24.0.1+9-1/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -28,8 +28,7 @@
  * @test
  * @bug 8046321 8153829
  * @summary OCSP Stapling for TLS
- * @library ../../../../java/security/testlibrary
- * @build CertificateBuilder SimpleOCSPServer
+ * @library /test/lib
  * @run main/othervm HttpsUrlConnClient RSA SHA256withRSA
  * @run main/othervm HttpsUrlConnClient RSASSA-PSS RSASSA-PSS
  */
@@ -59,8 +58,8 @@ import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 
-import sun.security.testlibrary.SimpleOCSPServer;
-import sun.security.testlibrary.CertificateBuilder;
+import jdk.test.lib.security.SimpleOCSPServer;
+import jdk.test.lib.security.CertificateBuilder;
 
 public class HttpsUrlConnClient {
 
diff -pruN 24.0.1+9-1/test/jdk/javax/net/ssl/Stapling/SSLEngineWithStapling.java 24.0.2+12-1/test/jdk/javax/net/ssl/Stapling/SSLEngineWithStapling.java
--- 24.0.1+9-1/test/jdk/javax/net/ssl/Stapling/SSLEngineWithStapling.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/javax/net/ssl/Stapling/SSLEngineWithStapling.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -28,8 +28,7 @@
  * @test
  * @bug 8046321 8153829
  * @summary OCSP Stapling for TLS
- * @library ../../../../java/security/testlibrary
- * @build CertificateBuilder SimpleOCSPServer
+ * @library /test/lib
  * @run main/othervm SSLEngineWithStapling
  */
 
@@ -87,8 +86,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
-import sun.security.testlibrary.SimpleOCSPServer;
-import sun.security.testlibrary.CertificateBuilder;
+import jdk.test.lib.security.SimpleOCSPServer;
+import jdk.test.lib.security.CertificateBuilder;
 
 public class SSLEngineWithStapling {
 
diff -pruN 24.0.1+9-1/test/jdk/javax/net/ssl/Stapling/SSLSocketWithStapling.java 24.0.2+12-1/test/jdk/javax/net/ssl/Stapling/SSLSocketWithStapling.java
--- 24.0.1+9-1/test/jdk/javax/net/ssl/Stapling/SSLSocketWithStapling.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/javax/net/ssl/Stapling/SSLSocketWithStapling.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -28,8 +28,7 @@
  * @test
  * @bug 8046321 8153829
  * @summary OCSP Stapling for TLS
- * @library ../../../../java/security/testlibrary
- * @build CertificateBuilder SimpleOCSPServer
+ * @library /test/lib
  * @run main/othervm SSLSocketWithStapling
  */
 
@@ -63,8 +62,8 @@ import java.util.Map;
 import java.util.HashMap;
 import java.util.concurrent.TimeUnit;
 
-import sun.security.testlibrary.SimpleOCSPServer;
-import sun.security.testlibrary.CertificateBuilder;
+import jdk.test.lib.security.SimpleOCSPServer;
+import jdk.test.lib.security.CertificateBuilder;
 
 public class SSLSocketWithStapling {
 
diff -pruN 24.0.1+9-1/test/jdk/javax/net/ssl/Stapling/StapleEnableProps.java 24.0.2+12-1/test/jdk/javax/net/ssl/Stapling/StapleEnableProps.java
--- 24.0.1+9-1/test/jdk/javax/net/ssl/Stapling/StapleEnableProps.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/javax/net/ssl/Stapling/StapleEnableProps.java	2025-06-27 08:03:14.000000000 +0000
@@ -28,8 +28,7 @@
  * @test
  * @bug 8145854 8153829
  * @summary SSLContextImpl.statusResponseManager should be generated if required
- * @library ../../../../java/security/testlibrary
- * @build CertificateBuilder SimpleOCSPServer
+ * @library /test/lib
  * @run main/othervm StapleEnableProps
  */
 
@@ -49,8 +48,8 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 
-import sun.security.testlibrary.SimpleOCSPServer;
-import sun.security.testlibrary.CertificateBuilder;
+import jdk.test.lib.security.SimpleOCSPServer;
+import jdk.test.lib.security.CertificateBuilder;
 
 public class StapleEnableProps {
 
diff -pruN 24.0.1+9-1/test/jdk/javax/print/attribute/PageRangesException.java 24.0.2+12-1/test/jdk/javax/print/attribute/PageRangesException.java
--- 24.0.1+9-1/test/jdk/javax/print/attribute/PageRangesException.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/jdk/javax/print/attribute/PageRangesException.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2001, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.print.attribute.standard.PageRanges;
+
+/*
+ * @test
+ * @bug 4433126 4433096
+ * @key printer
+ * @summary  The line "ERROR: <message>" should NOT appear.
+ * @run main PageRangesException
+ */
+
+public class PageRangesException {
+    public static void main(String[] args) throws Exception {
+        // test 4433126
+        try {
+            PageRanges pr = new PageRanges("0:22");
+            throw new RuntimeException("ERROR: no exceptions");
+        } catch (IllegalArgumentException ie) {
+            System.out.println("OKAY: IllegalArgumentException " + ie);
+        }
+
+        // test 4433096
+        try {
+            int[][] m = null;
+            PageRanges pr = new PageRanges(m);
+            throw new RuntimeException("ERROR: NullPointerException expected");
+        } catch (IllegalArgumentException ie) {
+            throw new RuntimeException("ERROR: IllegalArgumentException", ie);
+        } catch (NullPointerException e) {
+            System.out.println("OKAY: NullPointerException");
+        }
+    }
+}
diff -pruN 24.0.1+9-1/test/jdk/javax/swing/AbstractButton/bug6298940.java 24.0.2+12-1/test/jdk/javax/swing/AbstractButton/bug6298940.java
--- 24.0.1+9-1/test/jdk/javax/swing/AbstractButton/bug6298940.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/jdk/javax/swing/AbstractButton/bug6298940.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,93 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6298940
+ * @key headful
+ * @summary Tests that mnemonic keystroke fires an action
+ * @library /javax/swing/regtesthelpers
+ * @build Util
+ * @run main bug6298940
+ */
+
+import java.awt.Robot;
+import java.awt.event.KeyEvent;
+import java.util.concurrent.CountDownLatch;
+
+import javax.swing.ButtonModel;
+import javax.swing.DefaultButtonModel;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+public final class bug6298940 {
+    private static JFrame frame;
+
+    private static final CountDownLatch actionEvent = new CountDownLatch(1);
+
+    private static void createAndShowGUI() {
+        ButtonModel model = new DefaultButtonModel();
+        model.addActionListener(event -> {
+            System.out.println("ActionEvent");
+            actionEvent.countDown();
+        });
+        model.setMnemonic('T');
+
+        JButton button = new JButton("Test");
+        button.setModel(model);
+
+        frame = new JFrame("bug6298940");
+        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        frame.add(button);
+        frame.pack();
+        frame.setLocationRelativeTo(null);
+        frame.setVisible(true);
+        frame.toFront();
+    }
+
+    public static void main(String[] args) throws Exception {
+        Robot robot = new Robot();
+
+        SwingUtilities.invokeAndWait(bug6298940::createAndShowGUI);
+
+        robot.waitForIdle();
+        robot.delay(500);
+
+        Util.hitMnemonics(robot, KeyEvent.VK_T);
+
+        try {
+            if (!actionEvent.await(1, SECONDS)) {
+                throw new RuntimeException("Mnemonic didn't fire an action");
+            }
+        } finally {
+            SwingUtilities.invokeAndWait(() -> {
+                if (frame != null) {
+                    frame.dispose();
+                }
+            });
+        }
+    }
+}
diff -pruN 24.0.1+9-1/test/jdk/javax/swing/JMenu/4213634/bug4213634.java 24.0.2+12-1/test/jdk/javax/swing/JMenu/4213634/bug4213634.java
--- 24.0.1+9-1/test/jdk/javax/swing/JMenu/4213634/bug4213634.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/javax/swing/JMenu/4213634/bug4213634.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -21,103 +21,91 @@
  * questions.
  */
 
-import java.awt.AWTException;
 import java.awt.Robot;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.awt.event.KeyEvent;
-import java.lang.reflect.InvocationTargetException;
 import javax.swing.JButton;
 import javax.swing.JFrame;
 import javax.swing.JMenu;
 import javax.swing.JMenuBar;
 import javax.swing.JMenuItem;
-import javax.swing.JTextArea;
 import javax.swing.SwingUtilities;
 
 /*
  * @test
  * @key headful
  * @bug 4213634 8017187
- * @author Scott Violet
  * @library ../../regtesthelpers
  * @build Util
+ * @summary Verifies if Alt+mnemonic char works when
+ *          menu & menuitem have same mnemonic char
  * @run main bug4213634
  */
 
-
 public class bug4213634 {
 
-    private JMenu menu;
-
-    private JFrame frame;
-
-    public static void main(String[] args) throws Throwable {
-        new bug4213634();
-    }
-
-    bug4213634() throws AWTException, InterruptedException, InvocationTargetException {
-        SwingUtilities.invokeAndWait(new Runnable() {
-            @Override
-            public void run() {
-                createAndShowGUI();
-            }
-        });
-
-        test();
+    private static JMenu menu;
+    private static JFrame frame;
+    private static Robot robot;
+
+    public static void main(String[] args) throws Exception {
+        try {
+            robot = new Robot();
+            SwingUtilities.invokeAndWait(bug4213634::createAndShowGUI);
+
+            robot.waitForIdle();
+            robot.delay(1000);
+            test();
+        } finally {
+            SwingUtilities.invokeAndWait(() -> {
+                if (frame != null) {
+                    frame.dispose();
+                }
+            });
+        }
     }
 
-    public  void createAndShowGUI() {
-        frame = new JFrame("TEST");
+    public static void createAndShowGUI() {
+        frame = new JFrame("bug4213634");
         JMenuBar mb = new JMenuBar();
         menu = mb.add(createMenu("1 - First Menu", true));
         mb.add(createMenu("2 - Second Menu", false));
         frame.setJMenuBar(mb);
-        JTextArea ta = new JTextArea("This test dedicated to Nancy and Kathleen, testers and bowlers extraordinaire\n\n\nNo exception means pass.");
-        frame.getContentPane().add("Center", ta);
         JButton button = new JButton("Test");
         frame.getContentPane().add("South", button);
-        frame.setBounds(100, 100, 400, 400);
+        frame.setSize(300, 300);
+        frame.setLocationRelativeTo(null);
         frame.setVisible(true);
         button.requestFocusInWindow();
     }
 
-    private void test() throws AWTException, InterruptedException, InvocationTargetException {
-        Robot robot = new Robot();
-        robot.setAutoDelay(50);
-        robot.waitForIdle();
-
+    private static void test() throws Exception {
         Util.hitMnemonics(robot, KeyEvent.VK_1);
         robot.waitForIdle();
+        robot.delay(100);
 
-        SwingUtilities.invokeAndWait(new Runnable() {
-            @Override
-            public void run() {
-                if (!menu.isSelected()) {
-                    throw new RuntimeException(
-                        "Failed: Menu didn't remain posted at end of test");
-                } else {
-                    System.out.println("Test passed!");
-                    frame.dispose();
-                }
+        SwingUtilities.invokeAndWait(() -> {
+            if (!menu.isSelected()) {
+                throw new RuntimeException(
+                    "Failed: Menu didn't remain posted at end of test");
+            } else {
+                System.out.println("Test passed!");
             }
         });
     }
-    private JMenu createMenu(String str, boolean bFlag) {
+
+    private static JMenu createMenu(String str, boolean bFlag) {
         JMenuItem menuitem;
         JMenu menu = new JMenu(str);
         menu.setMnemonic(str.charAt(0));
 
-        for(int i = 0; i < 10; i ++) {
+        for (int i = 0; i < 10; i++) {
             menuitem = new JMenuItem("JMenuItem" + i);
-            menuitem.addActionListener(new ActionListener() {
-                public void actionPerformed(ActionEvent e) {
-                    throw new RuntimeException(
-                        "Failed: Mnemonic activated");
-                }
+            menuitem.addActionListener(e -> {
+                throw new RuntimeException("Failed: Mnemonic activated");
             });
-            if(bFlag)
+            if (bFlag) {
                 menuitem.setMnemonic('0' + i);
+            }
             menu.add(menuitem);
         }
         return menu;
diff -pruN 24.0.1+9-1/test/jdk/javax/swing/JRadioButton/ButtonGroupFocus/ButtonGroupFocusTest.java 24.0.2+12-1/test/jdk/javax/swing/JRadioButton/ButtonGroupFocus/ButtonGroupFocusTest.java
--- 24.0.1+9-1/test/jdk/javax/swing/JRadioButton/ButtonGroupFocus/ButtonGroupFocusTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/javax/swing/JRadioButton/ButtonGroupFocus/ButtonGroupFocusTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -28,26 +28,53 @@
  * @run main ButtonGroupFocusTest
  */
 
-import javax.swing.*;
-import java.awt.*;
+import java.awt.AWTEvent;
+import java.awt.Container;
+import java.awt.FlowLayout;
+import java.awt.KeyboardFocusManager;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.Toolkit;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
 import java.awt.event.KeyEvent;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.util.concurrent.CountDownLatch;
+
+import javax.imageio.ImageIO;
+import javax.swing.ButtonGroup;
+import javax.swing.JFrame;
+import javax.swing.JRadioButton;
+import javax.swing.SwingUtilities;
+
+import static java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
 
-public class ButtonGroupFocusTest {
+public final class ButtonGroupFocusTest {
 
     private static JRadioButton button1;
     private static JRadioButton button2;
     private static JRadioButton button3;
     private static JRadioButton button4;
     private static JRadioButton button5;
-    private static Robot robot;
+
+    private static final CountDownLatch button2FocusLatch = new CountDownLatch(1);
+    private static final CountDownLatch button3FocusLatch = new CountDownLatch(1);
+    private static final CountDownLatch button4FocusLatch = new CountDownLatch(1);
+
+    private static final CountDownLatch button2FocusLatch2 = new CountDownLatch(2);
+
+    private static final long FOCUS_TIMEOUT = 4;
+
     private static JFrame frame;
 
     public static void main(String[] args) throws Exception {
-        robot = new Robot();
-        robot.setAutoDelay(100);
+        final Robot robot = new Robot();
 
         SwingUtilities.invokeAndWait(() -> {
-            frame = new JFrame();
+            frame = new JFrame("ButtonGroupFocusTest");
             Container contentPane = frame.getContentPane();
             contentPane.setLayout(new FlowLayout());
             button1 = new JRadioButton("Button 1");
@@ -60,6 +87,7 @@ public class ButtonGroupFocusTest {
             contentPane.add(button4);
             button5 = new JRadioButton("Button 5");
             contentPane.add(button5);
+
             ButtonGroup group = new ButtonGroup();
             group.add(button1);
             group.add(button2);
@@ -69,52 +97,96 @@ public class ButtonGroupFocusTest {
             group.add(button4);
             group.add(button5);
 
+            button2.addFocusListener(new LatchFocusListener(button2FocusLatch));
+            button3.addFocusListener(new LatchFocusListener(button3FocusLatch));
+            button4.addFocusListener(new LatchFocusListener(button4FocusLatch));
+
+            button2.addFocusListener(new LatchFocusListener(button2FocusLatch2));
+
             button2.setSelected(true);
 
+            // Debugging aid: log focus owner changes...
+            KeyboardFocusManager focusManager = getCurrentKeyboardFocusManager();
+            focusManager.addPropertyChangeListener("focusOwner",
+                    e -> System.out.println(e.getPropertyName()
+                                            + "\n\t" + e.getOldValue()
+                                            + "\n\t" + e.getNewValue()));
+
+            // ...and dispatched key events
+            Toolkit.getDefaultToolkit().addAWTEventListener(
+                    e -> System.out.println("Dispatched " + e),
+                    AWTEvent.KEY_EVENT_MASK);
+
             frame.pack();
+            frame.setLocationRelativeTo(null);
             frame.setVisible(true);
         });
 
-        robot.waitForIdle();
-        robot.delay(200);
-
-        SwingUtilities.invokeAndWait(() -> {
-            if( !button2.hasFocus() ) {
-                frame.dispose();
-                throw new RuntimeException(
-                        "Button 2 should get focus after activation");
+        try {
+            if (!button2FocusLatch.await(FOCUS_TIMEOUT, SECONDS)) {
+                throw new RuntimeException("Button 2 should get focus "
+                                           + "after activation");
             }
-        });
+            robot.waitForIdle();
+            robot.delay(200);
 
-        robot.keyPress(KeyEvent.VK_TAB);
-        robot.keyRelease(KeyEvent.VK_TAB);
+            System.out.println("\n\n*** Tab 1st");
+            robot.keyPress(KeyEvent.VK_TAB);
+            robot.keyRelease(KeyEvent.VK_TAB);
 
-        robot.waitForIdle();
-        robot.delay(200);
-
-        SwingUtilities.invokeAndWait(() -> {
-            if( !button4.hasFocus() ) {
-                frame.dispose();
-                throw new RuntimeException(
-                        "Button 4 should get focus");
+            if (!button4FocusLatch.await(FOCUS_TIMEOUT, SECONDS)) {
+                throw new RuntimeException("Button 4 should get focus");
             }
-            button3.setSelected(true);
-        });
+            robot.waitForIdle();
+            robot.delay(200);
 
-        robot.keyPress(KeyEvent.VK_TAB);
-        robot.keyRelease(KeyEvent.VK_TAB);
+            if (button2FocusLatch2.await(1, MILLISECONDS)) {
+                throw new RuntimeException("Focus moved back to Button 2");
+            }
 
-        robot.waitForIdle();
-        robot.delay(200);
+            SwingUtilities.invokeAndWait(() -> button3.setSelected(true));
+            robot.waitForIdle();
+            robot.delay(200);
+
+            System.out.println("\n\n*** Tab 2nd");
+            robot.keyPress(KeyEvent.VK_TAB);
+            robot.keyRelease(KeyEvent.VK_TAB);
 
-        SwingUtilities.invokeAndWait(() -> {
-            if( !button3.hasFocus() ) {
-                frame.dispose();
-                throw new RuntimeException(
-                        "selected Button 3 should get focus");
+            if (!button3FocusLatch.await(FOCUS_TIMEOUT, SECONDS)) {
+                throw new RuntimeException("Selected Button 3 should get focus");
             }
-        });
+        } catch (Exception e) {
+            BufferedImage image = robot.createScreenCapture(getFrameBounds());
+            ImageIO.write(image, "png",
+                          new File("image.png"));
+
+            SwingUtilities.invokeAndWait(() ->
+                    System.err.println("Current focus owner: "
+                                       + getCurrentKeyboardFocusManager()
+                                         .getFocusOwner()));
+
+            throw e;
+        } finally {
+            SwingUtilities.invokeAndWait(frame::dispose);
+        }
+    }
+
+    private static Rectangle getFrameBounds() throws Exception {
+        Rectangle[] bounds = new Rectangle[1];
+        SwingUtilities.invokeAndWait(() -> bounds[0] = frame.getBounds());
+        return bounds[0];
+    }
+
+    private static final class LatchFocusListener extends FocusAdapter {
+        private final CountDownLatch focusGainedLatch;
 
-        SwingUtilities.invokeLater(frame::dispose);
+        private LatchFocusListener(CountDownLatch focusGainedLatch) {
+            this.focusGainedLatch = focusGainedLatch;
+        }
+
+        @Override
+        public void focusGained(FocusEvent e) {
+            focusGainedLatch.countDown();
+        }
     }
 }
diff -pruN 24.0.1+9-1/test/jdk/javax/swing/JTabbedPane/8134116/Bug8134116.java 24.0.2+12-1/test/jdk/javax/swing/JTabbedPane/8134116/Bug8134116.java
--- 24.0.1+9-1/test/jdk/javax/swing/JTabbedPane/8134116/Bug8134116.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/javax/swing/JTabbedPane/8134116/Bug8134116.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,13 +1,43 @@
+/*
+ * Copyright (c) 2015, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
 
-import java.awt.*;
+import java.awt.Component;
+import java.awt.Rectangle;
 import java.awt.event.KeyEvent;
 import java.util.ArrayList;
 import java.util.List;
+
 import javax.accessibility.Accessible;
 import javax.accessibility.AccessibleContext;
 import javax.accessibility.AccessibleState;
 import javax.accessibility.AccessibleStateSet;
-import javax.swing.*;
+import javax.swing.Icon;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
 import javax.swing.plaf.nimbus.NimbusLookAndFeel;
 
 /*
@@ -22,7 +52,7 @@ public class Bug8134116 {
     private static volatile Exception exception = null;
     private static JFrame frame;
 
-    public static void main(String args[]) throws Exception {
+    public static void main(String[] args) throws Exception {
 
         try {
             UIManager.setLookAndFeel(new NimbusLookAndFeel());
diff -pruN 24.0.1+9-1/test/jdk/jdk/internal/platform/cgroup/CgroupV1SubsystemControllerTest.java 24.0.2+12-1/test/jdk/jdk/internal/platform/cgroup/CgroupV1SubsystemControllerTest.java
--- 24.0.1+9-1/test/jdk/jdk/internal/platform/cgroup/CgroupV1SubsystemControllerTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/jdk/internal/platform/cgroup/CgroupV1SubsystemControllerTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Red Hat, Inc.
+ * Copyright (c) 2022, 2025, Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -64,6 +64,9 @@ public class CgroupV1SubsystemController
         assertEquals(expectedPath, ctrl.path());
     }
 
+    /*
+     * Less common cases: Containers
+     */
     @Test
     public void testCgPathSubstring() {
         String root = "/foo/bar/baz";
@@ -71,8 +74,18 @@ public class CgroupV1SubsystemController
         CgroupV1SubsystemController ctrl = new CgroupV1SubsystemController(root, mountPoint);
         String cgroupPath = "/foo/bar/baz/some";
         ctrl.setPath(cgroupPath);
-        String expectedPath = mountPoint + "/some";
+        String expectedPath = mountPoint;
         assertEquals(expectedPath, ctrl.path());
     }
 
+    @Test
+    public void testCgPathToMovedPath() {
+        String root = "/system.slice/garden.service/garden/good/2f57368b-0eda-4e52-64d8-af5c";
+        String mountPoint = "/sys/fs/cgroup/cpu,cpuacct";
+        CgroupV1SubsystemController ctrl = new CgroupV1SubsystemController(root, mountPoint);
+        String cgroupPath = "/system.slice/garden.service/garden/bad/2f57368b-0eda-4e52-64d8-af5c";
+        ctrl.setPath(cgroupPath);
+        String expectedPath = mountPoint;
+        assertEquals(expectedPath, ctrl.path());
+    }
 }
diff -pruN 24.0.1+9-1/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java 24.0.2+12-1/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java
--- 24.0.1+9-1/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, 2022, Red Hat Inc.
+ * Copyright (c) 2020, 2025, Red Hat Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,7 @@ import jdk.internal.platform.CgroupSubsy
 import jdk.internal.platform.CgroupSubsystemFactory.CgroupTypeResult;
 import jdk.internal.platform.CgroupV1MetricsImpl;
 import jdk.internal.platform.cgroupv1.CgroupV1Subsystem;
+import jdk.internal.platform.cgroupv1.CgroupV1SubsystemController;
 import jdk.internal.platform.Metrics;
 import jdk.test.lib.Utils;
 import jdk.test.lib.util.FileUtils;
@@ -75,8 +76,10 @@ public class TestCgroupSubsystemFactory
     private Path cgroupv1MntInfoDoubleControllers;
     private Path cgroupv1MntInfoDoubleControllers2;
     private Path cgroupv1MntInfoColonsHierarchy;
+    private Path cgroupv1MntInfoNonTrivialRoot;
     private Path cgroupv1SelfCgroup;
     private Path cgroupv1SelfColons;
+    private Path cgroupv1SelfNonTrivialRoot;
     private Path cgroupv2SelfCgroup;
     private Path cgroupv1SelfCgroupJoinCtrl;
     private Path cgroupv1CgroupsOnlyCPUCtrl;
@@ -175,6 +178,7 @@ public class TestCgroupSubsystemFactory
             "42 30 0:38 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:14 - cgroup none rw,seclabel,cpuset\n" +
             "43 30 0:39 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup none rw,seclabel,blkio\n" +
             "44 30 0:40 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:16 - cgroup none rw,seclabel,freezer\n";
+    private String mntInfoNonTrivialRoot = "2207 2196 0:43 /system.slice/garden.service/garden/good/2f57368b-0eda-4e52-64d8-af5c /sys/fs/cgroup/cpu,cpuacct ro,nosuid,nodev,noexec,relatime master:25 - cgroup cgroup rw,cpu,cpuacct\n";
     private String cgroupsNonZeroHierarchy =
             "#subsys_name hierarchy   num_cgroups enabled\n" +
             "cpuset  9   1   1\n" +
@@ -230,6 +234,7 @@ public class TestCgroupSubsystemFactory
             "2:cpu,cpuacct:/\n" +
             "1:name=systemd:/user.slice/user-1000.slice/user@1000.service/apps.slice/apps-org.gnome.Terminal.slice/vte-spawn-3c00b338-5b65-439f-8e97-135e183d135d.scope\n" +
             "0::/user.slice/user-1000.slice/user@1000.service/apps.slice/apps-org.gnome.Terminal.slice/vte-spawn-3c00b338-5b65-439f-8e97-135e183d135d.scope\n";
+    private String cgroupv1SelfNTRoot = "11:cpu,cpuacct:/system.slice/garden.service/garden/bad/2f57368b-0eda-4e52-64d8-af5c\n";
     private String cgroupv2SelfCgroupContent = "0::/user.slice/user-1000.slice/session-2.scope";
 
     // We have a mix of V1 and V2 controllers, but none of the V1 controllers
@@ -294,12 +299,18 @@ public class TestCgroupSubsystemFactory
             cgroupv1MntInfoColonsHierarchy = Paths.get(existingDirectory.toString(), "mountinfo_colons");
             Files.writeString(cgroupv1MntInfoColonsHierarchy, mntInfoColons);
 
+            cgroupv1MntInfoNonTrivialRoot = Paths.get(existingDirectory.toString(), "mountinfo_nt_root");
+            Files.writeString(cgroupv1MntInfoNonTrivialRoot, mntInfoNonTrivialRoot);
+
             cgroupv1SelfCgroup = Paths.get(existingDirectory.toString(), "self_cgroup_cgv1");
             Files.writeString(cgroupv1SelfCgroup, cgroupv1SelfCgroupContent);
 
             cgroupv1SelfColons = Paths.get(existingDirectory.toString(), "self_colons_cgv1");
             Files.writeString(cgroupv1SelfColons, cgroupv1SelfColonsContent);
 
+            cgroupv1SelfNonTrivialRoot = Paths.get(existingDirectory.toString(), "self_nt_root_cgv1");
+            Files.writeString(cgroupv1SelfNonTrivialRoot, cgroupv1SelfNTRoot);
+
             cgroupv2SelfCgroup = Paths.get(existingDirectory.toString(), "self_cgroup_cgv2");
             Files.writeString(cgroupv2SelfCgroup, cgroupv2SelfCgroupContent);
 
@@ -450,6 +461,27 @@ public class TestCgroupSubsystemFactory
     }
 
     @Test
+    public void testMountPrefixCgroupsV1() throws IOException {
+        String cgroups = cgroupv1CgInfoNonZeroHierarchy.toString();
+        String mountInfo = cgroupv1MntInfoNonTrivialRoot.toString();
+        String selfCgroup = cgroupv1SelfNonTrivialRoot.toString();
+        Optional<CgroupTypeResult> result = CgroupSubsystemFactory.determineType(mountInfo, cgroups, selfCgroup);
+
+        assertTrue("Expected non-empty cgroup result", result.isPresent());
+        CgroupTypeResult res = result.get();
+        CgroupInfo cpuInfo = res.getInfos().get("cpu");
+        assertEquals(cpuInfo.getCgroupPath(), "/system.slice/garden.service/garden/bad/2f57368b-0eda-4e52-64d8-af5c");
+        String expectedMountPoint = "/sys/fs/cgroup/cpu,cpuacct";
+        assertEquals(expectedMountPoint, cpuInfo.getMountPoint());
+        CgroupV1SubsystemController cgroupv1MemoryController = new CgroupV1SubsystemController(cpuInfo.getMountRoot(), cpuInfo.getMountPoint());
+        cgroupv1MemoryController.setPath(cpuInfo.getCgroupPath());
+        String actualPath = cgroupv1MemoryController.path();
+        assertNotNull(actualPath);
+        String expectedPath = expectedMountPoint;
+        assertEquals("Should be equal to the mount point path", expectedPath, actualPath);
+    }
+
+    @Test
     public void testZeroHierarchyCgroupsV1() throws IOException {
         String cgroups = cgroupv1CgInfoZeroHierarchy.toString();
         String mountInfo = cgroupv1MntInfoZeroHierarchy.toString();
diff -pruN 24.0.1+9-1/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java 24.0.2+12-1/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java
--- 24.0.1+9-1/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2025, BELLSOFT. 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.internal.platform.Metrics;
+import jdk.test.lib.Utils;
+import jdk.test.lib.containers.docker.Common;
+import jdk.test.lib.containers.docker.DockerfileConfig;
+import jdk.test.lib.containers.docker.DockerRunOptions;
+import jdk.test.lib.containers.docker.DockerTestUtils;
+
+import java.util.ArrayList;
+
+import jtreg.SkippedException;
+
+/*
+ * @test
+ * @bug 8343191
+ * @key cgroups
+ * @summary Cgroup v1 subsystem fails to set subsystem path
+ * @requires container.support
+ * @library /test/lib
+ * @modules java.base/jdk.internal.platform
+ * @build MetricsMemoryTester
+ * @run main TestDockerMemoryMetricsSubgroup
+ */
+
+public class TestDockerMemoryMetricsSubgroup {
+    private static final String imageName =
+            DockerfileConfig.getBaseImageName() + ":" +
+            DockerfileConfig.getBaseImageVersion();
+
+    public static void main(String[] args) throws Exception {
+        Metrics metrics = Metrics.systemMetrics();
+        if (metrics == null) {
+            System.out.println("Cgroup not configured.");
+            return;
+        }
+        if (!DockerTestUtils.canTestDocker()) {
+            System.out.println("Unable to run docker tests.");
+            return;
+        }
+        if ("cgroupv1".equals(metrics.getProvider())) {
+            testMemoryLimitSubgroupV1("200m", "400m", false);
+            testMemoryLimitSubgroupV1("500m", "1G", false);
+            testMemoryLimitSubgroupV1("200m", "400m", true);
+            testMemoryLimitSubgroupV1("500m", "1G", true);
+        } else if ("cgroupv2".equals(metrics.getProvider())) {
+            testMemoryLimitSubgroupV2("200m", "400m", false);
+            testMemoryLimitSubgroupV2("500m", "1G", false);
+            testMemoryLimitSubgroupV2("200m", "400m", true);
+            testMemoryLimitSubgroupV2("500m", "1G", true);
+        } else {
+            throw new SkippedException("Metrics are from neither cgroup v1 nor v2, skipped for now.");
+        }
+    }
+
+    private static void testMemoryLimitSubgroupV1(String innerSize, String outerGroupMemorySize, boolean privateNamespace) throws Exception {
+        Common.logNewTestCase("testMemoryLimitSubgroup, innerSize = " + innerSize);
+        DockerRunOptions opts =
+            new DockerRunOptions(imageName, "sh", "-c");
+        opts.javaOpts = new ArrayList<>();
+        opts.appendTestJavaOptions = false;
+        opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/")
+            .addDockerOpts("--volume", Utils.TEST_JDK + ":/jdk")
+            .addDockerOpts("--privileged")
+            .addDockerOpts("--cgroupns=" + (privateNamespace ? "private" : "host"))
+            .addDockerOpts("--memory", outerGroupMemorySize);
+        opts.addClassOptions("mkdir -p /sys/fs/cgroup/memory/test ; " +
+            "echo " + innerSize + " > /sys/fs/cgroup/memory/test/memory.limit_in_bytes ; " +
+            "echo $$ > /sys/fs/cgroup/memory/test/cgroup.procs ; " +
+            "/jdk/bin/java -cp /test-classes/ " +
+            "--add-exports java.base/jdk.internal.platform=ALL-UNNAMED " +
+            "MetricsMemoryTester memory " + innerSize);
+
+        DockerTestUtils.dockerRunJava(opts).shouldHaveExitValue(0).shouldContain("TEST PASSED!!!");
+    }
+
+    private static void testMemoryLimitSubgroupV2(String innerSize, String outerGroupMemorySize, boolean privateNamespace) throws Exception {
+        Common.logNewTestCase("testMemoryLimitSubgroup, innerSize = " + innerSize);
+        DockerRunOptions opts =
+            new DockerRunOptions(imageName, "sh", "-c");
+        opts.javaOpts = new ArrayList<>();
+        opts.appendTestJavaOptions = false;
+        opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/")
+            .addDockerOpts("--volume", Utils.TEST_JDK + ":/jdk")
+            .addDockerOpts("--privileged")
+            .addDockerOpts("--cgroupns=" + (privateNamespace ? "private" : "host"))
+            .addDockerOpts("--memory", outerGroupMemorySize);
+        opts.addClassOptions("mkdir -p /sys/fs/cgroup/memory/test ; " +
+            "echo $$ > /sys/fs/cgroup/memory/test/cgroup.procs ; " +
+            "echo '+memory' > /sys/fs/cgroup/cgroup.subtree_control ; " +
+            "echo '+memory' > /sys/fs/cgroup/memory/cgroup.subtree_control ; " +
+            "echo " + innerSize + " > /sys/fs/cgroup/memory/test/memory.max ; " +
+            "/jdk/bin/java -cp /test-classes/ " +
+            "--add-exports java.base/jdk.internal.platform=ALL-UNNAMED " +
+            "MetricsMemoryTester memory " + innerSize);
+
+        DockerTestUtils.dockerRunJava(opts).shouldHaveExitValue(0).shouldContain("TEST PASSED!!!");
+    }
+}
diff -pruN 24.0.1+9-1/test/jdk/jdk/jfr/event/compiler/TestCodeCacheFull.java 24.0.2+12-1/test/jdk/jdk/jfr/event/compiler/TestCodeCacheFull.java
--- 24.0.1+9-1/test/jdk/jdk/jfr/event/compiler/TestCodeCacheFull.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/jdk/jfr/event/compiler/TestCodeCacheFull.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -36,6 +36,7 @@ import jdk.test.whitebox.code.BlobType;
 /**
  * @test TestCodeCacheFull
  * @requires vm.hasJFR
+ * @requires vm.opt.UseCodeCacheFlushing == null | vm.opt.UseCodeCacheFlushing == true
  *
  * @library /test/lib
  * @modules jdk.jfr
diff -pruN 24.0.1+9-1/test/jdk/jdk/jfr/event/gc/collection/TestSystemGC.java 24.0.2+12-1/test/jdk/jdk/jfr/event/gc/collection/TestSystemGC.java
--- 24.0.1+9-1/test/jdk/jdk/jfr/event/gc/collection/TestSystemGC.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/jdk/jfr/event/gc/collection/TestSystemGC.java	2025-06-27 08:03:14.000000000 +0000
@@ -66,12 +66,12 @@ public class TestSystemGC {
             RecordedEvent event2 = events.get(1);
             Events.assertFrame(event2, Runtime.class, "gc");
             Events.assertEventThread(event2, Thread.currentThread());
-            Events.assertField(event1, "invokedConcurrent").isEqual(concurrent);
+            Events.assertField(event2, "invokedConcurrent").isEqual(concurrent);
 
             RecordedEvent event3 = events.get(2);
             // MemoryMXBean.class is an interface so can't assertFrame on it
             Events.assertEventThread(event3, Thread.currentThread());
-            Events.assertField(event1, "invokedConcurrent").isEqual(concurrent);
+            Events.assertField(event3, "invokedConcurrent").isEqual(concurrent);
         }
      }
 }
diff -pruN 24.0.1+9-1/test/jdk/jdk/jfr/event/oldobject/TestSanityDefault.java 24.0.2+12-1/test/jdk/jdk/jfr/event/oldobject/TestSanityDefault.java
--- 24.0.1+9-1/test/jdk/jdk/jfr/event/oldobject/TestSanityDefault.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/jdk/jfr/event/oldobject/TestSanityDefault.java	2025-06-27 08:03:14.000000000 +0000
@@ -35,6 +35,7 @@ import jdk.test.lib.jfr.Events;
  * @test
  * @key jfr
  * @requires vm.hasJFR
+ * @requires vm.flagless
  * @library /test/lib /test/jdk
  * @summary Purpose of this test is to run leak profiler without command line tweaks or WhiteBox hacks until we succeed
  * @run main/othervm -Xmx1G jdk.jfr.event.oldobject.TestSanityDefault
diff -pruN 24.0.1+9-1/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java 24.0.2+12-1/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java
--- 24.0.1+9-1/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 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
@@ -557,6 +557,36 @@
  * @run main/othervm/manual -Djava.security.debug=certpath CAInterop ssltlsrootrsa2022 CRL
  */
 
+/*
+ * @test id=sectigotlsrootr46
+ * @bug 8359170
+ * @summary Interoperability tests with Sectigo Public Server Authentication
+ * Root R46
+ * @library /test/lib
+ * @build jtreg.SkippedException ValidatePathWithURL CAInterop
+ * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop
+ * sectigotlsrootr46 OCSP
+ * @run main/othervm/manual -Djava.security.debug=certpath,ocsp
+ * -Dcom.sun.security.ocsp.useget=false CAInterop sectigotlsrootr46 OCSP
+ * @run main/othervm/manual -Djava.security.debug=certpath CAInterop
+ * sectigotlsrootr46 CRL
+ */
+
+/*
+ * @test id=sectigotlsroote46
+ * @bug 8359170
+ * @summary Interoperability tests with Sectigo Public Server Authentication
+ * Root E46
+ * @library /test/lib
+ * @build jtreg.SkippedException ValidatePathWithURL CAInterop
+ * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop
+ * sectigotlsroote46 OCSP
+ * @run main/othervm/manual -Djava.security.debug=certpath,ocsp
+ * -Dcom.sun.security.ocsp.useget=false CAInterop sectigotlsroote46 OCSP
+ * @run main/othervm/manual -Djava.security.debug=certpath CAInterop
+ * sectigotlsroote46 CRL
+ */
+
 /**
  * Collection of certificate validation tests for interoperability with external CAs.
  * These tests are marked as manual as they depend on external infrastructure and may fail
@@ -742,6 +772,13 @@ public class CAInterop {
                     new CATestURLs("https://test-root-2022-rsa.ssl.com",
                             "https://revoked-root-2022-rsa.ssl.com");
 
+            case "sectigotlsrootr46" ->
+                    new CATestURLs("https://sectigopublicserverauthenticationrootr46-ev.sectigo.com",
+                            "https://sectigopublicserverauthenticationrootr46-ev.sectigo.com:444");
+            case "sectigotlsroote46" ->
+                    new CATestURLs("https://sectigopublicserverauthenticationroote46-ev.sectigo.com",
+                            "https://sectigopublicserverauthenticationroote46-ev.sectigo.com:444");
+
             default -> throw new RuntimeException("No test setup found for: " + alias);
         };
     }
diff -pruN 24.0.1+9-1/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/SectigoCSRootCAs.java 24.0.2+12-1/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/SectigoCSRootCAs.java
--- 24.0.1+9-1/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/SectigoCSRootCAs.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/SectigoCSRootCAs.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8359170
+ * @summary Interoperability tests with Sectigo Public Code Signing Root CAs
+ * @build ValidatePathWithParams
+ * @run main/othervm/manual -Djava.security.debug=ocsp,certpath SectigoCSRootCAs OCSP
+ * @run main/othervm/manual -Djava.security.debug=certpath SectigoCSRootCAs CRL
+ */
+
+public class SectigoCSRootCAs {
+
+    public static void main(String[] args) throws Exception {
+
+        ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
+
+        if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
+            pathValidator.enableCRLCheck();
+        } else {
+            // OCSP check by default
+            pathValidator.enableOCSPCheck();
+        }
+
+        new SectigoCSRootCA_R46().runTest(pathValidator);
+        new SectigoCSRootCA_E46().runTest(pathValidator);
+    }
+}
+
+class SectigoCSRootCA_R46 {
+
+    // Owner: CN=Sectigo Public Code Signing CA R36, O=Sectigo Limited, C=GB
+    // Issuer: CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB
+    // Serial number: 621d6d0c52019e3b9079152089211c0a
+    // Valid from: Sun Mar 21 17:00:00 PDT 2021 until: Fri Mar 21 16:59:59
+    // PDT 2036
+    private static final String INT = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIGGjCCBAKgAwIBAgIQYh1tDFIBnjuQeRUgiSEcCjANBgkqhkiG9w0BAQwFADBW\n" +
+            "MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQD\n" +
+            "EyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwHhcNMjEwMzIy\n" +
+            "MDAwMDAwWhcNMzYwMzIxMjM1OTU5WjBUMQswCQYDVQQGEwJHQjEYMBYGA1UEChMP\n" +
+            "U2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1YmxpYyBDb2RlIFNp\n" +
+            "Z25pbmcgQ0EgUjM2MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAmyud\n" +
+            "U/o1P45gBkNqwM/1f/bIU1MYyM7TbH78WAeVF3llMwsRHgBGRmxDeEDIArCS2VCo\n" +
+            "Vk4Y/8j6stIkmYV5Gej4NgNjVQ4BYoDjGMwdjioXan1hlaGFt4Wk9vT0k2oWJMJj\n" +
+            "L9G//N523hAm4jF4UjrW2pvv9+hdPX8tbbAfI3v0VdJiJPFy/7XwiunD7mBxNtec\n" +
+            "M6ytIdUlh08T2z7mJEXZD9OWcJkZk5wDuf2q52PN43jc4T9OkoXZ0arWZVeffvMr\n" +
+            "/iiIROSCzKoDmWABDRzV/UiQ5vqsaeFaqQdzFf4ed8peNWh1OaZXnYvZQgWx/SXi\n" +
+            "JDRSAolRzZEZquE6cbcH747FHncs/Kzcn0Ccv2jrOW+LPmnOyB+tAfiWu01TPhCr\n" +
+            "9VrkxsHC5qFNxaThTG5j4/Kc+ODD2dX/fmBECELcvzUHf9shoFvrn35XGf2RPaNT\n" +
+            "O2uSZ6n9otv7jElspkfK9qEATHZcodp+R4q2OIypxR//YEb3fkDn3UayWW9bAgMB\n" +
+            "AAGjggFkMIIBYDAfBgNVHSMEGDAWgBQy65Ka/zWWSC8oQEJwIDaRXBeF5jAdBgNV\n" +
+            "HQ4EFgQUDyrLIIcouOxvSK4rVKYpqhekzQwwDgYDVR0PAQH/BAQDAgGGMBIGA1Ud\n" +
+            "EwEB/wQIMAYBAf8CAQAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwGwYDVR0gBBQwEjAG\n" +
+            "BgRVHSAAMAgGBmeBDAEEATBLBgNVHR8ERDBCMECgPqA8hjpodHRwOi8vY3JsLnNl\n" +
+            "Y3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ1Jvb3RSNDYuY3JsMHsG\n" +
+            "CCsGAQUFBwEBBG8wbTBGBggrBgEFBQcwAoY6aHR0cDovL2NydC5zZWN0aWdvLmNv\n" +
+            "bS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdSb290UjQ2LnA3YzAjBggrBgEFBQcw\n" +
+            "AYYXaHR0cDovL29jc3Auc2VjdGlnby5jb20wDQYJKoZIhvcNAQEMBQADggIBAAb/\n" +
+            "guF3YzZue6EVIJsT/wT+mHVEYcNWlXHRkT+FoetAQLHI1uBy/YXKZDk8+Y1LoNqH\n" +
+            "rp22AKMGxQtgCivnDHFyAQ9GXTmlk7MjcgQbDCx6mn7yIawsppWkvfPkKaAQsiqa\n" +
+            "T9DnMWBHVNIabGqgQSGTrQWo43MOfsPynhbz2Hyxf5XWKZpRvr3dMapandPfYgoZ\n" +
+            "8iDL2OR3sYztgJrbG6VZ9DoTXFm1g0Rf97Aaen1l4c+w3DC+IkwFkvjFV3jS49ZS\n" +
+            "c4lShKK6BrPTJYs4NG1DGzmpToTnwoqZ8fAmi2XlZnuchC4NPSZaPATHvNIzt+z1\n" +
+            "PHo35D/f7j2pO1S8BCysQDHCbM5Mnomnq5aYcKCsdbh0czchOm8bkinLrYrKpii+\n" +
+            "Tk7pwL7TjRKLXkomm5D1Umds++pip8wH2cQpf93at3VDcOK4N7EwoIJB0kak6pSz\n" +
+            "Eu4I64U6gZs7tS/dGNSljf2OSSnRr7KWzq03zl8l75jy+hOds9TWSenLbjBQUGR9\n" +
+            "6cFr6lEUfAIEHVC1L68Y1GGxx4/eRI82ut83axHMViw1+sVpbPxg51Tbnio1lB93\n" +
+            "079WPFnYaOvfGAA0e0zcfF/M9gXr+korwQTh2Prqooq2bYNMvUoUKD85gnJ+t0sm\n" +
+            "rWrb8dee2CvYZXD5laGtaAxOfy/VKNmwuWuAh9kc\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=Sectigo Limited, O=Sectigo Limited, ST=West Yorkshire, C=GB
+    // Issuer: CN=Sectigo Public Code Signing CA R36, O=Sectigo Limited, C=GB
+    // Serial number: c1de046377578f1605414f3fa91bf5f6
+    // Valid from: Wed Jun 04 17:00:00 PDT 2025 until: Fri Jun 05 16:59:59
+    // PDT 2026
+    private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIGRDCCBKygAwIBAgIRAMHeBGN3V48WBUFPP6kb9fYwDQYJKoZIhvcNAQEMBQAw\n" +
+            "VDELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDErMCkGA1UE\n" +
+            "AxMiU2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIENBIFIzNjAeFw0yNTA2MDUw\n" +
+            "MDAwMDBaFw0yNjA2MDUyMzU5NTlaMFoxCzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5X\n" +
+            "ZXN0IFlvcmtzaGlyZTEYMBYGA1UECgwPU2VjdGlnbyBMaW1pdGVkMRgwFgYDVQQD\n" +
+            "DA9TZWN0aWdvIExpbWl0ZWQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\n" +
+            "AQDCYjakgsoYkqVpENW0MuN5hBZDdIM60WJgBXU7zTAXORntSu/Grn/SQywwTg4o\n" +
+            "ltRcKuCp0Cd5zLAIjtgpVDDACWHgxKUtxerjjBZeGp0+viR+biLL0mVNPXgZZ5bQ\n" +
+            "AnDYVKJaGnPsXQD8l+Bn/R2c4cw7mXjBYp2KrTuqOBkPzk4LmdgpKXjxiw1yYb+n\n" +
+            "WKZ+3BMLIU6/k+LB9+WB6Odrl4Lff1jB4C6XhQELGjZAbpkFB2+Qr0ajIA3ZFXqU\n" +
+            "IMh0j5oD5juuXxryOvCgSBkEwxPHnlXxZBNd3DmrZ9NGClBIGE2f9FOjzo5Rl7lV\n" +
+            "KlzFdFmcH8LaLtWjniF+iT+YZw3Ld1O9VMK7RaHePsS4JYfbjeapoCEgudecmIz4\n" +
+            "5Q2tTjCdR5s/SxiVbynfEw+cAGeiv4sRXNSg0uhZ2eGMHh6mPley2pUoRMR8Qx1U\n" +
+            "0Uzg2NtPsHAo0DIH3jKEWU2zP5UPwCfqKYGaZLNLeGh07NZHBCp3TGp9kPVen5Ib\n" +
+            "tnJssu+pab7fixvbpDM4/r9MkKU6C1IsE6lffyON0PA6LaywwecYTJGpieXqoz03\n" +
+            "5UmQXvAzkb9omIAcQ6yWMZNrqwwG9XRKQEhvG3v7sbFkck1KZOz4r/KHkLx9sIxm\n" +
+            "vngdD/qLFebxPIvPT0GKnvSzuGcdQXVTdkZBBBrunv+XpQIDAQABo4IBiTCCAYUw\n" +
+            "HwYDVR0jBBgwFoAUDyrLIIcouOxvSK4rVKYpqhekzQwwHQYDVR0OBBYEFGMpbbJO\n" +
+            "xiuD6t+HEyA3hjp4devXMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBMG\n" +
+            "A1UdJQQMMAoGCCsGAQUFBwMDMEoGA1UdIARDMEEwNQYMKwYBBAGyMQECAQMCMCUw\n" +
+            "IwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5jb20vQ1BTMAgGBmeBDAEEATBJ\n" +
+            "BgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLnNlY3RpZ28uY29tL1NlY3RpZ29Q\n" +
+            "dWJsaWNDb2RlU2lnbmluZ0NBUjM2LmNybDB5BggrBgEFBQcBAQRtMGswRAYIKwYB\n" +
+            "BQUHMAKGOGh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVT\n" +
+            "aWduaW5nQ0FSMzYuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdv\n" +
+            "LmNvbTANBgkqhkiG9w0BAQwFAAOCAYEAP2OCzJ+0hrg4XK3w+Ypoe0G5hKfzZ9RH\n" +
+            "nDcgY8BjgWYVOlN9ad2bU70RfgkZzylkaSt02KHOpkXmYpgfjZsovmyUchvlZ4fU\n" +
+            "RmivZleuO3G/ZvDFX373S40QFDd+lC1LYYUolRVz7/ZU2Vzql4FxsM1psRaW17xj\n" +
+            "jf9qaAvDlOH45eEEkfRUbIDdn1UYqDxdCN+90jtD1vRWkYINvE1T6mq3rHpEVoTS\n" +
+            "dIOgmcSL3MAKMB0LxWUPfoVdhnoUuoIxIAcV1SuR6zej4wHjClEaR8ReT/C23Jr3\n" +
+            "hQ4VDbfGu3gvlZG8/+lNmT+t4WaNPECxbFP0BgbD70FP594mSVH3fgptYiiRN7ez\n" +
+            "iUfOSBeCZpSMm7Z5P0KkxkagyFIR3vzgvqbJS/iaomvd9ZIkd9AwMEhugJpITeZj\n" +
+            "lKSXs+2q2UHQdLTPGVoOjmqyPhDGKAeVVF+jLIUWwtAaAoJm6ooXSp8sAeLA+e+K\n" +
+            "6RUFETVxhCefCjkbWq64OYLXriDb0l+W\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=Sectigo Limited, O=Sectigo Limited, ST=West Yorkshire, C=GB
+    // Issuer: CN=Sectigo Public Code Signing CA R36, O=Sectigo Limited, C=GB
+    // Serial number: 5ca6fb60da04db99dedbbc0c37131ec
+    // Valid from: Wed Jun 04 17:00:00 PDT 2025 until: Sun Jun 04 16:59:59
+    // PDT 2028
+    private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIGQzCCBKugAwIBAgIQBcpvtg2gTbmd7bvAw3Ex7DANBgkqhkiG9w0BAQwFADBU\n" +
+            "MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQD\n" +
+            "EyJTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgQ0EgUjM2MB4XDTI1MDYwNTAw\n" +
+            "MDAwMFoXDTI4MDYwNDIzNTk1OVowWjELMAkGA1UEBhMCR0IxFzAVBgNVBAgMDldl\n" +
+            "c3QgWW9ya3NoaXJlMRgwFgYDVQQKDA9TZWN0aWdvIExpbWl0ZWQxGDAWBgNVBAMM\n" +
+            "D1NlY3RpZ28gTGltaXRlZDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\n" +
+            "ALDjoFCMN16zlrcv/saieSYT7FXEhTVDPLNzGAbNdBEX09FoL5EIkiN3biVIbDki\n" +
+            "bIocCFpo/yTrjARG/zz82AjdWHyomdtDjL35CQmgiUX7V8tu64xUfUAgadqm+0PL\n" +
+            "by1LRddKE7chpdJu+EDEmeYDPqcRGM+u8suPgosFf6XfVNFy/FZJiD1c7q6JNZ8i\n" +
+            "5NrvTs0zA9HckKE3uvPO9rw56EyF3SfUz9+zHKHwSElv8nCYpREudUf4yCzPNisK\n" +
+            "MVovzeCo36nzJFEdWTnDOr4mtvfCEGvJOU3mgzpECK7QF+yFifr90SG4lvrwzkig\n" +
+            "wYQymukXmB2gxN1tGOvgLig3Q/b4vljBiEeRPEba/L8YQnaXpR/BnPze8yb2t39l\n" +
+            "bzmnghkWkGA0PAB2vrzpi7pq12fGOD0+ErtAzAl/TAD/UFWwXDQLWX9LXRRKi5E+\n" +
+            "ScTlqLl9U1q9HsWYfM6CvLbc32TByaQ8yBytvsSRB0C0blp7CtP5MAc8j9xJdwAs\n" +
+            "Mj2bvSOfA+NJ0Kdg/tqdHHU6hex2HnGzDiEhovm6u/oAfDp/i2bBKLgARglMfGaC\n" +
+            "hFWeHLL6GAyBezMv+AQNCDCTYDMlqAihVMRUAfYgoHcVCfvTSETTTGdRUDFzIdCA\n" +
+            "wNwSVfykpadsev43I2IF+F3aNgJYuXnpxSCLPngemcgxAgMBAAGjggGJMIIBhTAf\n" +
+            "BgNVHSMEGDAWgBQPKssghyi47G9IritUpimqF6TNDDAdBgNVHQ4EFgQUlff/C/GC\n" +
+            "faJ+Y7ua3hKsCsrW9y4wDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYD\n" +
+            "VR0lBAwwCgYIKwYBBQUHAwMwSgYDVR0gBEMwQTA1BgwrBgEEAbIxAQIBAwIwJTAj\n" +
+            "BggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQQBMEkG\n" +
+            "A1UdHwRCMEAwPqA8oDqGOGh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1\n" +
+            "YmxpY0NvZGVTaWduaW5nQ0FSMzYuY3JsMHkGCCsGAQUFBwEBBG0wazBEBggrBgEF\n" +
+            "BQcwAoY4aHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNp\n" +
+            "Z25pbmdDQVIzNi5jcnQwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28u\n" +
+            "Y29tMA0GCSqGSIb3DQEBDAUAA4IBgQAfVq3mY7ggMcTJeWKKrGxs9RUiuAY0p4Xv\n" +
+            "CHNQViM/tHAn0t/nkPp+d2Ji3Zr6PefN+1F6zmsxsbZHse52JNHWYUwCb/Dx4Vw6\n" +
+            "3Wnc1zhXtZnvUTUfgrivuIsMjUG8yzTdEt/taMKEO0KqlKPsBPgFKveDVVaq9UZa\n" +
+            "FfxTWqgrnvkvP/Lag/YeKKj4cJG+a/MJZJm7kvyaBNKXVAamr/bumoxKDzpD67ds\n" +
+            "n9qwBi2Mv0rRXvZ2SHQXzsJ/zjNKWUhpPVrpypaER7EUxjNuSgC4L8AmfvHiO67v\n" +
+            "9EVIEud+beP3FtCXl/cSHhVeDxiC0KBXXBl9zLBaYvCH+8iABnZLStLgBDtfdkfk\n" +
+            "TZEAGbrNOXJDMnKRxr8y377Zq+KHwfiTnyizACHyMMTi+CCwg1ZFGcLOHa5shByc\n" +
+            "Ln9lYysM1/5vrEjt3ZUw11+pDqbPCGS++xgAwcftKfJ0TZrW/g6NZ9URg+11H9ad\n" +
+            "WalBv2VkhJAFJam9P2Y+pi9luk85sGo=\n" +
+            "-----END CERTIFICATE-----";
+
+    public void runTest(ValidatePathWithParams pathValidator) throws Exception {
+        // Validate valid
+        pathValidator.validate(new String[]{VALID, INT},
+                ValidatePathWithParams.Status.GOOD, null, System.out);
+
+        // Validate Revoked
+        pathValidator.validate(new String[]{REVOKED, INT},
+                ValidatePathWithParams.Status.REVOKED,
+                "Thu Jun 05 10:27:45 PDT 2025", System.out);
+    }
+}
+
+class SectigoCSRootCA_E46 {
+
+    // Owner: CN=Sectigo Public Code Signing CA EV E36, O=Sectigo Limited, C=GB
+    // Issuer: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB
+    // Serial number: 3774434f9eb40e221f9236ca1f2f2717
+    // Valid from: Sun Mar 21 17:00:00 PDT 2021 until: Fri Mar 21 16:59:59
+    // PDT 2036
+    private static final String INT_VALID = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDMDCCAragAwIBAgIQN3RDT560DiIfkjbKHy8nFzAKBggqhkjOPQQDAzBWMQsw\n" +
+            "CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRT\n" +
+            "ZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBFNDYwHhcNMjEwMzIyMDAw\n" +
+            "MDAwWhcNMzYwMzIxMjM1OTU5WjBXMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2Vj\n" +
+            "dGlnbyBMaW1pdGVkMS4wLAYDVQQDEyVTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25p\n" +
+            "bmcgQ0EgRVYgRTM2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3mMV9nNViYoH\n" +
+            "4aSrPwFjpbbeXHw2pMbqezwDGb45uEZQr3qI9Hgt0k4R26o5upfXzJt03F8efu0r\n" +
+            "RNEs4yDDz6OCAWMwggFfMB8GA1UdIwQYMBaAFM99LKCQepgd3bZehcLg2hVx0uVe\n" +
+            "MB0GA1UdDgQWBBQadKQ417m2DrNb+txerj+28HM9iDAOBgNVHQ8BAf8EBAMCAYYw\n" +
+            "EgYDVR0TAQH/BAgwBgEB/wIBADATBgNVHSUEDDAKBggrBgEFBQcDAzAaBgNVHSAE\n" +
+            "EzARMAYGBFUdIAAwBwYFZ4EMAQMwSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2Ny\n" +
+            "bC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdSb290RTQ2LmNy\n" +
+            "bDB7BggrBgEFBQcBAQRvMG0wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jcnQuc2VjdGln\n" +
+            "by5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nUm9vdEU0Ni5wN2MwIwYIKwYB\n" +
+            "BQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28uY29tMAoGCCqGSM49BAMDA2gAMGUC\n" +
+            "MQCger3L4CYx2W7HyHzvLaAnNee9QVqOwOrBYZyyqXERLtZg1DscsdoYZ2gszEW3\n" +
+            "zaUCMAaLtcwdoV35ADpru29wChS7kFgXt599Ex27wmL++uJCJth6xYr3nyF2b2YJ\n" +
+            "DAatOw==\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=Sectigo Public Code Signing CA E36, O=Sectigo Limited, C=GB
+    // Issuer: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB
+    // Serial number: 3602617636e7034b9cc1fc5ffeac2d54
+    // Valid from: Sun Mar 21 17:00:00 PDT 2021 until: Fri Mar 21 16:59:59
+    // PDT 2036
+    private static final String INT_REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDLjCCArSgAwIBAgIQNgJhdjbnA0ucwfxf/qwtVDAKBggqhkjOPQQDAzBWMQsw\n" +
+            "CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRT\n" +
+            "ZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBFNDYwHhcNMjEwMzIyMDAw\n" +
+            "MDAwWhcNMzYwMzIxMjM1OTU5WjBUMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2Vj\n" +
+            "dGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25p\n" +
+            "bmcgQ0EgRTM2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAElDe1m6jawDhrwMxJ\n" +
+            "yFPhKYf8EGu+lBw3bF5CzmfaH1I7Zi+WAmkeEwS3tiNxzPh8GbBBLtdaRuqGuyWc\n" +
+            "W6ERmaOCAWQwggFgMB8GA1UdIwQYMBaAFM99LKCQepgd3bZehcLg2hVx0uVeMB0G\n" +
+            "A1UdDgQWBBQlDZtt2Bh3t4rDOFFW5cfytf+DajAOBgNVHQ8BAf8EBAMCAYYwEgYD\n" +
+            "VR0TAQH/BAgwBgEB/wIBADATBgNVHSUEDDAKBggrBgEFBQcDAzAbBgNVHSAEFDAS\n" +
+            "MAYGBFUdIAAwCAYGZ4EMAQQBMEsGA1UdHwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwu\n" +
+            "c2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nUm9vdEU0Ni5jcmww\n" +
+            "ewYIKwYBBQUHAQEEbzBtMEYGCCsGAQUFBzAChjpodHRwOi8vY3J0LnNlY3RpZ28u\n" +
+            "Y29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ1Jvb3RFNDYucDdjMCMGCCsGAQUF\n" +
+            "BzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTAKBggqhkjOPQQDAwNoADBlAjBM\n" +
+            "ykNTSVvegC1m17yIi87qgx6QIGbw1Mw2bQ4gtOWBVb/C8ALByC1YK7yQJNLJFTkC\n" +
+            "MQCNBv3fe1eLrGELS5KQD0cEFbXGlzQ5r1mnOHePMqlK5d+rmMxff58/t6bo3QEb\n" +
+            "8SQ=\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=Sectigo Limited, O=Sectigo Limited, ST=West Yorkshire, C=GB,
+    // OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.3=GB,
+    // SERIALNUMBER=04058690
+    // Issuer: CN=Sectigo Public Code Signing CA EV E36, O=Sectigo Limited, C=GB
+    // Serial number: fa2aa131f36b337717ac73f606a6ec49
+    // Valid from: Tue Feb 13 16:00:00 PST 2024 until: Sat Feb 13 15:59:59
+    // PST 2027
+    private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDrjCCA1SgAwIBAgIRAPoqoTHzazN3F6xz9gam7EkwCgYIKoZIzj0EAwIwVzEL\n" +
+            "MAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEuMCwGA1UEAxMl\n" +
+            "U2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIENBIEVWIEUzNjAeFw0yNDAyMTQw\n" +
+            "MDAwMDBaFw0yNzAyMTMyMzU5NTlaMIGhMREwDwYDVQQFEwgwNDA1ODY5MDETMBEG\n" +
+            "CysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24x\n" +
+            "CzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5XZXN0IFlvcmtzaGlyZTEYMBYGA1UECgwP\n" +
+            "U2VjdGlnbyBMaW1pdGVkMRgwFgYDVQQDDA9TZWN0aWdvIExpbWl0ZWQwWTATBgcq\n" +
+            "hkjOPQIBBggqhkjOPQMBBwNCAASwXGEU01WkW/hWNYza08ZT7i0ZeZ9M1s93JYEB\n" +
+            "rZ/f1Ho1YzxtToqgIK2o+32afablPFYWlE6wGyuL/TYggBpKo4IBtDCCAbAwHwYD\n" +
+            "VR0jBBgwFoAUGnSkONe5tg6zW/rcXq4/tvBzPYgwHQYDVR0OBBYEFHEcsJgcYuDO\n" +
+            "dv1raL6h83a6j9C/MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBMGA1Ud\n" +
+            "JQQMMAoGCCsGAQUFBwMDMEkGA1UdIARCMEAwNQYMKwYBBAGyMQECAQYBMCUwIwYI\n" +
+            "KwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5jb20vQ1BTMAcGBWeBDAEDMEsGA1Ud\n" +
+            "HwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1Ymxp\n" +
+            "Y0NvZGVTaWduaW5nQ0FFVkUzNi5jcmwwewYIKwYBBQUHAQEEbzBtMEYGCCsGAQUF\n" +
+            "BzAChjpodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2ln\n" +
+            "bmluZ0NBRVZFMzYuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdv\n" +
+            "LmNvbTAmBgNVHREEHzAdoBsGCCsGAQUFBwgDoA8wDQwLR0ItMDQwNTg2OTAwCgYI\n" +
+            "KoZIzj0EAwIDSAAwRQIgQVp7IIkEZNmC7GfmT1MSEhDebIjjzd75ZVEEbPP/4ocC\n" +
+            "IQDSyfPDKNMbKNOKrweDLwSE2GZV6nDWbiLz6ZmSZHob8w==\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=Sectigo Limited, O=Sectigo Limited, ST=West Yorkshire, C=GB
+    // Issuer: CN=Sectigo Public Code Signing CA E36, O=Sectigo Limited, C=GB
+    // Serial number: a1f601514271f24ca0a31c0d7b856705
+    // Valid from: Wed Jun 04 17:00:00 PDT 2025 until: Sun Jun 04 16:59:59
+    // PDT 2028
+    private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDOTCCAt6gAwIBAgIRAKH2AVFCcfJMoKMcDXuFZwUwCgYIKoZIzj0EAwIwVDEL\n" +
+            "MAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDErMCkGA1UEAxMi\n" +
+            "U2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIENBIEUzNjAeFw0yNTA2MDUwMDAw\n" +
+            "MDBaFw0yODA2MDQyMzU5NTlaMFoxCzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5XZXN0\n" +
+            "IFlvcmtzaGlyZTEYMBYGA1UECgwPU2VjdGlnbyBMaW1pdGVkMRgwFgYDVQQDDA9T\n" +
+            "ZWN0aWdvIExpbWl0ZWQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASwXGEU01Wk\n" +
+            "W/hWNYza08ZT7i0ZeZ9M1s93JYEBrZ/f1Ho1YzxtToqgIK2o+32afablPFYWlE6w\n" +
+            "GyuL/TYggBpKo4IBiTCCAYUwHwYDVR0jBBgwFoAUJQ2bbdgYd7eKwzhRVuXH8rX/\n" +
+            "g2owHQYDVR0OBBYEFHEcsJgcYuDOdv1raL6h83a6j9C/MA4GA1UdDwEB/wQEAwIH\n" +
+            "gDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMEoGA1UdIARDMEEw\n" +
+            "NQYMKwYBBAGyMQECAQMCMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5j\n" +
+            "b20vQ1BTMAgGBmeBDAEEATBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLnNl\n" +
+            "Y3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ0NBRTM2LmNybDB5Bggr\n" +
+            "BgEFBQcBAQRtMGswRAYIKwYBBQUHMAKGOGh0dHA6Ly9jcnQuc2VjdGlnby5jb20v\n" +
+            "U2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nQ0FFMzYuY3J0MCMGCCsGAQUFBzABhhdo\n" +
+            "dHRwOi8vb2NzcC5zZWN0aWdvLmNvbTAKBggqhkjOPQQDAgNJADBGAiEAlEkiISLz\n" +
+            "PdJsFmVzJ2VZ8hnnVsOBXKbqISFQvIdguJoCIQCH4T0vwxn6uVkJpMvtxiMG/rYg\n" +
+            "jRFhfbxDcVee6likOw==\n" +
+            "-----END CERTIFICATE-----";
+
+    public void runTest(ValidatePathWithParams pathValidator) throws Exception {
+        // Validate valid
+        pathValidator.validate(new String[]{VALID, INT_VALID},
+                ValidatePathWithParams.Status.GOOD, null, System.out);
+
+        // Validate Revoked
+        pathValidator.validate(new String[]{REVOKED, INT_REVOKED},
+                ValidatePathWithParams.Status.REVOKED,
+                "Thu Jun 05 10:27:19 PDT 2025", System.out);
+    }
+}
diff -pruN 24.0.1+9-1/test/jdk/sun/security/ec/TestEC.java 24.0.2+12-1/test/jdk/sun/security/ec/TestEC.java
--- 24.0.1+9-1/test/jdk/sun/security/ec/TestEC.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/ec/TestEC.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -34,7 +34,6 @@
  * @library ../pkcs11
  * @library ../pkcs11/ec
  * @library ../pkcs11/sslecc
- * @library ../../../java/security/testlibrary
  * @library ../../../javax/net/ssl/TLSCommon
  * @modules jdk.crypto.cryptoki/sun.security.pkcs11.wrapper
  * @run main/othervm -Djdk.tls.namedGroups="secp256r1" TestEC
@@ -43,6 +42,7 @@
 import java.security.NoSuchProviderException;
 import java.security.Provider;
 import java.security.Security;
+import jdk.test.lib.security.ProvidersSnapshot;
 
 /*
  * Leverage the collection of EC tests used by PKCS11
diff -pruN 24.0.1+9-1/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java 24.0.2+12-1/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java
--- 24.0.1+9-1/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -28,7 +28,7 @@
  *      8223499 8225392 8232019 8234245 8233223 8225068 8225069 8243321 8243320
  *      8243559 8225072 8258630 8259312 8256421 8225081 8225082 8225083 8245654
  *      8305975 8304760 8307134 8295894 8314960 8317373 8317374 8318759 8319187
- *      8321408 8316138 8341057
+ *      8321408 8316138 8341057 8303770 8350498 8359170
  * @summary Check root CA entries in cacerts file
  */
 import java.io.ByteArrayInputStream;
@@ -47,12 +47,12 @@ public class VerifyCACerts {
             + File.separator + "security" + File.separator + "cacerts";
 
     // The numbers of certs now.
-    private static final int COUNT = 112;
+    private static final int COUNT = 113;
 
     // SHA-256 of cacerts, can be generated with
     // shasum -a 256 cacerts | sed -e 's/../&:/g' | tr '[:lower:]' '[:upper:]' | cut -c1-95
     private static final String CHECKSUM
-            = "21:68:E7:16:5B:94:23:D2:60:5C:BB:F2:AF:C1:66:5C:EC:36:BC:20:FF:5C:54:AF:91:D1:2C:38:AE:55:D3:27";
+            = "18:36:49:15:B6:71:85:FF:F1:8E:C0:10:BE:0A:41:52:5B:DC:F7:B3:1F:51:7A:45:7D:7A:14:10:3A:59:42:4C";
 
     // Hex formatter to upper case with ":" delimiter
     private static final HexFormat HEX = HexFormat.ofDelimiter(":").withUpperCase();
@@ -69,10 +69,6 @@ public class VerifyCACerts {
                     "ED:F7:EB:BC:A2:7A:2A:38:4D:38:7B:7D:40:10:C6:66:E2:ED:B4:84:3E:4C:29:B4:AE:1D:5B:93:32:E6:B2:4D");
             put("camerfirmachambersca [jdk]",
                     "06:3E:4A:FA:C4:91:DF:D3:32:F3:08:9B:85:42:E9:46:17:D8:93:D7:FE:94:4E:10:A7:93:7E:E2:9D:96:93:C0");
-            put("camerfirmachambersignca [jdk]",
-                    "13:63:35:43:93:34:A7:69:80:16:A0:D3:24:DE:72:28:4E:07:9D:7B:52:20:BB:8F:BD:74:78:16:EE:BE:BA:CA");
-            put("camerfirmachamberscommerceca [jdk]",
-                    "0C:25:8A:12:A5:67:4A:EF:25:F2:8B:A7:DC:FA:EC:EE:A3:48:E5:41:E6:F5:CC:4E:E6:3B:71:B3:61:60:6A:C3");
             put("certumca [jdk]",
                     "D8:E0:FE:BC:1D:B2:E3:8D:00:94:0F:37:D2:7D:41:34:4D:99:3E:73:4B:99:D5:65:6D:97:78:D4:D8:14:36:24");
             put("certumtrustednetworkca [jdk]",
@@ -95,8 +91,6 @@ public class VerifyCACerts {
                     "68:7F:A4:51:38:22:78:FF:F0:C8:B1:1F:8D:43:D5:76:67:1C:6E:B2:BC:EA:B4:13:FB:83:D9:65:D0:6D:2F:F2");
             put("addtrustqualifiedca [jdk]",
                     "80:95:21:08:05:DB:4B:BC:35:5E:44:28:D8:FD:6E:C2:CD:E3:AB:5F:B9:7A:99:42:98:8E:B8:F4:DC:D0:60:16");
-            put("baltimorecybertrustca [jdk]",
-                    "16:AF:57:A9:F6:76:B0:AB:12:60:95:AA:5E:BA:DE:F2:2A:B3:11:19:D6:44:AC:95:CD:4B:93:DB:F3:F2:6A:EB");
             put("digicertglobalrootca [jdk]",
                     "43:48:A0:E9:44:4C:78:CB:26:5E:05:8D:5E:89:44:B4:D8:4F:96:62:BD:26:DB:25:7F:89:34:A4:43:C7:01:61");
             put("digicertglobalrootg2 [jdk]",
@@ -285,6 +279,14 @@ public class VerifyCACerts {
                     "C3:2F:FD:9F:46:F9:36:D1:6C:36:73:99:09:59:43:4B:9A:D6:0A:AF:BB:9E:7C:F3:36:54:F1:44:CC:1B:A1:43");
             put("ssltlsrootrsa2022 [jdk]",
                     "8F:AF:7D:2E:2C:B4:70:9B:B8:E0:B3:36:66:BF:75:A5:DD:45:B5:DE:48:0F:8E:A8:D4:BF:E6:BE:BC:17:F2:ED");
+            put("sectigotlsrootr46 [jdk]",
+                    "7B:B6:47:A6:2A:EE:AC:88:BF:25:7A:A5:22:D0:1F:FE:A3:95:E0:AB:45:C7:3F:93:F6:56:54:EC:38:F2:5A:06");
+            put("sectigotlsroote46 [jdk]",
+                    "C9:0F:26:F0:FB:1B:40:18:B2:22:27:51:9B:5C:A2:B5:3E:2C:A5:B3:BE:5C:F1:8E:FE:1B:EF:47:38:0C:53:83");
+            put("sectigocodesignrootr46 [jdk]",
+                    "7E:76:26:0A:E6:9A:55:D3:F0:60:B0:FD:18:B2:A8:C0:14:43:C8:7B:60:79:10:30:C9:FA:0B:05:85:10:1A:38");
+            put("sectigocodesignroote46 [jdk]",
+                    "8F:63:71:D8:CC:5A:A7:CA:14:96:67:A9:8B:54:96:39:89:51:E4:31:9F:7A:FB:CC:6A:66:0D:67:3E:43:8D:0B");
         }
     };
 
diff -pruN 24.0.1+9-1/test/jdk/sun/security/pkcs11/ec/ReadCertificates.java 24.0.2+12-1/test/jdk/sun/security/pkcs11/ec/ReadCertificates.java
--- 24.0.1+9-1/test/jdk/sun/security/pkcs11/ec/ReadCertificates.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/pkcs11/ec/ReadCertificates.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -28,7 +28,6 @@
  *   and verify their signatures
  * @author Andreas Sterbenz
  * @library /test/lib ..
- * @library ../../../../java/security/testlibrary
  * @modules jdk.crypto.cryptoki
  * @run main/othervm ReadCertificates
  */
@@ -55,6 +54,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import javax.security.auth.x500.X500Principal;
+import jdk.test.lib.security.Providers;
 
 public class ReadCertificates extends PKCS11Test {
 
diff -pruN 24.0.1+9-1/test/jdk/sun/security/pkcs11/ec/ReadPKCS12.java 24.0.2+12-1/test/jdk/sun/security/pkcs11/ec/ReadPKCS12.java
--- 24.0.1+9-1/test/jdk/sun/security/pkcs11/ec/ReadPKCS12.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/pkcs11/ec/ReadPKCS12.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -27,7 +27,6 @@
  * @summary Verify that we can parse ECPrivateKeys from PKCS#12 and use them
  * @author Andreas Sterbenz
  * @library /test/lib ..
- * @library ../../../../java/security/testlibrary
  * @key randomness
  * @modules jdk.crypto.cryptoki java.base/sun.security.ec
  * @run main/othervm ReadPKCS12
@@ -54,6 +53,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
+import jdk.test.lib.security.Providers;
 
 public class ReadPKCS12 extends PKCS11Test {
 
diff -pruN 24.0.1+9-1/test/jdk/sun/security/pkcs11/ec/TestECDH.java 24.0.2+12-1/test/jdk/sun/security/pkcs11/ec/TestECDH.java
--- 24.0.1+9-1/test/jdk/sun/security/pkcs11/ec/TestECDH.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/pkcs11/ec/TestECDH.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -27,7 +27,6 @@
  * @summary Basic known answer test for ECDH
  * @author Andreas Sterbenz
  * @library /test/lib ..
- * @library ../../../../java/security/testlibrary
  * @modules jdk.crypto.cryptoki
  * @run main/othervm TestECDH
  */
@@ -43,6 +42,8 @@ import java.security.spec.PKCS8EncodedKe
 import java.security.spec.X509EncodedKeySpec;
 import java.util.Arrays;
 import javax.crypto.KeyAgreement;
+import jdk.test.lib.security.Providers;
+
 
 public class TestECDH extends PKCS11Test {
 
diff -pruN 24.0.1+9-1/test/jdk/sun/security/pkcs11/ec/TestECDH2.java 24.0.2+12-1/test/jdk/sun/security/pkcs11/ec/TestECDH2.java
--- 24.0.1+9-1/test/jdk/sun/security/pkcs11/ec/TestECDH2.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/pkcs11/ec/TestECDH2.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -27,7 +27,6 @@
  * @summary basic test of ECDSA signatures for P-256 and P-384 from the
  * example data in "Suite B Implementer's Guide to FIPS 186-3".
  * @library /test/lib ..
- * @library ../../../../java/security/testlibrary
  * @modules java.base/sun.security.util
  *          jdk.crypto.cryptoki
  * @compile -XDignore.symbol.file TestECDH2.java
diff -pruN 24.0.1+9-1/test/jdk/sun/security/pkcs11/ec/TestECDSA.java 24.0.2+12-1/test/jdk/sun/security/pkcs11/ec/TestECDSA.java
--- 24.0.1+9-1/test/jdk/sun/security/pkcs11/ec/TestECDSA.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/pkcs11/ec/TestECDSA.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -27,7 +27,6 @@
  * @summary basic test of SHA1withECDSA and NONEwithECDSA signing/verifying
  * @author Andreas Sterbenz
  * @library /test/lib ..
- * @library ../../../../java/security/testlibrary
  * @key randomness
  * @modules jdk.crypto.cryptoki
  * @run main/othervm TestECDSA
@@ -45,6 +44,7 @@ import java.security.interfaces.ECPublic
 import java.security.spec.PKCS8EncodedKeySpec;
 import java.security.spec.X509EncodedKeySpec;
 import java.util.Random;
+import jdk.test.lib.security.Providers;
 
 public class TestECDSA extends PKCS11Test {
 
diff -pruN 24.0.1+9-1/test/jdk/sun/security/pkcs11/ec/TestECDSA2.java 24.0.2+12-1/test/jdk/sun/security/pkcs11/ec/TestECDSA2.java
--- 24.0.1+9-1/test/jdk/sun/security/pkcs11/ec/TestECDSA2.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/pkcs11/ec/TestECDSA2.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -27,7 +27,6 @@
  * @summary basic test of ECDSA signatures for P-256 and P-384 from the
  * example data in "Suite B Implementer's Guide to FIPS 186-3".
  * @library /test/lib ..
- * @library ../../../../java/security/testlibrary
  * @modules java.base/sun.security.util
  *          jdk.crypto.cryptoki
  * @compile -XDignore.symbol.file TestECDSA2.java
diff -pruN 24.0.1+9-1/test/jdk/sun/security/pkcs11/rsa/TestCACerts.java 24.0.2+12-1/test/jdk/sun/security/pkcs11/rsa/TestCACerts.java
--- 24.0.1+9-1/test/jdk/sun/security/pkcs11/rsa/TestCACerts.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/pkcs11/rsa/TestCACerts.java	2025-06-27 08:03:14.000000000 +0000
@@ -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
@@ -27,7 +27,6 @@
  * @summary Test the new RSA provider can verify all the RSA certs in the cacerts file
  * @author Andreas Sterbenz
  * @library /test/lib ..
- * @library ../../../../java/security/testlibrary
  * @modules jdk.crypto.cryptoki
  * @run main/othervm TestCACerts
  */
@@ -42,6 +41,7 @@ import java.security.PublicKey;
 import java.security.Security;
 import java.security.cert.X509Certificate;
 import java.util.Enumeration;
+import jdk.test.lib.security.Providers;
 
 public class TestCACerts extends PKCS11Test {
 
diff -pruN 24.0.1+9-1/test/jdk/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 24.0.2+12-1/test/jdk/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java
--- 24.0.1+9-1/test/jdk/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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,6 @@
  * @summary Verify that all ciphersuites work (incl. ECC using NSS crypto)
  * @author Andreas Sterbenz
  * @library /test/lib .. ../../../../javax/net/ssl/TLSCommon
- * @library ../../../../java/security/testlibrary
  * @modules jdk.crypto.cryptoki
  * @run main/othervm -Djdk.tls.namedGroups="secp256r1,sect193r1"
  *      ClientJSSEServerJSSE
@@ -40,6 +39,7 @@
 
 import java.security.Provider;
 import java.security.Security;
+import jdk.test.lib.security.Providers;
 
 public class ClientJSSEServerJSSE extends PKCS11Test {
 
diff -pruN 24.0.1+9-1/test/jdk/sun/security/pkcs12/GetSetEntryTest.java 24.0.2+12-1/test/jdk/sun/security/pkcs12/GetSetEntryTest.java
--- 24.0.1+9-1/test/jdk/sun/security/pkcs12/GetSetEntryTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/pkcs12/GetSetEntryTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 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
@@ -25,10 +25,9 @@
  * @test
  * @bug 8327461
  * @summary engineGetEntry in PKCS12KeyStore should be thread-safe
- * @library /test/lib ../../../java/security/testlibrary
+ * @library /test/lib
  * @modules java.base/sun.security.x509
  *          java.base/sun.security.util
- * @build CertificateBuilder
  * @run main GetSetEntryTest
  */
 
@@ -42,7 +41,7 @@ import java.util.concurrent.atomic.Atomi
 import java.util.concurrent.TimeUnit;
 import java.util.Date;
 
-import sun.security.testlibrary.CertificateBuilder;
+import jdk.test.lib.security.CertificateBuilder;
 
 public class GetSetEntryTest {
 
diff -pruN 24.0.1+9-1/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java 24.0.2+12-1/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java
--- 24.0.1+9-1/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/pkcs12/KeytoolOpensslInteropTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -22,7 +22,7 @@
  */
 
 /*
- * @test
+ * @test id=GenerateOpensslPKCS12
  * @bug 8076190 8242151 8153005 8266182
  * @summary This is java keytool <-> openssl interop test. This test generates
  *          some openssl keystores on the fly, java operates on it and
@@ -31,13 +31,24 @@
  *          Note: This test executes some openssl command, so need to set
  *          openssl path using system property "test.openssl.path" or it should
  *          be available in /usr/bin or /usr/local/bin
- *          Required OpenSSL version : OpenSSL 1.1.*
+ *          Required OpenSSL version : OpensslArtifactFetcher.OPENSSL_BUNDLE_VERSION
  *
  * @modules java.base/sun.security.pkcs
  *          java.base/sun.security.util
- * @library /test/lib
- * @library /sun/security/pkcs11/
- * @run main/othervm/timeout=600 KeytoolOpensslInteropTest
+ * @library /test/lib /sun/security/pkcs11/
+ * @run main/othervm KeytoolOpensslInteropTest true
+ */
+
+/*
+ * @test id=UseExistingPKCS12
+ * @bug 8076190 8242151 8153005 8266182
+ * @summary This is java keytool <-> openssl interop test. This test uses
+ *          the existing PKCS12 files located in ./params dir and java operates on it
+ *
+ * @modules java.base/sun.security.pkcs
+ *          java.base/sun.security.util
+ * @library /test/lib /sun/security/pkcs11/
+ * @run main/othervm KeytoolOpensslInteropTest false
  */
 
 import jdk.test.lib.Asserts;
@@ -45,6 +56,7 @@ import jdk.test.lib.SecurityTools;
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.security.OpensslArtifactFetcher;
+import jtreg.SkippedException;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -67,22 +79,25 @@ import static sun.security.pkcs.ContentI
 public class KeytoolOpensslInteropTest {
 
     public static void main(String[] args) throws Throwable {
-        String opensslPath = OpensslArtifactFetcher.getOpenssl1dot1dotStar();
-        if (opensslPath != null) {
-            // if preferred version of openssl is available perform all
-            // keytool <-> openssl interop tests
-            generateInitialKeystores(opensslPath);
-            testWithJavaCommands();
-            testWithOpensslCommands(opensslPath);
+        boolean generatePKCS12 = Boolean.parseBoolean(args[0]);
+        if (generatePKCS12) {
+            String opensslPath = OpensslArtifactFetcher.getOpensslPath();
+            if (opensslPath != null) {
+                // if the current version of openssl is available, perform all
+                // keytool <-> openssl interop tests
+                generateInitialKeystores(opensslPath);
+                testWithJavaCommands();
+                testWithOpensslCommands(opensslPath);
+            } else {
+                String exMsg = "Can't find the version: "
+                        + OpensslArtifactFetcher.getTestOpensslBundleVersion()
+                        + " of openssl binary on this machine, please install"
+                        + " and set openssl path with property 'test.openssl.path'";
+                throw new SkippedException(exMsg);
+            }
         } else {
-            // since preferred version of openssl is not available skip all
-            // openssl command dependent tests with a warning
-            System.out.println("\n\u001B[31mWarning: Can't find openssl "
-                    + "(version 1.1.*) binary on this machine, please install"
-                    + " and set openssl path with property "
-                    + "'test.openssl.path'. Now running only half portion of "
-                    + "the test, skipping all tests which depends on openssl "
-                    + "commands.\u001B[0m\n");
+            // since this scenario is using preexisting PKCS12, skip all
+            // openssl command dependent tests
             // De-BASE64 textual files in ./params to `pwd`
             try (DirectoryStream<Path> stream = Files.newDirectoryStream(
                     Path.of(System.getProperty("test.src"), "params"),
@@ -103,6 +118,8 @@ public class KeytoolOpensslInteropTest {
 
     private static void generateInitialKeystores(String opensslPath)
             throws Throwable {
+        Path providerPath = OpensslArtifactFetcher.getProviderPath(opensslPath);
+
         keytool("-keystore ks -keyalg ec -genkeypair -storepass"
                 + " changeit -alias a -dname CN=A").shouldHaveExitValue(0);
 
@@ -123,7 +140,8 @@ public class KeytoolOpensslInteropTest {
         ProcessTools.executeCommand(opensslPath, "pkcs12", "-export", "-in",
                 "kandc", "-out", "os4", "-name", "a", "-passout",
                 "pass:changeit", "-certpbe", "PBE-SHA1-RC4-128", "-keypbe",
-                "PBE-SHA1-RC4-128", "-macalg", "SHA224")
+                "PBE-SHA1-RC4-128", "-macalg", "SHA224",
+                "-legacy", "-provider-path", providerPath.toString())
                 .shouldHaveExitValue(0);
 
         ProcessTools.executeCommand(opensslPath, "pkcs12", "-export", "-in",
@@ -480,12 +498,14 @@ public class KeytoolOpensslInteropTest {
         output1 = ProcessTools.executeCommand(opensslPath, "pkcs12", "-in",
                 "ksnopass", "-passin", "pass:changeit", "-info", "-nokeys",
                 "-nocerts");
-        output1.shouldNotHaveExitValue(0);
+        output1.shouldHaveExitValue(0)
+            .shouldContain("Warning: MAC is absent!");
 
         output1 = ProcessTools.executeCommand(opensslPath, "pkcs12", "-in",
                 "ksnopass", "-passin", "pass:changeit", "-info", "-nokeys",
                 "-nocerts", "-nomacver");
         output1.shouldHaveExitValue(0)
+            .shouldNotContain("Warning: MAC is absent!")
             .shouldNotContain("PKCS7 Encrypted data:")
             .shouldContain("Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC,"
                     + " Iteration 10000, PRF hmacWithSHA256")
diff -pruN 24.0.1+9-1/test/jdk/sun/security/provider/certpath/OCSP/OCSPNoContentLength.java 24.0.2+12-1/test/jdk/sun/security/provider/certpath/OCSP/OCSPNoContentLength.java
--- 24.0.1+9-1/test/jdk/sun/security/provider/certpath/OCSP/OCSPNoContentLength.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/provider/certpath/OCSP/OCSPNoContentLength.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 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
@@ -28,8 +28,7 @@
  * @modules java.base/sun.security.x509
  *          java.base/sun.security.provider.certpath
  *          java.base/sun.security.util
- * @library ../../../../../java/security/testlibrary
- * @build CertificateBuilder SimpleOCSPServer
+ * @library /test/lib
  * @run main/othervm OCSPNoContentLength
  */
 
@@ -46,8 +45,8 @@ import java.util.*;
 import java.util.concurrent.TimeUnit;
 
 
-import sun.security.testlibrary.SimpleOCSPServer;
-import sun.security.testlibrary.CertificateBuilder;
+import jdk.test.lib.security.SimpleOCSPServer;
+import jdk.test.lib.security.CertificateBuilder;
 
 public class OCSPNoContentLength {
 
diff -pruN 24.0.1+9-1/test/jdk/sun/security/provider/certpath/PKIXCertComparator/Order.java 24.0.2+12-1/test/jdk/sun/security/provider/certpath/PKIXCertComparator/Order.java
--- 24.0.1+9-1/test/jdk/sun/security/provider/certpath/PKIXCertComparator/Order.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/provider/certpath/PKIXCertComparator/Order.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 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
@@ -28,8 +28,7 @@
  * @modules java.base/sun.security.provider.certpath:+open
  *          java.base/sun.security.x509
  *          java.base/sun.security.util
- * @library /test/lib ../../../../../java/security/testlibrary
- * @build CertificateBuilder
+ * @library /test/lib
  * @run main Order
  */
 
@@ -43,7 +42,7 @@ import javax.security.auth.x500.X500Prin
 import sun.security.x509.X509CertImpl;
 
 import jdk.test.lib.Asserts;
-import sun.security.testlibrary.CertificateBuilder;
+import jdk.test.lib.security.CertificateBuilder;
 
 public class Order {
 
diff -pruN 24.0.1+9-1/test/jdk/sun/security/ssl/SSLCipher/SSLSocketNoServerHelloClientShutdown.java 24.0.2+12-1/test/jdk/sun/security/ssl/SSLCipher/SSLSocketNoServerHelloClientShutdown.java
--- 24.0.1+9-1/test/jdk/sun/security/ssl/SSLCipher/SSLSocketNoServerHelloClientShutdown.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/ssl/SSLCipher/SSLSocketNoServerHelloClientShutdown.java	2025-06-27 08:03:14.000000000 +0000
@@ -36,10 +36,11 @@ import static jdk.test.lib.Asserts.fail;
 import static jdk.test.lib.security.SecurityUtils.inspectTlsBuffer;
 
 import java.io.InputStream;
+import java.lang.Override;
 import java.net.InetSocketAddress;
 import java.nio.channels.SocketChannel;
 import java.security.GeneralSecurityException;
-
+import java.util.concurrent.CountDownLatch;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngineResult;
 import javax.net.ssl.SSLEngineResult.Status;
@@ -52,12 +53,15 @@ import javax.net.ssl.SSLSocket;
  * To reproduce @bug 8331682 (client sends an unencrypted TLS alert during
  * TLSv1.3 handshake) with SSLSockets we use an SSLSocket on the server side
  * and a plain TCP socket backed by SSLEngine on the client side.
+ * Using SSLEngine allows the client to force the generation of the plaintext
+ * alert messages.
  */
 public class SSLSocketNoServerHelloClientShutdown
     extends SSLEngineNoServerHelloClientShutdown {
 
     private volatile Exception clientException;
     private volatile Exception serverException;
+    private final CountDownLatch serverLatch;
 
     public static void main(String[] args) throws Exception {
         new SSLSocketNoServerHelloClientShutdown().runTest();
@@ -65,6 +69,7 @@ public class SSLSocketNoServerHelloClien
 
     public SSLSocketNoServerHelloClientShutdown() throws Exception {
         super();
+        serverLatch = new CountDownLatch(1);
     }
 
     private void runTest() throws Exception {
@@ -84,7 +89,6 @@ public class SSLSocketNoServerHelloClien
             try {
                 // Server-side SSL socket that will read.
                 SSLSocket socket = (SSLSocket) serverSocket.accept();
-                socket.setSoTimeout(2000);
                 InputStream is = socket.getInputStream();
                 byte[] inbound = new byte[512];
 
@@ -96,10 +100,12 @@ public class SSLSocketNoServerHelloClien
                 serverException = e;
                 log(e.toString());
             } finally {
+                serverLatch.countDown();
                 thread.join();
             }
         } finally {
             if (serverException != null) {
+                serverException.printStackTrace();
                 assertEquals(
                     SSLProtocolException.class, serverException.getClass());
                 assertEquals(GeneralSecurityException.class,
@@ -125,7 +131,6 @@ public class SSLSocketNoServerHelloClien
                         new InetSocketAddress("localhost", port))) {
 
                     SSLEngineResult clientResult;
-                    clientSocketChannel.socket().setSoTimeout(500);
 
                     log("=================");
 
@@ -162,9 +167,7 @@ public class SSLSocketNoServerHelloClien
                     log("---Client sends unencrypted alerts---");
                     int len = clientSocketChannel.write(cTOs);
 
-                    // Give server a chance to read before we shutdown via
-                    // the try-with-resources block.
-                    Thread.sleep(2000);
+                    serverLatch.await();
                 } catch (Exception e) {
                     clientException = e;
                 }
diff -pruN 24.0.1+9-1/test/jdk/sun/security/ssl/Stapling/StatusResponseManager.java 24.0.2+12-1/test/jdk/sun/security/ssl/Stapling/StatusResponseManager.java
--- 24.0.1+9-1/test/jdk/sun/security/ssl/Stapling/StatusResponseManager.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/ssl/Stapling/StatusResponseManager.java	2025-06-27 08:03:14.000000000 +0000
@@ -23,10 +23,12 @@
 
 /*
  * @test
+ * @library /test/lib
+ * @build jdk.test.lib.security.SimpleOCSPServer
+ *        jdk.test.lib.security.CertificateBuilder
  * @bug 8046321 8339403
- * @library ../../../../java/security/testlibrary
- * @build CertificateBuilder SimpleOCSPServer
- * @run main/othervm -Djavax.net.debug=ssl:respmgr java.base/sun.security.ssl.StatusResponseManagerTests
  * @summary OCSP Stapling for TLS
+ * @run main/othervm -Djavax.net.debug=ssl:respmgr
+ *      java.base/sun.security.ssl.StatusResponseManagerTests
  */
 
diff -pruN 24.0.1+9-1/test/jdk/sun/security/ssl/Stapling/java.base/sun/security/ssl/StatusResponseManagerTests.java 24.0.2+12-1/test/jdk/sun/security/ssl/Stapling/java.base/sun/security/ssl/StatusResponseManagerTests.java
--- 24.0.1+9-1/test/jdk/sun/security/ssl/Stapling/java.base/sun/security/ssl/StatusResponseManagerTests.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/ssl/Stapling/java.base/sun/security/ssl/StatusResponseManagerTests.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -34,8 +34,8 @@ import java.security.KeyStore;
 import java.security.PublicKey;
 import java.util.concurrent.TimeUnit;
 
-import sun.security.testlibrary.SimpleOCSPServer;
-import sun.security.testlibrary.CertificateBuilder;
+import jdk.test.lib.security.SimpleOCSPServer;
+import jdk.test.lib.security.CertificateBuilder;
 
 import static sun.security.ssl.CertStatusExtension.*;
 
diff -pruN 24.0.1+9-1/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Camerfirma.java 24.0.2+12-1/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Camerfirma.java
--- 24.0.1+9-1/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Camerfirma.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Camerfirma.java	2025-06-27 08:03:14.000000000 +0000
@@ -21,17 +21,19 @@
  * questions.
  */
 
+import javax.net.ssl.X509TrustManager;
 import java.io.File;
 import java.security.Security;
-import java.time.*;
-import java.util.*;
-import javax.net.ssl.*;
+import java.time.LocalDate;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.util.Date;
 
-/**
+/*
  * @test
- * @bug 8346587
+ * @bug 8346587 8350498
  * @summary Check that TLS Server certificates chaining back to distrusted
- *          Camerfirma roots are invalid
+ *          Camerfirma root are invalid
  * @library /test/lib
  * @modules java.base/sun.security.validator
  * @run main/othervm Camerfirma after policyOn invalid
@@ -42,13 +44,11 @@ import javax.net.ssl.*;
 
 public class Camerfirma {
 
-    private static final String certPath = "chains" + File.separator + "camerfirma";
+    private static final String CERT_PATH = "chains" + File.separator + "camerfirma";
 
     // Each of the roots have a test certificate chain stored in a file
     // named "<root>-chain.pem".
-    private static String[] rootsToTest = new String[] {
-            "camerfirmachamberscommerceca", "camerfirmachambersca",
-            "camerfirmachambersignca"};
+    private static final String ROOT_TO_TEST = "camerfirmachambersca";
 
     // Date after the restrictions take effect
     private static final ZonedDateTime DISTRUST_DATE =
@@ -56,7 +56,7 @@ public class Camerfirma {
 
     public static void main(String[] args) throws Exception {
 
-        // All of the test certificates are signed with SHA-1 so we need
+        // All the test certificates are signed with SHA-1, so we need
         // to remove the constraint that disallows SHA-1 certificates.
         String prop = Security.getProperty("jdk.certpath.disabledAlgorithms");
         String newProp = prop.replace(", SHA1 jdkCA & usage TLSServer", "");
@@ -70,6 +70,6 @@ public class Camerfirma {
         };
 
         Date notBefore = distrust.getNotBefore(DISTRUST_DATE);
-        distrust.testCertificateChain(certPath, notBefore, tms, rootsToTest);
+        distrust.testCertificateChain(CERT_PATH, notBefore, tms, ROOT_TO_TEST);
     }
 }
diff -pruN 24.0.1+9-1/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachamberscommerceca-chain.pem 24.0.2+12-1/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachamberscommerceca-chain.pem
--- 24.0.1+9-1/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachamberscommerceca-chain.pem	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachamberscommerceca-chain.pem	1970-01-01 00:00:00.000000000 +0000
@@ -1,48 +0,0 @@
-Owner:   CN=AC Camerfirma Certificados Camerales,
-         O=AC Camerfirma SA, SERIALNUMBER=A82743287,
-         L=Madrid (see current address at www.camerfirma.com/address),
-         EMAILADDRESS=ac_camerfirma_cc@camerfirma.com, C=ES
-Issuer:  CN=Chambers of Commerce Root, OU=http://www.chambersign.org,
-         O=AC Camerfirma SA CIF A82743287, C=EU
-Serial number: 5
-Valid from: Mon Feb 09 07:42:47 PST 2004 until: Thu Feb 09 07:42:47 PST 2034
-Certificate fingerprints:
-         SHA1: 9F:36:B4:BE:9D:AF:1C:91:01:B2:D7:61:58:FB:95:CB:53:82:01:10
-         SHA256: C7:D8:43:81:E1:1F:7C:57:46:77:1A:F5:B0:50:DC:51:FC:6F:DA:D6:F6:F3:5B:B5:3A:3D:E9:13:82:2E:A0:9E
-Signature algorithm name: SHA1withRSA (weak)
-Subject Public Key Algorithm: 2048-bit RSA key
-Version: 3
-
------BEGIN CERTIFICATE-----
-MIIFwDCCBKigAwIBAgIBBTANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn
-MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL
-ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg
-b2YgQ29tbWVyY2UgUm9vdDAeFw0wNDAyMDkxNTQyNDdaFw0zNDAyMDkxNTQyNDda
-MIHgMQswCQYDVQQGEwJFUzEuMCwGCSqGSIb3DQEJARYfYWNfY2FtZXJmaXJtYV9j
-Y0BjYW1lcmZpcm1hLmNvbTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBh
-ZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
-QTgyNzQzMjg3MRkwFwYDVQQKExBBQyBDYW1lcmZpcm1hIFNBMS0wKwYDVQQDEyRB
-QyBDYW1lcmZpcm1hIENlcnRpZmljYWRvcyBDYW1lcmFsZXMwggEgMA0GCSqGSIb3
-DQEBAQUAA4IBDQAwggEIAoIBAQCjxnvvj01f36lgGhihRYVf1fAPEXsTJKrY4aLQ
-cEUSh5szZE7VTtGiyMTMc2uCmnaXafjYHK8Lgmy6T9xxGEZ5OS4x6rgtuPyy13AP
-tu3X3Y2kPVLu7ZMw5HoQC64wBj6YcnxTnBwmVW05DjzRXp6OyBIEKEaAB9vv2qEl
-fh/Y234FG6Wd/ut1s0ScRZAo+6CSMNQxaY+ryXKD11uWkzWXJa9UZOasG7z4uPqc
-Gr4/Hz2/CTLDTgp0xkMJYuzOztpUvOACrxlkS2utKUwVlAikJnboNwf/en94RbHN
-zkKc5t0SAbzCf57ueawbzxSdPa+SAC25FNur64FKkfdq5PPjAgEDo4IB5TCCAeEw
-EgYDVR0TAQH/BAgwBgEB/wIBCzA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vY3Js
-LmNoYW1iZXJzaWduLm9yZy9jaGFtYmVyc3Jvb3QuY3JsMB0GA1UdDgQWBBS2H06d
-HGiRLjdyYOFGj1qlKjExuTCBqwYDVR0jBIGjMIGggBTjlPWxTenboSlbV4tNdgZ2
-4dGiiqGBhKSBgTB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt
-YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJz
-aWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdIIBADAO
-BgNVHQ8BAf8EBAMCAYYwKgYDVR0RBCMwIYEfYWNfY2FtZXJmaXJtYV9jY0BjYW1l
-cmZpcm1hLmNvbTAnBgNVHRIEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24u
-b3JnMFsGA1UdIARUMFIwUAYLKwYBBAGBhy4KCQEwQTA/BggrBgEFBQcCARYzaHR0
-cDovL2Nwcy5jYW1lcmZpcm1hLmNvbS9jcHMvYWNfY2FtZXJmaXJtYV9jYy5odG1s
-MA0GCSqGSIb3DQEBBQUAA4IBAQBl8KoPBYL//EBonqQWS0N+hLfxImP1eQ6nac+v
-R5QfF/0w+VCTkShfKwHaa6V/W1dPlVwXSECuvXHkX6DYrtxFGGFB6qxuP1rkIpRs
-sTkAlpvOx3REiFjIkhsijKd/ijvqxjbMbuYU+EFACK/jQIRoj+LEEZ+haiqbALZB
-Iqq/26HTqX0itDosBj6M94YWcIpbTDefQNWCGsSnZcw2+k+az/wAOZT6xAxlnEim
-HpDDlgRsmaLrHpDPDoIRYOih0gbJTnn4mKex9Wgr0sZ+XFl03j+bvcXL1tiuQnwb
-9dMRDe/OdXABT35W4ZzLbpost65ZW3Tx+oi/bLbmu6pbKCgs
------END CERTIFICATE-----
diff -pruN 24.0.1+9-1/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachambersignca-chain.pem 24.0.2+12-1/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachambersignca-chain.pem
--- 24.0.1+9-1/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachambersignca-chain.pem	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachambersignca-chain.pem	1970-01-01 00:00:00.000000000 +0000
@@ -1,62 +0,0 @@
-Owner:   CN=AC Camerfirma - 2009,
-         L=Madrid (see current address at https://www.camerfirma.com/address),
-         SERIALNUMBER=A82743287, O=AC Camerfirma S.A., C=ES
-Issuer:  CN=Global Chambersign Root - 2008,
-         O=AC Camerfirma S.A., SERIALNUMBER=A82743287,
-         L=Madrid (see current address at www.camerfirma.com/address), C=EU
-Serial number: 2
-Valid from: Mon Mar 16 10:16:25 PDT 2009 until: Sun Mar 11 10:16:25 PDT 2029
-Certificate fingerprints:
-         SHA1: BA:BA:69:CF:D5:CC:C9:4D:05:6B:5B:E7:80:5F:E2:03:CB:EB:5C:57
-         SHA256: B6:8D:5D:9B:4E:A6:35:95:7C:0C:32:15:C2:0D:35:B2:21:7B:69:E3:49:C7:A3:04:C4:F9:7F:20:C4:08:1F:88
-Signature algorithm name: SHA1withRSA (weak)
-Subject Public Key Algorithm: 4096-bit RSA key
-Version: 3
-
------BEGIN CERTIFICATE-----
-MIIIPzCCBiegAwIBAgIBAjANBgkqhkiG9w0BAQUFADCBrDELMAkGA1UEBhMCRVUx
-QzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2Ft
-ZXJmaXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UE
-ChMSQUMgQ2FtZXJmaXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNp
-Z24gUm9vdCAtIDIwMDgwHhcNMDkwMzE2MTcxNjI1WhcNMjkwMzExMTcxNjI1WjCB
-qjELMAkGA1UEBhMCRVMxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjESMBAG
-A1UEBRMJQTgyNzQzMjg3MUswSQYDVQQHE0JNYWRyaWQgKHNlZSBjdXJyZW50IGFk
-ZHJlc3MgYXQgaHR0cHM6Ly93d3cuY2FtZXJmaXJtYS5jb20vYWRkcmVzcykxHTAb
-BgNVBAMTFEFDIENhbWVyZmlybWEgLSAyMDA5MIICIjANBgkqhkiG9w0BAQEFAAOC
-Ag8AMIICCgKCAgEAmbHxFEYTJmMdPcYiPlWUGZu2+tQo4voohYi3dwCwoVuGdHSp
-kyoqs1B3YGx4u5KT4n0A7+Bb8YQ/QzbNy7UQ4JXAK+rT8JpNeKIvfN4lHnQJaChE
-4fdn0KpvHWymaNq2k+EbQClquZB6OsTLvsivwSuSnyLcUw5rbajj53wq77fwB12y
-phMjwz2AnD1BvHZd3vLOaH1jRQP3zzNmyjT/Oj6+jdux7SBKlJWgQEaKflwcvYyc
-DPFPhGM4KPwEGX61PCrS+l8Lw0Kdy6K4lE+GrfgJrXM5m1Ey1R0c9McYQQPAtYcm
-cOnHHgkJdEAFVDa76T9C+lcMP6DNckbJIyc/ENrmM2v4rq/JnsJKEEx0VLyLizQx
-cGU3gp4ckg0ImQ9hV3H/DLWEqfrPuD++zaV81gpstnc9+pLg0Jibvwg3qvIr7nS5
-acc//qqxH0iJGYoStHW5J5HoM9HcBvhACq5rjzjrNLPYSJqbPJwBHKcql/uUjQ6S
-SVWe3/CeJp6/vGuY1aRXAk9c/8oO0ZDrLKE8LsUgZesTLnWGd1LQcyQf6UMG1nb9
-5C3eZRkCVpKma6Hl/SUQNukerlbLOU9InFGNPdeEVq1Jo62XeEi8KMbTPdXou6Yl
-rpe99dFnOUjVOdY7gfBGSgIVJjORqf/V70jwsxcYz7j6PKl0XulJs06vpSECAwEA
-AaOCAmowggJmMBIGA1UdEwEB/wQIMAYBAf8CAQIwHQYDVR0OBBYEFMgAD/zGUvyf
-2ztkLjK5bi5x82V5MIHhBgNVHSMEgdkwgdaAFLkJypwe29NsOmuu7VTxW5MGNS5e
-oYGypIGvMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy
-cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG
-A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl
-BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwOIIJAMnN0+nVfSPO
-MH0GCCsGAQUFBwEBBHEwbzBFBggrBgEFBQcwAoY5aHR0cDovL3d3dy5jYW1lcmZp
-cm1hLmNvbS9jZXJ0cy9yb290X2NoYW1iZXJzaWduLTIwMDguY3J0MCYGCCsGAQUF
-BzABhhpodHRwOi8vb2NzcC5jYW1lcmZpcm1hLmNvbTAOBgNVHQ8BAf8EBAMCAQYw
-PgYDVR0gBDcwNTAzBgRVHSAAMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vcG9saWN5
-LmNhbWVyZmlybWEuY29tMH4GA1UdHwR3MHUwOKA2oDSGMmh0dHA6Ly9jcmwuY2Ft
-ZXJmaXJtYS5jb20vY2hhbWJlcnNpZ25yb290LTIwMDguY3JsMDmgN6A1hjNodHRw
-Oi8vY3JsMS5jYW1lcmZpcm1hLmNvbS9jaGFtYmVyc2lnbnJvb3QtMjAwOC5jcmww
-DQYJKoZIhvcNAQEFBQADggIBABNYG4jBwoI7e8pCuUyDc6rwpE9H6AgrUdL7O1xK
-TgTjDGBrMOBK+ZPS4Si8J3yZngvSrL694a1HmiiblJ+CmCdNGli2nBBM+OPK3tQB
-4TW6hgkIe3vSNg/9o9y6+MAJcm8Kn0nPCBkSRME87NwvpehtekuF1G2ng1KDVwAn
-F+eCXfNanEwY++vWbJAuPE69Z/0+rCgNyH1PzihiNu6vrUlSlLWKaG34O1DEttX+
-SsWTpEbpH9w5y9Vmw6WQ/B5nfhPM551HaMbiGgSxT9jHmf8APYQ3iT8EktcdTAdw
-m1miiyxfKG+WjPT7P/x8Np1spJZw+sNIDTLdZ0T1XQ6obVkBTFUDSULKW8949HDu
-VSwdl9Hu9lkDzzh9tyVYwwjEWVFZOiD/4TPVLfphf4ZEiyHt5YpNd9kZJIGGDxdc
-CdtzPm2dQODFpv72LnPQHbuBQPJ71zkoAmyeM/1Qj0DlrFsPcYnbRasck1VmYgDc
-Xc0+is0wcgCd7Gpx1zpEeVqwMD96am2xZPzd6nsbXvo+6TzsKLRMJo6nOERwrzuI
-F+/eq3WXxYMt2UenJsHqwSgPJRMdl3SFz0+SZN0viHeLuwb7qaHN74qC6GP8yHGp
-2xe6Z11mJDPLDSrQQ2dOceSJ1LurJgLP7amYmFlWwVnmM7LnfShhMWMV+MDrICnL
-2ksL
------END CERTIFICATE-----
diff -pruN 24.0.1+9-1/test/jdk/sun/security/tools/jarsigner/ConciseJarsigner.java 24.0.2+12-1/test/jdk/sun/security/tools/jarsigner/ConciseJarsigner.java
--- 24.0.1+9-1/test/jdk/sun/security/tools/jarsigner/ConciseJarsigner.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/tools/jarsigner/ConciseJarsigner.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -43,8 +43,15 @@ public class ConciseJarsigner {
     static OutputAnalyzer kt(String cmd) throws Exception {
         // Choose 2048-bit RSA to make sure it runs fine and fast. In
         // fact, every keyalg/keysize combination is OK for this test.
-        return SecurityTools.keytool("-storepass changeit -keypass changeit "
-                + "-keystore ks -keyalg rsa -keysize 2048 " + cmd);
+        // The start date is set to -1M to prevent the certificate not yet valid during fast enough execution.
+        // If -startdate is specified in cmd, cmd version will be used.
+        if (cmd.contains("-startdate")) {
+            return SecurityTools.keytool("-storepass changeit -keypass changeit "
+                    + "-keystore ks -keyalg rsa -keysize 2048 " + cmd);
+        } else {
+            return SecurityTools.keytool("-storepass changeit -keypass changeit "
+                    + "-keystore ks -keyalg rsa -keysize 2048 -startdate -1M " + cmd);
+        }
     }
 
     static void gencert(String owner, String cmd) throws Exception {
diff -pruN 24.0.1+9-1/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java 24.0.2+12-1/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java
--- 24.0.1+9-1/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java	2025-06-27 08:03:14.000000000 +0000
@@ -905,7 +905,7 @@ public class TimestampCheck {
         }
 
         gencert("tsold", "-ext eku:critical=ts -startdate -40d -validity 500");
-        gencert("tsbefore2019", "-ext eku:critical=ts -startdate 2018/01/01 -validity 3000");
+        gencert("tsbefore2019", "-ext eku:critical=ts -startdate 2018/01/01 -validity 5000");
 
         gencert("tsweak", "-ext eku:critical=ts");
         gencert("tsdisabled", "-ext eku:critical=ts");
diff -pruN 24.0.1+9-1/test/jdk/sun/security/tools/jarsigner/TsacertOptionTest.java 24.0.2+12-1/test/jdk/sun/security/tools/jarsigner/TsacertOptionTest.java
--- 24.0.1+9-1/test/jdk/sun/security/tools/jarsigner/TsacertOptionTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/tools/jarsigner/TsacertOptionTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2024, 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
@@ -103,6 +103,7 @@ public class TsacertOptionTest extends T
                 "-alias", CA_KEY_ALIAS,
                 "-keystore", KEYSTORE,
                 "-storepass", PASSWORD,
+                "-startdate", "-1M",
                 "-keypass", PASSWORD,
                 "-validity", Integer.toString(VALIDITY),
                 "-infile", "certreq",
diff -pruN 24.0.1+9-1/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java 24.0.2+12-1/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java
--- 24.0.1+9-1/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2024, 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
@@ -67,6 +67,7 @@ import java.util.jar.Manifest;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
+import jdk.security.jarsigner.JarSigner;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.util.JarUtils;
@@ -1437,7 +1438,9 @@ public class Compatibility {
         String expectedDigestAlg() {
             return digestAlgorithm != null
                     ? digestAlgorithm
-                    : jdkInfo.majorVersion >= 20 ? "SHA-384" : "SHA-256";
+                    : jdkInfo.majorVersion >= 20
+                        ? JarSigner.Builder.getDefaultDigestAlgorithm()
+                        : "SHA-256";
         }
 
         private SignItem tsaDigestAlgorithm(String tsaDigestAlgorithm) {
@@ -1446,7 +1449,11 @@ public class Compatibility {
         }
 
         String expectedTsaDigestAlg() {
-            return tsaDigestAlgorithm != null ? tsaDigestAlgorithm : "SHA-256";
+            return tsaDigestAlgorithm != null
+                    ? tsaDigestAlgorithm
+                    : jdkInfo.majorVersion >= 20
+                        ? JarSigner.Builder.getDefaultDigestAlgorithm()
+                        : "SHA-256";
         }
 
         private SignItem tsaIndex(int tsaIndex) {
diff -pruN 24.0.1+9-1/test/jdk/sun/security/tools/keytool/KeyToolTest.java 24.0.2+12-1/test/jdk/sun/security/tools/keytool/KeyToolTest.java
--- 24.0.1+9-1/test/jdk/sun/security/tools/keytool/KeyToolTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/tools/keytool/KeyToolTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @library /java/security/testlibrary
+ * @library /test/lib
  * @bug 6251120 8231950 8242151
  * @summary Testing keytool
  *
@@ -68,10 +68,10 @@ import java.security.NoSuchAlgorithmExce
 import java.util.*;
 import java.security.cert.X509Certificate;
 import jdk.test.lib.util.FileUtils;
+import jdk.test.lib.security.HumanInputStream;
 import jdk.test.lib.security.SecurityUtils;
 import sun.security.util.ObjectIdentifier;
 
-
 public class KeyToolTest {
 
     // The stdout and stderr outputs after a keytool run
diff -pruN 24.0.1+9-1/test/jdk/sun/security/tools/keytool/NssTest.java 24.0.2+12-1/test/jdk/sun/security/tools/keytool/NssTest.java
--- 24.0.1+9-1/test/jdk/sun/security/tools/keytool/NssTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/tools/keytool/NssTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -29,7 +29,7 @@ import java.nio.file.Paths;
 /*
  * @test
  * @summary It tests (almost) all keytool behaviors with NSS.
- * @library /test/lib /test/jdk/sun/security/pkcs11 /java/security/testlibrary
+ * @library /test/lib /test/jdk/sun/security/pkcs11
  * @modules java.base/sun.security.tools.keytool
  *          java.base/sun.security.util
  *          java.base/sun.security.x509
diff -pruN 24.0.1+9-1/test/jdk/sun/security/x509/URICertStore/AIACertTimeout.java 24.0.2+12-1/test/jdk/sun/security/x509/URICertStore/AIACertTimeout.java
--- 24.0.1+9-1/test/jdk/sun/security/x509/URICertStore/AIACertTimeout.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/sun/security/x509/URICertStore/AIACertTimeout.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 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
@@ -27,8 +27,7 @@
  * @summary Enhance OCSP, CRL and Certificate Fetch Timeouts
  * @modules java.base/sun.security.x509
  *          java.base/sun.security.util
- * @library /test/lib ../../../../java/security/testlibrary
- * @build CertificateBuilder
+ * @library /test/lib
  * @run main/othervm -Dcom.sun.security.enableAIAcaIssuers=true
  *      -Dcom.sun.security.cert.readtimeout=1 AIACertTimeout 5000 false
  * @run main/othervm -Dcom.sun.security.enableAIAcaIssuers=true
@@ -55,10 +54,7 @@ import java.security.spec.*;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 
-import sun.security.testlibrary.CertificateBuilder;
-
-import sun.security.x509.*;
-import sun.security.util.*;
+import jdk.test.lib.security.CertificateBuilder;
 
 public class AIACertTimeout {
 
diff -pruN 24.0.1+9-1/test/jdk/tools/jimage/JImageToolTest.java 24.0.2+12-1/test/jdk/tools/jimage/JImageToolTest.java
--- 24.0.1+9-1/test/jdk/tools/jimage/JImageToolTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/tools/jimage/JImageToolTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -23,6 +23,7 @@
 /*
  * @test
  * @library /test/lib
+ * @requires vm.flagless
  * @build jdk.test.lib.process.ProcessTools
  * @summary Test to check if jimage tool exists and is working
  * @run main/timeout=360 JImageToolTest
diff -pruN 24.0.1+9-1/test/jdk/tools/jlink/runtimeImage/UpgradeableFileCacertsTest.java 24.0.2+12-1/test/jdk/tools/jlink/runtimeImage/UpgradeableFileCacertsTest.java
--- 24.0.1+9-1/test/jdk/tools/jlink/runtimeImage/UpgradeableFileCacertsTest.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/jdk/tools/jlink/runtimeImage/UpgradeableFileCacertsTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2025, Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import tests.Helper;
+
+/*
+ * @test
+ * @summary Verify that no errors are reported for files that have been
+ *          upgraded when linking from the run-time image
+ * @requires (vm.compMode != "Xcomp" & os.maxMemory >= 2g)
+ * @library ../../lib /test/lib
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.plugin
+ *          jdk.jlink/jdk.tools.jimage
+ * @build tests.* jdk.test.lib.process.OutputAnalyzer
+ *        jdk.test.lib.process.ProcessTools
+ * @run main/othervm -Xmx1g UpgradeableFileCacertsTest
+ */
+public class UpgradeableFileCacertsTest extends ModifiedFilesTest {
+
+    /*
+     * Generated with:
+     * $ rm -f server.keystore && keytool -genkey -alias jlink-upgrade-test \
+     *                              -keyalg RSA -dname CN=jlink-upgrade-test \
+     *                              -storepass changeit -keysize 3072 -sigalg SHA512withRSA \
+     *                              -validity 7300 -keystore server.keystore
+     * $ keytool -export -alias jlink-upgrade-test -storepass changeit \
+     *           -keystore server.keystore -rfc
+     */
+    private static final String CERT = """
+            -----BEGIN CERTIFICATE-----
+            MIID3jCCAkagAwIBAgIJALiT/+HXBkSIMA0GCSqGSIb3DQEBDQUAMB0xGzAZBgNV
+            BAMTEmpsaW5rLXVwZ3JhZGUtdGVzdDAeFw0yNTA0MDQxMjA3MjJaFw00NTAzMzAx
+            MjA3MjJaMB0xGzAZBgNVBAMTEmpsaW5rLXVwZ3JhZGUtdGVzdDCCAaIwDQYJKoZI
+            hvcNAQEBBQADggGPADCCAYoCggGBANmrnCDKqSXEJRIiSi4yHWN97ILls3RqYjED
+            la3AZTeXnZrrEIgSjVFUMxCztYqbWoVzKa2lov42Vue2BXVYffcQ8TKc2EJDNO+2
+            uRKQZpsN7RI4QoVBR2Rq8emrO8CrdOQT7Hh4agxkN9AOvGKMFdt+fXeCIPIuflKP
+            f+RfvhLfC2A70Y+Uu74C5uWgLloA/HF0SsVxf9KmqS9fZBQaiTYhKyoDghCRlWpa
+            nPIHB1XVaRdw8aSpCuzIOQzSCTTlLcammJkBjbFwMZdQG7eglTWzIYryZwe/cyY2
+            xctLVW3xhUHvnMFG+MajeFny2mxNu163Rxf/rBu4e7jRC/LGSU784nJGapq5K170
+            WbaeceKp+YORJBviFFORrmkPIwIgE+iGCD6PD6Xwu8vcpeuTVDgsSWMlfgCL3NoI
+            GXmdGiI2Xc/hQX7uzu3UBF6IcPDMTcYr2JKYbgu3v2/vDlJu3qO2ycUeePo5jhuG
+            X2WgcHkb6uOU4W5qdbCA+wFPVZBuwQIDAQABoyEwHzAdBgNVHQ4EFgQUtMJM0+ct
+            ssKqryRckk4YEWdYAZkwDQYJKoZIhvcNAQENBQADggGBAI8A6gJQ8wDx12sy2ZI4
+            1q9b+WG6w3LcFEF6Fko5NBizhtfmVycQv4mBa/NJgx4DZmd+5d60gJcTp/hJXGY0
+            LZyFilm/AgxsLNUUQLbHAV6TWqd3ODWwswAuew9sFU6izl286a9W65tbMWL5r1EA
+            t34ZYVWZYbCS9+czU98WomH4uarRAOlzcEUui3ZX6ZcQxWbz/R2wtKcUPUAYnsqH
+            JPivpE25G5xW2Dp/yeQTrlffq9OLgZWVz0jtOguBUMnsUsgCcpQZtqZX08//wtpz
+            ohLHFGvpXTPbRumRasWWtnRR/QqGRT66tYDqybXXz37UtKZ8VKW0sv2ypVbmAEs5
+            pLkA/3XiXlstJuCD6cW0Gfbpb5rrPPD46O3FDVlmqlTH3b/MsiQREdydqGzqY7uG
+            AA2GFVaKFASA5ls01CfHLAcrKxSVixditXvsjeIqhddB7Pnbsx20RdzPQoeo9/hF
+            WeIrh4zePDPZChuLR8ZyxeVJhLB71nTrTDDjwXarVez9Xw==
+            -----END CERTIFICATE-----
+            """;
+
+    private static final String CERT_ALIAS = "jlink-upgrade-test";
+
+    public static void main(String[] args) throws Exception {
+        UpgradeableFileCacertsTest test = new UpgradeableFileCacertsTest();
+        test.run();
+    }
+
+    @Override
+    String initialImageName() {
+        return "java-base-jlink-upgrade-cacerts";
+    }
+
+    @Override
+    void testAndAssert(Path modifiedFile, Helper helper, Path initialImage) throws Exception {
+        CapturingHandler handler = new CapturingHandler();
+        jlinkUsingImage(new JlinkSpecBuilder()
+                                .helper(helper)
+                                .imagePath(initialImage)
+                                .name("java-base-jlink-upgrade-cacerts-target")
+                                .addModule("java.base")
+                                .validatingModule("java.base")
+                                .build(), handler);
+        OutputAnalyzer analyzer = handler.analyzer();
+        // verify we don't get any modified warning
+        analyzer.stdoutShouldNotContain(modifiedFile.toString() + " has been modified");
+        analyzer.stdoutShouldNotContain("java.lang.IllegalArgumentException");
+        analyzer.stdoutShouldNotContain("IOException");
+    }
+
+    // Add an extra certificate in the cacerts file so that it no longer matches
+    // the recorded hash sum at build time.
+    protected Path modifyFileInImage(Path jmodLessImg)
+            throws IOException, AssertionError {
+        Path cacerts = jmodLessImg.resolve(Path.of("lib", "security", "cacerts"));
+        try (FileInputStream fin = new FileInputStream(cacerts.toFile())) {
+            KeyStore certStore = KeyStore.getInstance(cacerts.toFile(),
+                                                      (char[])null);
+            certStore.load(fin, (char[])null);
+            X509Certificate cert;
+            try (ByteArrayInputStream bin = new ByteArrayInputStream(CERT.getBytes())) {
+                cert = (X509Certificate)generateCertificate(bin);
+            } catch (ClassCastException | CertificateException ce) {
+                throw new AssertionError("Test failed unexpectedly", ce);
+            }
+            certStore.setCertificateEntry(CERT_ALIAS, cert);
+            ByteArrayOutputStream bout = new ByteArrayOutputStream();
+            certStore.store(bout, (char[])null);
+            try (FileOutputStream fout = new FileOutputStream(cacerts.toFile())) {
+                fout.write(bout.toByteArray());
+            }
+        } catch (Exception e) {
+            throw new AssertionError("Test failed unexpectedly: ", e);
+        }
+        return cacerts;
+    }
+
+    private Certificate generateCertificate(InputStream in)
+            throws CertificateException, IOException {
+        byte[] data = in.readAllBytes();
+        return CertificateFactory.getInstance("X.509")
+                                 .generateCertificate(new ByteArrayInputStream(data));
+    }
+}
diff -pruN 24.0.1+9-1/test/jdk/tools/jpackage/TEST.properties 24.0.2+12-1/test/jdk/tools/jpackage/TEST.properties
--- 24.0.1+9-1/test/jdk/tools/jpackage/TEST.properties	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/tools/jpackage/TEST.properties	2025-06-27 08:03:14.000000000 +0000
@@ -14,4 +14,5 @@ exclusiveAccess.dirs=share windows
 modules=jdk.jpackage/jdk.jpackage.internal:+open \
         jdk.jpackage/jdk.jpackage.internal.util \
         jdk.jpackage/jdk.jpackage.internal.util.function \
-        java.base/jdk.internal.util
+        java.base/jdk.internal.util \
+        jdk.jlink/jdk.tools.jlink.internal
diff -pruN 24.0.1+9-1/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java 24.0.2+12-1/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java
--- 24.0.1+9-1/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 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
@@ -53,7 +53,6 @@ public final class Executor extends Comm
 
     public Executor() {
         saveOutputType = new HashSet<>(Set.of(SaveOutputType.NONE));
-        removePathEnvVar = false;
         winEnglishOutput = false;
     }
 
@@ -86,8 +85,8 @@ public final class Executor extends Comm
         return setExecutable(v.getPath());
     }
 
-    public Executor setRemovePathEnvVar(boolean value) {
-        removePathEnvVar = value;
+    public Executor removeEnvVar(String envVarName) {
+        removeEnvVars.add(Objects.requireNonNull(envVarName));
         return this;
     }
 
@@ -372,10 +371,12 @@ public final class Executor extends Comm
             builder.directory(directory.toFile());
             sb.append(String.format("; in directory [%s]", directory));
         }
-        if (removePathEnvVar) {
-            // run this with cleared Path in Environment
-            TKit.trace("Clearing PATH in environment");
-            builder.environment().remove("PATH");
+        if (!removeEnvVars.isEmpty()) {
+            final var envComm = Comm.compare(builder.environment().keySet(), removeEnvVars);
+            builder.environment().keySet().removeAll(envComm.common());
+            envComm.common().forEach(envVar -> {
+                TKit.trace(String.format("Clearing %s in environment", envVar));
+            });
         }
 
         trace("Execute " + sb.toString() + "...");
@@ -504,7 +505,7 @@ public final class Executor extends Comm
     private Path executable;
     private Set<SaveOutputType> saveOutputType;
     private Path directory;
-    private boolean removePathEnvVar;
+    private Set<String> removeEnvVars = new HashSet<>();
     private boolean winEnglishOutput;
     private String winTmpDir = null;
 
diff -pruN 24.0.1+9-1/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java 24.0.2+12-1/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java
--- 24.0.1+9-1/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 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
@@ -472,14 +472,14 @@ public final class HelloApp {
                 }
             }
 
-            final List<String> launcherArgs = List.of(args);
-            return new Executor()
+            final var executor = new Executor()
                     .setDirectory(outputFile.getParent())
                     .saveOutput(saveOutput)
                     .dumpOutput()
-                    .setRemovePathEnvVar(removePathEnvVar)
                     .setExecutable(executablePath)
-                    .addArguments(launcherArgs);
+                    .addArguments(List.of(args));
+
+            return configureEnvironment(executor);
         }
 
         private boolean launcherNoExit;
@@ -496,6 +496,14 @@ public final class HelloApp {
         return new AppOutputVerifier(helloAppLauncher);
     }
 
+    public static Executor configureEnvironment(Executor executor) {
+        if (CLEAR_JAVA_ENV_VARS) {
+            executor.removeEnvVar("JAVA_TOOL_OPTIONS");
+            executor.removeEnvVar("_JAVA_OPTIONS");
+        }
+        return executor;
+    }
+
     static final String OUTPUT_FILENAME = "appOutput.txt";
 
     private final JavaAppDesc appDesc;
@@ -505,4 +513,7 @@ public final class HelloApp {
 
     private static final String CLASS_NAME = HELLO_JAVA.getFileName().toString().split(
             "\\.", 2)[0];
+
+    private static final boolean CLEAR_JAVA_ENV_VARS = Optional.ofNullable(
+            TKit.getConfigProperty("clear-app-launcher-java-env-vars")).map(Boolean::parseBoolean).orElse(false);
 }
diff -pruN 24.0.1+9-1/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java 24.0.2+12-1/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java
--- 24.0.1+9-1/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 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
@@ -593,7 +593,7 @@ public final class JPackageCommand exten
     }
 
     public boolean isFakeRuntime(String msg) {
-        if (isFakeRuntime()) {
+        if (isFakeRuntime(appRuntimeDirectory())) {
             // Fake runtime
             Path runtimeDir = appRuntimeDirectory();
             TKit.trace(String.format(
@@ -604,7 +604,7 @@ public final class JPackageCommand exten
         return false;
     }
 
-    private boolean isFakeRuntime() {
+    private static boolean isFakeRuntime(Path runtimeDir) {
         final Collection<Path> criticalRuntimeFiles;
         if (TKit.isWindows()) {
             criticalRuntimeFiles = WindowsHelper.CRITICAL_RUNTIME_FILES;
@@ -616,7 +616,6 @@ public final class JPackageCommand exten
             throw TKit.throwUnknownPlatformError();
         }
 
-        Path runtimeDir = appRuntimeDirectory();
         return !criticalRuntimeFiles.stream().map(runtimeDir::resolve).allMatch(
                 Files::exists);
     }
@@ -690,10 +689,8 @@ public final class JPackageCommand exten
     }
 
     public JPackageCommand ignoreFakeRuntime() {
-        if (isFakeRuntime()) {
-            ignoreDefaultRuntime(true);
-        }
-        return this;
+        return ignoreDefaultRuntime(Optional.ofNullable(DEFAULT_RUNTIME_IMAGE)
+                .map(JPackageCommand::isFakeRuntime).orElse(false));
     }
 
     public JPackageCommand ignoreDefaultVerbose(boolean v) {
diff -pruN 24.0.1+9-1/test/jdk/tools/jpackage/share/AppLauncherEnvTest.java 24.0.2+12-1/test/jdk/tools/jpackage/share/AppLauncherEnvTest.java
--- 24.0.1+9-1/test/jdk/tools/jpackage/share/AppLauncherEnvTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/tools/jpackage/share/AppLauncherEnvTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -30,6 +30,7 @@ import java.util.stream.Stream;
 import jdk.jpackage.test.JPackageCommand;
 import jdk.jpackage.test.Annotations.Test;
 import jdk.jpackage.test.Executor;
+import static jdk.jpackage.test.HelloApp.configureEnvironment;
 import jdk.jpackage.test.TKit;
 
 /**
@@ -53,6 +54,7 @@ public class AppLauncherEnvTest {
 
         JPackageCommand cmd = JPackageCommand
                 .helloAppImage(TEST_APP_JAVA + "*Hello")
+                .ignoreFakeRuntime()
                 .addArguments("--java-options", "-D" + testAddDirProp
                         + "=$APPDIR");
 
@@ -62,7 +64,7 @@ public class AppLauncherEnvTest {
 
         final int attempts = 3;
         final int waitBetweenAttemptsSeconds = 5;
-        List<String> output = new Executor()
+        List<String> output = configureEnvironment(new Executor())
                 .saveOutput()
                 .setExecutable(cmd.appLauncherPath().toAbsolutePath())
                 .addArguments("--print-env-var=" + envVarName)
diff -pruN 24.0.1+9-1/test/jdk/tools/jpackage/share/BasicTest.java 24.0.2+12-1/test/jdk/tools/jpackage/share/BasicTest.java
--- 24.0.1+9-1/test/jdk/tools/jpackage/share/BasicTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/tools/jpackage/share/BasicTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -27,6 +27,8 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.List;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Optional;
 import java.util.function.Function;
 import java.util.function.Predicate;
@@ -41,7 +43,9 @@ import jdk.jpackage.test.Executor;
 import jdk.jpackage.test.JavaTool;
 import jdk.jpackage.test.Annotations.Test;
 import jdk.jpackage.test.Annotations.Parameter;
+import jdk.jpackage.test.Annotations.ParameterSupplier;
 import jdk.jpackage.internal.util.function.ThrowingConsumer;
+import jdk.tools.jlink.internal.LinkableRuntimeImage;
 import static jdk.jpackage.test.RunnablePackageTest.Action.CREATE_AND_UNPACK;
 
 /*
@@ -55,6 +59,32 @@ import static jdk.jpackage.test.Runnable
  */
 
 public final class BasicTest {
+
+    public static Collection addModulesParams() {
+        List<Object[][]> params = new ArrayList<>();
+        params.add(new Object[][] { new String[] { "--add-modules", "ALL-DEFAULT"  } });
+        params.add(new Object[][] { new String[] { "--add-modules", "java.desktop" } });
+        params.add(new Object[][] { new String[] { "--add-modules", "java.desktop,jdk.jartool" } });
+        params.add(new Object[][] { new String[] { "--add-modules", "java.desktop", "--add-modules", "jdk.jartool" } });
+        if (isAllModulePathCapable()) {
+            final Path jmods = Path.of(System.getProperty("java.home"), "jmods");
+            params.add(new Object[][] { new String[] { "--add-modules", "ALL-MODULE-PATH",
+                                                       // Since JDK-8345259 ALL-MODULE-PATH requires --module-path arg
+                                                       "--module-path", jmods.toString() } });
+        }
+        return Collections.unmodifiableList(params);
+    }
+
+    private static boolean isAllModulePathCapable() {
+        Path jmods = Path.of(System.getProperty("java.home"), "jmods");
+        boolean noJmods = Files.notExists(jmods);
+        if (LinkableRuntimeImage.isLinkableRuntime() && noJmods) {
+           TKit.trace("ALL-MODULE-PATH test skipped for linkable run-time image");
+           return false;
+        }
+        return true;
+    }
+
     @Test
     public void testNoArgs() {
         List<String> output =
@@ -306,17 +336,12 @@ public final class BasicTest {
     }
 
     @Test
-    @Parameter("ALL-MODULE-PATH")
-    @Parameter("ALL-DEFAULT")
-    @Parameter("java.desktop")
-    @Parameter("java.desktop,jdk.jartool")
-    @Parameter({ "java.desktop", "jdk.jartool" })
-    public void testAddModules(String... addModulesArg) {
+    @ParameterSupplier("addModulesParams")
+    public void testAddModules(String[] addModulesArg) {
         JPackageCommand cmd = JPackageCommand
                 .helloAppImage("goodbye.jar:com.other/com.other.Hello")
                 .ignoreDefaultRuntime(true); // because of --add-modules
-        Stream.of(addModulesArg).map(v -> Stream.of("--add-modules", v)).flatMap(
-                s -> s).forEachOrdered(cmd::addArgument);
+        Stream.of(addModulesArg).forEachOrdered(cmd::addArgument);
         cmd.executeAndAssertHelloAppImageCreated();
     }
 
diff -pruN 24.0.1+9-1/test/jdk/tools/jpackage/share/JLinkOptionsTest.java 24.0.2+12-1/test/jdk/tools/jpackage/share/JLinkOptionsTest.java
--- 24.0.1+9-1/test/jdk/tools/jpackage/share/JLinkOptionsTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/tools/jpackage/share/JLinkOptionsTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -58,24 +58,26 @@ public final class JLinkOptionsTest {
                     "--jlink-options",
                     "--strip-debug --no-man-pages --no-header-files",
                     "--jlink-options",
-                    "--bind-services",
+                    "--verbose --bind-services --limit-modules java.smartcardio,jdk.crypto.cryptoki,java.desktop",
                     },
-                    // with bind-services should have some services
+                    // with limit-modules and bind-services should have them in the result
                     new String[]{"java.smartcardio", "jdk.crypto.cryptoki"},
                     null,
                     },
             // bind-services
             {"Hello", new String[]{
-                    "--jlink-options", "--bind-services",
+                    "--jlink-options",
+                    "--bind-services --limit-modules jdk.jartool,jdk.unsupported,java.desktop",
                     },
-                    // non modular should have everything
+                    // non modular should have at least the module limits
                     new String[]{"jdk.jartool", "jdk.unsupported"},
                     null,
                     },
 
             // jlink-options --bind-services
             {"com.other/com.other.Hello", new String[]{
-                    "--jlink-options", "--bind-services",
+                    "--jlink-options",
+                    "--bind-services --limit-modules java.smartcardio,jdk.crypto.cryptoki,java.desktop",
                     },
                     // with bind-services should have some services
                     new String[]{"java.smartcardio", "jdk.crypto.cryptoki"},
diff -pruN 24.0.1+9-1/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java 24.0.2+12-1/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java
--- 24.0.1+9-1/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -51,7 +51,6 @@ public class RuntimeImageSymbolicLinksTe
 
     @Test
     public static void test() throws Exception {
-        final Path jmods = Path.of(System.getProperty("java.home"), "jmods");
         final Path workDir = TKit.createTempDirectory("runtime").resolve("data");
         final Path jlinkOutputDir = workDir.resolve("temp.runtime");
         Files.createDirectories(jlinkOutputDir.getParent());
@@ -61,8 +60,7 @@ public class RuntimeImageSymbolicLinksTe
         .dumpOutput()
         .addArguments(
                 "--output", jlinkOutputDir.toString(),
-                "--add-modules", "ALL-MODULE-PATH",
-                "--module-path", jmods.toString(),
+                "--add-modules", "java.desktop",
                 "--strip-debug",
                 "--no-header-files",
                 "--no-man-pages",
diff -pruN 24.0.1+9-1/test/jdk/tools/jpackage/share/RuntimeImageTest.java 24.0.2+12-1/test/jdk/tools/jpackage/share/RuntimeImageTest.java
--- 24.0.1+9-1/test/jdk/tools/jpackage/share/RuntimeImageTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/tools/jpackage/share/RuntimeImageTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -44,7 +44,6 @@ public class RuntimeImageTest {
 
     @Test
     public static void test() throws Exception {
-        final Path jmods = Path.of(System.getProperty("java.home"), "jmods");
         final Path workDir = TKit.createTempDirectory("runtime").resolve("data");
         final Path jlinkOutputDir = workDir.resolve("temp.runtime");
         Files.createDirectories(jlinkOutputDir.getParent());
@@ -54,8 +53,7 @@ public class RuntimeImageTest {
         .dumpOutput()
         .addArguments(
                 "--output", jlinkOutputDir.toString(),
-                "--add-modules", "ALL-MODULE-PATH",
-                "--module-path", jmods.toString(),
+                "--add-modules", "java.desktop",
                 "--strip-debug",
                 "--no-header-files",
                 "--no-man-pages",
diff -pruN 24.0.1+9-1/test/jdk/tools/jpackage/share/RuntimePackageTest.java 24.0.2+12-1/test/jdk/tools/jpackage/share/RuntimePackageTest.java
--- 24.0.1+9-1/test/jdk/tools/jpackage/share/RuntimePackageTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/tools/jpackage/share/RuntimePackageTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -101,7 +101,6 @@ public class RuntimePackageTest {
         .forTypes(types)
         .addInitializer(cmd -> {
             final Path runtimeImageDir;
-            final Path jmods = Path.of(System.getProperty("java.home"), "jmods");
 
             if (JPackageCommand.DEFAULT_RUNTIME_IMAGE != null) {
                 runtimeImageDir = JPackageCommand.DEFAULT_RUNTIME_IMAGE;
@@ -113,8 +112,7 @@ public class RuntimePackageTest {
                 .dumpOutput()
                 .addArguments(
                         "--output", runtimeImageDir.toString(),
-                        "--add-modules", "ALL-MODULE-PATH",
-                        "--module-path", jmods.toString(),
+                        "--add-modules", "java.desktop",
                         "--strip-debug",
                         "--no-header-files",
                         "--no-man-pages")
diff -pruN 24.0.1+9-1/test/jdk/tools/jpackage/windows/WinChildProcessTest.java 24.0.2+12-1/test/jdk/tools/jpackage/windows/WinChildProcessTest.java
--- 24.0.1+9-1/test/jdk/tools/jpackage/windows/WinChildProcessTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/tools/jpackage/windows/WinChildProcessTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 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
@@ -40,6 +40,7 @@ import java.util.Optional;
 import java.nio.file.Path;
 
 import jdk.jpackage.test.JPackageCommand;
+import static jdk.jpackage.test.HelloApp.configureEnvironment;
 import jdk.jpackage.test.Annotations.Test;
 import jdk.jpackage.test.Executor;
 import jdk.jpackage.test.TKit;
@@ -54,14 +55,15 @@ public class WinChildProcessTest {
         long childPid = 0;
         try {
             JPackageCommand cmd = JPackageCommand
-                    .helloAppImage(TEST_APP_JAVA + "*Hello");
+                    .helloAppImage(TEST_APP_JAVA + "*Hello")
+                    .ignoreFakeRuntime();
 
             // Create the image of the third party application launcher
             cmd.executeAndAssertImageCreated();
 
             // Start the third party application launcher and dump and save the
             // output of the application
-            List<String> output = new Executor().saveOutput().dumpOutput()
+            List<String> output = configureEnvironment(new Executor()).saveOutput().dumpOutput()
                     .setExecutable(cmd.appLauncherPath().toAbsolutePath())
                     .execute(0).getOutput();
             String pidStr = output.get(0);
diff -pruN 24.0.1+9-1/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java 24.0.2+12-1/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java
--- 24.0.1+9-1/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -122,13 +122,13 @@ public class WinInstallerUiTest {
         StringBuilder sb = new StringBuilder(cmd.name());
         sb.append("With");
         if (withDirChooser) {
-            sb.append("DirChooser");
+            sb.append("Dc"); // DirChooser
         }
         if (withShortcutPrompt) {
-            sb.append("ShortcutPrompt");
+            sb.append("Sp"); // ShortcutPrompt
         }
         if (withLicense) {
-            sb.append("License");
+            sb.append("L"); // License
         }
         cmd.setArgumentValue("--name", sb.toString());
     }
diff -pruN 24.0.1+9-1/test/langtools/ProblemList.txt 24.0.2+12-1/test/langtools/ProblemList.txt
--- 24.0.1+9-1/test/langtools/ProblemList.txt	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/langtools/ProblemList.txt	2025-06-27 08:03:14.000000000 +0000
@@ -71,3 +71,6 @@ tools/javap/output/RepeatingTypeAnnotati
 ###########################################################################
 #
 # jdeps
+
+# Mechanically added:
+jdk/jshell/ToolProviderTest.java 8353332 macosx-aarch64
diff -pruN 24.0.1+9-1/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java 24.0.2+12-1/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java
--- 24.0.1+9-1/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -62,6 +62,7 @@ public class FailOverDirectExecutionCont
 
     ClassLoader ccl;
     ExecutionControlProvider provider;
+    Logger logger;
     LogTestHandler hndlr;
     Map<Level, List<String>> logged;
 
@@ -95,7 +96,7 @@ public class FailOverDirectExecutionCont
     @BeforeMethod
     @Override
     public void setUp() {
-        Logger logger = Logger.getLogger("jdk.jshell.execution");
+        logger = Logger.getLogger("jdk.jshell.execution");
         logger.setLevel(Level.ALL);
         hndlr = new LogTestHandler();
         logger.addHandler(hndlr);
@@ -137,8 +138,8 @@ public class FailOverDirectExecutionCont
     @Override
     public void tearDown() {
         super.tearDown();
-        Logger logger = Logger.getLogger("jdk.jshell.execution");
         logger.removeHandler(hndlr);
+        logger = null;
         Thread.currentThread().setContextClassLoader(ccl);
     }
 
diff -pruN 24.0.1+9-1/test/langtools/jdk/jshell/JdiHangingListenExecutionControlTest.java 24.0.2+12-1/test/langtools/jdk/jshell/JdiHangingListenExecutionControlTest.java
--- 24.0.1+9-1/test/langtools/jdk/jshell/JdiHangingListenExecutionControlTest.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/langtools/jdk/jshell/JdiHangingListenExecutionControlTest.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -46,7 +46,11 @@ public class JdiHangingListenExecutionCo
             System.err.printf("Unexpected return value: %s\n",
                     HangingRemoteAgent.state(false, null).eval("33;"));
         } catch (IllegalStateException ex) {
-            assertTrue(ex.getMessage().startsWith(EXPECTED_ERROR), ex.getMessage());
+            if (!ex.getMessage().startsWith(EXPECTED_ERROR)) {
+                // unexpected message in the exception, rethrow the original exception
+                throw ex;
+            }
+            // received expected exception
             return;
         }
         fail("Expected IllegalStateException");
diff -pruN 24.0.1+9-1/test/langtools/tools/javac/processing/model/type/BasicAnnoTests.java 24.0.2+12-1/test/langtools/tools/javac/processing/model/type/BasicAnnoTests.java
--- 24.0.1+9-1/test/langtools/tools/javac/processing/model/type/BasicAnnoTests.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/langtools/tools/javac/processing/model/type/BasicAnnoTests.java	2025-06-27 08:03:14.000000000 +0000
@@ -163,7 +163,7 @@ public class BasicAnnoTests extends Java
      */
     class TestTypeScanner extends TypeScanner<Void, Void> {
         Element elem;
-        NavigableMap<Integer, AnnotationMirror> toBeFound;
+        NavigableMap<Integer, List<AnnotationMirror>> toBeFound;
         int count = 0;
         Set<TypeMirror> seen = new HashSet<>();
 
@@ -171,10 +171,10 @@ public class BasicAnnoTests extends Java
             super(types);
             this.elem = elem;
 
-            NavigableMap<Integer, AnnotationMirror> testByPos = new TreeMap<>();
+            NavigableMap<Integer, List<AnnotationMirror>> testByPos = new TreeMap<>();
             for (AnnotationMirror test : tests) {
                 for (int pos : getPosn(test)) {
-                    testByPos.put(pos, test);
+                    testByPos.computeIfAbsent(pos, ArrayList::new).add(test);
                 }
             }
             this.toBeFound = testByPos;
@@ -196,17 +196,18 @@ public class BasicAnnoTests extends Java
                         out.println("scan " + count + ": " + t);
                     if (toBeFound.size() > 0) {
                         if (toBeFound.firstKey().equals(count)) {
-                            AnnotationMirror test = toBeFound.pollFirstEntry().getValue();
-                            String annoType = getAnnoType(test);
-                            AnnotationMirror anno = getAnnotation(t, annoType);
-                            if (anno == null) {
-                                error(elem, "annotation not found on " + count + ": " + t);
-                            } else {
-                                String v = getValue(anno, "value").toString();
-                                if (v.equals(getExpect(test))) {
-                                    out.println("found " + anno + " as expected");
+                            for (AnnotationMirror test : toBeFound.pollFirstEntry().getValue()) {
+                                String annoType = getAnnoType(test);
+                                AnnotationMirror anno = getAnnotation(t, annoType);
+                                if (anno == null) {
+                                    error(elem, "annotation not found on " + count + ": " + t);
                                 } else {
-                                    error(elem, "Unexpected value: " + v + ", expected: " + getExpect(test));
+                                    String v = getValue(anno, "value").toString();
+                                    if (v.equals(getExpect(test))) {
+                                        out.println("found " + anno + " as expected");
+                                    } else {
+                                        error(elem, "Unexpected value: " + v + ", expected: " + getExpect(test));
+                                    }
                                 }
                             }
                         } else if (count > toBeFound.firstKey()) {
diff -pruN 24.0.1+9-1/test/lib/jdk/test/lib/security/CertificateBuilder.java 24.0.2+12-1/test/lib/jdk/test/lib/security/CertificateBuilder.java
--- 24.0.1+9-1/test/lib/jdk/test/lib/security/CertificateBuilder.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/lib/jdk/test/lib/security/CertificateBuilder.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2015, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.lib.security;
+
+import java.io.*;
+import java.util.*;
+import java.security.*;
+import java.security.cert.X509Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.Extension;
+import java.time.temporal.ChronoUnit;
+import java.time.Instant;
+import javax.security.auth.x500.X500Principal;
+import java.math.BigInteger;
+
+import sun.security.util.DerOutputStream;
+import sun.security.util.DerValue;
+import sun.security.util.ObjectIdentifier;
+import sun.security.util.SignatureUtil;
+import sun.security.x509.AccessDescription;
+import sun.security.x509.AlgorithmId;
+import sun.security.x509.AuthorityInfoAccessExtension;
+import sun.security.x509.AuthorityKeyIdentifierExtension;
+import sun.security.x509.SubjectKeyIdentifierExtension;
+import sun.security.x509.BasicConstraintsExtension;
+import sun.security.x509.CertificateSerialNumber;
+import sun.security.x509.ExtendedKeyUsageExtension;
+import sun.security.x509.DNSName;
+import sun.security.x509.GeneralName;
+import sun.security.x509.GeneralNames;
+import sun.security.x509.KeyUsageExtension;
+import sun.security.x509.SerialNumber;
+import sun.security.x509.SubjectAlternativeNameExtension;
+import sun.security.x509.URIName;
+import sun.security.x509.KeyIdentifier;
+
+/**
+ * Helper class that builds and signs X.509 certificates.
+ *
+ * A CertificateBuilder is created with a default constructor, and then
+ * uses additional public methods to set the public key, desired validity
+ * dates, serial number and extensions.  It is expected that the caller will
+ * have generated the necessary key pairs prior to using a CertificateBuilder
+ * to generate certificates.
+ *
+ * The following methods are mandatory before calling build():
+ * <UL>
+ * <LI>{@link #setSubjectName(java.lang.String)}
+ * <LI>{@link #setPublicKey(java.security.PublicKey)}
+ * <LI>{@link #setNotBefore(java.util.Date)} and
+ * {@link #setNotAfter(java.util.Date)}, or
+ * {@link #setValidity(java.util.Date, java.util.Date)}
+ * <LI>{@link #setSerialNumber(java.math.BigInteger)}
+ * </UL><BR>
+ *
+ * Additionally, the caller can either provide a {@link List} of
+ * {@link Extension} objects, or use the helper classes to add specific
+ * extension types.
+ *
+ * When all required and desired parameters are set, the
+ * {@link #build(java.security.cert.X509Certificate, java.security.PrivateKey,
+ * java.lang.String)} method can be used to create the {@link X509Certificate}
+ * object.
+ *
+ * Multiple certificates may be cut from the same settings using subsequent
+ * calls to the build method.  Settings may be cleared using the
+ * {@link #reset()} method.
+ */
+public class CertificateBuilder {
+    private final CertificateFactory factory;
+
+    private X500Principal subjectName = null;
+    private BigInteger serialNumber = null;
+    private PublicKey publicKey = null;
+    private Date notBefore = null;
+    private Date notAfter = null;
+    private final Map<String, Extension> extensions = new HashMap<>();
+    private byte[] tbsCertBytes;
+    private byte[] signatureBytes;
+
+    /**
+     * Default constructor for a {@code CertificateBuilder} object.
+     *
+     * @throws CertificateException if the underlying {@link CertificateFactory}
+     * cannot be instantiated.
+     */
+    public CertificateBuilder() throws CertificateException {
+        factory = CertificateFactory.getInstance("X.509");
+    }
+
+    /**
+     * Set the subject name for the certificate.
+     *
+     * @param name An {@link X500Principal} to be used as the subject name
+     * on this certificate.
+     */
+    public CertificateBuilder setSubjectName(X500Principal name) {
+        subjectName = name;
+        return this;
+    }
+
+    /**
+     * Set the subject name for the certificate.
+     *
+     * @param name The subject name in RFC 2253 format
+     */
+    public CertificateBuilder setSubjectName(String name) {
+        subjectName = new X500Principal(name);
+        return this;
+    }
+
+    /**
+     * Set the public key for this certificate.
+     *
+     * @param pubKey The {@link PublicKey} to be used on this certificate.
+     */
+    public CertificateBuilder setPublicKey(PublicKey pubKey) {
+        publicKey = Objects.requireNonNull(pubKey, "Caught null public key");
+        return this;
+    }
+
+    /**
+     * Set the NotBefore date on the certificate.
+     *
+     * @param nbDate A {@link Date} object specifying the start of the
+     * certificate validity period.
+     */
+    public CertificateBuilder setNotBefore(Date nbDate) {
+        Objects.requireNonNull(nbDate, "Caught null notBefore date");
+        notBefore = (Date)nbDate.clone();
+        return this;
+    }
+
+    /**
+     * Set the NotAfter date on the certificate.
+     *
+     * @param naDate A {@link Date} object specifying the end of the
+     * certificate validity period.
+     */
+    public CertificateBuilder setNotAfter(Date naDate) {
+        Objects.requireNonNull(naDate, "Caught null notAfter date");
+        notAfter = (Date)naDate.clone();
+        return this;
+    }
+
+    /**
+     * Set the validity period for the certificate
+     *
+     * @param nbDate A {@link Date} object specifying the start of the
+     * certificate validity period.
+     * @param naDate A {@link Date} object specifying the end of the
+     * certificate validity period.
+     */
+    public CertificateBuilder setValidity(Date nbDate, Date naDate) {
+        return setNotBefore(nbDate).setNotAfter(naDate);
+    }
+
+    /**
+     * Set the serial number on the certificate.
+     *
+     * @param serial A serial number in {@link BigInteger} form.
+     */
+    public CertificateBuilder setSerialNumber(BigInteger serial) {
+        Objects.requireNonNull(serial, "Caught null serial number");
+        serialNumber = serial;
+        return this;
+    }
+
+
+    /**
+     * Add a single extension to the certificate.
+     *
+     * @param ext The extension to be added.
+     */
+    public CertificateBuilder addExtension(Extension ext) {
+        Objects.requireNonNull(ext, "Caught null extension");
+        extensions.put(ext.getId(), ext);
+        return this;
+    }
+
+    /**
+     * Add multiple extensions contained in a {@code List}.
+     *
+     * @param extList The {@link List} of extensions to be added to
+     * the certificate.
+     */
+    public CertificateBuilder addExtensions(List<Extension> extList) {
+        Objects.requireNonNull(extList, "Caught null extension list");
+        for (Extension ext : extList) {
+            extensions.put(ext.getId(), ext);
+        }
+        return this;
+    }
+
+    /**
+     * Helper method to add DNSName types for the SAN extension
+     *
+     * @param dnsNames A {@code List} of names to add as DNSName types
+     *
+     * @throws IOException if an encoding error occurs.
+     */
+    public CertificateBuilder addSubjectAltNameDNSExt(List<String> dnsNames)
+            throws IOException {
+        if (!dnsNames.isEmpty()) {
+            GeneralNames gNames = new GeneralNames();
+            for (String name : dnsNames) {
+                gNames.add(new GeneralName(new DNSName(name)));
+            }
+            addExtension(new SubjectAlternativeNameExtension(false,
+                    gNames));
+        }
+        return this;
+    }
+
+    /**
+     * Helper method to add one or more OCSP URIs to the Authority Info Access
+     * certificate extension.  Location strings can be in two forms:
+     * 1) Just a URI by itself: This will be treated as using the OCSP
+     *    access description (legacy behavior).
+     * 2) An access description name (case-insensitive) followed by a
+     *    pipe (|) and the URI (e.g. OCSP|http://ocsp.company.com/revcheck).
+     * Current description names are OCSP and CAISSUER. Others may be
+     * added later.
+     *
+     * @param locations A list of one or more access descriptor URIs as strings
+     *
+     * @throws IOException if an encoding error occurs.
+     */
+    public CertificateBuilder addAIAExt(List<String> locations)
+            throws IOException {
+        if (!locations.isEmpty()) {
+            List<AccessDescription> acDescList = new ArrayList<>();
+            for (String loc : locations) {
+                String[] tokens = loc.split("\\|", 2);
+                ObjectIdentifier adObj;
+                String uriLoc;
+                if (tokens.length == 1) {
+                    // Legacy form, assume OCSP
+                    adObj = AccessDescription.Ad_OCSP_Id;
+                    uriLoc = tokens[0];
+                } else {
+                    switch (tokens[0].toUpperCase()) {
+                        case "OCSP":
+                            adObj = AccessDescription.Ad_OCSP_Id;
+                            break;
+                        case "CAISSUER":
+                            adObj = AccessDescription.Ad_CAISSUERS_Id;
+                            break;
+                        default:
+                            throw new IOException("Unknown AD: " + tokens[0]);
+                    }
+                    uriLoc = tokens[1];
+                }
+                acDescList.add(new AccessDescription(adObj,
+                        new GeneralName(new URIName(uriLoc))));
+            }
+            addExtension(new AuthorityInfoAccessExtension(acDescList));
+        }
+        return this;
+    }
+
+
+    /**
+     * Set a Key Usage extension for the certificate.  The extension will
+     * be marked critical.
+     *
+     * @param bitSettings Boolean array for all nine bit settings in the order
+     * documented in RFC 5280 section 4.2.1.3.
+     *
+     * @throws IOException if an encoding error occurs.
+     */
+    public CertificateBuilder addKeyUsageExt(boolean[] bitSettings)
+            throws IOException {
+        return addExtension(new KeyUsageExtension(bitSettings));
+    }
+
+    /**
+     * Set the Basic Constraints Extension for a certificate.
+     *
+     * @param crit {@code true} if critical, {@code false} otherwise
+     * @param isCA {@code true} if the extension will be on a CA certificate,
+     * {@code false} otherwise
+     * @param maxPathLen The maximum path length issued by this CA.  Values
+     * less than zero will omit this field from the resulting extension and
+     * no path length constraint will be asserted.
+     *
+     * @throws IOException if an encoding error occurs.
+     */
+    public CertificateBuilder addBasicConstraintsExt(boolean crit, boolean isCA,
+            int maxPathLen) throws IOException {
+        return addExtension(new BasicConstraintsExtension(crit, isCA,
+                maxPathLen));
+    }
+
+    /**
+     * Add the Authority Key Identifier extension.
+     *
+     * @param authorityCert The certificate of the issuing authority.
+     *
+     * @throws IOException if an encoding error occurs.
+     */
+    public CertificateBuilder addAuthorityKeyIdExt(X509Certificate authorityCert)
+            throws IOException {
+        return addAuthorityKeyIdExt(authorityCert.getPublicKey());
+    }
+
+    /**
+     * Add the Authority Key Identifier extension.
+     *
+     * @param authorityKey The public key of the issuing authority.
+     *
+     * @throws IOException if an encoding error occurs.
+     */
+    public CertificateBuilder addAuthorityKeyIdExt(PublicKey authorityKey)
+            throws IOException {
+        KeyIdentifier kid = new KeyIdentifier(authorityKey);
+        return addExtension(new AuthorityKeyIdentifierExtension(kid,
+                null, null));
+    }
+
+    /**
+     * Add the Subject Key Identifier extension.
+     *
+     * @param subjectKey The public key to be used in the resulting certificate
+     *
+     * @throws IOException if an encoding error occurs.
+     */
+    public CertificateBuilder addSubjectKeyIdExt(PublicKey subjectKey)
+            throws IOException {
+        byte[] keyIdBytes = new KeyIdentifier(subjectKey).getIdentifier();
+        return addExtension(new SubjectKeyIdentifierExtension(keyIdBytes));
+    }
+
+    /**
+     * Add the Extended Key Usage extension.
+     *
+     * @param ekuOids A {@link List} of object identifiers in string form.
+     *
+     * @throws IOException if an encoding error occurs.
+     */
+    public CertificateBuilder addExtendedKeyUsageExt(List<String> ekuOids)
+            throws IOException {
+        if (!ekuOids.isEmpty()) {
+            Vector<ObjectIdentifier> oidVector = new Vector<>();
+            for (String oid : ekuOids) {
+                oidVector.add(ObjectIdentifier.of(oid));
+            }
+            addExtension(new ExtendedKeyUsageExtension(oidVector));
+        }
+        return this;
+    }
+
+    /**
+     * Clear all settings and return the {@code CertificateBuilder} to
+     * its default state.
+     */
+    public CertificateBuilder reset() {
+        extensions.clear();
+        subjectName = null;
+        notBefore = null;
+        notAfter = null;
+        serialNumber = null;
+        publicKey = null;
+        signatureBytes = null;
+        tbsCertBytes = null;
+        return this;
+    }
+
+    /**
+     * Build the certificate.
+     *
+     * @param issuerCert The certificate of the issuing authority, or
+     * {@code null} if the resulting certificate is self-signed.
+     * @param issuerKey The private key of the issuing authority
+     * @param algName The signature algorithm name
+     *
+     * @return The resulting {@link X509Certificate}
+     *
+     * @throws IOException if an encoding error occurs.
+     * @throws CertificateException If the certificate cannot be generated
+     * by the underlying {@link CertificateFactory}
+     * @throws NoSuchAlgorithmException If an invalid signature algorithm
+     * is provided.
+     */
+    public X509Certificate build(X509Certificate issuerCert,
+            PrivateKey issuerKey, String algName)
+            throws IOException, CertificateException, NoSuchAlgorithmException {
+        // TODO: add some basic checks (key usage, basic constraints maybe)
+
+        byte[] encodedCert = encodeTopLevel(issuerCert, issuerKey, algName);
+        ByteArrayInputStream bais = new ByteArrayInputStream(encodedCert);
+        return (X509Certificate)factory.generateCertificate(bais);
+    }
+
+    /**
+     * Encode the contents of the outer-most ASN.1 SEQUENCE:
+     *
+     * <PRE>
+     *  Certificate  ::=  SEQUENCE  {
+     *      tbsCertificate       TBSCertificate,
+     *      signatureAlgorithm   AlgorithmIdentifier,
+     *      signatureValue       BIT STRING  }
+     * </PRE>
+     *
+     * @param issuerCert The certificate of the issuing authority, or
+     * {@code null} if the resulting certificate is self-signed.
+     * @param issuerKey The private key of the issuing authority
+     * @param algName The signature algorithm object
+     *
+     * @return The DER-encoded X.509 certificate
+     *
+     * @throws CertificateException If an error occurs during the
+     * signing process.
+     * @throws IOException if an encoding error occurs.
+     */
+    private byte[] encodeTopLevel(X509Certificate issuerCert,
+            PrivateKey issuerKey, String algName)
+            throws CertificateException, IOException, NoSuchAlgorithmException {
+
+        AlgorithmId signAlg = AlgorithmId.get(algName);
+        DerOutputStream outerSeq = new DerOutputStream();
+        DerOutputStream topLevelItems = new DerOutputStream();
+
+        try {
+            Signature sig = SignatureUtil.fromKey(signAlg.getName(), issuerKey, (Provider)null);
+            // Rewrite signAlg, RSASSA-PSS needs some parameters.
+            signAlg = SignatureUtil.fromSignature(sig, issuerKey);
+            tbsCertBytes = encodeTbsCert(issuerCert, signAlg);
+            sig.update(tbsCertBytes);
+            signatureBytes = sig.sign();
+        } catch (GeneralSecurityException ge) {
+            throw new CertificateException(ge);
+        }
+        topLevelItems.write(tbsCertBytes);
+        signAlg.encode(topLevelItems);
+        topLevelItems.putBitString(signatureBytes);
+        outerSeq.write(DerValue.tag_Sequence, topLevelItems);
+
+        return outerSeq.toByteArray();
+    }
+
+    /**
+     * Encode the bytes for the TBSCertificate structure:
+     * <PRE>
+     *  TBSCertificate  ::=  SEQUENCE  {
+     *      version         [0]  EXPLICIT Version DEFAULT v1,
+     *      serialNumber         CertificateSerialNumber,
+     *      signature            AlgorithmIdentifier,
+     *      issuer               Name,
+     *      validity             Validity,
+     *      subject              Name,
+     *      subjectPublicKeyInfo SubjectPublicKeyInfo,
+     *      issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
+     *                        -- If present, version MUST be v2 or v3
+     *      subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
+     *                        -- If present, version MUST be v2 or v3
+     *      extensions      [3]  EXPLICIT Extensions OPTIONAL
+     *                        -- If present, version MUST be v3
+     *      }
+     *
+     * @param issuerCert The certificate of the issuing authority, or
+     * {@code null} if the resulting certificate is self-signed.
+     * @param signAlg The signature algorithm object
+     *
+     * @return The DER-encoded bytes for the TBSCertificate structure
+     *
+     * @throws IOException if an encoding error occurs.
+     */
+    private byte[] encodeTbsCert(X509Certificate issuerCert,
+            AlgorithmId signAlg) throws IOException {
+        DerOutputStream tbsCertSeq = new DerOutputStream();
+        DerOutputStream tbsCertItems = new DerOutputStream();
+
+        // If extensions exist then it needs to be v3, otherwise
+        // we can make it v1 and omit the version field as v1 is the default.
+        if (!extensions.isEmpty()) {
+            byte[] v3int = {0x02, 0x01, 0x02};
+            tbsCertItems.write(DerValue.createTag(DerValue.TAG_CONTEXT, true,
+                    (byte) 0), v3int);
+        }
+
+        // Serial Number
+        CertificateSerialNumber sn = (serialNumber != null) ?
+            new CertificateSerialNumber(serialNumber) :
+            CertificateSerialNumber.newRandom64bit(new SecureRandom());
+        sn.encode(tbsCertItems);
+
+        // Algorithm ID
+        signAlg.encode(tbsCertItems);
+
+        // Issuer Name
+        if (issuerCert != null) {
+            tbsCertItems.write(
+                    issuerCert.getSubjectX500Principal().getEncoded());
+        } else {
+            // Self-signed
+            tbsCertItems.write(subjectName.getEncoded());
+        }
+
+        // Validity period (set as UTCTime)
+        DerOutputStream valSeq = new DerOutputStream();
+        Instant now = Instant.now();
+        Date startDate = (notBefore != null) ? notBefore : Date.from(now);
+        valSeq.putUTCTime(startDate);
+        Date endDate = (notAfter != null) ? notAfter :
+            Date.from(now.plus(90, ChronoUnit.DAYS));
+        valSeq.putUTCTime(endDate);
+        tbsCertItems.write(DerValue.tag_Sequence, valSeq);
+
+        // Subject Name
+        tbsCertItems.write(subjectName.getEncoded());
+
+        // SubjectPublicKeyInfo
+        tbsCertItems.write(publicKey.getEncoded());
+
+        // Encode any extensions in the builder
+        encodeExtensions(tbsCertItems);
+
+        // Wrap it all up in a SEQUENCE and return the bytes
+        tbsCertSeq.write(DerValue.tag_Sequence, tbsCertItems);
+        return tbsCertSeq.toByteArray();
+    }
+
+    /**
+     * Encode the extensions segment for an X.509 Certificate:
+     *
+     * <PRE>
+     *  Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
+     *
+     *  Extension  ::=  SEQUENCE  {
+     *      extnID      OBJECT IDENTIFIER,
+     *      critical    BOOLEAN DEFAULT FALSE,
+     *      extnValue   OCTET STRING
+     *                  -- contains the DER encoding of an ASN.1 value
+     *                  -- corresponding to the extension type identified
+     *                  -- by extnID
+     *      }
+     * </PRE>
+     *
+     * @param tbsStream The {@code DerOutputStream} that holds the
+     * TBSCertificate contents.
+     *
+     * @throws IOException if an encoding error occurs.
+     */
+    private void encodeExtensions(DerOutputStream tbsStream)
+            throws IOException {
+
+        if (extensions.isEmpty()) {
+            return;
+        }
+        DerOutputStream extSequence = new DerOutputStream();
+        DerOutputStream extItems = new DerOutputStream();
+
+        for (Extension ext : extensions.values()) {
+            ext.encode(extItems);
+        }
+        extSequence.write(DerValue.tag_Sequence, extItems);
+        tbsStream.write(DerValue.createTag(DerValue.TAG_CONTEXT, true,
+                (byte)3), extSequence);
+    }
+}
diff -pruN 24.0.1+9-1/test/lib/jdk/test/lib/security/HumanInputStream.java 24.0.2+12-1/test/lib/jdk/test/lib/security/HumanInputStream.java
--- 24.0.1+9-1/test/lib/jdk/test/lib/security/HumanInputStream.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/lib/jdk/test/lib/security/HumanInputStream.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2024, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.lib.security;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+/**
+ * HumanInputStream tries to act like a human sitting in front of a computer
+ * terminal typing on the keyboard while a program is running.
+ * <p>
+ * The program may call InputStream.read() and BufferedReader.readLine() in
+ * various places. a call to B.readLine() will try to buffer as much input as
+ * possible. Thus, a trivial InputStream will find it impossible to feed
+ * anything to I.read() after a B.readLine() call.
+ * <p>
+ * This is why HumanInputStream was created, which will only send a single line
+ * to B.readLine(), no more, no less, and the next I.read() can have a chance
+ * to read the exact character right after "\n".
+ *
+ */
+
+public class HumanInputStream extends InputStream {
+    byte[] src;
+    int pos;
+    int length;
+    boolean inLine;
+    int stopIt;
+
+    public HumanInputStream(String input) {
+        src = input.getBytes();
+        pos = 0;
+        length = src.length;
+        stopIt = 0;
+        inLine = false;
+    }
+
+    // the trick: when called through read(byte[], int, int),
+    // return -1 twice after "\n"
+
+    @Override public int read() throws IOException {
+        int re;
+        if(pos < length) {
+            re = src[pos];
+            if(inLine) {
+                if(stopIt > 0) {
+                    stopIt--;
+                    re = -1;
+                } else {
+                    if(re == '\n') {
+                        stopIt = 2;
+                    }
+                    pos++;
+                }
+            } else {
+                pos++;
+            }
+        } else {
+            re = -1; //throws new IOException("NO MORE TO READ");
+        }
+        return re;
+    }
+
+    @Override public int read(byte[] buffer, int offset, int len) {
+        inLine = true;
+        try {
+            return super.read(buffer, offset, len);
+        } catch(Exception e) {
+            throw new RuntimeException("HumanInputStream error");
+        } finally {
+            inLine = false;
+        }
+    }
+
+    @Override public int available() {
+        if (pos < length) return 1;
+        return 0;
+    }
+
+    // test part
+    static void assertTrue(boolean bool) {
+        if (!bool)
+            throw new RuntimeException();
+    }
+
+    public static void test() throws Exception {
+        class Tester {
+            HumanInputStream is;
+            BufferedReader reader;
+            Tester(String s) {
+                is = new HumanInputStream(s);
+                reader = new BufferedReader(new InputStreamReader(is));
+            }
+
+            // three kinds of test method
+            // 1. read byte by byte from InputStream
+            void testStreamReadOnce(int expection) throws Exception {
+                assertTrue(is.read() == expection);
+            }
+            void testStreamReadMany(String expectation) throws Exception {
+                char[] keys = expectation.toCharArray();
+                for (char key : keys) {
+                    assertTrue(is.read() == key);
+                }
+            }
+            // 2. read a line with a newly created Reader
+            void testReaderReadline(String expectation) throws Exception {
+                String s = new BufferedReader(new InputStreamReader(is)).readLine();
+                if(s == null) assertTrue(expectation == null);
+                else assertTrue(s.equals(expectation));
+            }
+            // 3. read a line with the old Reader
+            void testReaderReadline2(String expectation) throws Exception  {
+                String s = reader.readLine();
+                if(s == null) assertTrue(expectation == null);
+                else assertTrue(s.equals(expectation));
+            }
+        }
+
+        Tester test;
+
+        test = new Tester("111\n222\n\n444\n\n");
+        test.testReaderReadline("111");
+        test.testReaderReadline("222");
+        test.testReaderReadline("");
+        test.testReaderReadline("444");
+        test.testReaderReadline("");
+        test.testReaderReadline(null);
+
+        test = new Tester("111\n222\n\n444\n\n");
+        test.testReaderReadline2("111");
+        test.testReaderReadline2("222");
+        test.testReaderReadline2("");
+        test.testReaderReadline2("444");
+        test.testReaderReadline2("");
+        test.testReaderReadline2(null);
+
+        test = new Tester("111\n222\n\n444\n\n");
+        test.testReaderReadline2("111");
+        test.testReaderReadline("222");
+        test.testReaderReadline2("");
+        test.testReaderReadline2("444");
+        test.testReaderReadline("");
+        test.testReaderReadline2(null);
+
+        test = new Tester("1\n2");
+        test.testStreamReadMany("1\n2");
+        test.testStreamReadOnce(-1);
+
+        test = new Tester("12\n234");
+        test.testStreamReadOnce('1');
+        test.testReaderReadline("2");
+        test.testStreamReadOnce('2');
+        test.testReaderReadline2("34");
+        test.testReaderReadline2(null);
+
+        test = new Tester("changeit\n");
+        test.testStreamReadMany("changeit\n");
+        test.testReaderReadline(null);
+
+        test = new Tester("changeit\nName\nCountry\nYes\n");
+        test.testStreamReadMany("changeit\n");
+        test.testReaderReadline("Name");
+        test.testReaderReadline("Country");
+        test.testReaderReadline("Yes");
+        test.testReaderReadline(null);
+
+        test = new Tester("Me\nHere\n");
+        test.testReaderReadline2("Me");
+        test.testReaderReadline2("Here");
+    }
+}
diff -pruN 24.0.1+9-1/test/lib/jdk/test/lib/security/OpensslArtifactFetcher.java 24.0.2+12-1/test/lib/jdk/test/lib/security/OpensslArtifactFetcher.java
--- 24.0.1+9-1/test/lib/jdk/test/lib/security/OpensslArtifactFetcher.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/lib/jdk/test/lib/security/OpensslArtifactFetcher.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -25,6 +25,7 @@ package jdk.test.lib.security;
 
 import java.io.File;
 
+import java.nio.file.Path;
 import jdk.test.lib.Platform;
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.artifacts.Artifact;
@@ -33,43 +34,49 @@ import jdk.test.lib.artifacts.ArtifactRe
 
 public class OpensslArtifactFetcher {
 
+    private static final String OPENSSL_BUNDLE_VERSION = "3.0.14";
+    private static final String OPENSSL_ORG = "jpg.tests.jdk.openssl";
+
     /**
-     * Gets the openssl binary path of version 1.1.*
+     * Gets the openssl binary path of OPENSSL_BUNDLE_VERSION
      *
      * Openssl selection flow:
         1. Check whether property test.openssl.path is set and it's the
-           preferred version(1.1.*) of openssl, then return that path.
-        2. Else look for already installed openssl (version 1.1.*) in system
+           current version of openssl, then return that path.
+        2. Else look for already installed openssl in system
            path /usr/bin/openssl or /usr/local/bin/openssl, then return that
            path.
-        3. Else try to download openssl (version 1.1.*) from the artifactory
+        3. Else try to download the current version of openssl from the artifactory
            and return that path, if download fails then return null.
      *
-     * @return openssl binary path of version 1.1.*
+     * @return openssl binary path of the current version
      */
-    public static String getOpenssl1dot1dotStar() {
-        String version = "1.1.";
-        String path = getOpensslFromSystemProp(version);
+    public static String getOpensslPath() {
+        String path = getOpensslFromSystemProp(OPENSSL_BUNDLE_VERSION);
         if (path != null) {
             return path;
-        } else {
-            path = getDefaultSystemOpensslPath(version);
-            if (path != null) {
-                return path;
-            } else if (Platform.is64bit()) {
-                if (Platform.isLinux()) {
-                    path = fetchOpenssl(LINUX_X64.class);
-                } else if (Platform.isOSX()) {
-                    path = fetchOpenssl(MACOSX_X64.class);
-                } else if (Platform.isWindows()) {
-                    path = fetchOpenssl(WINDOWS_X64.class);
-                }
-                if (verifyOpensslVersion(path, version)) {
-                    return path;
-                }
+        }
+        path = getDefaultSystemOpensslPath(OPENSSL_BUNDLE_VERSION);
+        if (path != null) {
+            return path;
+        }
+        if (Platform.isX64()) {
+            if (Platform.isLinux()) {
+                path = fetchOpenssl(LINUX_X64.class);
+            } else if (Platform.isOSX()) {
+                path = fetchOpenssl(MACOSX_X64.class);
+            } else if (Platform.isWindows()) {
+                path = fetchOpenssl(WINDOWS_X64.class);
+            }
+        } else if (Platform.isAArch64()) {
+            if (Platform.isLinux()) {
+                path = fetchOpenssl(LINUX_AARCH64.class);
+            }
+            if (Platform.isOSX()) {
+                path = fetchOpenssl(MACOSX_AARCH64.class);
             }
         }
-        return null;
+        return verifyOpensslVersion(path, OPENSSL_BUNDLE_VERSION) ? path : null;
     }
 
     private static String getOpensslFromSystemProp(String version) {
@@ -124,24 +131,52 @@ public class OpensslArtifactFetcher {
         return path;
     }
 
+    // retrieve the provider directory path from <OPENSSL_HOME>/bin/openssl
+    public static Path getProviderPath(String opensslPath) {
+        Path openSslRootPath = Path.of(opensslPath).getParent().getParent();
+        String libDir = "lib";
+        if (Platform.isX64() && (Platform.isLinux() || Platform.isWindows())) {
+            libDir = "lib64";
+        }
+        return openSslRootPath.resolve(libDir, "ossl-modules");
+    }
+
+    public static String getTestOpensslBundleVersion() {
+        return OPENSSL_BUNDLE_VERSION;
+    }
+
     @Artifact(
-            organization = "jpg.tests.jdk.openssl",
+            organization = OPENSSL_ORG,
             name = "openssl-linux_x64",
-            revision = "1.1.1g",
+            revision = OPENSSL_BUNDLE_VERSION,
             extension = "zip")
     private static class LINUX_X64 { }
 
     @Artifact(
-            organization = "jpg.tests.jdk.openssl",
+            organization = OPENSSL_ORG,
+            name = "openssl-linux_aarch64",
+            revision = OPENSSL_BUNDLE_VERSION,
+            extension = "zip")
+    private static class LINUX_AARCH64{ }
+
+    @Artifact(
+            organization = OPENSSL_ORG,
             name = "openssl-macosx_x64",
-            revision = "1.1.1g",
+            revision = OPENSSL_BUNDLE_VERSION,
             extension = "zip")
     private static class MACOSX_X64 { }
 
     @Artifact(
-            organization = "jpg.tests.jdk.openssl",
+            organization = OPENSSL_ORG,
+            name = "openssl-macosx_aarch64",
+            revision = OPENSSL_BUNDLE_VERSION,
+            extension = "zip")
+    private static class MACOSX_AARCH64 { }
+
+    @Artifact(
+            organization = OPENSSL_ORG,
             name = "openssl-windows_x64",
-            revision = "1.1.1g",
+            revision = OPENSSL_BUNDLE_VERSION,
             extension = "zip")
     private static class WINDOWS_X64 { }
 }
diff -pruN 24.0.1+9-1/test/lib/jdk/test/lib/security/Providers.java 24.0.2+12-1/test/lib/jdk/test/lib/security/Providers.java
--- 24.0.1+9-1/test/lib/jdk/test/lib/security/Providers.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/lib/jdk/test/lib/security/Providers.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,38 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.lib.security;
+
+import java.security.Provider;
+import java.security.Security;
+
+public class Providers {
+    public static void setAt(Provider p, int pos) throws Exception {
+        if (Security.getProvider(p.getName()) != null) {
+            Security.removeProvider(p.getName());
+        }
+        if (Security.insertProviderAt(p, pos) == -1) {
+            throw new Exception("cannot setAt");
+        }
+    }
+}
diff -pruN 24.0.1+9-1/test/lib/jdk/test/lib/security/ProvidersSnapshot.java 24.0.2+12-1/test/lib/jdk/test/lib/security/ProvidersSnapshot.java
--- 24.0.1+9-1/test/lib/jdk/test/lib/security/ProvidersSnapshot.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/lib/jdk/test/lib/security/ProvidersSnapshot.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,50 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.lib.security;
+
+import java.security.Provider;
+import java.security.Security;
+
+public class ProvidersSnapshot {
+
+    private Provider[] oldProviders;
+
+    private ProvidersSnapshot() {
+        oldProviders = Security.getProviders();
+    }
+
+    public static ProvidersSnapshot create() {
+        return new ProvidersSnapshot();
+    }
+
+    public void restore() {
+        Provider[] newProviders = Security.getProviders();
+        for (Provider p: newProviders) {
+            Security.removeProvider(p.getName());
+        }
+        for (Provider p: oldProviders) {
+            Security.addProvider(p);
+        }
+    }
+}
diff -pruN 24.0.1+9-1/test/lib/jdk/test/lib/security/SimpleOCSPServer.java 24.0.2+12-1/test/lib/jdk/test/lib/security/SimpleOCSPServer.java
--- 24.0.1+9-1/test/lib/jdk/test/lib/security/SimpleOCSPServer.java	1970-01-01 00:00:00.000000000 +0000
+++ 24.0.2+12-1/test/lib/jdk/test/lib/security/SimpleOCSPServer.java	2025-06-27 08:03:14.000000000 +0000
@@ -0,0 +1,1694 @@
+/*
+ * Copyright (c) 2015, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.lib.security;
+
+import java.io.*;
+import java.net.*;
+import java.security.*;
+import java.security.cert.CRLReason;
+import java.security.cert.X509Certificate;
+import java.security.cert.Extension;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateEncodingException;
+import java.security.Signature;
+import java.util.*;
+import java.util.concurrent.*;
+import java.text.SimpleDateFormat;
+import java.math.BigInteger;
+
+import sun.security.x509.*;
+import sun.security.x509.PKIXExtensions;
+import sun.security.provider.certpath.ResponderId;
+import sun.security.provider.certpath.CertId;
+import sun.security.provider.certpath.OCSPResponse;
+import sun.security.provider.certpath.OCSPResponse.ResponseStatus;
+import sun.security.util.*;
+
+
+/**
+ * This is a simple OCSP server designed to listen and respond to incoming
+ * requests.
+ */
+public class SimpleOCSPServer {
+    private final Debug debug = Debug.getInstance("oserv");
+    private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID =
+            ObjectIdentifier.of(KnownOIDs.OCSPBasicResponse);
+
+    private static final SimpleDateFormat utcDateFmt =
+            new SimpleDateFormat("MMM dd yyyy, HH:mm:ss z");
+
+    static final int FREE_PORT = 0;
+
+    // CertStatus values
+    public static enum CertStatus {
+        CERT_STATUS_GOOD,
+        CERT_STATUS_REVOKED,
+        CERT_STATUS_UNKNOWN,
+    }
+
+    // Fields used for the networking portion of the responder
+    private ServerSocket servSocket;
+    private InetAddress listenAddress;
+    private int listenPort;
+
+    // Keystore information (certs, keys, etc.)
+    private KeyStore keystore;
+    private X509Certificate issuerCert;
+    private X509Certificate signerCert;
+    private PrivateKey signerKey;
+
+    // Fields used for the operational portions of the server
+    private boolean logEnabled = false;
+    private ExecutorService threadPool;
+    private volatile boolean started = false;
+    private CountDownLatch serverReady = new CountDownLatch(1);
+    private volatile boolean receivedShutdown = false;
+    private volatile boolean acceptConnections = true;
+    private volatile long delayMsec = 0;
+    private boolean omitContentLength = false;
+
+    // Fields used in the generation of responses
+    private long nextUpdateInterval = -1;
+    private Date nextUpdate = null;
+    private ResponderId respId;
+    private AlgorithmId sigAlgId;
+    private Map<CertId, CertStatusInfo> statusDb =
+            Collections.synchronizedMap(new HashMap<>());
+
+    /**
+     * Construct a SimpleOCSPServer using keystore, password, and alias
+     * parameters.
+     *
+     * @param ks the keystore to be used
+     * @param password the password to access key material in the keystore
+     * @param issuerAlias the alias of the issuer certificate
+     * @param signerAlias the alias of the signer certificate and key.  A
+     * value of {@code null} means that the {@code issuerAlias} will be used
+     * to look up the signer key.
+     *
+     * @throws GeneralSecurityException if there are problems accessing the
+     * keystore or finding objects within the keystore.
+     * @throws IOException if a {@code ResponderId} cannot be generated from
+     * the signer certificate.
+     */
+    public SimpleOCSPServer(KeyStore ks, String password, String issuerAlias,
+            String signerAlias) throws GeneralSecurityException, IOException {
+        this(null, FREE_PORT, ks, password, issuerAlias, signerAlias);
+    }
+
+    /**
+     * Construct a SimpleOCSPServer using specific network parameters,
+     * keystore, password, and alias.
+     *
+     * @param addr the address to bind the server to.  A value of {@code null}
+     * means the server will bind to all interfaces.
+     * @param port the port to listen on.  A value of {@code 0} will mean that
+     * the server will randomly pick an open ephemeral port to bind to.
+     * @param ks the keystore to be used
+     * @param password the password to access key material in the keystore
+     * @param issuerAlias the alias of the issuer certificate
+     * @param signerAlias the alias of the signer certificate and key.  A
+     * value of {@code null} means that the {@code issuerAlias} will be used
+     * to look up the signer key.
+     *
+     * @throws GeneralSecurityException if there are problems accessing the
+     * keystore or finding objects within the keystore.
+     * @throws IOException if a {@code ResponderId} cannot be generated from
+     * the signer certificate.
+     */
+    public SimpleOCSPServer(InetAddress addr, int port, KeyStore ks,
+            String password, String issuerAlias, String signerAlias)
+            throws GeneralSecurityException, IOException {
+        Objects.requireNonNull(ks, "Null keystore provided");
+        Objects.requireNonNull(issuerAlias, "Null issuerName provided");
+
+        utcDateFmt.setTimeZone(TimeZone.getTimeZone("GMT"));
+
+        keystore = ks;
+        issuerCert = (X509Certificate)ks.getCertificate(issuerAlias);
+        if (issuerCert == null) {
+            throw new IllegalArgumentException("Certificate for alias " +
+                    issuerAlias + " not found");
+        }
+
+        if (signerAlias != null) {
+            signerCert = (X509Certificate)ks.getCertificate(signerAlias);
+            if (signerCert == null) {
+                throw new IllegalArgumentException("Certificate for alias " +
+                    signerAlias + " not found");
+            }
+            signerKey = (PrivateKey)ks.getKey(signerAlias,
+                    password.toCharArray());
+            if (signerKey == null) {
+                throw new IllegalArgumentException("PrivateKey for alias " +
+                    signerAlias + " not found");
+            }
+        } else {
+            signerCert = issuerCert;
+            signerKey = (PrivateKey)ks.getKey(issuerAlias,
+                    password.toCharArray());
+            if (signerKey == null) {
+                throw new IllegalArgumentException("PrivateKey for alias " +
+                    issuerAlias + " not found");
+            }
+        }
+        sigAlgId = AlgorithmId.get(SignatureUtil.getDefaultSigAlgForKey(signerKey));
+        respId = new ResponderId(signerCert.getSubjectX500Principal());
+        listenAddress = addr;
+        listenPort = port;
+    }
+
+    /**
+     * Start the server.  The server will bind to the specified network
+     * address and begin listening for incoming connections.
+     *
+     * @throws IOException if any number of things go wonky.
+     */
+    public synchronized void start() throws IOException {
+        // You cannot start the server twice.
+        if (started) {
+            log("Server has already been started");
+            return;
+        } else {
+            started = true;
+        }
+
+        // Create and start the thread pool
+        threadPool = Executors.newFixedThreadPool(32, new ThreadFactory() {
+            @Override
+            public Thread newThread(Runnable r) {
+                Thread t = Executors.defaultThreadFactory().newThread(r);
+                t.setDaemon(true);
+                return t;
+            }
+        });
+
+        threadPool.submit(new Runnable() {
+            @Override
+            public void run() {
+                try (ServerSocket sSock = new ServerSocket()) {
+                    servSocket = sSock;
+                    servSocket.setReuseAddress(true);
+                    servSocket.setSoTimeout(500);
+                    servSocket.bind(new InetSocketAddress(listenAddress,
+                            listenPort), 128);
+                    log("Listening on " + servSocket.getLocalSocketAddress());
+
+                    // Update the listenPort with the new port number.  If
+                    // the server is restarted, it will bind to the same
+                    // port rather than picking a new one.
+                    listenPort = servSocket.getLocalPort();
+
+                    // Decrement the latch, allowing any waiting entities
+                    // to proceed with their requests.
+                    serverReady.countDown();
+
+                    // Main dispatch loop
+                    while (!receivedShutdown) {
+                        try {
+                            Socket newConnection = servSocket.accept();
+                            if (!acceptConnections) {
+                                try {
+                                    log("Reject connection");
+                                    newConnection.close();
+                                } catch (IOException e) {
+                                    // ignore
+                                }
+                                continue;
+                            }
+                            threadPool.submit(new OcspHandler(newConnection));
+                        } catch (SocketTimeoutException timeout) {
+                            // Nothing to do here.  If receivedShutdown
+                            // has changed to true then the loop will
+                            // exit on its own.
+                        } catch (IOException ioe) {
+                            // Something bad happened, log and force a shutdown
+                            log("Unexpected Exception: " + ioe);
+                            stop();
+                        }
+                    }
+
+                    log("Shutting down...");
+                    threadPool.shutdown();
+                } catch (IOException ioe) {
+                    err(ioe);
+                } finally {
+                    // Reset state variables so the server can be restarted
+                    receivedShutdown = false;
+                    started = false;
+                    serverReady = new CountDownLatch(1);
+                }
+            }
+        });
+    }
+
+    /**
+     * Make the OCSP server reject incoming connections.
+     */
+    public synchronized void rejectConnections() {
+        log("Reject OCSP connections");
+        acceptConnections = false;
+    }
+
+    /**
+     * Make the OCSP server accept incoming connections.
+     */
+    public synchronized void acceptConnections() {
+        log("Accept OCSP connections");
+        acceptConnections = true;
+    }
+
+
+    /**
+     * Stop the OCSP server.
+     */
+    public synchronized void stop() {
+        if (started) {
+            receivedShutdown = true;
+            started = false;
+            log("Received shutdown notification");
+        }
+    }
+
+    public synchronized void shutdownNow() {
+        stop();
+        if (threadPool != null) {
+            threadPool.shutdownNow();
+        }
+    }
+
+    /**
+     * Print {@code SimpleOCSPServer} operating parameters.
+     *
+     * @return the {@code SimpleOCSPServer} operating parameters in
+     * {@code String} form.
+     */
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("OCSP Server:\n");
+        sb.append("----------------------------------------------\n");
+        sb.append("issuer: ").append(issuerCert.getSubjectX500Principal()).
+                append("\n");
+        sb.append("signer: ").append(signerCert.getSubjectX500Principal()).
+                append("\n");
+        sb.append("ResponderId: ").append(respId).append("\n");
+        sb.append("----------------------------------------------");
+
+        return sb.toString();
+    }
+
+    /**
+     * Helpful debug routine to hex dump byte arrays.
+     *
+     * @param data the array of bytes to dump to stdout.
+     *
+     * @return the hexdump of the byte array
+     */
+    private static String dumpHexBytes(byte[] data) {
+        return dumpHexBytes(data, data.length, 16, "\n", " ");
+    }
+
+    /**
+     *
+     * @param data the array of bytes to dump to stdout
+     * @param dataLen the length of the data to be displayed
+     * @param itemsPerLine the number of bytes to display per line
+     * if the {@code lineDelim} character is blank then all bytes will be
+     * printed on a single line.
+     * @param lineDelim the delimiter between lines
+     * @param itemDelim the delimiter between bytes
+     *
+     * @return The hexdump of the byte array
+     */
+    private static String dumpHexBytes(byte[] data, int dataLen,
+            int itemsPerLine, String lineDelim, String itemDelim) {
+        StringBuilder sb = new StringBuilder();
+        if (data != null) {
+            for (int i = 0; i < dataLen; i++) {
+                if (i % itemsPerLine == 0 && i != 0) {
+                    sb.append(lineDelim);
+                }
+                sb.append(String.format("%02X", data[i])).append(itemDelim);
+            }
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Enable or disable the logging feature.
+     *
+     * @param enable {@code true} to enable logging, {@code false} to
+     * disable it.  The setting must be activated before the server calls
+     * its start method.  Any calls after that have no effect.
+     */
+    public void enableLog(boolean enable) {
+        if (!started) {
+            logEnabled = enable;
+        }
+    }
+
+    /**
+     * Sets the nextUpdate interval.  Intervals will be calculated relative
+     * to the server startup time.  When first set, the nextUpdate date is
+     * calculated based on the current time plus the interval.  After that,
+     * calls to getNextUpdate() will return this date if it is still
+     * later than current time.  If not, the Date will be updated to the
+     * next interval that is later than current time.  This value must be set
+     * before the server has had its start method called.  Calls made after
+     * the server has been started have no effect.
+     *
+     * @param interval the recurring time interval in seconds used to
+     * calculate nextUpdate times.   A value less than or equal to 0 will
+     * disable the nextUpdate feature.
+     */
+    public synchronized void setNextUpdateInterval(long interval) {
+        if (!started) {
+            if (interval <= 0) {
+                nextUpdateInterval = -1;
+                nextUpdate = null;
+                log("nexUpdate support has been disabled");
+            } else {
+                nextUpdateInterval = interval * 1000;
+                nextUpdate = new Date(System.currentTimeMillis() +
+                        nextUpdateInterval);
+                log("nextUpdate set to " + nextUpdate);
+            }
+        }
+    }
+
+    /**
+     * Return the nextUpdate {@code Date} object for this server.  If the
+     * nextUpdate date has already passed, set a new nextUpdate based on
+     * the nextUpdate interval and return that date.
+     *
+     * @return a {@code Date} object set to the nextUpdate field for OCSP
+     * responses.
+     */
+    private synchronized Date getNextUpdate() {
+        if (nextUpdate != null && nextUpdate.before(new Date())) {
+            long nuEpochTime = nextUpdate.getTime();
+            long currentTime = System.currentTimeMillis();
+
+            // Keep adding nextUpdate intervals until you reach a date
+            // that is later than current time.
+            while (currentTime >= nuEpochTime) {
+                nuEpochTime += nextUpdateInterval;
+            }
+
+            // Set the nextUpdate for future threads
+            nextUpdate = new Date(nuEpochTime);
+            log("nextUpdate updated to new value: " + nextUpdate);
+        }
+        return nextUpdate;
+    }
+
+    /**
+     * Add entries into the responder's status database.
+     *
+     * @param newEntries a map of {@code CertStatusInfo} objects, keyed on
+     * their serial number (as a {@code BigInteger}).  All serial numbers
+     * are assumed to have come from this responder's issuer certificate.
+     *
+     * @throws IOException if a CertId cannot be generated.
+     */
+    public void updateStatusDb(Map<BigInteger, CertStatusInfo> newEntries)
+            throws IOException {
+         if (newEntries != null) {
+            for (BigInteger serial : newEntries.keySet()) {
+                CertStatusInfo info = newEntries.get(serial);
+                if (info != null) {
+                    CertId cid = new CertId(issuerCert,
+                            new SerialNumber(serial));
+                    statusDb.put(cid, info);
+                    log("Added entry for serial " + serial + "(" +
+                            info.getType() + ")");
+                }
+            }
+        }
+    }
+
+    /**
+     * Check the status database for revocation information on one or more
+     * certificates.
+     *
+     * @param reqList the list of {@code LocalSingleRequest} objects taken
+     * from the incoming OCSP request.
+     *
+     * @return a {@code Map} of {@code CertStatusInfo} objects keyed by their
+     * {@code CertId} values, for each single request passed in.  Those
+     * CertIds not found in the statusDb will have returned List members with
+     * a status of UNKNOWN.
+     */
+    private Map<CertId, CertStatusInfo> checkStatusDb(
+            List<LocalOcspRequest.LocalSingleRequest> reqList) {
+        // TODO figure out what, if anything to do with request extensions
+        Map<CertId, CertStatusInfo> returnMap = new HashMap<>();
+
+        for (LocalOcspRequest.LocalSingleRequest req : reqList) {
+            CertId cid = req.getCertId();
+            CertStatusInfo info = statusDb.get(cid);
+            if (info != null) {
+                log("Status for SN " + cid.getSerialNumber() + ": " +
+                        info.getType());
+                returnMap.put(cid, info);
+            } else {
+                log("Status for SN " + cid.getSerialNumber() +
+                        " not found, using CERT_STATUS_UNKNOWN");
+                returnMap.put(cid,
+                        new CertStatusInfo(CertStatus.CERT_STATUS_UNKNOWN));
+            }
+        }
+
+        return Collections.unmodifiableMap(returnMap);
+    }
+
+    /**
+     * Set the digital signature algorithm used to sign OCSP responses.
+     *
+     * @param algName The algorithm name
+     *
+     * @throws NoSuchAlgorithmException if the algorithm name is invalid.
+     */
+    public void setSignatureAlgorithm(String algName)
+            throws NoSuchAlgorithmException {
+        if (!started) {
+            sigAlgId = AlgorithmId.get(algName);
+            log("Signature algorithm set to " + sigAlgId.getName());
+        }
+    }
+
+    /**
+     * Get the port the OCSP server is running on.
+     *
+     * @return the port that the OCSP server is running on, or -1 if the
+     * server has not yet been bound to a port.
+     */
+    public int getPort() {
+        if (serverReady.getCount() == 0) {
+            InetSocketAddress inetSock =
+                    (InetSocketAddress)servSocket.getLocalSocketAddress();
+            return inetSock.getPort();
+        } else {
+            return -1;
+        }
+    }
+
+    /**
+     * Allow SimpleOCSPServer consumers to wait for the server to be in
+     * the ready state before sending requests.
+     *
+     * @param timeout the length of time to wait for the server to be ready
+     * @param unit the unit of time applied to the timeout parameter
+     *
+     * @return true if the server enters the ready state, false if the
+     *      timeout period elapses while the caller is waiting for the server
+     *      to become ready.
+     *
+     * @throws InterruptedException if the current thread is interrupted.
+     */
+    public boolean awaitServerReady(long timeout, TimeUnit unit)
+            throws InterruptedException {
+        return serverReady.await(timeout, unit);
+    }
+
+    /**
+     * Set a delay between the reception of the request and production of
+     * the response.
+     *
+     * @param delayMillis the number of milliseconds to wait before acting
+     * on the incoming request.
+     */
+    public void setDelay(long delayMillis) {
+        delayMsec = delayMillis > 0 ? delayMillis : 0;
+        if (delayMsec > 0) {
+            log("OCSP latency set to " + delayMsec + " milliseconds.");
+        } else {
+            log("OCSP latency disabled");
+        }
+    }
+
+    /**
+     * Setting to control whether HTTP responses have the Content-Length
+     * field asserted or not.
+     *
+     * @param isDisabled true if the Content-Length field should not be
+     *        asserted, false otherwise.
+     */
+    public void setDisableContentLength(boolean isDisabled) {
+        if (!started) {
+            omitContentLength = isDisabled;
+            log("Response Content-Length field " +
+                    (isDisabled ? "disabled" : "enabled"));
+        }
+    }
+
+    /**
+     * Log a message to stdout.
+     *
+     * @param message the message to log
+     */
+    private synchronized void log(String message) {
+        if (logEnabled || debug != null) {
+            System.out.println("[" + Thread.currentThread().getName() + "][" +
+                    System.currentTimeMillis() + "]: " + message);
+        }
+    }
+
+    /**
+     * Log an error message on the stderr stream.
+     *
+     * @param message the message to log
+     */
+    private static synchronized void err(String message) {
+        System.err.println("[" + Thread.currentThread().getName() + "]: " +
+                message);
+    }
+
+    /**
+     * Log exception information on the stderr stream.
+     *
+     * @param exc the exception to dump information about
+     */
+    private static synchronized void err(Throwable exc) {
+        System.out.print("[" + Thread.currentThread().getName() +
+                "]: Exception: ");
+        exc.printStackTrace(System.out);
+    }
+
+    /**
+     * The {@code CertStatusInfo} class defines an object used to return
+     * information from the internal status database.  The data in this
+     * object may be used to construct OCSP responses.
+     */
+    public static class CertStatusInfo {
+        private CertStatus certStatusType;
+        private CRLReason reason;
+        private Date revocationTime;
+
+        /**
+         * Create a Certificate status object by providing the status only.
+         * If the status is {@code REVOKED} then current time is assumed
+         * for the revocation time.
+         *
+         * @param statType the status for this entry.
+         */
+        public CertStatusInfo(CertStatus statType) {
+            this(statType, null, null);
+        }
+
+        /**
+         * Create a CertStatusInfo providing both type and revocation date
+         * (if applicable).
+         *
+         * @param statType the status for this entry.
+         * @param revDate if applicable, the date that revocation took place.
+         * A value of {@code null} indicates that current time should be used.
+         * If the value of {@code statType} is not {@code CERT_STATUS_REVOKED},
+         * then the {@code revDate} parameter is ignored.
+         */
+        public CertStatusInfo(CertStatus statType, Date revDate) {
+            this(statType, revDate, null);
+        }
+
+        /**
+         * Create a CertStatusInfo providing type, revocation date
+         * (if applicable) and revocation reason.
+         *
+         * @param statType the status for this entry.
+         * @param revDate if applicable, the date that revocation took place.
+         * A value of {@code null} indicates that current time should be used.
+         * If the value of {@code statType} is not {@code CERT_STATUS_REVOKED},
+         * then the {@code revDate} parameter is ignored.
+         * @param revReason the reason the certificate was revoked.  A value of
+         * {@code null} means that no reason was provided.
+         */
+        public CertStatusInfo(CertStatus statType, Date revDate,
+                CRLReason revReason) {
+            Objects.requireNonNull(statType, "Cert Status must be non-null");
+            certStatusType = statType;
+            switch (statType) {
+                case CERT_STATUS_GOOD:
+                case CERT_STATUS_UNKNOWN:
+                    revocationTime = null;
+                    break;
+                case CERT_STATUS_REVOKED:
+                    revocationTime = revDate != null ? (Date)revDate.clone() :
+                            new Date();
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown status type: " +
+                            statType);
+            }
+        }
+
+        /**
+         * Get the cert status type
+         *
+         * @return the status applied to this object (e.g.
+         * {@code CERT_STATUS_GOOD}, {@code CERT_STATUS_UNKNOWN}, etc.)
+         */
+        public CertStatus getType() {
+            return certStatusType;
+        }
+
+        /**
+         * Get the revocation time (if applicable).
+         *
+         * @return the revocation time as a {@code Date} object, or
+         * {@code null} if not applicable (i.e. if the certificate hasn't been
+         * revoked).
+         */
+        public Date getRevocationTime() {
+            return (revocationTime != null ? (Date)revocationTime.clone() :
+                    null);
+        }
+
+        /**
+         * Get the revocation reason.
+         *
+         * @return the revocation reason, or {@code null} if one was not
+         * provided.
+         */
+        public CRLReason getRevocationReason() {
+            return reason;
+        }
+    }
+
+    /**
+     * Runnable task that handles incoming OCSP Requests and returns
+     * responses.
+     */
+    private class OcspHandler implements Runnable {
+        private final boolean USE_GET =
+            !System.getProperty("com.sun.security.ocsp.useget", "").equals("false");
+
+        private final Socket sock;
+        InetSocketAddress peerSockAddr;
+
+        /**
+         * Construct an {@code OcspHandler}.
+         *
+         * @param incomingSocket the socket the server created on accept()
+         */
+        private OcspHandler(Socket incomingSocket) {
+            sock = incomingSocket;
+        }
+
+        /**
+         * Run the OCSP Request parser and construct a response to be sent
+         * back to the client.
+         */
+        @Override
+        public void run() {
+            // If we have implemented a delay to simulate network latency
+            // wait out the delay here before any other processing.
+            try {
+                if (delayMsec > 0) {
+                    log("Delaying response for " + delayMsec + " milliseconds.");
+                    Thread.sleep(delayMsec);
+                }
+            } catch (InterruptedException ie) {
+                // Just log the interrupted sleep
+                log("Delay of " + delayMsec + " milliseconds was interrupted");
+            }
+
+            try (Socket ocspSocket = sock;
+                    InputStream in = ocspSocket.getInputStream();
+                    OutputStream out = ocspSocket.getOutputStream()) {
+                peerSockAddr =
+                        (InetSocketAddress)ocspSocket.getRemoteSocketAddress();
+
+                // Read in the first line which will be the request line.
+                // This will be tokenized so we know if we are dealing with
+                // a GET or POST.
+                String[] headerTokens = readLine(in).split(" ");
+                LocalOcspRequest ocspReq = null;
+                LocalOcspResponse ocspResp = null;
+                ResponseStatus respStat = ResponseStatus.INTERNAL_ERROR;
+                try {
+                    if (headerTokens[0] != null) {
+                        log("Received incoming HTTP " + headerTokens[0] +
+                                " from " + peerSockAddr);
+                        switch (headerTokens[0].toUpperCase()) {
+                            case "POST":
+                                ocspReq = parseHttpOcspPost(in);
+                                break;
+                            case "GET":
+                                ocspReq = parseHttpOcspGet(headerTokens, in);
+                                break;
+                            default:
+                                respStat = ResponseStatus.MALFORMED_REQUEST;
+                                throw new IOException("Not a GET or POST");
+                        }
+                    } else {
+                        respStat = ResponseStatus.MALFORMED_REQUEST;
+                        throw new IOException("Unable to get HTTP method");
+                    }
+
+                    if (ocspReq != null) {
+                        log(ocspReq.toString());
+                        // Get responses for all CertIds in the request
+                        Map<CertId, CertStatusInfo> statusMap =
+                                checkStatusDb(ocspReq.getRequests());
+                        if (statusMap.isEmpty()) {
+                            respStat = ResponseStatus.UNAUTHORIZED;
+                        } else {
+                            ocspResp = new LocalOcspResponse(
+                                    ResponseStatus.SUCCESSFUL, statusMap,
+                                    ocspReq.getExtensions());
+                        }
+                    } else {
+                        respStat = ResponseStatus.MALFORMED_REQUEST;
+                        throw new IOException("Found null request");
+                    }
+                } catch (IOException | RuntimeException exc) {
+                    err(exc);
+                }
+                if (ocspResp == null) {
+                    ocspResp = new LocalOcspResponse(respStat);
+                }
+                sendResponse(out, ocspResp);
+                out.flush();
+
+                log("Closing " + ocspSocket);
+            } catch (IOException | CertificateException exc) {
+                err(exc);
+            }
+        }
+
+        /**
+         * Send an OCSP response on an {@code OutputStream}.
+         *
+         * @param out the {@code OutputStream} on which to send the response.
+         * @param resp the OCSP response to send.
+         *
+         * @throws IOException if an encoding error occurs.
+         */
+        public void sendResponse(OutputStream out, LocalOcspResponse resp)
+                throws IOException {
+            StringBuilder sb = new StringBuilder();
+
+            byte[] respBytes;
+            try {
+                respBytes = resp.getBytes();
+            } catch (RuntimeException re) {
+                err(re);
+                return;
+            }
+
+            sb.append("HTTP/1.0 200 OK\r\n");
+            sb.append("Content-Type: application/ocsp-response\r\n");
+            if (!omitContentLength) {
+                sb.append("Content-Length: ").append(respBytes.length).
+                        append("\r\n");
+            }
+            sb.append("\r\n");
+
+            out.write(sb.toString().getBytes("UTF-8"));
+            out.write(respBytes);
+            log(resp.toString());
+        }
+
+        /**
+         * Parse the incoming HTTP POST of an OCSP Request.
+         *
+         * @param inStream the input stream from the socket bound to this
+         * {@code OcspHandler}.
+         *
+         * @return the OCSP Request as a {@code LocalOcspRequest}
+         *
+         * @throws IOException if there are network related issues or problems
+         * occur during parsing of the OCSP request.
+         * @throws CertificateException if one or more of the certificates in
+         * the OCSP request cannot be read/parsed.
+         */
+        private LocalOcspRequest parseHttpOcspPost(InputStream inStream)
+                throws IOException, CertificateException {
+            boolean endOfHeader = false;
+            boolean properContentType = false;
+            int length = -1;
+
+            while (!endOfHeader) {
+                String[] lineTokens = readLine(inStream).split(" ");
+                if (lineTokens[0].isEmpty()) {
+                    endOfHeader = true;
+                } else if (lineTokens[0].equalsIgnoreCase("Content-Type:")) {
+                    if (lineTokens[1] == null ||
+                            !lineTokens[1].equals(
+                                    "application/ocsp-request")) {
+                        log("Unknown Content-Type: " +
+                                (lineTokens[1] != null ?
+                                        lineTokens[1] : "<NULL>"));
+                        return null;
+                    } else {
+                        properContentType = true;
+                        log("Content-Type = " + lineTokens[1]);
+                    }
+                } else if (lineTokens[0].equalsIgnoreCase("Content-Length:")) {
+                    if (lineTokens[1] != null) {
+                        length = Integer.parseInt(lineTokens[1]);
+                        log("Content-Length = " + length);
+                    }
+                }
+            }
+
+            // Okay, make sure we got what we needed from the header, then
+            // read the remaining OCSP Request bytes
+            if (properContentType && length >= 0) {
+                if (USE_GET && length <= 255) {
+                    // Received a small POST request. Check that our client code properly
+                    // handled the relevant flag. We expect small GET requests, unless
+                    // explicitly disabled.
+                    throw new IOException("Should have received small GET, not POST.");
+                }
+                byte[] ocspBytes = new byte[length];
+                inStream.read(ocspBytes);
+                return new LocalOcspRequest(ocspBytes);
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Parse the incoming HTTP GET of an OCSP Request.
+         *
+         * @param headerTokens the individual String tokens from the first
+         * line of the HTTP GET.
+         * @param inStream the input stream from the socket bound to this
+         * {@code OcspHandler}.
+         *
+         * @return the OCSP Request as a {@code LocalOcspRequest}
+         *
+         * @throws IOException if there are network related issues or problems
+         * occur during parsing of the OCSP request.
+         * @throws CertificateException if one or more of the certificates in
+         * the OCSP request cannot be read/parsed.
+         */
+        private LocalOcspRequest parseHttpOcspGet(String[] headerTokens,
+                InputStream inStream) throws IOException, CertificateException {
+            // Display the whole request
+            StringBuilder sb = new StringBuilder("OCSP GET REQUEST\n");
+            for (String hTok : headerTokens) {
+                sb.append(hTok).append("\n");
+            }
+            log(sb.toString());
+
+            // Before we process the remainder of the GET URL, we should drain
+            // the InputStream of any other header data.  We (for now) won't
+            // use it, but will display the contents if logging is enabled.
+            boolean endOfHeader = false;
+            while (!endOfHeader) {
+                String[] lineTokens = readLine(inStream).split(":", 2);
+                // We expect to see a type and value pair delimited by a colon.
+                if (lineTokens[0].isEmpty()) {
+                    endOfHeader = true;
+                } else if (lineTokens.length == 2) {
+                    log(String.format("ReqHdr: %s: %s", lineTokens[0].trim(),
+                            lineTokens[1].trim()));
+                } else {
+                    // A colon wasn't found and token 0 should be the whole line
+                    log("ReqHdr: " + lineTokens[0].trim());
+                }
+            }
+
+            // We have already established headerTokens[0] to be "GET".
+            // We should have the URL-encoded base64 representation of the
+            // OCSP request in headerTokens[1].  We need to strip any leading
+            // "/" off before decoding.
+            return new LocalOcspRequest(Base64.getMimeDecoder().decode(
+                    URLDecoder.decode(headerTokens[1].replaceAll("/", ""),
+                            "UTF-8")));
+        }
+
+        /**
+         * Read a line of text that is CRLF-delimited.
+         *
+         * @param is the {@code InputStream} tied to the socket
+         * for this {@code OcspHandler}
+         *
+         * @return a {@code String} consisting of the line of text
+         * read from the stream with the CRLF stripped.
+         *
+         * @throws IOException if any I/O error occurs.
+         */
+        private String readLine(InputStream is) throws IOException {
+            PushbackInputStream pbis = new PushbackInputStream(is);
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            boolean done = false;
+            while (!done) {
+                byte b = (byte)pbis.read();
+                if (b == '\r') {
+                    byte bNext = (byte)pbis.read();
+                    if (bNext == '\n' || bNext == -1) {
+                        done = true;
+                    } else {
+                        pbis.unread(bNext);
+                        bos.write(b);
+                    }
+                } else if (b == -1) {
+                    done = true;
+                } else {
+                    bos.write(b);
+                }
+            }
+
+            return new String(bos.toByteArray(), "UTF-8");
+        }
+    }
+
+
+    /**
+     * Simple nested class to handle OCSP requests without making
+     * changes to sun.security.provider.certpath.OCSPRequest
+     */
+    public class LocalOcspRequest {
+
+        private byte[] nonce;
+        private byte[] signature = null;
+        private AlgorithmId algId = null;
+        private int version = 0;
+        private GeneralName requestorName = null;
+        private Map<String, Extension> extensions = Collections.emptyMap();
+        private final List<LocalSingleRequest> requestList = new ArrayList<>();
+        private final List<X509Certificate> certificates = new ArrayList<>();
+
+        /**
+         * Construct a {@code LocalOcspRequest} from its DER encoding.
+         *
+         * @param requestBytes the DER-encoded bytes
+         *
+         * @throws IOException if decoding errors occur
+         * @throws CertificateException if certificates are found in the
+         * OCSP request and they do not parse correctly.
+         */
+        private LocalOcspRequest(byte[] requestBytes) throws IOException,
+                CertificateException {
+            Objects.requireNonNull(requestBytes, "Received null input");
+
+            // Display the DER encoding before parsing
+            log("Local OCSP Request Constructor, parsing bytes:\n" +
+                    dumpHexBytes(requestBytes));
+
+            DerInputStream dis = new DerInputStream(requestBytes);
+
+            // Parse the top-level structure, it should have no more than
+            // two elements.
+            DerValue[] topStructs = dis.getSequence(2);
+            for (DerValue dv : topStructs) {
+                if (dv.tag == DerValue.tag_Sequence) {
+                    parseTbsRequest(dv);
+                } else if (dv.isContextSpecific((byte)0)) {
+                    parseSignature(dv);
+                } else {
+                    throw new IOException("Unknown tag at top level: " +
+                            dv.tag);
+                }
+            }
+        }
+
+        /**
+         * Parse the signature block from an OCSP request
+         *
+         * @param sigSequence a {@code DerValue} containing the signature
+         * block at the outer sequence datum.
+         *
+         * @throws IOException if any non-certificate-based parsing errors occur
+         * @throws CertificateException if certificates are found in the
+         * OCSP request and they do not parse correctly.
+         */
+        private void parseSignature(DerValue sigSequence)
+                throws IOException, CertificateException {
+            DerValue[] sigItems = sigSequence.data.getSequence(3);
+            if (sigItems.length != 3) {
+                throw new IOException("Invalid number of signature items: " +
+                        "expected 3, got " + sigItems.length);
+            }
+
+            algId = AlgorithmId.parse(sigItems[0]);
+            signature = sigItems[1].getBitString();
+
+            if (sigItems[2].isContextSpecific((byte)0)) {
+                DerValue[] certDerItems = sigItems[2].data.getSequence(4);
+                int i = 0;
+                for (DerValue dv : certDerItems) {
+                    X509Certificate xc = new X509CertImpl(dv);
+                    certificates.add(xc);
+                }
+            } else {
+                throw new IOException("Invalid tag in signature block: " +
+                    sigItems[2].tag);
+            }
+        }
+
+        /**
+         * Parse the to-be-signed request data
+         *
+         * @param tbsReqSeq a {@code DerValue} object containing the to-be-
+         * signed OCSP request at the outermost SEQUENCE tag.
+         * @throws IOException if any parsing errors occur
+         */
+        private void parseTbsRequest(DerValue tbsReqSeq) throws IOException {
+            while (tbsReqSeq.data.available() > 0) {
+                DerValue dv = tbsReqSeq.data.getDerValue();
+                if (dv.isContextSpecific((byte)0)) {
+                    // The version was explicitly called out
+                    version = dv.data.getInteger();
+                } else if (dv.isContextSpecific((byte)1)) {
+                    // A GeneralName was provided
+                    requestorName = new GeneralName(dv.data.getDerValue());
+                } else if (dv.isContextSpecific((byte)2)) {
+                    // Parse the extensions
+                    DerValue[] extItems = dv.data.getSequence(2);
+                    extensions = parseExtensions(extItems);
+                } else if (dv.tag == DerValue.tag_Sequence) {
+                    while (dv.data.available() > 0) {
+                        requestList.add(new LocalSingleRequest(dv.data));
+                    }
+                }
+            }
+        }
+
+        /**
+         * Parse a SEQUENCE of extensions.  This routine is used both
+         * at the overall request level and down at the singleRequest layer.
+         *
+         * @param extDerItems an array of {@code DerValue} items, each one
+         * consisting of a DER-encoded extension.
+         *
+         * @return a {@code Map} of zero or more extensions,
+         * keyed by its object identifier in {@code String} form.
+         *
+         * @throws IOException if any parsing errors occur.
+         */
+        private Map<String, Extension> parseExtensions(DerValue[] extDerItems)
+                throws IOException {
+            Map<String, Extension> extMap = new HashMap<>();
+
+            if (extDerItems != null && extDerItems.length != 0) {
+                for (DerValue extDerVal : extDerItems) {
+                    sun.security.x509.Extension ext =
+                            new sun.security.x509.Extension(extDerVal);
+                    extMap.put(ext.getId(), ext);
+                }
+            }
+
+            return extMap;
+        }
+
+        /**
+         * Return the list of single request objects in this OCSP request.
+         *
+         * @return an unmodifiable {@code List} of zero or more requests.
+         */
+        private List<LocalSingleRequest> getRequests() {
+            return Collections.unmodifiableList(requestList);
+        }
+
+        /**
+         * Return the list of X.509 Certificates in this OCSP request.
+         *
+         * @return an unmodifiable {@code List} of zero or more
+         * {@cpde X509Certificate} objects.
+         */
+        private List<X509Certificate> getCertificates() {
+            return Collections.unmodifiableList(certificates);
+        }
+
+        /**
+         * Return the map of OCSP request extensions.
+         *
+         * @return an unmodifiable {@code Map} of zero or more
+         * {@code Extension} objects, keyed by their object identifiers
+         * in {@code String} form.
+         */
+        private Map<String, Extension> getExtensions() {
+            return Collections.unmodifiableMap(extensions);
+        }
+
+        /**
+         * Display the {@code LocalOcspRequest} in human readable form.
+         *
+         * @return a {@code String} representation of the
+         * {@code LocalOcspRequest}
+         */
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+
+            sb.append(String.format("OCSP Request: Version %d (0x%X)",
+                    version + 1, version)).append("\n");
+            if (requestorName != null) {
+                sb.append("Requestor Name: ").append(requestorName).
+                        append("\n");
+            }
+
+            int requestCtr = 0;
+            for (LocalSingleRequest lsr : requestList) {
+                sb.append("Request [").append(requestCtr++).append("]\n");
+                sb.append(lsr).append("\n");
+            }
+            if (!extensions.isEmpty()) {
+                sb.append("Extensions (").append(extensions.size()).
+                        append(")\n");
+                for (Extension ext : extensions.values()) {
+                    sb.append("\t").append(ext).append("\n");
+                }
+            }
+            if (signature != null) {
+                sb.append("Signature: ").append(algId).append("\n");
+                sb.append(dumpHexBytes(signature)).append("\n");
+                int certCtr = 0;
+                for (X509Certificate cert : certificates) {
+                    sb.append("Certificate [").append(certCtr++).append("]").
+                            append("\n");
+                    sb.append("\tSubject: ");
+                    sb.append(cert.getSubjectX500Principal()).append("\n");
+                    sb.append("\tIssuer: ");
+                    sb.append(cert.getIssuerX500Principal()).append("\n");
+                    sb.append("\tSerial: ").append(cert.getSerialNumber());
+                }
+            }
+
+            return sb.toString();
+        }
+
+        /**
+         * Inner class designed to handle the decoding/representation of
+         * single requests within a {@code LocalOcspRequest} object.
+         */
+        public class LocalSingleRequest {
+            private final CertId cid;
+            private Map<String, Extension> extensions = Collections.emptyMap();
+
+            private LocalSingleRequest(DerInputStream dis)
+                    throws IOException {
+                DerValue[] srItems = dis.getSequence(2);
+
+                // There should be 1, possibly 2 DerValue items
+                if (srItems.length == 1 || srItems.length == 2) {
+                    // The first parsable item should be the mandatory CertId
+                    cid = new CertId(srItems[0].data);
+                    if (srItems.length == 2) {
+                        if (srItems[1].isContextSpecific((byte)0)) {
+                            DerValue[] extDerItems = srItems[1].data.getSequence(2);
+                            extensions = parseExtensions(extDerItems);
+                        } else {
+                            throw new IOException("Illegal tag in Request " +
+                                    "extensions: " + srItems[1].tag);
+                        }
+                    }
+                } else {
+                    throw new IOException("Invalid number of items in " +
+                            "Request (" + srItems.length + ")");
+                }
+            }
+
+            /**
+             * Get the {@code CertId} for this single request.
+             *
+             * @return the {@code CertId} for this single request.
+             */
+            private CertId getCertId() {
+                return cid;
+            }
+
+            /**
+             * Return the map of single request extensions.
+             *
+             * @return an unmodifiable {@code Map} of zero or more
+             * {@code Extension} objects, keyed by their object identifiers
+             * in {@code String} form.
+             */
+            private Map<String, Extension> getExtensions() {
+                return Collections.unmodifiableMap(extensions);
+            }
+
+            /**
+             * Display the {@code LocalSingleRequest} in human readable form.
+             *
+             * @return a {@code String} representation of the
+             * {@code LocalSingleRequest}
+             */
+            @Override
+            public String toString() {
+                StringBuilder sb = new StringBuilder();
+                sb.append("CertId, Algorithm = ");
+                sb.append(cid.getHashAlgorithm()).append("\n");
+                sb.append("\tIssuer Name Hash: ");
+                byte[] cidHashBuf = cid.getIssuerNameHash();
+                sb.append(dumpHexBytes(cidHashBuf, cidHashBuf.length,
+                        256, "", ""));
+                sb.append("\n");
+                sb.append("\tIssuer Key Hash: ");
+                cidHashBuf = cid.getIssuerKeyHash();
+                sb.append(dumpHexBytes(cidHashBuf, cidHashBuf.length,
+                        256, "", ""));
+                sb.append("\n");
+                sb.append("\tSerial Number: ").append(cid.getSerialNumber());
+                if (!extensions.isEmpty()) {
+                    sb.append("Extensions (").append(extensions.size()).
+                            append(")\n");
+                    for (Extension ext : extensions.values()) {
+                        sb.append("\t").append(ext).append("\n");
+                    }
+                }
+
+                return sb.toString();
+            }
+        }
+    }
+
+    /**
+     * Simple nested class to handle OCSP requests without making
+     * changes to sun.security.provider.certpath.OCSPResponse
+     */
+    public class LocalOcspResponse {
+        private final int version = 0;
+        private final OCSPResponse.ResponseStatus responseStatus;
+        private final Map<CertId, CertStatusInfo> respItemMap;
+        private final Date producedAtDate;
+        private final List<LocalSingleResponse> singleResponseList =
+                new ArrayList<>();
+        private final Map<String, Extension> responseExtensions;
+        private byte[] signature;
+        private final List<X509Certificate> certificates;
+        private final byte[] encodedResponse;
+
+        /**
+         * Constructor for the generation of non-successful responses
+         *
+         * @param respStat the OCSP response status.
+         *
+         * @throws IOException if an error happens during encoding
+         * @throws NullPointerException if {@code respStat} is {@code null}
+         * or {@code respStat} is successful.
+         */
+        public LocalOcspResponse(OCSPResponse.ResponseStatus respStat)
+                throws IOException {
+            this(respStat, null, null);
+        }
+
+        /**
+         * Construct a response from a list of certificate
+         * status objects and extensions.
+         *
+         * @param respStat the status of the entire response
+         * @param itemMap a {@code Map} of {@code CertId} objects and their
+         * respective revocation statuses from the server's response DB.
+         * @param reqExtensions a {@code Map} of request extensions
+         *
+         * @throws IOException if an error happens during encoding
+         * @throws NullPointerException if {@code respStat} is {@code null}
+         * or {@code respStat} is successful, and a {@code null} {@code itemMap}
+         * has been provided.
+         */
+        public LocalOcspResponse(OCSPResponse.ResponseStatus respStat,
+                Map<CertId, CertStatusInfo> itemMap,
+                Map<String, Extension> reqExtensions) throws IOException {
+            responseStatus = Objects.requireNonNull(respStat,
+                    "Illegal null response status");
+            if (responseStatus == ResponseStatus.SUCCESSFUL) {
+                respItemMap = Objects.requireNonNull(itemMap,
+                        "SUCCESSFUL responses must have a response map");
+                producedAtDate = new Date();
+
+                // Turn the answerd from the response DB query into a list
+                // of single responses.
+                for (CertId id : itemMap.keySet()) {
+                    singleResponseList.add(
+                            new LocalSingleResponse(id, itemMap.get(id)));
+                }
+
+                responseExtensions = setResponseExtensions(reqExtensions);
+                certificates = new ArrayList<>();
+                if (signerCert != issuerCert) {
+                    certificates.add(signerCert);
+                }
+                certificates.add(issuerCert);
+            } else {
+                respItemMap = null;
+                producedAtDate = null;
+                responseExtensions = null;
+                certificates = null;
+            }
+            encodedResponse = this.getBytes();
+        }
+
+        /**
+         * Set the response extensions based on the request extensions
+         * that were received.  Right now, this is limited to the
+         * OCSP nonce extension.
+         *
+         * @param reqExts a {@code Map} of zero or more request extensions
+         *
+         * @return a {@code Map} of zero or more response extensions, keyed
+         * by the extension object identifier in {@code String} form.
+         */
+        private Map<String, Extension> setResponseExtensions(
+                Map<String, Extension> reqExts) {
+            Map<String, Extension> respExts = new HashMap<>();
+            String ocspNonceStr = PKIXExtensions.OCSPNonce_Id.toString();
+
+            if (reqExts != null) {
+                for (String id : reqExts.keySet()) {
+                    if (id.equals(ocspNonceStr)) {
+                        // We found a nonce, add it into the response extensions
+                        Extension ext = reqExts.get(id);
+                        if (ext != null) {
+                            respExts.put(id, ext);
+                            log("Added OCSP Nonce to response");
+                        } else {
+                            log("Error: Found nonce entry, but found null " +
+                                    "value.  Skipping");
+                        }
+                    }
+                }
+            }
+
+            return respExts;
+        }
+
+        /**
+         * Get the DER-encoded response bytes for this response
+         *
+         * @return a byte array containing the DER-encoded bytes for
+         * the response
+         *
+         * @throws IOException if any encoding errors occur
+         */
+        private byte[] getBytes() throws IOException {
+            DerOutputStream outerSeq = new DerOutputStream();
+            DerOutputStream responseStream = new DerOutputStream();
+            responseStream.putEnumerated(responseStatus.ordinal());
+            if (responseStatus == ResponseStatus.SUCCESSFUL &&
+                    respItemMap != null) {
+                encodeResponseBytes(responseStream);
+            }
+
+            // Commit the outermost sequence bytes
+            outerSeq.write(DerValue.tag_Sequence, responseStream);
+            return outerSeq.toByteArray();
+        }
+
+        private void encodeResponseBytes(DerOutputStream responseStream)
+                throws IOException {
+            DerOutputStream explicitZero = new DerOutputStream();
+            DerOutputStream respItemStream = new DerOutputStream();
+
+            respItemStream.putOID(OCSP_BASIC_RESPONSE_OID);
+
+            byte[] basicOcspBytes = encodeBasicOcspResponse();
+            respItemStream.putOctetString(basicOcspBytes);
+            explicitZero.write(DerValue.tag_Sequence, respItemStream);
+            responseStream.write(DerValue.createTag(DerValue.TAG_CONTEXT,
+                    true, (byte)0), explicitZero);
+        }
+
+        private byte[] encodeBasicOcspResponse() throws IOException {
+            DerOutputStream outerSeq = new DerOutputStream();
+            DerOutputStream basicORItemStream = new DerOutputStream();
+
+            // Encode the tbsResponse
+            byte[] tbsResponseBytes = encodeTbsResponse();
+            basicORItemStream.write(tbsResponseBytes);
+
+            try {
+                // Create the signature
+                Signature sig = SignatureUtil.fromKey(
+                        sigAlgId.getName(), signerKey, (Provider)null);
+                sig.update(tbsResponseBytes);
+                signature = sig.sign();
+                // Rewrite signAlg, RSASSA-PSS needs some parameters.
+                sigAlgId = SignatureUtil.fromSignature(sig, signerKey);
+                sigAlgId.encode(basicORItemStream);
+                basicORItemStream.putBitString(signature);
+            } catch (GeneralSecurityException exc) {
+                err(exc);
+                throw new IOException(exc);
+            }
+
+            // Add certificates
+            try {
+                DerOutputStream certStream = new DerOutputStream();
+                ArrayList<DerValue> certList = new ArrayList<>();
+                if (signerCert != issuerCert) {
+                    certList.add(new DerValue(signerCert.getEncoded()));
+                }
+                certList.add(new DerValue(issuerCert.getEncoded()));
+                DerValue[] dvals = new DerValue[certList.size()];
+                certStream.putSequence(certList.toArray(dvals));
+                basicORItemStream.write(DerValue.createTag(DerValue.TAG_CONTEXT,
+                        true, (byte)0), certStream);
+            } catch (CertificateEncodingException cex) {
+                err(cex);
+                throw new IOException(cex);
+            }
+
+            // Commit the outermost sequence bytes
+            outerSeq.write(DerValue.tag_Sequence, basicORItemStream);
+            return outerSeq.toByteArray();
+        }
+
+        private byte[] encodeTbsResponse() throws IOException {
+            DerOutputStream outerSeq = new DerOutputStream();
+            DerOutputStream tbsStream = new DerOutputStream();
+
+            // Note: We're not going explicitly assert the version
+            tbsStream.write(respId.getEncoded());
+            tbsStream.putGeneralizedTime(producedAtDate);
+
+            // Sequence of responses
+            encodeSingleResponses(tbsStream);
+
+            // TODO: add response extension support
+            encodeExtensions(tbsStream);
+
+            outerSeq.write(DerValue.tag_Sequence, tbsStream);
+            return outerSeq.toByteArray();
+        }
+
+        private void encodeSingleResponses(DerOutputStream tbsStream)
+                throws IOException {
+            DerValue[] srDerVals = new DerValue[singleResponseList.size()];
+            int srDvCtr = 0;
+
+            for (LocalSingleResponse lsr : singleResponseList) {
+                srDerVals[srDvCtr++] = new DerValue(lsr.getBytes());
+            }
+
+            tbsStream.putSequence(srDerVals);
+        }
+
+        private void encodeExtensions(DerOutputStream tbsStream)
+                throws IOException {
+            DerOutputStream extSequence = new DerOutputStream();
+            DerOutputStream extItems = new DerOutputStream();
+
+            for (Extension ext : responseExtensions.values()) {
+                ext.encode(extItems);
+            }
+            extSequence.write(DerValue.tag_Sequence, extItems);
+            tbsStream.write(DerValue.createTag(DerValue.TAG_CONTEXT, true,
+                    (byte)1), extSequence);
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+
+            sb.append("OCSP Response: ").append(responseStatus).append("\n");
+            if (responseStatus == ResponseStatus.SUCCESSFUL) {
+                sb.append("Response Type: ").
+                        append(OCSP_BASIC_RESPONSE_OID.toString()).append("\n");
+                sb.append(String.format("Version: %d (0x%X)", version + 1,
+                        version)).append("\n");
+                sb.append("Responder Id: ").append(respId.toString()).
+                        append("\n");
+                sb.append("Produced At: ").
+                        append(utcDateFmt.format(producedAtDate)).append("\n");
+
+                int srCtr = 0;
+                for (LocalSingleResponse lsr : singleResponseList) {
+                    sb.append("SingleResponse [").append(srCtr++).append("]\n");
+                    sb.append(lsr);
+                }
+
+                if (!responseExtensions.isEmpty()) {
+                    sb.append("Extensions (").append(responseExtensions.size()).
+                            append(")\n");
+                    for (Extension ext : responseExtensions.values()) {
+                        sb.append("\t").append(ext).append("\n");
+                    }
+                } else {
+                    sb.append("\n");
+                }
+
+                if (signature != null) {
+                    sb.append("Signature: ").append(sigAlgId).append("\n");
+                    sb.append(dumpHexBytes(signature)).append("\n");
+                    int certCtr = 0;
+                    for (X509Certificate cert : certificates) {
+                        sb.append("Certificate [").append(certCtr++).append("]").
+                                append("\n");
+                        sb.append("\tSubject: ");
+                        sb.append(cert.getSubjectX500Principal()).append("\n");
+                        sb.append("\tIssuer: ");
+                        sb.append(cert.getIssuerX500Principal()).append("\n");
+                        sb.append("\tSerial: ").append(cert.getSerialNumber());
+                        sb.append("\n");
+                    }
+                }
+            }
+
+            return sb.toString();
+        }
+
+        private class LocalSingleResponse {
+            private final CertId certId;
+            private final CertStatusInfo csInfo;
+            private final Date thisUpdate;
+            private final Date lsrNextUpdate;
+            private final Map<String, Extension> singleExtensions;
+
+            public LocalSingleResponse(CertId cid, CertStatusInfo info) {
+                certId = Objects.requireNonNull(cid, "CertId must be non-null");
+                csInfo = Objects.requireNonNull(info,
+                        "CertStatusInfo must be non-null");
+
+                // For now, we'll keep things simple and make the thisUpdate
+                // field the same as the producedAt date.
+                thisUpdate = producedAtDate;
+                lsrNextUpdate = getNextUpdate();
+
+                // TODO Add extensions support
+                singleExtensions = Collections.emptyMap();
+            }
+
+            @Override
+            public String toString() {
+                StringBuilder sb = new StringBuilder();
+                sb.append("Certificate Status: ").append(csInfo.getType());
+                sb.append("\n");
+                if (csInfo.getType() == CertStatus.CERT_STATUS_REVOKED) {
+                    sb.append("Revocation Time: ");
+                    sb.append(utcDateFmt.format(csInfo.getRevocationTime()));
+                    sb.append("\n");
+                    if (csInfo.getRevocationReason() != null) {
+                        sb.append("Revocation Reason: ");
+                        sb.append(csInfo.getRevocationReason()).append("\n");
+                    }
+                }
+
+                sb.append("CertId, Algorithm = ");
+                sb.append(certId.getHashAlgorithm()).append("\n");
+                sb.append("\tIssuer Name Hash: ");
+                byte[] cidHashBuf = certId.getIssuerNameHash();
+                sb.append(dumpHexBytes(cidHashBuf, cidHashBuf.length,
+                        256, "", ""));
+                sb.append("\n");
+                sb.append("\tIssuer Key Hash: ");
+                cidHashBuf = certId.getIssuerKeyHash();
+                sb.append(dumpHexBytes(cidHashBuf, cidHashBuf.length,
+                        256, "", ""));
+                sb.append("\n");
+                sb.append("\tSerial Number: ").append(certId.getSerialNumber());
+                sb.append("\n");
+                sb.append("This Update: ");
+                sb.append(utcDateFmt.format(thisUpdate)).append("\n");
+                if (lsrNextUpdate != null) {
+                    sb.append("Next Update: ");
+                    sb.append(utcDateFmt.format(lsrNextUpdate)).append("\n");
+                }
+
+                if (!singleExtensions.isEmpty()) {
+                    sb.append("Extensions (").append(singleExtensions.size()).
+                            append(")\n");
+                    for (Extension ext : singleExtensions.values()) {
+                        sb.append("\t").append(ext).append("\n");
+                    }
+                }
+
+                return sb.toString();
+            }
+
+            public byte[] getBytes() throws IOException {
+                byte[] nullData = { };
+                DerOutputStream responseSeq = new DerOutputStream();
+                DerOutputStream srStream = new DerOutputStream();
+
+                // Encode the CertId
+                certId.encode(srStream);
+
+                // Next, encode the CertStatus field
+                CertStatus csiType = csInfo.getType();
+                switch (csiType) {
+                    case CERT_STATUS_GOOD:
+                        srStream.write(DerValue.createTag(DerValue.TAG_CONTEXT,
+                                false, (byte)0), nullData);
+                        break;
+                    case CERT_STATUS_REVOKED:
+                        DerOutputStream revInfo = new DerOutputStream();
+                        revInfo.putGeneralizedTime(csInfo.getRevocationTime());
+                        CRLReason revReason = csInfo.getRevocationReason();
+                        if (revReason != null) {
+                            byte[] revDer = new byte[3];
+                            revDer[0] = DerValue.tag_Enumerated;
+                            revDer[1] = 1;
+                            revDer[2] = (byte)revReason.ordinal();
+                            revInfo.write(DerValue.createTag(
+                                    DerValue.TAG_CONTEXT, true, (byte)0),
+                                    revDer);
+                        }
+                        srStream.write(DerValue.createTag(
+                                DerValue.TAG_CONTEXT, true, (byte)1),
+                                revInfo);
+                        break;
+                    case CERT_STATUS_UNKNOWN:
+                        srStream.write(DerValue.createTag(DerValue.TAG_CONTEXT,
+                                false, (byte)2), nullData);
+                        break;
+                    default:
+                        throw new IOException("Unknown CertStatus: " + csiType);
+                }
+
+                // Add the necessary dates
+                srStream.putGeneralizedTime(thisUpdate);
+                if (lsrNextUpdate != null) {
+                    DerOutputStream nuStream = new DerOutputStream();
+                    nuStream.putGeneralizedTime(lsrNextUpdate);
+                    srStream.write(DerValue.createTag(DerValue.TAG_CONTEXT,
+                            true, (byte)0), nuStream);
+                }
+
+                // TODO add singleResponse Extension support
+
+                // Add the single response to the response output stream
+                responseSeq.write(DerValue.tag_Sequence, srStream);
+                return responseSeq.toByteArray();
+            }
+        }
+    }
+}
diff -pruN 24.0.1+9-1/test/lib/jdk/test/lib/security/timestamp/TsaServer.java 24.0.2+12-1/test/lib/jdk/test/lib/security/timestamp/TsaServer.java
--- 24.0.1+9-1/test/lib/jdk/test/lib/security/timestamp/TsaServer.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/lib/jdk/test/lib/security/timestamp/TsaServer.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -87,7 +87,7 @@ public class TsaServer implements AutoCl
      *
      * @param handler a {@link TsaHandler}
      */
-    public void setHandler(TsaHandler handler) {
+    public final void setHandler(TsaHandler handler) {
         server.createContext("/", handler);
     }
 
@@ -113,7 +113,7 @@ public class TsaServer implements AutoCl
     }
 
     @Override
-    public void close() throws Exception {
+    public void close() {
         stop();
     }
 }
diff -pruN 24.0.1+9-1/test/micro/org/openjdk/bench/java/lang/foreign/CallByRefHighArity.java 24.0.2+12-1/test/micro/org/openjdk/bench/java/lang/foreign/CallByRefHighArity.java
--- 24.0.1+9-1/test/micro/org/openjdk/bench/java/lang/foreign/CallByRefHighArity.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/micro/org/openjdk/bench/java/lang/foreign/CallByRefHighArity.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 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
@@ -35,7 +35,7 @@ import java.util.function.Supplier;
 @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
 @State(org.openjdk.jmh.annotations.Scope.Thread)
 @OutputTimeUnit(TimeUnit.NANOSECONDS)
-@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "-Djava.library.path=micro/native" })
+@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED", "-Djava.library.path=micro/native" })
 public class CallByRefHighArity {
 
     static {
diff -pruN 24.0.1+9-1/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverRandom.java 24.0.2+12-1/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverRandom.java
--- 24.0.1+9-1/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverRandom.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverRandom.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 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
@@ -46,7 +46,7 @@ import jdk.internal.misc.Unsafe;
 @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
 @State(org.openjdk.jmh.annotations.Scope.Thread)
 @OutputTimeUnit(TimeUnit.MICROSECONDS)
-@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"})
+@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"})
 public class LoopOverRandom extends JavaLayouts {
     static final int SEED = 0;
 
diff -pruN 24.0.1+9-1/test/micro/org/openjdk/bench/java/lang/foreign/SegmentOfBuffer.java 24.0.2+12-1/test/micro/org/openjdk/bench/java/lang/foreign/SegmentOfBuffer.java
--- 24.0.1+9-1/test/micro/org/openjdk/bench/java/lang/foreign/SegmentOfBuffer.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/micro/org/openjdk/bench/java/lang/foreign/SegmentOfBuffer.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ *  Copyright (c) 2024, 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
@@ -57,13 +57,13 @@ public class SegmentOfBuffer {
     }
 
     @Benchmark
-    @Fork(value = 3, jvmArgsAppend = "-XX:CompileCommand=inline,jdk.internal.foreign.AbstractMemorySegmentImpl::ofBuffer,false")
+    @Fork(value = 3, jvmArgs = "-XX:CompileCommand=inline,jdk.internal.foreign.AbstractMemorySegmentImpl::ofBuffer,false")
     public long ofBufferInlineFalse() {
         return MemorySegment.ofBuffer(buffer).address();
     }
 
     @Benchmark
-    @Fork(value = 3, jvmArgsAppend = "-XX:CompileCommand=inline,jdk.internal.foreign.AbstractMemorySegmentImpl::ofBuffer,true")
+    @Fork(value = 3, jvmArgs = "-XX:CompileCommand=inline,jdk.internal.foreign.AbstractMemorySegmentImpl::ofBuffer,true")
     public long ofBufferInlineTrue() {
         return MemorySegment.ofBuffer(buffer).address();
     }
diff -pruN 24.0.1+9-1/test/micro/org/openjdk/bench/java/security/MLDSA.java 24.0.2+12-1/test/micro/org/openjdk/bench/java/security/MLDSA.java
--- 24.0.1+9-1/test/micro/org/openjdk/bench/java/security/MLDSA.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/micro/org/openjdk/bench/java/security/MLDSA.java	2025-06-27 08:03:14.000000000 +0000
@@ -56,7 +56,7 @@ import java.util.concurrent.TimeUnit;
 @State(Scope.Thread)
 @Warmup(iterations = 5, time = 1)
 @Measurement(iterations = 5, time = 1)
-@Fork(value = 3, jvmArgsAppend = {"--add-opens", "java.base/sun.security.provider=ALL-UNNAMED"})
+@Fork(value = 3, jvmArgs = {"--add-opens", "java.base/sun.security.provider=ALL-UNNAMED"})
 
 public class MLDSA {
         @Param({"ML-DSA-44", "ML-DSA-65", "ML-DSA-87"} )
diff -pruN 24.0.1+9-1/test/micro/org/openjdk/bench/java/security/MLKEMBench.java 24.0.2+12-1/test/micro/org/openjdk/bench/java/security/MLKEMBench.java
--- 24.0.1+9-1/test/micro/org/openjdk/bench/java/security/MLKEMBench.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/micro/org/openjdk/bench/java/security/MLKEMBench.java	2025-06-27 08:03:14.000000000 +0000
@@ -55,7 +55,7 @@ import java.util.concurrent.TimeUnit;
 @State(Scope.Thread)
 @Warmup(iterations = 5, time = 1)
 @Measurement(iterations = 5, time = 1)
-@Fork(value = 3, jvmArgsAppend = {"--add-opens", "java.base/com.sun.crypto.provider=ALL-UNNAMED"})
+@Fork(value = 3, jvmArgs = {"--add-opens", "java.base/com.sun.crypto.provider=ALL-UNNAMED"})
 
 public class MLKEMBench {
         @Param({"ML-KEM-512", "ML-KEM-768", "ML-KEM-1024"} )
diff -pruN 24.0.1+9-1/test/micro/org/openjdk/bench/java/time/format/ZonedDateTimeFormatterBenchmark.java 24.0.2+12-1/test/micro/org/openjdk/bench/java/time/format/ZonedDateTimeFormatterBenchmark.java
--- 24.0.1+9-1/test/micro/org/openjdk/bench/java/time/format/ZonedDateTimeFormatterBenchmark.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/micro/org/openjdk/bench/java/time/format/ZonedDateTimeFormatterBenchmark.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 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
@@ -40,7 +40,7 @@ public class ZonedDateTimeFormatterBench
     private static final DateTimeFormatter df = new DateTimeFormatterBuilder()
             .appendPattern("yyyy:MM:dd:HH:mm:v")
             .toFormatter();
-    private static final String TEXT = "2015:03:10:12:13:ECT";
+    private static final String TEXT = "2015:03:10:12:13:PST";
 
     @Setup
     public void setUp() {
diff -pruN 24.0.1+9-1/test/micro/org/openjdk/bench/javax/crypto/full/AESBench.java 24.0.2+12-1/test/micro/org/openjdk/bench/javax/crypto/full/AESBench.java
--- 24.0.1+9-1/test/micro/org/openjdk/bench/javax/crypto/full/AESBench.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/micro/org/openjdk/bench/javax/crypto/full/AESBench.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -39,7 +39,7 @@ import java.security.InvalidKeyException
 import java.security.NoSuchAlgorithmException;
 import java.security.spec.InvalidParameterSpecException;
 
-@Fork(jvmArgsAppend = {"-Xms20g", "-Xmx20g", "-XX:+UseZGC"})
+@Fork(jvmArgs = {"-Xms20g", "-Xmx20g", "-XX:+UseZGC"})
 public class AESBench extends CryptoBase {
 
     public static final int SET_SIZE = 8;
diff -pruN 24.0.1+9-1/test/micro/org/openjdk/bench/jdk/incubator/vector/IndexInRangeBenchmark.java 24.0.2+12-1/test/micro/org/openjdk/bench/jdk/incubator/vector/IndexInRangeBenchmark.java
--- 24.0.1+9-1/test/micro/org/openjdk/bench/jdk/incubator/vector/IndexInRangeBenchmark.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/micro/org/openjdk/bench/jdk/incubator/vector/IndexInRangeBenchmark.java	2025-06-27 08:03:14.000000000 +0000
@@ -48,7 +48,7 @@ public class IndexInRangeBenchmark {
 
     @Setup(Level.Trial)
     public void Setup() {
-        mask = new boolean[512];
+        mask = new boolean[size + 64];
     }
 
     @Benchmark
diff -pruN 24.0.1+9-1/test/micro/org/openjdk/bench/jdk/incubator/vector/SpiltReplicate.java 24.0.2+12-1/test/micro/org/openjdk/bench/jdk/incubator/vector/SpiltReplicate.java
--- 24.0.1+9-1/test/micro/org/openjdk/bench/jdk/incubator/vector/SpiltReplicate.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/micro/org/openjdk/bench/jdk/incubator/vector/SpiltReplicate.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 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
@@ -31,7 +31,7 @@ import org.openjdk.jmh.annotations.*;
 
 @BenchmarkMode(Mode.AverageTime)
 @OutputTimeUnit(TimeUnit.NANOSECONDS)
-@Fork(1)
+@Fork(value=1, jvmArgs={"--add-modules=jdk.incubator.vector"})
 public class SpiltReplicate {
     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
     public long broadcastInt() {
diff -pruN 24.0.1+9-1/test/micro/org/openjdk/bench/jdk/incubator/vector/VectorMultiplyOptBenchmark.java 24.0.2+12-1/test/micro/org/openjdk/bench/jdk/incubator/vector/VectorMultiplyOptBenchmark.java
--- 24.0.1+9-1/test/micro/org/openjdk/bench/jdk/incubator/vector/VectorMultiplyOptBenchmark.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/micro/org/openjdk/bench/jdk/incubator/vector/VectorMultiplyOptBenchmark.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 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 @@ import java.util.stream.*;
 @State(Scope.Benchmark)
 @Warmup(iterations = 3, time = 1)
 @Measurement(iterations = 5, time = 1)
-@Fork(value = 1, jvmArgsPrepend = {"--add-modules=jdk.incubator.vector"})
+@Fork(value = 1, jvmArgs = {"--add-modules=jdk.incubator.vector"})
 public class VectorMultiplyOptBenchmark {
     @Param({"1024", "2048", "4096"})
     private int  SIZE;
diff -pruN 24.0.1+9-1/test/micro/org/openjdk/bench/jdk/incubator/vector/VectorXXH3HashingBenchmark.java 24.0.2+12-1/test/micro/org/openjdk/bench/jdk/incubator/vector/VectorXXH3HashingBenchmark.java
--- 24.0.1+9-1/test/micro/org/openjdk/bench/jdk/incubator/vector/VectorXXH3HashingBenchmark.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/micro/org/openjdk/bench/jdk/incubator/vector/VectorXXH3HashingBenchmark.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 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 @@ import java.util.stream.*;
 @State(Scope.Benchmark)
 @Warmup(iterations = 3, time = 1)
 @Measurement(iterations = 5, time = 1)
-@Fork(value = 1, jvmArgsPrepend = {"--add-modules=jdk.incubator.vector"})
+@Fork(value = 1, jvmArgs = {"--add-modules=jdk.incubator.vector"})
 public class VectorXXH3HashingBenchmark {
     @Param({"1024", "2048", "4096", "8192"})
     private int  SIZE;
diff -pruN 24.0.1+9-1/test/micro/org/openjdk/bench/loom/obsolete/FreezeAndThaw.java 24.0.2+12-1/test/micro/org/openjdk/bench/loom/obsolete/FreezeAndThaw.java
--- 24.0.1+9-1/test/micro/org/openjdk/bench/loom/obsolete/FreezeAndThaw.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/micro/org/openjdk/bench/loom/obsolete/FreezeAndThaw.java	1970-01-01 00:00:00.000000000 +0000
@@ -1,149 +0,0 @@
-/*
- * Copyright (c) 2018, 2022, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org.openjdk.bench.loom.obsolete;
-
-import jdk.internal.vm.Continuation;
-import jdk.internal.vm.ContinuationScope;
-
-import java.util.concurrent.TimeUnit;
-import org.openjdk.jmh.annotations.*;
-
-@BenchmarkMode(Mode.AverageTime)
-@OutputTimeUnit(TimeUnit.NANOSECONDS)
-@State(Scope.Thread)
-@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
-@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
-@Fork(1)
-public class FreezeAndThaw {
-    static final ContinuationScope SCOPE = new ContinuationScope() { };
-
-    static class Arg {
-        volatile int field;
-    }
-
-    /**
-     * A recursive task that optionally yields when the stack gets to a specific
-     * depth. If continued after yielding, it runs to completion.
-     */
-    static class Yielder implements Runnable {
-        private final int paramCount;
-        private final int maxDepth;
-        private final boolean yieldAtLimit;
-
-        private Yielder(int paramCount, int maxDepth, boolean yieldAtLimit) {
-            if (paramCount < 1 || paramCount > 3)
-                throw new IllegalArgumentException();
-            this.paramCount = paramCount;
-            this.maxDepth = maxDepth;
-            this.yieldAtLimit = yieldAtLimit;
-        }
-
-        @Override
-        public void run() {
-            switch (paramCount) {
-                case 1: run1(maxDepth); break;
-                case 2: run2(maxDepth, new Arg()); break;
-                case 3: run3(maxDepth, new Arg(), new Arg()); break;
-                default: throw new Error("should not happen");
-            }
-        }
-
-        private void run1(int depth) {
-            if (depth > 0) {
-                run1(depth - 1);
-            } if (depth == 0) {
-                if (yieldAtLimit) Continuation.yield(SCOPE);
-            }
-        }
-
-        private void run2(int depth, Arg arg2) {
-            if (depth > 0) {
-                run2(depth - 1, arg2);
-            } if (depth == 0) {
-                if (yieldAtLimit) Continuation.yield(SCOPE);
-            } else {
-                // never executed
-                arg2.field = 0;
-            }
-        }
-
-        private void run3(int depth, Arg arg2, Arg arg3) {
-            if (depth > 0) {
-                run3(depth - 1, arg2, arg3);
-            } if (depth == 0) {
-                if (yieldAtLimit) {
-                    Continuation.yield(SCOPE);
-                }
-            } else {
-                // never executed
-                arg2.field = 0;
-                arg3.field = 0;
-            }
-        }
-
-        static Continuation continuation(int paramCount, int maxDepth,
-                                         boolean yieldAtLimit) {
-            Runnable task = new Yielder(paramCount, maxDepth, yieldAtLimit);
-            return new Continuation(SCOPE, task);
-        }
-    }
-
-    @Param({"1", "2", "3"})
-    public int paramCount;
-
-    @Param({"5", "10", "20", "100"})
-    public int stackDepth;
-
-    Continuation cont;
-    Continuation cont0;
-
-    @Setup(Level.Invocation)
-    public void setup() {
-        // System.out.println("pc = " + paramCount + " sd = " + stackDepth);
-        cont = Yielder.continuation(paramCount, stackDepth, true);
-        cont0 = Yielder.continuation(paramCount, stackDepth, false);
-    }
-
-    /**
-     * Creates and runs a continuation that yields at a given stack depth.
-     */
-    @Benchmark
-    public void baseline() {
-        // Continuation cont0 = Yielder.continuation(paramCount, stackDepth, false);
-        cont0.run();
-        assert cont0.isDone();
-    }
-
-    /**
-     * Creates and runs a continuation that yields at a given stack depth.
-     */
-    @Benchmark
-    public void yieldAndContinue() {
-        // Continuation cont = Yielder.continuation(paramCount, stackDepth, true);
-        cont.run();
-        assert !cont.isDone();
-        cont.run();
-        assert cont.isDone();
-    }
-}
diff -pruN 24.0.1+9-1/test/micro/org/openjdk/bench/loom/obsolete/OneShot.java 24.0.2+12-1/test/micro/org/openjdk/bench/loom/obsolete/OneShot.java
--- 24.0.1+9-1/test/micro/org/openjdk/bench/loom/obsolete/OneShot.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/micro/org/openjdk/bench/loom/obsolete/OneShot.java	1970-01-01 00:00:00.000000000 +0000
@@ -1,252 +0,0 @@
-/*
- * Copyright (c) 2018, 2022, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org.openjdk.bench.loom.obsolete;
-
-import jdk.internal.vm.Continuation;
-import jdk.internal.vm.ContinuationScope;
-
-import java.util.concurrent.TimeUnit;
-import org.openjdk.jmh.annotations.*;
-
-@BenchmarkMode(Mode.AverageTime)
-@OutputTimeUnit(TimeUnit.NANOSECONDS)
-@State(Scope.Thread)
-@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
-@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
-@Fork(1)
-public class OneShot {
-    static final ContinuationScope SCOPE = new ContinuationScope() { };
-
-    static class Arg {
-        volatile int field;
-    }
-
-    /**
-     * A recursive task that optionally yields when the stack gets to a specific
-     * depth. If continued after yielding, it runs to completion.
-     */
-    static class Yielder implements Runnable {
-        private final int paramCount;
-        private final int maxDepth;
-        private final boolean yieldAtLimit;
-
-        private Yielder(int paramCount, int maxDepth, boolean yieldAtLimit) {
-            if (paramCount < 1 || paramCount > 3)
-                throw new IllegalArgumentException();
-            this.paramCount = paramCount;
-            this.maxDepth = maxDepth;
-            this.yieldAtLimit = yieldAtLimit;
-        }
-
-        @Override
-        public void run() {
-            switch (paramCount) {
-                case 1: run1(maxDepth); break;
-                case 2: run2(maxDepth, new Arg()); break;
-                case 3: run3(maxDepth, new Arg(), new Arg()); break;
-                default: throw new Error("should not happen");
-            }
-        }
-
-        private void run1(int depth) {
-            if (depth > 0) {
-                run1(depth - 1);
-            } if (depth == 0) {
-                if (yieldAtLimit) Continuation.yield(SCOPE);
-            }
-        }
-
-        private void run2(int depth, Arg arg2) {
-            if (depth > 0) {
-                run2(depth - 1, arg2);
-            } if (depth == 0) {
-                if (yieldAtLimit) Continuation.yield(SCOPE);
-            } else {
-                // never executed
-                arg2.field = 0;
-            }
-        }
-
-        private void run3(int depth, Arg arg2, Arg arg3) {
-            if (depth > 0) {
-                run3(depth - 1, arg2, arg3);
-            } if (depth == 0) {
-                if (yieldAtLimit) Continuation.yield(SCOPE);
-            } else {
-                // never executed
-                arg2.field = 0;
-                arg3.field = 0;
-            }
-        }
-
-        static Continuation continuation(int paramCount, int maxDepth,
-                                         boolean yieldAtLimit) {
-            Runnable task = new Yielder(paramCount, maxDepth, yieldAtLimit);
-            return new Continuation(SCOPE, task);
-        }
-    }
-
-    /**
-     * A recursive task that optionally yields before and/or after each call.
-     */
-    static class Stepper implements Runnable {
-        private final int paramCount;
-        private final int maxDepth;
-        private final boolean yieldBefore;
-        private final boolean yieldAfter;
-
-        private Stepper(int paramCount,
-                        int maxDepth,
-                        boolean yieldBefore,
-                        boolean yieldAfter) {
-            this.paramCount = paramCount;
-            this.maxDepth = maxDepth;
-            this.yieldBefore = yieldBefore;
-            this.yieldAfter = yieldAfter;
-        }
-
-        public void run() {
-            switch (paramCount) {
-                case 1: run1(maxDepth); break;
-                case 2: run2(maxDepth, new Arg()); break;
-                case 3: run3(maxDepth, new Arg(), new Arg()); break;
-                default: throw new Error("should not happen");
-            }
-        }
-
-        private void run1(int depth) {
-            if (depth > 0) {
-                if (yieldBefore) Continuation.yield(SCOPE);
-                run1(depth - 1);
-                if (yieldAfter) Continuation.yield(SCOPE);
-            }
-        }
-
-        private void run2(int depth, Arg arg2) {
-            if (depth > 0) {
-                if (yieldBefore) Continuation.yield(SCOPE);
-                run2(depth - 1, arg2);
-                if (yieldAfter) Continuation.yield(SCOPE);
-            } else if (depth < 0) {
-                // never executed
-                arg2.field = 0;
-            }
-        }
-
-        private void run3(int depth, Arg arg2, Arg arg3) {
-            if (depth > 0) {
-                if (yieldBefore) Continuation.yield(SCOPE);
-                run3(depth - 1, arg2, arg3);
-                if (yieldAfter) Continuation.yield(SCOPE);
-            } else if (depth < 0) {
-                // never executed
-                arg2.field = 0;
-                arg3.field = 0;
-            }
-        }
-
-        static Continuation continuation(int paramCount, int maxDepth,
-                                         boolean yieldBefore, boolean yieldAfter) {
-            Runnable task = new Stepper(paramCount, maxDepth, yieldBefore, yieldAfter);
-            return new Continuation(SCOPE, task);
-        }
-    }
-
-    @Param({"1", "2", "3"})
-    public int paramCount;
-
-    @Param({"5", "10", "20", "100"})
-    public int stackDepth;
-
-    /**
-     * Creates and run continuation that does not yield.
-     */
-    @Benchmark
-    public void noYield() {
-        Continuation cont = Yielder.continuation(paramCount, stackDepth, false);
-        cont.run();
-        if (!cont.isDone())
-            throw new RuntimeException("continuation not done???");
-    }
-
-    /**
-     * Creates and runs a continuation that yields at a given stack depth.
-     */
-    @Benchmark
-    public void yield() {
-        Continuation cont = Yielder.continuation(paramCount, stackDepth, true);
-        cont.run();
-        if (cont.isDone())
-            throw new RuntimeException("continuation done???");
-    }
-
-    /**
-     * Creates and runs a continuation that yields at a given stack depth, it is
-     * then continued to run to completion.
-     */
-    @Benchmark
-    public void yieldThenContinue() {
-        Continuation cont = Yielder.continuation(paramCount, stackDepth, true);
-        cont.run();
-        cont.run();  // continue
-        if (!cont.isDone())
-            throw new RuntimeException("continuation not done???");
-    }
-
-    /**
-     * Creates and runs a continuation to the given stack depth, yielding before
-     * each call.
-     */
-    @Benchmark
-    public void yieldBeforeEachCall() {
-        Continuation cont = Stepper.continuation(paramCount, stackDepth, true, false);
-        while (!cont.isDone()) {
-            cont.run();
-        }
-    }
-
-    /**
-     * Creates and runs a continuation to the given stack depth, yielding after
-     * each call.
-     */
-    @Benchmark
-    public void yieldAfterEachCall() {
-        Continuation cont = Stepper.continuation(paramCount, stackDepth, false, true);
-        while (!cont.isDone()) {
-            cont.run();
-        }
-    }
-
-    /**
-     * Creates and runs a continuation to the given stack depth, yielding before
-     * and after each call.
-     */
-    @Benchmark
-    public void yieldBeforeAndAfterEachCall() {
-        Continuation cont = Stepper.continuation(paramCount, stackDepth, true, true);
-        while (!cont.isDone()) {
-            cont.run();
-        }
-    }
-}
diff -pruN 24.0.1+9-1/test/micro/org/openjdk/bench/loom/obsolete/Oscillation.java 24.0.2+12-1/test/micro/org/openjdk/bench/loom/obsolete/Oscillation.java
--- 24.0.1+9-1/test/micro/org/openjdk/bench/loom/obsolete/Oscillation.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/micro/org/openjdk/bench/loom/obsolete/Oscillation.java	1970-01-01 00:00:00.000000000 +0000
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2018, 2022, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org.openjdk.bench.loom.obsolete;
-
-import jdk.internal.vm.Continuation;
-import jdk.internal.vm.ContinuationScope;
-
-import java.util.concurrent.TimeUnit;
-import org.openjdk.jmh.annotations.*;
-
-@BenchmarkMode(Mode.AverageTime)
-@OutputTimeUnit(TimeUnit.NANOSECONDS)
-@State(Scope.Benchmark)
-@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
-@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
-@Fork(1)
-public class Oscillation {
-    static final ContinuationScope SCOPE = new ContinuationScope() { };
-
-    /**
-     * A task that oscillates between a minimum and maximum stack depth, yielding
-     * at the maximum stack until continued.
-     */
-    static class Wave implements Runnable {
-        private final int min;
-        private final int max;
-
-        private enum Mode { GROW, SHRINK }
-        private Mode mode;
-
-        Wave(int min, int max) {
-            if (min < 0)
-                throw new IllegalArgumentException("negative min");
-            if (max <= min)
-                throw new IllegalArgumentException("max must be greater than min");
-            this.min = min;
-            this.max = max;
-            this.mode = Mode.GROW;
-        }
-
-        private void run(int depth) {
-            if (depth == max) {
-                Continuation.yield(SCOPE);
-                mode = Mode.SHRINK;
-            } else if (depth == min) {
-                while (true) {
-                    mode = Mode.GROW;
-                    run(depth + 1);
-                }
-            } else if (mode == Mode.GROW) {
-                run(depth + 1);
-            }
-        }
-
-        @Override
-        public void run() {
-            run(0);
-        }
-    }
-
-    @Param({"2", "3", "4"})
-    public int minDepth;
-
-    @Param({"5", "6", "7", "8"})
-    public int maxDepth;
-
-    @Param({"10", "100", "1000"})
-    public int repeat;
-
-    /**
-     * Creates and runs a continuation that oscillates between a minimum and
-     * maximum stack depth, yielding at the maximum stack until continued.
-     *
-     * Useful to measure freeze and thaw, also to compare full stack vs. lazy copy.
-     */
-    @Benchmark
-    public void oscillate() {
-        Continuation cont = new Continuation(SCOPE, new Wave(minDepth, maxDepth));
-        for (int i=0; i<repeat; i++) {
-            cont.run();
-        }
-    }
-}
diff -pruN 24.0.1+9-1/test/micro/org/openjdk/bench/vm/compiler/MergeStores.java 24.0.2+12-1/test/micro/org/openjdk/bench/vm/compiler/MergeStores.java
--- 24.0.1+9-1/test/micro/org/openjdk/bench/vm/compiler/MergeStores.java	2025-03-05 07:19:53.000000000 +0000
+++ 24.0.2+12-1/test/micro/org/openjdk/bench/vm/compiler/MergeStores.java	2025-06-27 08:03:14.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 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
@@ -743,8 +743,10 @@ public class MergeStores {
         UNSAFE.putLongUnaligned(null, native_adr + offset + 0, vL);
     }
 
-    @Fork(value = 1, jvmArgsPrepend = {
-        "-XX:+UnlockDiagnosticVMOptions", "-XX:-MergeStores"
+    @Fork(value = 1, jvmArgs = {
+        "-XX:+UnlockDiagnosticVMOptions", "-XX:-MergeStores",
+        "--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED",
+        "--add-exports", "java.base/jdk.internal.util=ALL-UNNAMED"
     })
     public static class MergeStoresDisabled extends MergeStores {}
 }
