Compare commits

..

96 Commits

Author SHA1 Message Date
Vitaly Provodin
57697fad0b JBR-4370 create a test checking all JBR artifacts exist - fix Teamcity messages 2022-04-26 05:58:47 +07:00
Vitaly Provodin
f4f3a3625b JBR-4370 create a test checking all JBR artifacts exist
(cherry picked from commit f16c4814c7)
2022-04-26 05:30:35 +07:00
Anton Tarasov
dd7e30f12d JBR-3906 JBR for Linux aarch64 with JCEF is missing, is there any support plan? 2022-04-23 17:09:02 +07:00
Atrem Bochkarev
55eb404576 JBR-4094: fixed MouseEventAfterHideAndShowBrowserTest 2022-04-23 17:08:59 +07:00
Vitaly Provodin
56d463d29a Revert "JBR-4325 Implement creating an event to call NSAccessibilityShowMenuAction"
This reverts commit f6cf71ce68.
2022-04-22 18:28:22 +07:00
Phil Race
aa625213b5 8223543: [TESTBUG] Regression test java/awt/Graphics2D/DrawString/LCDTextSrcEa.java has issues
Reviewed-by: serb, azvegint, aivanov
2022-04-22 00:07:32 +02:00
Alexey Ushakov
1538f1e6ad Revert "JBR-1380: [TESTBUG] Regression test java/awt/Graphics2D/DrawString/LCDTextSrcEa.java works incorrectly"
This reverts commit b7449a593a.
2022-04-22 00:02:31 +02:00
Alexey Ushakov
47017e1e14 Revert "JBR-1388 [TESTBUG] Regression test java/awt/Graphics2D/DrawString/LCDTextSrcEa.java fails on macOS Mojave"
This reverts commit 603f214e2c.
2022-04-22 00:02:00 +02:00
Roger Riggs
decffd42a5 JBR-3483 8282008: Incorrect handling of quoted arguments in ProcessBuilder
Reviewed-by: bchristi
2022-04-21 16:24:43 +03:00
Anton Tarasov
f189c552a6 JBR-4355 javax/swing/GraphicsConfigNotifier/StalePreferredSize.java: # C [libobjc.A.dylib+0x90ff] objc_release+0x1f
(cherry picked from commit c0b2b59d4a)
2022-04-21 13:42:12 +03:00
Anton Tarasov
c20bd5a658 JBR-4389 [update_1] IDEA UI font becomes too large after disconnecting the external monitor / sleep 2022-04-21 11:53:22 +03:00
Anton Tarasov
e900d17295 JBR-4389 IDEA UI font becomes too large after disconnecting the external monitor / sleep 2022-04-21 11:32:24 +03:00
Dmitry Batrak
35f18de090 remove duplicate bundled JetBrains Mono bold italic font
following JBR-4402

(cherry picked from commit b7e5d3cfcf)
2022-04-20 21:50:44 +03:00
Dmitry Batrak
47d473b1a1 JBR-4402 The wrong text is rendered in editor 2022-04-20 21:07:42 +03:00
Maxim Kartashev
70dde74a8f JBR-4062 Undo parts of JBR-4145 that have become obsolete by upstream changes. 2022-04-20 16:23:43 +03:00
Andrew Leonard
5745455f66 JBR-4062 8284661: Reproducible assembly builds without relative linking
Reviewed-by: ihse
2022-04-20 15:04:01 +03:00
Zhengyu Gu
a9ce9c763b JBR-4378 8284093: Memory leak: X11SD_DisposeXImage should also free obdata
Reviewed-by: prr, andrew
2022-04-20 01:58:38 -07:00
Andrew Leonard
c5507f0d9a JBR-4062 8284539: Configure --with-source-date=version fails on MacOS
Reviewed-by: erikj, ihse
2022-04-20 11:25:49 +03:00
Magnus Ihse Bursie
8670e275a1 JBR-4062 8282769: BSD date cannot handle all ISO 8601 formats
Reviewed-by: erikj
2022-04-20 11:25:22 +03:00
Martin Doerr
2fc34e9f04 8281811: assert(_base == Tuple) failed: Not a Tuple after JDK-8280799
Backport-of: fcce24c5b3

(cherry picked from commit cdf144edba)
2022-04-20 00:35:15 +03:00
Dmitry Batrak
fae9ac43a5 JBR-4398 Gear emoji displayed monochrome in Editor since 2022.1
this reverts JBR-4072 and associated fixes (JBR-4194, JBR-4314)
2022-04-19 22:10:45 +03:00
Konstantin Bulenkov
68db465ae1 Added support for otf into the build scripts. Updated prebuild maps. 2022-04-19 15:54:03 +02:00
Vitaly Provodin
0aa9b4f7de JBR-4297 add a regression test
(cherry picked from commit 8e94fff6aa)
2022-04-18 07:25:55 +07:00
Vitaly Provodin
d40250ddf5 Merge pull request #132
JBR-4392 - use only loaded classes when collecting affected classes
2022-04-17 03:42:41 +07:00
Vladimir Dvorak
63b1c11712 JBR-4386 - disable AllowEnhancedClassRedefinition in jfr 2022-04-17 03:39:37 +07:00
Vladimir Dvorak
1eab1527d5 JBR-4392 - use only loaded classes when collecting affected classes 2022-04-16 12:30:27 +02:00
Vitaly Provodin
9b5ebaaa5a exclude java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java due to 8280392 2022-04-16 05:55:55 +07:00
Konstantin Bulenkov
a37db66560 Update JetBrains Mono font to 2.225 2022-04-15 22:32:25 +02:00
Dmitry Batrak
39dd2f608c JBR-4382 [i3] All dialogs are tiled
(cherry picked from commit 800220af16)
2022-04-15 22:27:51 +03:00
Konstantin Bulenkov
890efa0ea8 bundle Inter font 2022-04-14 19:04:47 +02:00
Anton Tarasov
7efb0075bc JBR-4362 [mac] system menu opens with duplicated items
(cherry picked from commit e32defe49d)
2022-04-12 15:50:50 +03:00
Alexey Ushakov
413ff95d63 Removed comma from tag parsing result 2022-04-11 19:41:28 +02:00
Alexey Ushakov
bfa7a36237 JBR-4363 Changes in fonts rendering between JBR11 and JBR17
Resolved merge artifact after applying IDEA-57233 fix
2022-04-11 19:34:30 +02:00
Andrew Leonard
138596467d JBR-4062 8284437: Building from different users/workspace is not always deterministic
Reviewed-by: erikj
(cherry picked from commit 4451257b14)
2022-04-08 10:41:39 +03:00
Dmitry Batrak
f7a0716ccd JBR-4346 [Xfce] Windows are moved unexpectedly between workspaces when modal dialog is shown
(cherry picked from commit ad299f1e74)
2022-04-06 22:41:56 +03:00
Zhengyu Gu
bdb9d3f12f JBR-4360 284023: java.sun.awt.X11GraphicsDevice.getDoubleBufferVisuals() leaks XdbeScreenVisualInfo
Reviewed-by: prr, serb
2022-04-06 16:07:42 +03:00
Maxim Kartashev
1e8d2c0873 JBR-4357 8284033: Leak XVisualInfo in getAllConfigs in awt_GraphicsEnv.c
Reviewed-by: serb, prr
2022-04-04 23:03:35 -07:00
Vladimir Dvorak
360f8f332c Remove version-numbers left over from the merge of dcevm17 2022-04-05 04:38:32 +07:00
Vladimir Dvorak
13512decff JBR-4352 - fix AARCH64 compilation issues
- use correct INCLUDE_JFR condition for jfr code
- exclude jvmtiEnhancedRedefineClasses.cpp if INCLUDE_JVMTI=0
2022-04-02 16:33:54 +01:00
Vitaly Provodin
28ebc0c2e0 excludejava/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java on windows
and java/io/File/createTempFile/SpecialTempFile.java on windows11
2022-04-02 06:29:47 +07:00
Anton Tarasov
9a35ca0b25 JBR-4349 jb/java/awt/Toolkit/LWCToolkitInvokeAndWaitTest.java: Test FAILED! (not found in the log: “lost”) 2022-04-01 21:34:03 +03:00
Anton Tarasov
e424a5bf19 JBR-4347 jb/java/awt/Toolkit/AWTThreadingCMenuTest.java fails by ClassNotFoundException 2022-04-01 21:32:14 +03:00
Alexey Ushakov
ca4d838caf 8273355: Flickering on tooltip appearance IntelliJ IDEA 2021.2.1
Reviewed-by: serb, aghaisas
2022-03-30 20:42:06 +02:00
Alexey Ushakov
6ed5106466 Revert "JBR-3727 JBR17-Metal: Flickering on tooltip appearance"
This reverts commit eaa9c1618e.
2022-03-30 20:27:45 +02:00
Dmitry Batrak
098a50d91a JBR-4334 java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Extra.java fails
re-fix JBR-4306 in a different way

(cherry picked from commit 3b5ded0d02)
2022-03-30 12:16:24 +03:00
Dmitry Batrak
050990303b JBR-4334 java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Extra.java fails
revert original fix for JBR-4306

(cherry picked from commit 0f33031484)
2022-03-30 12:16:24 +03:00
Anton Tarasov
9f9416a12e JBR-4328 remove LWCToolkit.unsafeNonblockingExecute
(cherry picked from commit 9a3f31a6c4)
2022-03-28 22:00:59 +03:00
Anton Tarasov
b6cb489fee JBR-4134 PyCharm is slow and unusable on MacBook Pro with M1
(cherry picked from commit 36190505f5)
2022-03-28 22:00:52 +03:00
Anton Tarasov
446535b706 JBR-4284 Sub items of main menu options are not displayed
A regression of JBR-4208 LWCToolkit.invokeAndWait should not stuck on invocation loss

(cherry picked from commit c464e4748e)
2022-03-28 21:59:41 +03:00
Anton Tarasov
c18934bb98 JBR-4119 UI freezes at sun.lwawt.macosx.CAccessibility.getChildrenAndRoles
(cherry picked from commit 6ba79774d8)
2022-03-28 21:59:36 +03:00
Anton Tarasov
e8a6e8bd6e JBR-4106 PyCharm hangs with 100% CPU usage on one core 2022-03-28 21:59:28 +03:00
Mikhail Grishchenko
4a7241931f JBR-3975 print Teamcity messages 2022-03-26 05:32:40 +07:00
Mikhail Grishchenko
b45b8c9913 JBR-3975 add processing of "." java version separator 2022-03-24 08:55:51 +07:00
Artem Semenov
f6cf71ce68 JBR-4325 Implement creating an event to call NSAccessibilityShowMenuAction 2022-03-23 21:29:36 +03:00
Dmitry Batrak
803039d6db JBR-4306 Robot doesn't work as expected in some cases on macOS
(cherry picked from commit 7d69734465)
2022-03-23 12:53:42 +03:00
Vladimir Dvorak
436223316f JBR-4312 - fix crash call ResolvedMethodTable from ServiceThread
adjust_metod_entries_dcevm incorrectly changed the hashes of resolved
method oops stored in ResolvedMethodTable. Now all oops of old methods
are first removed, then updated and then added to table again
2022-03-23 11:08:36 +07:00
Dmitry Batrak
9a0ab296fe better handle multi-monitor configurations in tests related to macOS spaces
Detect the presence of an additional space by looking at number of spaces for the first monitor, not at the total number of spaces.
The latter is larger than one in a multi-monitor configuration, as each monitor corresponds to a separate space.
This approach should be better than the original one, but it relies on the primary (default) monitor to be mentioned first
in the plist file, which isn't known to be always true.

(cherry picked from commit 9040fd56cd)
2022-03-21 21:30:12 +03:00
Artem Semenov
bf4a191246 JBR-4318 On MacOS, some context menu items are not voiced 2022-03-21 15:40:18 +03:00
Andrew Leonard
cdfff8f6ac JBR-4062 8283315: jrt-fs.jar not always deterministically built
Reviewed-by: ihse
2022-03-21 14:03:00 +03:00
Alexey Ushakov
6d6de1034a JBR-3827 SIGILL at [libsystem_kernel] __kill in Java Exception at -[CDragSource convertData:]
Added check for drag source
2022-03-18 18:36:10 +01:00
Vitaly Provodin
2333999906 JBR-4303 add a regression test
(cherry picked from commit bc7cb5711b)
2022-03-18 09:50:29 +07:00
Alexey Ushakov
6ffcd2bf91 JBR-3366 SIGILL at [libsystem_kernel] __kill in NSWindowStyleMaskFullScreen cleared on a window outside of a full screen transition
Wrapped the native exception and added logging
2022-03-17 18:09:49 +01:00
Artem Semenov
822b4a8c49 JBR-4235 Context menu not readable after opening on Mac OS 2022-03-17 16:34:39 +03:00
Dmitry Batrak
debc6336c0 JBR-4314 2022.1 EAP version's JBR use incorrect fallback font to render Chinese characters in macOS
(cherry picked from commit 82048d1d73)
2022-03-17 15:15:34 +03:00
Mikhail Grishchenko
1f93154f62 JBR-3975 add PASSED message in check_jbr_size.sh 2022-03-17 03:35:05 +07:00
Mikhail Grishchenko
9f069ca59e JBR-3975 Fix regexp in check_jbr_size.sh
(cherry picked from commit 23131fc435)
2022-03-17 01:45:51 +07:00
Vladimir Kempik
53f1a647fd JBR-4309: jdk/tools/launcher/modules/illegalaccess/IllegalAccessTest.java fails after JBR-4291 2022-03-14 11:27:16 +03:00
Alexander Lobas
7d31563471 JBR-4305 (#119)
* IDEA-283934 Top panel (toolbar, Editor tabs) hides under the Mac menu in full-screen mode

* IDEA-283934 Top panel (toolbar, Editor tabs) hides under the Mac menu in full-screen mode

* JBR-4305 IDEA-283934 Top panel (toolbar, Editor tabs) hides under the Mac menu in full-screen mode

* JBR-4305 IDEA-283934 Top panel (toolbar, Editor tabs) hides under the Mac menu in full-screen mode
2022-03-10 20:23:11 +01:00
Alexey Ushakov
36ded60698 JBR-3365 SIGILL at [libsystem_kernel] __kill in java.lang.RuntimeException: Failed to convert, no screen / primaryScreen
Wrapped the native exception and added logging
2022-03-10 14:28:18 +01:00
Dmitry Batrak
d53de90f8a JBR-3751 Window content isn't rendered with some window managers on Linux
(cherry picked from commit 8d22e4dcb0)
2022-03-09 13:40:40 +03:00
VladimirKempik
6196076b95 JBR-4291: Ability to ignore all add-opens 2022-03-04 15:05:43 +03:00
Vitaly Provodin
0ee50cbed6 JBR-4272 generate and save debug symbols for JBR on macos/linux 2022-03-03 19:34:10 +07:00
Roland Westrelin
d6e6d315d2 JBR-4256: backport 8280799: С2: assert(false) failed: cyclic dependency prevents range check elimination
Reviewed-by: thartmann, kvn
2022-02-28 18:31:45 +07:00
Roland Westrelin
0a3f7bd9b1 JBR-4256: 8275330: C2: assert(n->is_Root() || n->is_Region() || n->is_Phi() || n->is_MachMerge() || def_block->dominates(block)) failed: uses must be dominated by definitions
Reviewed-by: thartmann, chagedorn
(cherry picked from commit 3e798dd40c)
2022-02-28 18:31:43 +07:00
Vladimir Kempik
a2636bc8b2 JBR-4283: Provide native JBR builds for alpine Linux-aarch64 2022-02-28 11:11:24 +03:00
Dmitry Batrak
11ad455c7a JBR-4281 Window losing focus isn't detected in some cases on macOS
(cherry picked from commit 363650bbf4)
2022-02-25 00:35:34 +03:00
Vitaly Provodin
4141e567c0 exclude java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java due to 8282232 2022-02-23 06:32:04 +07:00
Ivan Lopatin
8373eeea85 exclude javax/swing/plaf/basic/BasicMenuUI/4983388/bug4983388.java due to 8253184 2022-02-23 06:31:35 +07:00
Nikita Gubarkov
9f10f63459 Fixed threading issues & restoring of default titlebar for custom titlebar on macOS 2022-02-21 22:16:31 +03:00
Nikita Provotorov
0cb7b4565c JBR-4271: JBR17 and dev built without --with-vendor-name parameter have invalid value of the java.vm.vendor property.
Changes the default JBR's vendor from "Oracle Corporation" to "JetBrains s.r.o.".
2022-02-21 22:35:35 +07:00
Nikita Provotorov
e19109f401 Revert "Changing the default JBR's vendor from "Oracle Corporation" to "JetBrains s.r.o"."
This reverts commit 409e4932ad. Just for JBR-4271.
2022-02-21 22:24:47 +07:00
Nikita Gubarkov
c450a40e16 JBR-4266 Fix JBR API ProxyInfoResolvingTest, missing JBR-side implementation now doesn't throw an exception 2022-02-21 15:20:26 +03:00
Maxim Kartashev
fe79f047d0 fixup! JBR-3917 Problem using windows certificate store (trustStoreType=Windows-ROOT not recognized) 2022-02-18 13:25:20 +03:00
Vladimir Kempik
484bc6f18f JBR-4242:Provide native JBR builds for alpine Linux 2022-02-18 09:36:56 +03:00
Nikita Gubarkov
1af965d658 Refactored internal services in JBR API
Fixed IllegalAccessException when retrieving lists of known proxies & services
2022-02-17 20:25:15 +03:00
Maxim Kartashev
d330782b50 fixup! JBR-3917 Problem using windows certificate store (trustStoreType=Windows-ROOT not recognized) 2022-02-17 15:20:49 +03:00
Maxim Kartashev
ff6002ab87 JBR-3917 Problem using windows certificate store (trustStoreType=Windows-ROOT not recognized) 2022-02-17 12:31:06 +03:00
Nikita Gubarkov
ee9fe4ee55 Custom macOS window decorations via JBR API 2022-02-16 22:11:59 +03:00
Nikita Gubarkov
b8e1373b53 Added internal services to JBR API 2022-02-16 22:10:30 +03:00
Vitaly.Provodin
1b9f385336 exclude java/awt/Dialog/NonResizableDialogSysMenuResize/NonResizableDialogSysMenuResize.java and java/awt/Dialog/NestedDialogs/Modeless/NestedModelessDialogTest.java on windows-all 2022-02-16 16:37:32 +07:00
Vitaly Provodin
cd9cc5f395 exclude javax/imageio/plugins/external_plugin_tests/TestClassPathPlugin.sh from commit testing 2022-02-16 16:34:53 +07:00
Vitaly Provodin
54199dc06c JBR-4154 extract version info from sources 2022-02-16 16:14:21 +07:00
Anton Tarasov
66ddc58397 JBR-4208 LWCToolkit.invokeAndWait should not stuck on invocation loss 2022-02-16 11:38:31 +03:00
Nikita Gubarkov
c5d124735c JBR API v0.0.4 - Implemented client-side fallbacks for JBR API 2022-02-15 18:30:17 +03:00
Nikita Provotorov
409e4932ad Changing the default JBR's vendor from "Oracle Corporation" to "JetBrains s.r.o". 2022-02-15 04:27:14 +07:00
Nikita Gubarkov
3bbd930114 JBR API v0.0.3
JBR-4228 report HTMINBUTTON, HTMAXBUTTON, HTCLOSE, HTMENU, HTCAPTION targets via JBR API & handle corresponding non-client mouse events for windows with custom decorations
2022-02-14 19:17:39 +03:00
200 changed files with 6161 additions and 1099 deletions

View File

@@ -31,6 +31,7 @@ RUN export DEBIAN_FRONTEND=noninteractive \
libxt-dev \
libxtst-dev \
make \
rsync \
tar \
unzip \
zip && \

View File

@@ -0,0 +1,22 @@
# NOTE: This Dockerfile is meant to be used from the mkdocker_musl_aarch64.sh script.
# Pull a concrete version of Linux that does NOT recieve updates after it's
# been created. This is so that the image is as stable as possible to make
# image creation reproducible.
# NB: this also means there may be no security-related fixes there, need to
# move the version to the next manually.
FROM arm64v8/alpine:3.12
# Install the necessary build tools
RUN apk --no-cache add --update bash grep tar zip bzip2 rsync fontconfig build-base \
git libx11-dev libxext-dev libxrandr-dev libxrender-dev libxt-dev \
libxtst-dev autoconf freetype-dev cups-dev alsa-lib-dev file \
fontconfig fontconfig-dev linux-headers
# Set up boot JDK for building
COPY boot_jdk_musl_aarch64.tar.gz /jdk17/
RUN cd /jdk17 && tar --strip-components=1 -xzf boot_jdk_musl_aarch64.tar.gz && rm /jdk17/boot_jdk_musl_aarch64.tar.gz
ENV BOOT_JDK=/jdk17
RUN git config --global user.email "teamcity@jetbrains.com" && \
git config --global user.name "builduser"

View File

@@ -0,0 +1,22 @@
# NOTE: This Dockerfile is meant to be used from the mkdocker_musl_x64.sh script.
# Pull a concrete version of Linux that does NOT recieve updates after it's
# been created. This is so that the image is as stable as possible to make
# image creation reproducible.
# NB: this also means there may be no security-related fixes there, need to
# move the version to the next manually.
FROM alpine:3.5
# Install the necessary build tools
RUN apk --no-cache add --update bash grep tar zip bzip2 rsync fontconfig build-base \
git libx11-dev libxext-dev libxrandr-dev libxrender-dev libxt-dev \
libxtst-dev autoconf freetype-dev cups-dev alsa-lib-dev file \
fontconfig fontconfig-dev linux-headers
# Set up boot JDK for building
COPY boot_jdk_musl_amd64.tar.gz /jdk17/
RUN cd /jdk17 && tar --strip-components=1 -xzf boot_jdk_musl_amd64.tar.gz && rm /jdk17/boot_jdk_musl_amd64.tar.gz
ENV BOOT_JDK=/jdk17
RUN git config --global user.email "teamcity@jetbrains.com" && \
git config --global user.name "builduser"

View File

@@ -0,0 +1,26 @@
#!/bin/bash -x
# This script creates a Docker image suitable for building musl AArch64 variant
# of the JetBrains Runtime version 17.
BOOT_JDK_REMOTE_FILE=zulu17.32.13-ca-jdk17.0.2-linux_musl_aarch64.tar.gz
BOOT_JDK_SHA=6b920559abafbe9bdef386a20ecf3a2f318bc1f0d8359eb1f95aee26606bbc70
BOOT_JDK_LOCAL_FILE=boot_jdk_musl_aarch64.tar.gz
if [ ! -f $BOOT_JDK_LOCAL_FILE ]; then
# Obtain "boot JDK" from outside of the container.
wget -nc https://cdn.azul.com/zulu/bin/${BOOT_JDK_REMOTE_FILE} -O $BOOT_JDK_LOCAL_FILE
else
echo "boot JDK \"$BOOT_JDK_LOCAL_FILE\" present, skipping download"
fi
# Verify that what we've downloaded can be trusted.
sha256sum -c - <<EOF
$BOOT_JDK_SHA *$BOOT_JDK_LOCAL_FILE
EOF
docker build -t jbr17buildenv -f Dockerfile.musl_aarch64 .
# NB: the resulting container can (and should) be used without the network
# connection (--network none) during build in order to reduce the chance
# of build contamination.

View File

@@ -0,0 +1,26 @@
#!/bin/bash -x
# This script creates a Docker image suitable for building musl-x64 variant
# of the JetBrains Runtime version 17.
BOOT_JDK_REMOTE_FILE=zulu17.32.13-ca-jdk17.0.2-linux_musl_x64.tar.gz
BOOT_JDK_SHA=bcc5342011bd9f3643372aadbdfa68d47463ff0d8621668a0bdf2910614d95c6
BOOT_JDK_LOCAL_FILE=boot_jdk_musl_amd64.tar.gz
if [ ! -f $BOOT_JDK_LOCAL_FILE ]; then
# Obtain "boot JDK" from outside of the container.
wget -nc https://cdn.azul.com/zulu/bin/${BOOT_JDK_REMOTE_FILE} -O $BOOT_JDK_LOCAL_FILE
else
echo "boot JDK \"$BOOT_JDK_LOCAL_FILE\" present, skipping download"
fi
# Verify that what we've downloaded can be trusted.
sha256sum -c - <<EOF
$BOOT_JDK_SHA *$BOOT_JDK_LOCAL_FILE
EOF
docker build -t jbr17buildenv -f Dockerfile.musl_x64 .
# NB: the resulting container can (and should) be used without the network
# connection (--network none) during build in order to reduce the chance
# of build contamination.

View File

@@ -31,7 +31,7 @@ architecture=$3 # aarch64 or x64
bundle_type=$(do_maketest)
do_maketest=$?
tag_prefix="jbr-"
OPENJDK_TAG=$(git log --simplify-by-decoration --decorate=short --pretty=short | grep "$tag_prefix" | cut -d "(" -f2 | cut -d ")" -f1 | awk '{print $2}' | sort -t "-" -k 2 -g | tail -n 1)
OPENJDK_TAG=$(git log --simplify-by-decoration --decorate=short --pretty=short | grep "$tag_prefix" | cut -d "(" -f2 | cut -d ")" -f1 | awk '{print $2}' | sort -t "-" -k 2 -g | tail -n 1 | tr -d ",")
VERSION_FEATURE=$(getVersionProp "DEFAULT_VERSION_FEATURE")
VERSION_INTERIM=$(getVersionProp "DEFAULT_VERSION_INTERIM")
VERSION_UPDATE=$(getVersionProp "DEFAULT_VERSION_UPDATE")
@@ -77,15 +77,27 @@ case "$OS_NAME" in
;;
esac
WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS="--with-native-debug-symbols=zipped"
REPRODUCIBLE_BUILD_OPTS="--enable-reproducible-build
--with-source-date=$SOURCE_DATE_EPOCH
--with-hotspot-build-time=$BUILD_TIME
--with-copyright-year=$COPYRIGHT_YEAR
--disable-absolute-paths-in-output"
function zip_native_debug_symbols() {
image_bundle_path=$(echo $1 | cut -d"/" -f-4)
jbr_diz_name=$2
(cd $image_bundle_path && find . -name '*.diz' -exec rsync -R {} ../../../../dizfiles \; )
(cd dizfiles && find . -print0 | COPYFILE_DISABLE=1 \
tar --no-recursion --null -T - -czf ../"$jbr_diz_name".tar.gz) || do_exit $?
}
function do_exit() {
exit_code=$1
[ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java
[ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java
if [ $do_reset_dcevm -eq 1 ]; then
[ ! -z $HEAD_REVISION ] && git reset --hard $HEAD_REVISION
fi

View File

@@ -1,71 +1,153 @@
#!/bin/bash -x
# The following parameter must be specified:
# The following parameters must be specified:
# build_number - specifies the number of JetBrainsRuntime build
# bundle_type - specifies bundle to be built;possible values:
# <empty> or nomod - the release bundles without any additional modules (jcef)
# jcef - the release bundles with jcef
# fd - the fastdebug bundles which also include the jcef module
#
# This script makes test-image along with JDK images when bundle_type is set to "jcef".
# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images.
#
# Environment variables:
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument
# to configure
# By default JDK_BUILD_NUMBER is set zero
# JCEF_PATH - specifies the path to the directory with JCEF binaries.
# By default JCEF binaries should be located in ./jcef_linux_aarch64
source jb/project/tools/common/scripts/common.sh
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
JCEF_PATH=${JCEF_PATH:=./jcef_linux_aarch64}
sh configure \
--with-debug-level=release \
--with-vendor-name="${VENDOR_NAME}" \
--with-vendor-version-string="${VENDOR_VERSION_STRING}" \
--with-jvm-features=shenandoahgc \
--with-version-pre= \
--with-version-build="${JDK_BUILD_NUMBER}" \
--with-version-opt=b${build_number} \
--with-boot-jdk=${BOOT_JDK} \
--enable-cds=yes \
$REPRODUCIBLE_BUILD_OPTS \
|| exit $?
make clean CONF=linux-aarch64-server-release || exit $?
make images CONF=linux-aarch64-server-release test-image || exit $?
function do_configure {
sh configure \
$WITH_DEBUG_LEVEL \
--with-vendor-name="$VENDOR_NAME" \
--with-vendor-version-string="$VENDOR_VERSION_STRING" \
--with-jvm-features=shenandoahgc \
--with-version-pre= \
--with-version-build="$JDK_BUILD_NUMBER" \
--with-version-opt=b"$build_number" \
--with-boot-jdk="$BOOT_JDK" \
--enable-cds=yes \
$REPRODUCIBLE_BUILD_OPTS \
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \
|| do_exit $?
}
JBSDK=${JBRSDK_BASE_NAME}-linux-aarch64-b${build_number}
BASE_DIR=build/linux-aarch64-server-release/images
JSDK=${BASE_DIR}/jdk
function is_musl {
libc=$(ldd /bin/ls | grep 'musl' | head -1 | cut -d ' ' -f1)
if [ -z $libc ]; then
# This is not Musl, return 1 == false
return 1
fi
return 0
}
function create_image_bundle {
__bundle_name=$1
__arch_name=$2
__modules_path=$3
__modules=$4
libc_type_suffix=''
if is_musl; then libc_type_suffix='musl-' ; fi
[ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-"
JBR=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}aarch64-${fastdebug_infix}b${build_number}
echo Running jlink....
[ -d "$IMAGES_DIR"/"$__arch_name" ] && rm -rf "${IMAGES_DIR:?}"/"$__arch_name"
$JSDK/bin/jlink \
--module-path "$__modules_path" --no-man-pages --compress=2 \
--add-modules "$__modules" --output "$IMAGES_DIR"/"$__arch_name"
grep -v "^JAVA_VERSION" "$JSDK"/release | grep -v "^MODULES" >> "$IMAGES_DIR"/"$__arch_name"/release
if [ "$__arch_name" == "$JBRSDK_BUNDLE" ]; then
sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__arch_name"/release > release
mv release "$IMAGES_DIR"/"$__arch_name"/release
copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__arch_name"/jmods
zip_native_debug_symbols $IMAGES_DIR/jdk "${JBR}_diz"
fi
# jmod does not preserve file permissions (JDK-8173610)
[ -f "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper
echo Creating "$JBR".tar.gz ...
(cd "$IMAGES_DIR" &&
find "$__arch_name" -print0 | LC_ALL=C sort -z | \
tar $REPRODUCIBLE_TAR_OPTS \
--no-recursion --null -T - -cf "$JBR".tar) || do_exit $?
mv "$IMAGES_DIR"/"$JBR".tar ./"$JBR".tar
[ -f "$JBR".tar.gz ] && rm "$JBR.tar.gz"
touch -c -d "@$SOURCE_DATE_EPOCH" "$JBR".tar
gzip "$JBR".tar || do_exit $?
rm -rf "${IMAGES_DIR:?}"/"$__arch_name"
}
WITH_DEBUG_LEVEL="--with-debug-level=release"
RELEASE_NAME=linux-aarch64-server-release
case "$bundle_type" in
"jcef")
do_reset_changes=1
do_maketest=1
;;
"nomod" | "")
bundle_type=""
;;
"fd")
do_reset_changes=1
WITH_DEBUG_LEVEL="--with-debug-level=fastdebug"
RELEASE_NAME=linux-aarch64-server-fastdebug
;;
esac
if [ -z "$INC_BUILD" ]; then
do_configure || do_exit $?
make clean CONF=$RELEASE_NAME || do_exit $?
fi
make images CONF=$RELEASE_NAME || do_exit $?
IMAGES_DIR=build/$RELEASE_NAME/images
JSDK=$IMAGES_DIR/jdk
JSDK_MODS_DIR=$IMAGES_DIR/jmods
JBRSDK_BUNDLE=jbrsdk
echo Fixing permissions
chmod -R a+r $JSDK
rm -rf $BASE_DIR/$JBRSDK_BUNDLE
cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $?
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
git apply -p0 < jb/project/tools/patches/add_jcef_module_aarch64.patch || do_exit $?
update_jsdk_mods $JSDK $JCEF_PATH/jmods $JSDK/jmods $JSDK_MODS_DIR || do_exit $?
cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed
echo Creating $JBSDK.tar.gz ...
sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release
mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release
jbr_name_postfix="_${bundle_type}"
fi
# NB: --sort=name requires tar1.28
tar $REPRODUCIBLE_TAR_OPTS --sort=name -pcf $JBSDK.tar \
--exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \
-C $BASE_DIR ${JBRSDK_BUNDLE} || exit $?
touch -c -d @$SOURCE_DATE_EPOCH $JBRSDK.tar
gzip $JBSDK.tar || exit $?
# create runtime image bundle
modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $?
create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $?
JBR_BUNDLE=jbr
JBR_BASE_NAME=jbr-$JBSDK_VERSION
rm -rf $BASE_DIR/$JBR_BUNDLE
# create sdk image bundle
modules=$(cat $JSDK/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\n//g) || do_exit $?
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then
modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods)
fi
create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $?
JBR=$JBR_BASE_NAME-linux-aarch64-b$build_number
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.aarch64
echo Running jlink....
${JSDK}/bin/jlink \
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
--add-modules $(xargs < modules.list.aarch64 | sed s/" "//g | sed s/',$'//g) \
--output ${BASE_DIR}/${JBR_BUNDLE} || exit $?
if [ $do_maketest -eq 1 ]; then
JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-linux-${libc_type_suffix}test-aarch64-b${build_number}
echo Creating "$JBRSDK_TEST" ...
[ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java
make test-image CONF=$RELEASE_NAME || do_exit $?
tar -pcf "$JBRSDK_TEST".tar -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $?
[ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz"
gzip "$JBRSDK_TEST".tar || do_exit $?
fi
echo Modifying release info ...
grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${BASE_DIR}/${JBR_BUNDLE}/release
echo Creating $JBR.tar.gz ...
tar $REPRODUCIBLE_TAR_OPTS --sort=name -pcf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE} || exit $?
touch -c -d @$SOURCE_DATE_EPOCH $JBR.tar
gzip $JBR.tar || exit $?
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-aarch64-b$build_number
echo Creating $JBRSDK_TEST.tar.gz ...
tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $?
gzip $JBRSDK_TEST.tar || exit $?
do_exit 0

View File

@@ -33,17 +33,31 @@ function do_configure {
--with-boot-jdk="$BOOT_JDK" \
--enable-cds=yes \
$REPRODUCIBLE_BUILD_OPTS \
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \
|| do_exit $?
}
function is_musl {
libc=$(ldd /bin/ls | grep 'musl' | head -1 | cut -d ' ' -f1)
if [ -z $libc ]; then
# This is not Musl, return 1 == false
return 1
fi
return 0
}
function create_image_bundle {
__bundle_name=$1
__arch_name=$2
__modules_path=$3
__modules=$4
libc_type_suffix=''
if is_musl; then libc_type_suffix='musl-' ; fi
[ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-"
JBR=${__bundle_name}-${JBSDK_VERSION}-linux-x64-${fastdebug_infix}b${build_number}
JBR=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}x64-${fastdebug_infix}b${build_number}
echo Running jlink....
[ -d "$IMAGES_DIR"/"$__arch_name" ] && rm -rf "${IMAGES_DIR:?}"/"$__arch_name"
@@ -56,6 +70,7 @@ function create_image_bundle {
sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__arch_name"/release > release
mv release "$IMAGES_DIR"/"$__arch_name"/release
copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__arch_name"/jmods
zip_native_debug_symbols $IMAGES_DIR/jdk "${JBR}_diz"
fi
# jmod does not preserve file permissions (JDK-8173610)
@@ -115,7 +130,7 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
fi
# create runtime image bundle
modules=$(xargs < modules.list | sed s/" "//g) || do_exit $?
modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $?
create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $?
# create sdk image bundle
@@ -126,9 +141,9 @@ fi
create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $?
if [ $do_maketest -eq 1 ]; then
JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-linux-test-x64-b${build_number}
JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-linux-${libc_type_suffix}test-x64-b${build_number}
echo Creating "$JBRSDK_TEST" ...
[ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java
[ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java
make test-image CONF=$RELEASE_NAME || do_exit $?
tar -pcf "$JBRSDK_TEST".tar -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $?
[ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz"

View File

@@ -61,7 +61,7 @@ JBR_BASE_NAME=jbr-$JBSDK_VERSION
rm -rf $BASE_DIR/$JBR_BUNDLE
JBR=$JBR_BASE_NAME-linux-x86-b$build_number
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
grep -v javafx jb/project/tools/common/modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
echo Running jlink....
${JSDK}/bin/jlink \
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
@@ -77,4 +77,4 @@ gzip $JBR.tar || exit $?
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x86-b$build_number
echo Creating $JBRSDK_TEST.tar.gz ...
tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' --exclude='test/hotspot/gtest' test || exit $?
gzip $JBRSDK_TEST.tar || exit $?
gzip $JBRSDK_TEST.tar || exit $?

View File

@@ -45,6 +45,7 @@ function do_configure {
--with-extra-cxxflags="-F$(pwd)/Frameworks" \
--with-extra-ldflags="-F$(pwd)/Frameworks" \
$REPRODUCIBLE_BUILD_OPTS \
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \
|| do_exit $?
else
sh configure \
@@ -61,6 +62,7 @@ function do_configure {
--with-macosx-version-max="${MACOSX_VERSION_MAX:="10.12.00"}" \
--enable-cds=yes \
$REPRODUCIBLE_BUILD_OPTS \
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \
|| do_exit $?
fi
}
@@ -90,6 +92,7 @@ function create_image_bundle {
sed 's/JBR/JBRSDK/g' $JRE_CONTENTS/Home/release > release
mv release $JRE_CONTENTS/Home/release
copy_jmods "$__modules" "$__modules_path" "$JRE_CONTENTS"/Home/jmods
zip_native_debug_symbols $IMAGES_DIR/jdk-bundle/jdk-$JBSDK_VERSION.jdk "${JBR}_diz"
fi
cp -R "$JSDK"/../MacOS "$JRE_CONTENTS"
@@ -153,7 +156,7 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
fi
# create runtime image bundle
modules=$(xargs < modules.list | sed s/" "//g) || do_exit $?
modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $?
create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $?
# create sdk image bundle
@@ -166,7 +169,7 @@ create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" "$JBRSDK_BUNDLE" "$JSDK_
if [ $do_maketest -eq 1 ]; then
JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-osx-test-${architecture}-b${build_number}
echo Creating "$JBRSDK_TEST" ...
[ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java
[ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java
make test-image CONF=$RELEASE_NAME || do_exit $?
[ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz"
COPYFILE_DISABLE=1 tar -pczf "$JBRSDK_TEST".tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $?

View File

@@ -1,8 +1,8 @@
diff --git modules.list modules.list
index 054f21d1ee0..d9a121f0273 100644
--- modules.list
+++ modules.list
@@ -49,4 +49,7 @@ jdk.unsupported,
diff --git jb/project/tools/common/modules.list jb/project/tools/common/modules.list
index 522acb7cb43..c40e689d5de 100644
--- jb/project/tools/common/modules.list
+++ jb/project/tools/common/modules.list
@@ -51,4 +51,7 @@ jdk.unsupported.desktop,
jdk.xml.dom,
jdk.zipfs,
jdk.hotspot.agent,

View File

@@ -0,0 +1,30 @@
diff --git jb/project/tools/common/modules.list jb/project/tools/common/modules.list
index 522acb7..c40e689 100644
--- jb/project/tools/common/modules.list
+++ jb/project/tools/common/modules.list
@@ -51,4 +51,7 @@ jdk.unsupported.desktop,
jdk.xml.dom,
jdk.zipfs,
jdk.hotspot.agent,
-jdk.jcmd
+jdk.jcmd,
+jcef,
+gluegen.rt,
+jogl.all
diff --git src/java.desktop/share/classes/module-info.java src/java.desktop/share/classes/module-info.java
index 897647e..781d180 100644
--- src/java.desktop/share/classes/module-info.java
+++ src/java.desktop/share/classes/module-info.java
@@ -116,7 +116,11 @@ module java.desktop {
// see make/GensrcModuleInfo.gmk
exports sun.awt to
jdk.accessibility,
- jdk.unsupported.desktop;
+ jdk.unsupported.desktop,
+ jcef,
+ jogl.all;
+
+ exports java.awt.peer to jcef;
exports java.awt.dnd.peer to jdk.unsupported.desktop;
exports sun.awt.dnd to jdk.unsupported.desktop;

View File

@@ -1,5 +1,16 @@
#!/bin/bash
while getopts ":t" o; do
case "${o}" in
t)
t="With Teamcity tests info"
TC_PRINT=1
;;
esac
done
shift $((OPTIND-1))
NEWFILEPATH=$1
CONFIGID=$2
BUILDID=$3
@@ -7,6 +18,7 @@ TOKEN=$4
#
# Get the size of new artifact
#
unameOut="$(uname -s)"
case "${unameOut}" in
Linux*)
@@ -16,7 +28,11 @@ case "${unameOut}" in
NEWFILESIZE=$(stat -f%z "$NEWFILEPATH")
;;
CYGWIN*)
NEWFILESIZE=$(stat -c%s "$NEWFILEPATH")
NEWFILESIZE=$(stat -c%s$4
#
# Get the size of new artifact
#
"$NEWFILEPATH")
;;
MINGW*)
NEWFILESIZE=$(stat -c%s "$NEWFILEPATH")
@@ -25,32 +41,88 @@ case "${unameOut}" in
echo "Unknown machine: ${unameOut}"
exit 1
esac
FILENAME=$(basename ${NEWFILEPATH})
echo "New size of $NEWFILEPATH = $NEWFILESIZE bytes."
#
# Get pattern of artifact name
# Base filename pattern: <BUNDLE_TYPE>-<JDK_VERSION>-<OS>-<ARCH>-b<BUILD>.tar.gz: jbr_dcevm-17.0.2-osx-x64-b1234.tar.gz
# BUNDLE_TYPE: jbr, jbrsdk, jbr_dcevm, jbrsdk_jcef etc.
# OS_ARCH_PATTERN - <os_architecture>: osx-x64, linux-aarch64, windows-x64 etc.
# example: IntellijCustomJdk_Jdk17_Master_LinuxX64jcef
BUNDLE_TYPE=jbrsdk
OS_ARCH_PATTERN=""
FILE_EXTENSION=tar.gz
re='(jbr[a-z_]*).*-[0-9_\.]+-(.+)-b[0-9]+(.+)'
if [[ $FILENAME =~ $re ]]; then
BUNDLE_TYPE=${BASH_REMATCH[1]}
OS_ARCH_PATTERN=${BASH_REMATCH[2]}
FILE_EXTENSION=${BASH_REMATCH[3]}
fi
if [ $TC_PRINT -eq 1 ]; then
testname_file_ext=`echo $FILE_EXTENSION | sed 's/\./_/g'`
testname=$BUNDLE_TYPE"_"$OS_ARCH_PATTERN$testname_file_ext
echo \#\#teamcity[testStarted name=\'$testname\']
fi
echo "BUNDLE_TYPE: " $BUNDLE_TYPE
echo "OS_ARCH_PATTERN: " $OS_ARCH_PATTERN
echo "FILE_EXTENSION: " $FILE_EXTENSION
echo "New size of $FILENAME = $NEWFILESIZE bytes."
function test_failed_msg() {
if [ $3 -eq 1 ]; then
echo \#\#teamcity[testFailed name=\'$1\' message=\'$2\']
fi
}
function test_finished_msg() {
if [ $2 -eq 1 ]; then
echo \#\#teamcity[testFinished name=\'$1\']
fi
}
#
# Get previous successful build ID
# Example:
# CONFIGID=IntellijCustomJdk_Jdk17_Master_LinuxX64jcef
# BUILDID=12345678
#
# expected return value
# id="123".number="567"
#
CURL_RESPONSE=$(curl --header "Authorization: Bearer $TOKEN" "https://buildserver.labs.intellij.net/app/rest/builds/?locator=buildType:(id:$CONFIGID),status:success,count:1,finishDate:(build:$BUILDID,condition:before)")
re='id=\"([0-9]+)\".+number=\"([0-9\.]+)\"'
re='id=\"([0-9]+)\".+number=\"([0-9]+)\"'
# ID: Previous successful build id
ID=0
if [[ $CURL_RESPONSE =~ $re ]]; then
ID=${BASH_REMATCH[1]}
echo "BUILD Number: ${BASH_REMATCH[2]}"
else
echo "ERROR: can't find previous build"
msg="ERROR: can't find previous build"
echo $msg
echo $CURL_RESPONSE
test_failed_msg $testname $msg $TC_PRINT
test_finished_msg $testname $TC_PRINT
exit 1
fi
#
# Get artifacts from previous successful build
#
# expected return value
# name="jbrsdk_jcef*.tar.gz size="123'
#
CURL_RESPONSE=$(curl --header "Authorization: Bearer $TOKEN" "https://buildserver.labs.intellij.net/app/rest/builds/$ID?fields=id,number,artifacts(file(name,size))")
echo "Atrifacts of last pinned build of $CONFIGID :\n"
echo "Atrifacts of previous build of $CONFIGID :"
echo $CURL_RESPONSE
# Find size (in response) with reg exp
re='name=\"(jbrsdk_jcef[^\"]+\.tar\.gz)\" size=\"([0-9]+)\"'
# Find binary size (in response) with reg exp
re='name=\"('$BUNDLE_TYPE'[^\"]+'${OS_ARCH_PATTERN}'[^\"]+'${FILE_EXTENSION}')\" size=\"([0-9]+)\"'
if [[ $CURL_RESPONSE =~ $re ]]; then
OLDFILENAME=${BASH_REMATCH[1]}
@@ -61,12 +133,20 @@ if [[ $CURL_RESPONSE =~ $re ]]; then
let allowedSize=OLDFILESIZE+OLDFILESIZE/20 # use 5% threshold
echo "Allowed size = $allowedSize"
if [[ "$NEWFILESIZE" -gt "$allowedSize" ]]; then
echo "ERROR: new size is significally greater than prev size (need to investigate)"
msg="ERROR: new size is significally greater than prev size (need to investigate)"
echo $msg
test_failed_msg $testname $msg $TC_PRINT
test_finished_msg $testname $TC_PRINT
exit 1
else
echo "PASSED"
test_finished_msg $testname $TC_PRINT
fi
else
echo "ERROR: can't find string with size in xml response:"
msg="ERROR: can't find string with size in xml response:"
echo $msg
echo $CURL_RESPONSE
test_failed_msg $testname $msg $TC_PRINT
test_finished_msg $testname $TC_PRINT
exit 1
fi

View File

@@ -107,7 +107,8 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
fi
# create runtime image bundlef
modules=$(xargs < modules.list | sed s/" "//g) || do_exit $?
modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $?
modules+=",jdk.crypto.mscapi"
create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $?
# create sdk image bundle

View File

@@ -53,7 +53,8 @@ mv release ${JBRSDK_BUNDLE}/release
JBR_BUNDLE=jbr
rm -rf ${JBR_BUNDLE}
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
grep -v javafx jb/project/tools/common/modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
echo ",jdk.crypto.mscapi" >> modules.list.x86
${JSDK}/bin/jlink \
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
--add-modules $(xargs < modules.list.x86 | sed s/" "//g) --output ${JBR_BUNDLE} || exit $?

View File

@@ -95,8 +95,24 @@ AC_DEFUN([FLAGS_SETUP_DEBUG_SYMBOLS],
# info flags for toolchains unless we know they work.
# See JDK-8207057.
ASFLAGS_DEBUG_SYMBOLS=""
# Debug prefix mapping if supported by compiler
DEBUG_PREFIX_CFLAGS=
# Debug symbols
if test "x$TOOLCHAIN_TYPE" = xgcc; then
if test "x$ALLOW_ABSOLUTE_PATHS_IN_OUTPUT" = "xfalse"; then
# Check if compiler supports -fdebug-prefix-map. If so, use that to make
# the debug symbol paths resolve to paths relative to the workspace root.
workspace_root_trailing_slash="${WORKSPACE_ROOT%/}/"
DEBUG_PREFIX_CFLAGS="-fdebug-prefix-map=${workspace_root_trailing_slash}="
FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [${DEBUG_PREFIX_CFLAGS}],
IF_FALSE: [
DEBUG_PREFIX_CFLAGS=
]
)
fi
CFLAGS_DEBUG_SYMBOLS="-g"
ASFLAGS_DEBUG_SYMBOLS="-g"
elif test "x$TOOLCHAIN_TYPE" = xclang; then
@@ -108,6 +124,11 @@ AC_DEFUN([FLAGS_SETUP_DEBUG_SYMBOLS],
CFLAGS_DEBUG_SYMBOLS="-Z7"
fi
if test "x$DEBUG_PREFIX_CFLAGS" != x; then
CFLAGS_DEBUG_SYMBOLS="$CFLAGS_DEBUG_SYMBOLS $DEBUG_PREFIX_CFLAGS"
ASFLAGS_DEBUG_SYMBOLS="$ASFLAGS_DEBUG_SYMBOLS $DEBUG_PREFIX_CFLAGS"
fi
AC_SUBST(CFLAGS_DEBUG_SYMBOLS)
AC_SUBST(ASFLAGS_DEBUG_SYMBOLS)
])
@@ -778,8 +799,6 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
FILE_MACRO_CFLAGS=
]
)
# -fdebug-prefix-map is supported by all modern versions of gcc/clang
DEBUG_PREFIX_CFLAGS=" -fdebug-prefix-map=${workspace_root_trailing_slash}="
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft &&
test "x$ENABLE_REPRODUCIBLE_BUILD" = xtrue; then
# There is a known issue with the pathmap if the mapping is made to the
@@ -810,12 +829,12 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
$TOOLCHAIN_CFLAGS_JVM ${$1_TOOLCHAIN_CFLAGS_JVM} \
$OS_CFLAGS $OS_CFLAGS_JVM $CFLAGS_OS_DEF_JVM $DEBUG_CFLAGS_JVM \
$WARNING_CFLAGS $WARNING_CFLAGS_JVM $JVM_PICFLAG $FILE_MACRO_CFLAGS \
$REPRODUCIBLE_CFLAGS $DEBUG_PREFIX_CFLAGS"
$REPRODUCIBLE_CFLAGS"
CFLAGS_JDK_COMMON="$ALWAYS_CFLAGS_JDK $ALWAYS_DEFINES_JDK $TOOLCHAIN_CFLAGS_JDK \
$OS_CFLAGS $CFLAGS_OS_DEF_JDK $DEBUG_CFLAGS_JDK $DEBUG_OPTIONS_FLAGS_JDK \
$WARNING_CFLAGS $WARNING_CFLAGS_JDK $DEBUG_SYMBOLS_CFLAGS_JDK \
$FILE_MACRO_CFLAGS $REPRODUCIBLE_CFLAGS $DEBUG_PREFIX_CFLAGS"
$FILE_MACRO_CFLAGS $REPRODUCIBLE_CFLAGS"
# Use ${$2EXTRA_CFLAGS} to block EXTRA_CFLAGS to be added to build flags.
# (Currently we don't have any OPENJDK_BUILD_EXTRA_CFLAGS, but that might

View File

@@ -82,14 +82,6 @@ AC_DEFUN([FLAGS_SETUP_ASFLAGS],
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
BASIC_ASFLAGS="-nologo -c"
fi
if test "x$ALLOW_ABSOLUTE_PATHS_IN_OUTPUT" = "xfalse"; then
if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang; then
workspace_root_trailing_slash="${WORKSPACE_ROOT%/}/"
BASIC_ASFLAGS+=" -fdebug-prefix-map=${workspace_root_trailing_slash}="
fi
fi
AC_SUBST(BASIC_ASFLAGS)
if test "x$OPENJDK_TARGET_OS" = xmacosx; then

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 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
@@ -230,8 +230,6 @@ AC_DEFUN([UTIL_GET_MATCHING_VALUES],
# Converts an ISO-8601 date/time string to a unix epoch timestamp. If no
# suitable conversion method was found, an empty string is returned.
#
# Sets the specified variable to the resulting list.
#
# $1: result variable name
# $2: input date/time string
AC_DEFUN([UTIL_GET_EPOCH_TIMESTAMP],
@@ -241,11 +239,16 @@ AC_DEFUN([UTIL_GET_EPOCH_TIMESTAMP],
timestamp=$($DATE --utc --date=$2 +"%s" 2> /dev/null)
else
# BSD date
timestamp=$($DATE -u -j -f "%F %T" "$2" "+%s" 2> /dev/null)
# ISO-8601 date&time in Zulu 'date'T'time'Z
timestamp=$($DATE -u -j -f "%FT%TZ" "$2" "+%s" 2> /dev/null)
if test "x$timestamp" = x; then
# Perhaps the time was missing
timestamp=$($DATE -u -j -f "%F %T" "$2 00:00:00" "+%s" 2> /dev/null)
# If this did not work, we give up and return the empty string
# BSD date cannot handle trailing milliseconds.
# Try again ignoring characters at end
timestamp=$($DATE -u -j -f "%Y-%m-%dT%H:%M:%S" "$2" "+%s" 2> /dev/null)
fi
if test "x$timestamp" = x; then
# Perhaps the time was missing.
timestamp=$($DATE -u -j -f "%FT%TZ" "$2""T00:00:00Z" "+%s" 2> /dev/null)
fi
fi
$1=$timestamp

View File

@@ -1,55 +0,0 @@
#
# Copyright (c) 2011, 2019, 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.
#
# Default version, product, and vendor information to use,
# unless overridden by configure
DEFAULT_VERSION_FEATURE=15
DEFAULT_VERSION_INTERIM=0
DEFAULT_VERSION_UPDATE=0
DEFAULT_VERSION_PATCH=0
DEFAULT_VERSION_EXTRA1=0
DEFAULT_VERSION_EXTRA2=0
DEFAULT_VERSION_EXTRA3=0
DEFAULT_VERSION_DATE=2020-09-15
DEFAULT_VERSION_CLASSFILE_MAJOR=59 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`"
DEFAULT_VERSION_CLASSFILE_MINOR=0
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="14 15"
DEFAULT_JDK_SOURCE_TARGET_VERSION=15
DEFAULT_PROMOTED_VERSION_PRE=
LAUNCHER_NAME=openjdk
PRODUCT_NAME=OpenJDK
PRODUCT_SUFFIX="Runtime Environment"
JDK_RC_PLATFORM_NAME=Platform
COMPANY_NAME=N/A
HOTSPOT_VM_DISTRO="Dynamic Code Evolution"
VENDOR_URL=https://openjdk.java.net/
VENDOR_URL_BUG=https://bugreport.java.com/bugreport/
VENDOR_URL_VM_BUG=https://bugreport.java.com/bugreport/crash.jsp
# Might need better names for these
MACOSX_BUNDLE_NAME_BASE="OpenJDK"
MACOSX_BUNDLE_ID_BASE="net.java.openjdk"

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 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
@@ -193,7 +193,8 @@ define SetupJarArchiveBody
$1_UPDATE_CONTENTS=\
if [ "`$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'`" -gt "0" ]; then \
$(ECHO) " updating" `$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'` files && \
$$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents; \
$(SORT) $$($1_BIN)/_the.$$($1_JARNAME)_contents > $$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted && \
$$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted; \
fi $$(NEWLINE)
# The s-variants of the above macros are used when the jar is created from scratch.
# NOTICE: please leave the parentheses space separated otherwise the AIX build will break!
@@ -212,7 +213,9 @@ define SetupJarArchiveBody
| $(SED) 's|$$(src)/|-C $$(src) |g' >> \
$$($1_BIN)/_the.$$($1_JARNAME)_contents) $$(NEWLINE) )
endif
$1_SUPDATE_CONTENTS=$$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)
$1_SUPDATE_CONTENTS=\
$(SORT) $$($1_BIN)/_the.$$($1_JARNAME)_contents > $$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted && \
$$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted $$(NEWLINE)
# Use a slightly shorter name for logging, but with enough path to identify this jar.
$1_NAME:=$$(subst $$(OUTPUTDIR)/,,$$($1_JAR))

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 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
@@ -358,6 +358,20 @@ define SetupCompileNativeFileBody
# Compile as preprocessed assembler file
$1_FLAGS := $(BASIC_ASFLAGS) $$($1_BASE_ASFLAGS)
$1_COMPILER := $(AS)
# gcc assembly files must contain an appropriate relative .file
# path for reproducible builds.
ifeq ($(TOOLCHAIN_TYPE), gcc)
# If no absolute paths allowed, work out relative source file path
# for assembly .file substitution, otherwise use full file path
ifeq ($(ALLOW_ABSOLUTE_PATHS_IN_OUTPUT), false)
$1_REL_ASM_SRC := $$(call RelativePath, $$($1_FILE), $(WORKSPACE_ROOT))
else
$1_REL_ASM_SRC := $$($1_FILE)
endif
$1_FLAGS := $$($1_FLAGS) -DASSEMBLY_SRC_FILE='"$$($1_REL_ASM_SRC)"' \
-include $(TOPDIR)/make/data/autoheaders/assemblyprefix.h
endif
else ifneq ($$(filter %.cpp %.cc %.mm, $$($1_FILENAME)), )
# Compile as a C++ or Objective-C++ file
$1_FLAGS := $(CFLAGS_CCACHE) $$($1_USE_PCH_FLAGS) $$($1_BASE_CXXFLAGS) \
@@ -389,6 +403,12 @@ define SetupCompileNativeFileBody
$1_OBJ_DEPS := $$($1_SRC_FILE) $$($$($1_BASE)_COMPILE_VARDEPS_FILE) \
$$($$($1_BASE)_EXTRA_DEPS) $$($1_VARDEPS_FILE)
$1_COMPILE_OPTIONS := $$($1_FLAGS) $(CC_OUT_OPTION)$$($1_OBJ) $$($1_SRC_FILE)
# For reproducible builds with gcc ensure random symbol generation is seeded deterministically
ifeq ($(TOOLCHAIN_TYPE), gcc)
ifeq ($$(ENABLE_REPRODUCIBLE_BUILD), true)
$1_COMPILE_OPTIONS += -frandom-seed="$$($1_FILENAME)"
endif
endif
$$($1_OBJ_JSON): $$($1_OBJ_DEPS)
$$(call WriteCompileCommandsFragment, $$@, $$(PWD), $$($1_SRC_FILE), \

View File

@@ -0,0 +1,29 @@
#
# Copyright (c) 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.
#
// ASSEMBLY_SRC_FILE gets replaced by relative or absolute file path
// in NativeCompilation.gmk for gcc tooling on Linux. This ensures a
// reproducible object file through a predictable value of the STT_FILE
// symbol, and subsequently a reproducible .debuginfo.
.file ASSEMBLY_SRC_FILE

View File

@@ -58,6 +58,9 @@ ifeq ($(call check-jvm-feature, compiler2), true)
ADLC_CFLAGS += -I$(TOPDIR)/src/hotspot/share
# Add file macro mappings
ADLC_CFLAGS += $(FILE_MACRO_CFLAGS)
$(eval $(call SetupNativeCompilation, BUILD_ADLC, \
NAME := adlc, \
TYPE := EXECUTABLE, \

View File

@@ -84,7 +84,7 @@ ifneq ($(call check-jvm-feature, jvmti), true)
jvmtiImpl.cpp jvmtiManageCapabilities.cpp jvmtiRawMonitor.cpp jvmtiUtil.cpp jvmtiTrace.cpp \
jvmtiCodeBlobEvents.cpp jvmtiEnv.cpp jvmtiRedefineClasses.cpp jvmtiEnvBase.cpp jvmtiEnvThreadState.cpp \
jvmtiTagMap.cpp jvmtiEventController.cpp evmCompat.cpp jvmtiEnter.xsl jvmtiExport.cpp \
jvmtiClassFileReconstituter.cpp jvmtiTagMapTable.cpp
jvmtiClassFileReconstituter.cpp jvmtiTagMapTable.cpp jvmtiEnhancedRedefineClasses.cpp
endif
ifneq ($(call check-jvm-feature, jvmci), true)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 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
@@ -204,6 +204,10 @@ public class MakeZipReproducible {
entry.setTimeLocal(timestamp);
}
// Ensure "extra" field is not set from original ZipEntry info that may be not deterministic
// eg.may contain specific UID/GID
entry.setExtra(null);
zos.putNextEntry(entry);
if (entry.getSize() > 0 && entryInputStream != null) {
entryInputStream.transferTo(zos);

View File

@@ -84,7 +84,7 @@ TARGETS += $(COPY_LEGAL)
################################################################################
FONTFILE_SRC_DIR := $(TOPDIR)/src/java.desktop/share
FONTFILE_SRCS := $(wildcard $(FONTFILE_SRC_DIR)/fonts/*.ttf) $(FONTFILE_SRC_DIR)/fonts/fonts.dir $(FONTFILE_SRC_DIR)/fonts/font.conf
FONTFILE_SRCS := $(wildcard $(FONTFILE_SRC_DIR)/fonts/*.ttf) $(wildcard $(FONTFILE_SRC_DIR)/fonts/*.otf) $(FONTFILE_SRC_DIR)/fonts/fonts.dir $(FONTFILE_SRC_DIR)/fonts/font.conf
FONTFILE_TARGET_FILES := $(subst $(FONTFILE_SRC_DIR),$(LIB_DST_DIR),$(FONTFILE_SRCS))
$(LIB_DST_DIR)/fonts/%: $(FONTFILE_SRC_DIR)/fonts/%

View File

@@ -31,7 +31,6 @@
#define ELF_TYPE(name, description) .type name,description
#endif
.file "bsd_x86_32.S"
.globl SYMBOL(fixcw)
# NOTE WELL! The _Copy functions are called directly

View File

@@ -30,7 +30,6 @@
#define ELF_TYPE(name, description) .type name,description
#endif
.file "bsd_x86_64.S"
# NOTE WELL! The _Copy functions are called directly
# from server-compiler-generated code via CallLeafNoFP,
# which means that they *must* either not use floating

View File

@@ -19,7 +19,6 @@
// or visit www.oracle.com if you need additional information or have any
// questions.
.file "atomic_linux_aarch64.S"
.text

View File

@@ -21,8 +21,6 @@
* questions.
*
*/
.file "copy_linux_aarch64.S"
.global _Copy_conjoint_words
.global _Copy_disjoint_words

View File

@@ -19,8 +19,6 @@
// or visit www.oracle.com if you need additional information or have any
// questions.
.file "threadLS_linux_aarch64.S"
// JavaThread::aarch64_get_thread_helper()
//
// Return the current thread pointer in x0.

View File

@@ -21,7 +21,6 @@
# questions.
#
.file "linux_arm_32.S"
# NOTE WELL! The _Copy functions are called directly
# from server-compiler-generated code via CallLeafNoFP,

View File

@@ -22,8 +22,6 @@
#
.file "linux_x86_32.S"
# NOTE WELL! The _Copy functions are called directly
# from server-compiler-generated code via CallLeafNoFP,
# which means that they *must* either not use floating

View File

@@ -21,8 +21,6 @@
# questions.
#
.file "linux_x86_64.S"
# NOTE WELL! The _Copy functions are called directly
# from server-compiler-generated code via CallLeafNoFP,
# which means that they *must* either not use floating

View File

@@ -335,16 +335,6 @@ void ClassLoaderData::classes_do(KlassClosure* klass_closure) {
}
}
void ClassLoaderData::initialized_classes_do(KlassClosure* klass_closure) {
// Lock-free access requires load_acquire
for (Klass* k = Atomic::load_acquire(&_klasses); k != NULL; k = k->next_link()) {
if (k->is_instance_klass() && InstanceKlass::cast(k)->is_initialized()) {
klass_closure->do_klass(k);
}
assert(k != k->next_link(), "no loops!");
}
}
void ClassLoaderData::classes_do(void f(Klass * const)) {
// Lock-free access requires load_acquire
for (Klass* k = Atomic::load_acquire(&_klasses); k != NULL; k = k->next_link()) {

View File

@@ -272,7 +272,6 @@ class ClassLoaderData : public CHeapObj<mtClass> {
void oops_do(OopClosure* f, int claim_value, bool clear_modified_oops = false);
void classes_do(KlassClosure* klass_closure);
void initialized_classes_do(KlassClosure* klass_closure);
Klass* klasses() { return _klasses; }
JNIMethodBlock* jmethod_ids() const { return _jmethod_ids; }

View File

@@ -361,13 +361,6 @@ void ClassLoaderDataGraph::classes_do(KlassClosure* klass_closure) {
}
}
void ClassLoaderDataGraph::initialized_classes_do(KlassClosure* klass_closure) {
ClassLoaderDataGraphIterator iter;
while (ClassLoaderData* cld = iter.get_next()) {
cld->initialized_classes_do(klass_closure);
}
}
void ClassLoaderDataGraph::classes_do(void f(Klass* const)) {
ClassLoaderDataGraphIterator iter;
while (ClassLoaderData* cld = iter.get_next()) {

View File

@@ -79,9 +79,6 @@ class ClassLoaderDataGraph : public AllStatic {
// Walking the ClassLoaderDataGraph also includes hidden classes.
static void classes_do(KlassClosure* klass_closure);
// Enhanced class redefinition
static void initialized_classes_do(KlassClosure* klass_closure);
static void classes_do(void f(Klass* const));
static void methods_do(void f(Method*));
static void modules_do(void f(ModuleEntry*));

View File

@@ -68,6 +68,7 @@ static bool enable() {
}
_enabled = FlightRecorder;
assert(_enabled, "invariant");
AllowEnhancedClassRedefinition = false;
return _enabled;
}

View File

@@ -3714,11 +3714,11 @@ bool PhaseIdealLoop::only_has_infinite_loops() {
//----------------------------build_and_optimize-------------------------------
// Create a PhaseLoop. Build the ideal Loop tree. Map each Ideal Node to
// its corresponding LoopNode. If 'optimize' is true, do some loop cleanups.
void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) {
void PhaseIdealLoop::build_and_optimize() {
assert(!C->post_loop_opts_phase(), "no loop opts allowed");
bool do_split_ifs = (mode == LoopOptsDefault);
bool skip_loop_opts = (mode == LoopOptsNone);
bool do_split_ifs = (_mode == LoopOptsDefault);
bool skip_loop_opts = (_mode == LoopOptsNone);
int old_progress = C->major_progress();
uint orig_worklist_size = _igvn._worklist.size();
@@ -3789,9 +3789,9 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) {
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
// Nothing to do, so get out
bool stop_early = !C->has_loops() && !skip_loop_opts && !do_split_ifs && !_verify_me && !_verify_only &&
!bs->is_gc_specific_loop_opts_pass(mode);
!bs->is_gc_specific_loop_opts_pass(_mode);
bool do_expensive_nodes = C->should_optimize_expensive_nodes(_igvn);
bool strip_mined_loops_expanded = bs->strip_mined_loops_expanded(mode);
bool strip_mined_loops_expanded = bs->strip_mined_loops_expanded(_mode);
if (stop_early && !do_expensive_nodes) {
return;
}
@@ -3883,7 +3883,7 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) {
if (_verify_only) {
C->restore_major_progress(old_progress);
assert(C->unique() == unique, "verification mode made Nodes? ? ?");
assert(C->unique() == unique, "verification _mode made Nodes? ? ?");
assert(_igvn._worklist.size() == orig_worklist_size, "shouldn't push anything");
return;
}
@@ -3913,8 +3913,8 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) {
#ifndef PRODUCT
C->verify_graph_edges();
if (_verify_me) { // Nested verify pass?
// Check to see if the verify mode is broken
assert(C->unique() == unique, "non-optimize mode made Nodes? ? ?");
// Check to see if the verify _mode is broken
assert(C->unique() == unique, "non-optimize _mode made Nodes? ? ?");
return;
}
if (VerifyLoopOptimizations) verify();
@@ -3928,7 +3928,7 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) {
return;
}
if (mode == LoopOptsMaxUnroll) {
if (_mode == LoopOptsMaxUnroll) {
for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) {
IdealLoopTree* lpt = iter.current();
if (lpt->is_innermost() && lpt->_allow_optimizations && !lpt->_has_call && lpt->is_counted()) {
@@ -3949,7 +3949,7 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) {
return;
}
if (bs->optimize_loops(this, mode, visited, nstack, worklist)) {
if (bs->optimize_loops(this, _mode, visited, nstack, worklist)) {
return;
}
@@ -5383,7 +5383,7 @@ void PhaseIdealLoop::build_loop_late_post_work(Node *n, bool pinned) {
}
// Try not to place code on a loop entry projection
// which can inhibit range check elimination.
if (least != early) {
if (least != early && !BarrierSet::barrier_set()->barrier_set_c2()->is_gc_specific_loop_opts_pass(_mode)) {
Node* ctrl_out = least->unique_ctrl_out();
if (ctrl_out && ctrl_out->is_Loop() &&
least == ctrl_out->in(LoopNode::EntryControl) &&

View File

@@ -1050,9 +1050,10 @@ private:
Node **_idom; // Array of immediate dominators
uint *_dom_depth; // Used for fast LCA test
GrowableArray<uint>* _dom_stk; // For recomputation of dom depth
LoopOptsMode _mode;
// build the loop tree and perform any requested optimizations
void build_and_optimize(LoopOptsMode mode);
void build_and_optimize();
// Dominators for the sea of nodes
void Dominators();
@@ -1063,9 +1064,10 @@ private:
_igvn(igvn),
_verify_me(nullptr),
_verify_only(false),
_mode(mode),
_nodes_required(UINT_MAX) {
assert(mode != LoopOptsVerify, "wrong constructor to verify IdealLoop");
build_and_optimize(mode);
build_and_optimize();
}
#ifndef PRODUCT
@@ -1076,8 +1078,9 @@ private:
_igvn(igvn),
_verify_me(verify_me),
_verify_only(verify_me == nullptr),
_mode(LoopOptsVerify),
_nodes_required(UINT_MAX) {
build_and_optimize(LoopOptsVerify);
build_and_optimize();
}
#endif

View File

@@ -2129,6 +2129,11 @@ class AffectedKlassClosure : public KlassClosure {
void do_klass(Klass* klass) {
assert(!_affected_klasses->contains(klass), "must not occur more than once!");
// allow only loaded classes
if (!klass->is_instance_klass() || !InstanceKlass::cast(klass)->is_loaded()) {
return;
}
if (klass->new_version() != NULL) {
return;
}
@@ -2185,12 +2190,8 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) {
{
MutexLocker mcld(ClassLoaderDataGraph_lock);
// We can't use ClassLoaderDataGraph::classes_do since classes can be uninitialized in cld,
// fully initialized class is in system dictionary, but hidden classes are excluded. Therefore
// we use special method iterating over initialized classes only
// ClassLoaderDataGraph::classes_do(&closure);
ClassLoaderDataGraph::initialized_classes_do(&closure);
// Hidden classes are not in SystemDictionary, so we have to iterate ClassLoaderDataGraph
ClassLoaderDataGraph::classes_do(&closure);
}
log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length());

View File

@@ -372,10 +372,12 @@ public:
};
class AdjustMethodEntriesDcevm : public StackObj {
bool* _trace_name_printed;
GrowableArray<oop>* _oops_to_add;
GrowableArray<oop>* _oops_to_update;
GrowableArray<Method*>* _old_methods;
public:
AdjustMethodEntriesDcevm(GrowableArray<oop>* oops_to_add, bool* trace_name_printed) : _trace_name_printed(trace_name_printed), _oops_to_add(oops_to_add) {};
AdjustMethodEntriesDcevm(GrowableArray<oop>* oops_to_update, GrowableArray<Method*>* old_methods) :
_oops_to_update(oops_to_update), _old_methods(old_methods) {};
bool operator()(WeakHandle* entry) {
oop mem_name = entry->peek();
if (mem_name == NULL) {
@@ -386,46 +388,8 @@ public:
Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
if (old_method->is_old()) {
InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version());
Method* newer_method;
// Method* new_method;
if (old_method->is_deleted()) {
newer_method = Universe::throw_no_such_method_error();
} else {
newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum());
log_debug(redefine, class, update)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string());
assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts");
assert(newer_method != NULL, "method_with_idnum() should not be NULL");
assert(old_method != newer_method, "sanity check");
Thread* thread = Thread::current();
ResolvedMethodTableLookup lookup(thread, method_hash(newer_method), newer_method);
ResolvedMethodGet rmg(thread, newer_method);
if (_local_table->get(thread, lookup, rmg)) {
// old method was already adjusted if new method exists in _the_table
return true;
}
}
java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method);
java_lang_invoke_ResolvedMethodName::set_vmholder(mem_name, newer_method->method_holder()->java_mirror());
newer_klass->set_has_resolved_methods();
_oops_to_add->append(mem_name);
ResourceMark rm;
if (!(*_trace_name_printed)) {
log_debug(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
*_trace_name_printed = true;
}
log_debug(redefine, class, update, constantpool)
("ResolvedMethod method update: %s(%s)",
newer_method->name()->as_C_string(), newer_method->signature()->as_C_string());
_oops_to_update->append(mem_name);
_old_methods->append(old_method);
}
return true;
@@ -440,36 +404,70 @@ void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) {
_local_table->do_safepoint_scan(adjust);
}
// It is called at safepoint only for RedefineClasses
// It is called at safepoint only for EnhancedRedefineClasses
void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) {
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
// For each entry in RMT, change to new method
GrowableArray<oop> oops_to_add(0);
AdjustMethodEntriesDcevm adjust(&oops_to_add, trace_name_printed);
GrowableArray<oop> oops_to_update(0);
GrowableArray<Method*> old_methods(0);
AdjustMethodEntriesDcevm adjust(&oops_to_update, &old_methods);
_local_table->do_safepoint_scan(adjust);
Thread* thread = Thread::current();
for (int i = 0; i < oops_to_add.length(); i++) {
oop mem_name = oops_to_add.at(i);
Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
// The hash table takes ownership of the WeakHandle, even if it's not inserted.
for (int i = 0; i < oops_to_update.length(); i++) {
oop mem_name = oops_to_update.at(i);
Method *old_method = old_methods.at(i);
ResolvedMethodTableLookup lookup(thread, method_hash(method), method);
ResolvedMethodGet rmg(thread, method);
// 1. Remove old method, since we are going to update class that could be used for hash evaluation in parallel running ServiceThread
ResolvedMethodTableLookup lookup(thread, method_hash(old_method), old_method);
_local_table->remove(thread, lookup);
InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version());
Method* newer_method;
// Method* new_method;
if (old_method->is_deleted()) {
newer_method = Universe::throw_no_such_method_error();
} else {
newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum());
assert(newer_method != NULL, "method_with_idnum() should not be NULL");
assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts");
assert(old_method != newer_method, "sanity check");
Thread* thread = Thread::current();
ResolvedMethodTableLookup lookup(thread, method_hash(newer_method), newer_method);
ResolvedMethodGet rmg(thread, newer_method);
while (true) {
if (_local_table->get(thread, lookup, rmg)) {
break;
}
WeakHandle wh(_oop_storage, mem_name);
// The hash table takes ownership of the WeakHandle, even if it's not inserted.
if (_local_table->insert(thread, lookup, wh)) {
log_insert(method);
wh.resolve();
break;
// old method was already adjusted if new method exists in _the_table
continue;
}
}
log_debug(redefine, class, update)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string());
// 2. Update method
java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method);
java_lang_invoke_ResolvedMethodName::set_vmholder(mem_name, newer_method->method_holder()->java_mirror());
newer_klass->set_has_resolved_methods();
ResourceMark rm;
if (!(*trace_name_printed)) {
log_debug(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
*trace_name_printed = true;
}
log_debug(redefine, class, update, constantpool)
("ResolvedMethod method update: %s(%s)",
newer_method->name()->as_C_string(), newer_method->signature()->as_C_string());
// 3. add updated method to table again
add_method(newer_method, Handle(thread, mem_name));
}
}
#endif // INCLUDE_JVMTI

View File

@@ -117,7 +117,7 @@ const char* Abstract_VM_Version::vm_vendor() {
#ifdef VENDOR
return VENDOR;
#else
return "Oracle Corporation";
return "JetBrains s.r.o.";
#endif
}

View File

@@ -1337,6 +1337,7 @@ bool Arguments::add_property(const char* prop, PropertyWriteable writeable, Prop
log_info(cds)("optimized module handling: disabled due to incompatible property: %s=%s", key, value);
}
if (strcmp(key, "jdk.module.showModuleResolution") == 0 ||
strcmp(key, "jdk.module.illegalAccess") == 0 ||
strcmp(key, "jdk.module.validation") == 0 ||
strcmp(key, "java.system.class.loader") == 0) {
MetaspaceShared::disable_full_module_graph();
@@ -2131,7 +2132,8 @@ bool Arguments::parse_uintx(const char* value,
}
bool Arguments::create_module_property(const char* prop_name, const char* prop_value, PropertyInternal internal) {
assert(is_internal_module_property(prop_name), "unknown module property: '%s'", prop_name);
assert(is_internal_module_property(prop_name) ||
strcmp(prop_name, "jdk.module.illegalAccess") == 0, "unknown module property: '%s'", prop_name);
size_t prop_len = strlen(prop_name) + strlen(prop_value) + 2;
char* property = AllocateHeap(prop_len, mtArguments);
int ret = jio_snprintf(property, prop_len, "%s=%s", prop_name, prop_value);
@@ -2503,6 +2505,11 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m
char version[256];
JDK_Version::jdk(17).to_string(version, sizeof(version));
warning("Ignoring option %s; support was removed in %s", option->optionString, version);
} else if (match_option(option, "--jbr-illegal-access", &tail)) {
warning("Option --jbr-illegal-access is deprecated and will be removed in a future release.");
if (!create_module_property("jdk.module.illegalAccess", "permit", ExternalProperty)) {
return JNI_ENOMEM;
}
// -agentlib and -agentpath
} else if (match_option(option, "-agentlib:", &tail) ||
(is_absolute_path = match_option(option, "-agentpath:", &tail))) {
@@ -4027,9 +4034,9 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) {
// Set object alignment values.
set_object_alignment();
#ifndef ZERO
#if INCLUDE_JFR
if (FlightRecorder) {
if (AllowEnhancedClassRedefinition) {
if (AllowEnhancedClassRedefinition || StartFlightRecording != NULL) {
warning("EnhancedClassRedefinition was disabled, it is not allowed in FlightRecorder.");
AllowEnhancedClassRedefinition = false;
}

View File

@@ -16,6 +16,8 @@
package com.jetbrains.internal;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -103,9 +105,10 @@ public class JBRApi {
JBRApi.outerLookup = outerLookup;
try {
Class<?> metadataClass = outerLookup.findClass("com.jetbrains.JBR$Metadata");
knownServices = Set.of((String[]) outerLookup.findStaticVarHandle(metadataClass,
Lookup lookup = MethodHandles.privateLookupIn(metadataClass, outerLookup);
knownServices = Set.of((String[]) lookup.findStaticVarHandle(metadataClass,
"KNOWN_SERVICES", String[].class).get());
knownProxies = Set.of((String[]) outerLookup.findStaticVarHandle(metadataClass,
knownProxies = Set.of((String[]) lookup.findStaticVarHandle(metadataClass,
"KNOWN_PROXIES", String[].class).get());
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
@@ -156,13 +159,52 @@ public class JBRApi {
RegisteredProxyInfo info = registeredProxyInfoByTargetName.get(targetName);
if (info == null) return null;
try {
return (info.type() == ProxyInfo.Type.CLIENT_PROXY ? info.apiModule() : outerLookup)
return (info.type().isPublicApi() ? outerLookup : info.apiModule())
.findClass(info.interfaceName());
} catch (ClassNotFoundException | IllegalAccessException e) {
return null;
}
}
public static InternalServiceBuilder internalServiceBuilder(Lookup interFace, String target) {
return new InternalServiceBuilder(new RegisteredProxyInfo(
interFace, interFace.lookupClass().getName(), target, ProxyInfo.Type.INTERNAL_SERVICE, new ArrayList<>()));
}
public static class InternalServiceBuilder {
private final RegisteredProxyInfo info;
private InternalServiceBuilder(RegisteredProxyInfo info) {
this.info = info;
}
public InternalServiceBuilder withStatic(String methodName, String clazz) {
return withStatic(methodName, clazz, methodName);
}
public InternalServiceBuilder withStatic(String interfaceMethodName, String clazz, String methodName) {
info.staticMethods().add(
new RegisteredProxyInfo.StaticMethodMapping(interfaceMethodName, clazz, methodName));
return this;
}
public Object build() {
ProxyInfo info = ProxyInfo.resolve(this.info);
if (info == null) return null;
ProxyGenerator generator = new ProxyGenerator(info);
if (!generator.areAllMethodsImplemented()) return null;
generator.defineClasses();
MethodHandle constructor = generator.findConstructor();
generator.init();
try {
return constructor.invoke();
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
/**
* Called by {@linkplain com.jetbrains.bootstrap.JBRApiBootstrap#MODULES registry classes}
* to register a new mapping for corresponding modules.

View File

@@ -78,7 +78,7 @@ class ProxyGenerator {
*/
ProxyGenerator(ProxyInfo info) {
this.info = info;
generateBridge = info.type != ProxyInfo.Type.CLIENT_PROXY;
generateBridge = info.type.isPublicApi();
int nameId = nameCounter.getAndIncrement();
proxyName = Type.getInternalName(info.interFace) + "$$JBRApiProxy$" + nameId;
bridgeName = generateBridge ? info.apiModule.lookupClass().getPackageName().replace('.', '/') + "/" +
@@ -153,7 +153,7 @@ class ProxyGenerator {
} else {
MethodHandle c = generatedProxy.findConstructor(generatedProxy.lookupClass(),
MethodType.methodType(void.class, Object.class));
if (info.type == ProxyInfo.Type.SERVICE) {
if (info.type.isService()) {
try {
return MethodHandles.foldArguments(c, info.target.findConstructor(info.target.lookupClass(),
MethodType.methodType(void.class)).asType(MethodType.methodType(Object.class)));

View File

@@ -66,7 +66,7 @@ class ProxyInfo {
}
Lookup getInterfaceLookup() {
return type == Type.CLIENT_PROXY ? apiModule : JBRApi.outerLookup;
return type == Type.CLIENT_PROXY || type == Type.INTERNAL_SERVICE ? apiModule : JBRApi.outerLookup;
}
Lookup getTargetLookup() {
@@ -74,12 +74,18 @@ class ProxyInfo {
}
private Lookup lookup(Lookup lookup, String clazz) {
try {
return MethodHandles.privateLookupIn(lookup.findClass(clazz), lookup);
} catch (ClassNotFoundException | IllegalAccessException e) {
if (lookup == JBRApi.outerLookup) return null;
else throw new RuntimeException(e);
String[] nestedClasses = clazz.split("\\$");
clazz = "";
for (int i = 0; i < nestedClasses.length; i++) {
try {
if (i != 0) clazz += "$";
clazz += nestedClasses[i];
lookup = MethodHandles.privateLookupIn(lookup.findClass(clazz), lookup);
} catch (ClassNotFoundException | IllegalAccessException ignore) {
return null;
}
}
return lookup;
}
record StaticMethodMapping(Lookup lookup, String methodName) {}
@@ -90,6 +96,15 @@ class ProxyInfo {
enum Type {
PROXY,
SERVICE,
CLIENT_PROXY
CLIENT_PROXY,
INTERNAL_SERVICE;
public boolean isPublicApi() {
return this == PROXY || this == SERVICE;
}
public boolean isService() {
return this == SERVICE || this == INTERNAL_SERVICE;
}
}
}

View File

@@ -68,4 +68,14 @@ class ExplodedSystemModules implements SystemModules {
public Map<String, Set<String>> moduleReads() {
throw new InternalError();
}
@Override
public Map<String, Set<String>> concealedPackagesToOpen() {
return Map.of();
}
@Override
public Map<String, Set<String>> exportedPackagesToOpen() {
return Map.of();
}
}

View File

@@ -0,0 +1,130 @@
/*
* Copyright (c) 2017, 2019, 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 jdk.internal.module;
import sun.nio.cs.UTF_8;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Generates the maps of concealed and exported packages to open at run-time.
*
* This is used at run-time for exploded builds, and at link-time to generate
* the maps for the system modules in the run-time image.
*/
public class IllegalAccessMaps {
private final Map<String, Set<String>> concealedPackagesToOpen;
private final Map<String, Set<String>> exportedPackagesToOpen;
private IllegalAccessMaps(Map<String, Set<String>> map1,
Map<String, Set<String>> map2) {
this.concealedPackagesToOpen = map1;
this.exportedPackagesToOpen = map2;
}
/**
* Returns the map of concealed packages to open. The map key is the
* module name, the value is the set of concealed packages to open.
*/
public Map<String, Set<String>> concealedPackagesToOpen() {
return concealedPackagesToOpen;
}
/**
* Returns the map of exported packages to open. The map key is the
* module name, the value is the set of exported packages to open.
*/
public Map<String, Set<String>> exportedPackagesToOpen() {
return exportedPackagesToOpen;
}
/**
* Generate the maps of module to concealed and exported packages for
* the system modules that are observable with the given module finder.
*/
public static IllegalAccessMaps generate(ModuleFinder finder) {
Map<String, ModuleDescriptor> map = new HashMap<>();
finder.findAll().stream()
.map(ModuleReference::descriptor)
.forEach(md -> md.packages().forEach(pn -> map.putIfAbsent(pn, md)));
Map<String, Set<String>> concealedPackagesToOpen = new HashMap<>();
Map<String, Set<String>> exportedPackagesToOpen = new HashMap<>();
String rn = "jdk8_packages.dat";
InputStream in = IllegalAccessMaps.class.getResourceAsStream(rn);
if (in == null) {
throw new InternalError(rn + " not found");
}
try (BufferedReader br = new BufferedReader(
new InputStreamReader(in, UTF_8.INSTANCE)))
{
br.lines()
.filter(line -> !line.isEmpty() && !line.startsWith("#"))
.forEach(pn -> {
ModuleDescriptor descriptor = map.get(pn);
if (descriptor != null && !isOpen(descriptor, pn)) {
String name = descriptor.name();
if (isExported(descriptor, pn)) {
exportedPackagesToOpen.computeIfAbsent(name,
k -> new HashSet<>()).add(pn);
} else {
concealedPackagesToOpen.computeIfAbsent(name,
k -> new HashSet<>()).add(pn);
}
}
});
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
}
return new IllegalAccessMaps(concealedPackagesToOpen, exportedPackagesToOpen);
}
private static boolean isExported(ModuleDescriptor descriptor, String pn) {
return descriptor.exports()
.stream()
.anyMatch(e -> e.source().equals(pn) && !e.isQualified());
}
private static boolean isOpen(ModuleDescriptor descriptor, String pn) {
return descriptor.opens()
.stream()
.anyMatch(e -> e.source().equals(pn) && !e.isQualified());
}
}

View File

@@ -147,7 +147,8 @@ public final class ModuleBootstrap {
getProperty("jdk.module.limitmods") == null && // --limit-modules
getProperty("jdk.module.addreads.0") == null && // --add-reads
getProperty("jdk.module.addexports.0") == null && // --add-exports
getProperty("jdk.module.addopens.0") == null; // --add-opens
getProperty("jdk.module.addopens.0") == null && // --add-opens
getProperty("jdk.module.illegalAccess") == null; // --jbr-illegal-access
}
/**
@@ -188,6 +189,7 @@ public final class ModuleBootstrap {
String mainModule = System.getProperty("jdk.module.main");
Set<String> addModules = addModules();
Set<String> limitModules = limitModules();
String illegalAccess = getAndRemoveProperty("jdk.module.illegalAccess");
PrintStream traceOutput = null;
String trace = getAndRemoveProperty("jdk.module.showModuleResolution");
@@ -219,7 +221,8 @@ public final class ModuleBootstrap {
&& !haveModulePath
&& addModules.isEmpty()
&& limitModules.isEmpty()
&& !isPatched) {
&& !isPatched
&& illegalAccess == null) {
systemModuleFinder = archivedModuleGraph.finder();
hasSplitPackages = archivedModuleGraph.hasSplitPackages();
hasIncubatorModules = archivedModuleGraph.hasIncubatorModules();
@@ -454,10 +457,19 @@ public final class ModuleBootstrap {
checkIncubatingStatus(cf);
}
// --add-reads, --add-exports/--add-opens
// --add-reads, --add-exports/--add-opens, and --jbr-illegal-access
addExtraReads(bootLayer);
boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer);
if (illegalAccess != null) {
assert systemModules != null;
addIllegalAccess(illegalAccess,
systemModules,
upgradeModulePath,
bootLayer,
extraExportsOrOpens);
}
// add enable native access
addEnableNativeAccess(bootLayer);
@@ -813,6 +825,74 @@ public final class ModuleBootstrap {
return modules;
}
/**
* Process the --jbr-illegal-access option to open packages of system modules
* in the boot layer to code in unnamed modules.
*/
private static void addIllegalAccess(String illegalAccess,
SystemModules systemModules,
ModuleFinder upgradeModulePath,
ModuleLayer bootLayer,
boolean extraExportsOrOpens) {
Map<String, Set<String>> concealedPackagesToOpen = systemModules.concealedPackagesToOpen();
Map<String, Set<String>> exportedPackagesToOpen = systemModules.exportedPackagesToOpen();
if (concealedPackagesToOpen.isEmpty() && exportedPackagesToOpen.isEmpty()) {
// need to generate (exploded build)
IllegalAccessMaps maps = IllegalAccessMaps.generate(limitedFinder());
concealedPackagesToOpen = maps.concealedPackagesToOpen();
exportedPackagesToOpen = maps.exportedPackagesToOpen();
}
// open specific packages in the system modules
Set<String> emptySet = Set.of();
for (Module m : bootLayer.modules()) {
ModuleDescriptor descriptor = m.getDescriptor();
String name = m.getName();
// skip open modules
if (descriptor.isOpen()) {
continue;
}
// skip modules loaded from the upgrade module path
if (upgradeModulePath != null
&& upgradeModulePath.find(name).isPresent()) {
continue;
}
Set<String> concealedPackages = concealedPackagesToOpen.getOrDefault(name, emptySet);
Set<String> exportedPackages = exportedPackagesToOpen.getOrDefault(name, emptySet);
// refresh the set of concealed and exported packages if needed
if (extraExportsOrOpens) {
concealedPackages = new HashSet<>(concealedPackages);
exportedPackages = new HashSet<>(exportedPackages);
Iterator<String> iterator = concealedPackages.iterator();
while (iterator.hasNext()) {
String pn = iterator.next();
if (m.isExported(pn, BootLoader.getUnnamedModule())) {
// concealed package is exported to ALL-UNNAMED
iterator.remove();
exportedPackages.add(pn);
}
}
iterator = exportedPackages.iterator();
while (iterator.hasNext()) {
String pn = iterator.next();
if (m.isOpen(pn, BootLoader.getUnnamedModule())) {
// exported package is opened to ALL-UNNAMED
iterator.remove();
}
}
}
// open the packages to unnamed modules
JLA.addOpensToAllUnnamed(m, concealedPackages, exportedPackages);
}
}
/**
* Decodes the values of --add-reads, -add-exports, --add-opens or
* --patch-modules options that are encoded in system properties.

View File

@@ -83,4 +83,16 @@ interface SystemModules {
* by this SystemModules object.
*/
Map<String, Set<String>> moduleReads();
/**
* Returns the map of module concealed packages to open. The map key is the
* module name, the value is the set of concealed packages to open.
*/
Map<String, Set<String>> concealedPackagesToOpen();
/**
* Returns the map of module exported packages to open. The map key is the
* module name, the value is the set of exported packages to open.
*/
Map<String, Set<String>> exportedPackagesToOpen();
}

File diff suppressed because it is too large Load Diff

View File

@@ -188,6 +188,10 @@ java.launcher.X.usage=\n\
\ --add-opens <module>/<package>=<target-module>(,<target-module>)*\n\
\ updates <module> to open <package> to\n\
\ <target-module>, regardless of module declaration.\n\
\ --jbr-illegal-access\n\
\ permit access to members of types in named modules\n\
\ by code in unnamed modules.\n\
\ This option will be removed in a future release.\n\
\ --limit-modules <module name>[,<module name>...]\n\
\ limit the universe of observable modules\n\
\ --patch-module <module>=<file>({0}<file>)*\n\

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 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
@@ -47,7 +47,6 @@ import java.util.regex.Pattern;
import jdk.internal.access.JavaIOFileDescriptorAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.ref.CleanerFactory;
import sun.security.action.GetBooleanAction;
import sun.security.action.GetPropertyAction;
/* This class is for the exclusive use of ProcessBuilder.start() to
@@ -269,11 +268,22 @@ final class ProcessImpl extends Process {
// command line parser. The case of the [""] tail escape
// sequence could not be realized due to the argument validation
// procedure.
int count = countLeadingBackslash(verificationType, s, s.length());
while (count-- > 0) {
cmdbuf.append(BACKSLASH); // double the number of backslashes
if (verificationType == VERIFICATION_WIN32_SAFE ||
verificationType == VERIFICATION_LEGACY) {
int count = countLeadingBackslash(verificationType, s, s.length());
while (count-- > 0) {
cmdbuf.append(BACKSLASH); // double the number of backslashes
}
}
cmdbuf.append('"');
} else if (verificationType == VERIFICATION_WIN32_SAFE &&
(s.startsWith("\"") && s.endsWith("\"") && s.length() > 2)) {
// Check that quoted argument does not escape the final quote
cmdbuf.append(s);
int count = countLeadingBackslash(verificationType, s, s.length() - 1);
while (count-- > 0) {
cmdbuf.insert(cmdbuf.length() - 1, BACKSLASH); // double the number of backslashes
}
} else {
cmdbuf.append(s);
}
@@ -282,9 +292,7 @@ final class ProcessImpl extends Process {
}
/**
* Return the argument without quotes (1st and last) if properly quoted, else the arg.
* A properly quoted string has first and last characters as quote and
* the last quote is not escaped.
* Return the argument without quotes (first and last) if quoted, otherwise the arg.
* @param str a string
* @return the string without quotes
*/
@@ -292,9 +300,6 @@ final class ProcessImpl extends Process {
if (!str.startsWith("\"") || !str.endsWith("\"") || str.length() < 2)
return str; // no beginning or ending quote, or too short not quoted
if (str.endsWith("\\\"")) {
return str; // not properly quoted, treat as unquoted
}
// Strip leading and trailing quotes
return str.substring(1, str.length() - 1);
}

View File

@@ -41,12 +41,14 @@ import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.MacOSFlags;
import sun.java2d.metal.MTLGraphicsConfig;
import sun.java2d.opengl.CGLGraphicsConfig;
import sun.util.logging.PlatformLogger;
import static java.awt.peer.ComponentPeer.SET_BOUNDS;
public final class CGraphicsDevice extends GraphicsDevice
implements DisplayChangedListener {
private static final PlatformLogger logger = PlatformLogger.getLogger(CGraphicsDevice.class.getName());
/**
* CoreGraphics display ID. This identifier can become non-valid at any time
* therefore methods, which is using this id should be ready to it.
@@ -381,6 +383,7 @@ public final class CGraphicsDevice extends GraphicsDevice
}
private void initScaleFactor() {
int _scale = scale;
if (SunGraphicsEnvironment.isUIScaleEnabled()) {
double debugScale = SunGraphicsEnvironment.getDebugScale();
scale = (int) (debugScale >= 1
@@ -389,6 +392,9 @@ public final class CGraphicsDevice extends GraphicsDevice
} else {
scale = 1;
}
if (_scale != scale && logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("current scale = " + _scale + ", new scale = " + scale + " (" + this + ")");
}
}
private static native double nativeGetScaleFactor(int displayID);

View File

@@ -128,8 +128,12 @@ public class CCharToGlyphMapper extends CharToGlyphMapper {
};
}
// Missing characters for any font on the system will be returned as 0,
// as the getMissingGlyphCode() function above indicates.
// This mapper returns either the glyph code, or if the character can be
// replaced on-the-fly using CoreText substitution; the negative unicode
// value. If this "glyph code int" is treated as an opaque code, it will
// strike and measure exactly as a real glyph code - whether the character
// is present or not. Missing characters for any font on the system will
// be returned as 0, as the getMissingGlyphCode() function above indicates.
private static native void nativeCharsToGlyphs(final long nativeFontPtr,
int count, char[] unicodes,
int[] glyphs);

View File

@@ -0,0 +1,81 @@
/*
* Copyright 2000-2018 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sun.font;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;
public final class CCompositeFont extends CompositeFont {
private final List<CFont> fallbackFonts = new ArrayList<>();
public CCompositeFont(CFont font) {
super(new PhysicalFont[]{font});
mapper = new CCompositeGlyphMapper(this);
}
@Override
public synchronized int getNumSlots() {
return super.getNumSlots();
}
@Override
public CFont getSlotFont(int slot) {
if (slot == 0) return (CFont) super.getSlotFont(0);
synchronized (this) {
return fallbackFonts.get(slot - 1);
}
}
@Override
synchronized FontStrike getStrike(FontStrikeDesc desc, boolean copy) {
return super.getStrike(desc, copy);
}
@Override
protected synchronized int getValidatedGlyphCode(int glyphCode) {
return super.getValidatedGlyphCode(glyphCode);
}
@Override
public boolean hasSupplementaryChars() {
return false;
}
@Override
public boolean useAAForPtSize(int ptsize) {
return true;
}
public synchronized int findSlot(String fontName) {
for (int slot = 0; slot < numSlots; slot++) {
CFont slotFont = getSlotFont(slot);
if (fontName.equals(slotFont.getNativeFontName())) {
return slot;
}
}
return -1;
}
public synchronized int addSlot(CFont font) {
int slot = findSlot(font.getNativeFontName());
if (slot >= 0) return slot;
fallbackFonts.add(font);
lastFontStrike = new SoftReference<>(null);
strikeCache.clear();
return numSlots++;
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2015, 2018, 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.font;
import java.awt.*;
public final class CCompositeGlyphMapper extends CompositeGlyphMapper {
public CCompositeGlyphMapper(CCompositeFont compFont) {
super(compFont);
}
@Override
protected int convertToGlyph(int unicode) {
CCompositeFont compositeFont = (CCompositeFont) font;
CFont mainFont = (CFont) font.getSlotFont(0);
String[] fallbackFontInfo = new String[2];
int glyphCode = nativeCodePointToGlyph(mainFont.getNativeFontPtr(), unicode, fallbackFontInfo);
if (glyphCode == missingGlyph) {
setCachedGlyphCode(unicode, missingGlyph);
return missingGlyph;
}
String fallbackFontName = fallbackFontInfo[0];
String fallbackFontFamilyName = fallbackFontInfo[1];
if (fallbackFontName == null || fallbackFontFamilyName == null) {
int result = compositeGlyphCode(0, glyphCode);
setCachedGlyphCode(unicode, result);
return result;
}
int slot = compositeFont.findSlot(fallbackFontName);
if (slot < 0) {
Font2D fallbackFont = FontManagerFactory.getInstance().findFont2D(fallbackFontName,
Font.PLAIN, FontManager.NO_FALLBACK);
if (!(fallbackFont instanceof CFont) ||
!fallbackFontName.equals(((CFont) fallbackFont).getNativeFontName())) {
// Native font fallback mechanism can return "hidden" fonts - their names start with dot,
// and they are not returned in a list of fonts available in system, but they can still be used
// if requested explicitly.
fallbackFont = new CFont(fallbackFontName, fallbackFontFamilyName, null);
}
if (mainFont.isFakeItalic()) fallbackFont = ((CFont)fallbackFont).createItalicVariant(false);
slot = compositeFont.addSlot((CFont) fallbackFont);
}
int result = compositeGlyphCode(slot, glyphCode);
setCachedGlyphCode(unicode, result);
return result;
}
// This invokes native font fallback mechanism, returning information about font (its Postscript and family names)
// able to display a given character, and corresponding glyph code
private static native int nativeCodePointToGlyph(long nativeFontPtr, int codePoint, String[] result);
}

View File

@@ -31,9 +31,6 @@ import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Set;
// Right now this class is final to avoid a problem with native code.
// For some reason the JNI IsInstanceOf was not working correctly
@@ -178,12 +175,14 @@ public final class CFont extends PhysicalFont implements FontSubstitution, FontW
isFakeItalic = other.isFakeItalic;
}
public CFont createItalicVariant() {
public CFont createItalicVariant(boolean updateStyle) {
CFont font = new CFont(this, familyName);
font.nativeFontName = fullName;
font.fullName =
fullName + (style == Font.BOLD ? "" : "-") + "Italic-Derived";
font.style |= Font.ITALIC;
if (updateStyle) {
font.style |= Font.ITALIC;
}
font.isFakeItalic = true;
return font;
}
@@ -205,51 +204,11 @@ public final class CFont extends PhysicalFont implements FontSubstitution, FontW
return getCGFontPtrNative(getNativeFontPtr());
}
static native void getCascadeList(long nativeFontPtr, ArrayList<String> listOfString);
private CompositeFont createCompositeFont() {
ArrayList<String> listOfString = new ArrayList<String>();
getCascadeList(getNativeFontPtr(), listOfString);
Set<String> components = new LinkedHashSet<>(listOfString);
// In some italic cases the standard Mac cascade list is missing Arabic.
components.add("GeezaPro");
CFontManager fm = (CFontManager) FontManagerFactory.getInstance();
components.addAll(fm.getAdditionalFallbackVariants());
int numFonts = 1 + components.size();
PhysicalFont[] fonts = new PhysicalFont[numFonts];
fonts[0] = this;
int idx = 1;
if (FontUtilities.isLogging()) {
FontUtilities.logInfo("Cascading list for " + this + " :");
}
for (String s : components) {
if (FontUtilities.isLogging()) {
FontUtilities.logInfo("Fallback:" + s);
}
if (s.equals(".AppleSymbolsFB")) {
// Don't know why we get the weird name above .. replace.
s = "AppleSymbols";
}
Font2D f2d = fm.getOrCreateFallbackFont(s);
if (f2d == null || f2d == this) {
continue;
}
fonts[idx++] = (PhysicalFont)f2d;
}
if (idx < fonts.length) {
PhysicalFont[] orig = fonts;
fonts = new PhysicalFont[idx];
System.arraycopy(orig, 0, fonts, 0, idx);
}
return new CompositeFont(fonts);
}
private CompositeFont compFont;
public CompositeFont getCompositeFont2D() {
if (compFont == null) {
compFont = createCompositeFont();
compFont = new CCompositeFont(this);
}
return compFont;
}
@@ -277,6 +236,14 @@ public final class CFont extends PhysicalFont implements FontSubstitution, FontW
return new CStrike(this, desc);
}
boolean isFakeItalic() {
return isFakeItalic;
}
String getNativeFontName() {
return nativeFontName;
}
@Override
public String getTypographicSubfamilyName() {
return faceName == null ? super.getTypographicSubfamilyName() : faceName;
@@ -309,4 +276,8 @@ public final class CFont extends PhysicalFont implements FontSubstitution, FontW
", familyName: " + familyName + ", style: " + style +
" } aka: " + super.toString();
}
public Font2D createItalic() {
return this.createItalicVariant(true);
}
}

View File

@@ -30,27 +30,20 @@ import java.io.File;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import javax.swing.plaf.FontUIResource;
import sun.awt.FontConfiguration;
import sun.awt.HeadlessToolkit;
import sun.lwawt.macosx.*;
import sun.security.action.GetBooleanAction;
import sun.util.logging.PlatformLogger;
public final class CFontManager extends SunFontManager {
private static Hashtable<String, Font2D> genericFonts = new Hashtable<String, Font2D>();
private final Map<String, Font2D> fallbackFonts = new ConcurrentHashMap<>();
private final List<String> extFallbackVariants = new ArrayList<>();
@Override
protected FontConfiguration createFontConfiguration() {
@@ -237,7 +230,6 @@ public final class CFontManager extends SunFontManager {
public Object run() {
if (!loadedAllFonts) {
loadNativeFonts();
collectAdditionalFallbackVariants();
loadedAllFonts = true;
}
return null;
@@ -345,40 +337,4 @@ public final class CFontManager extends SunFontManager {
@Override
protected void populateFontFileNameMap(HashMap<String, String> fontToFileMap, HashMap<String, String> fontToFamilyNameMap,
HashMap<String, ArrayList<String>> familyToFontListMap, Locale locale) {}
@SuppressWarnings("removal")
private void collectAdditionalFallbackVariants() {
if (AccessController.doPrivileged(new GetBooleanAction("mac.ext.font.fallback"))) {
for (String fontName : genericFonts.keySet()) {
boolean accept = false;
if (fontName.equals("ArialUnicodeMS")) {
accept = true;
} else if (fontName.startsWith("NotoSans")) {
int pos = fontName.indexOf('-');
accept = pos == -1 || fontName.substring(pos + 1).equals("Regular");
}
if (accept) {
extFallbackVariants.add(fontName);
}
}
Collections.sort(extFallbackVariants); // ensure predictable order
}
}
List<String> getAdditionalFallbackVariants() {
return extFallbackVariants;
}
Font2D getOrCreateFallbackFont(String fontName) {
Font2D font2D = findFont2D(fontName, Font.PLAIN, FontManager.NO_FALLBACK);
if (font2D != null || fontName.startsWith(".")) {
return font2D;
} else {
// macOS doesn't list some system fonts in [NSFontManager availableFontFamilies] output,
// so they are not registered in font manager as part of 'loadNativeFonts'.
// These fonts are present in [NSFontManager availableFonts] output though,
// and can be accessed in the same way as other system fonts.
return fallbackFonts.computeIfAbsent(fontName, name -> new CFont(name, null, null));
}
}
}

View File

@@ -249,13 +249,6 @@ public final class CStrike extends PhysicalStrike {
}
}
int getSlot0GlyphImagePtrs(int[] glyphCodes, long[] images, int len) {
int ourGlyphs = 0;
while (ourGlyphs < len && (glyphCodes[ourGlyphs] & CompositeGlyphMapper.SLOTMASK) == 0) ourGlyphs++;
getGlyphImagePtrs(glyphCodes, images, ourGlyphs);
return ourGlyphs;
}
// called from the Sun2D renderer
void getGlyphImagePtrs(int[] glyphCodes, long[] images, int len) {
synchronized (glyphInfoCache) {
@@ -365,14 +358,18 @@ public final class CStrike extends PhysicalStrike {
}
}
// This class stores glyph pointers, and is indexed based on glyph codes.
// This class stores glyph pointers, and is indexed based on glyph codes,
// and negative unicode values. See the comments in
// CCharToGlyphMapper for more details on our glyph code strategy.
private static class GlyphInfoCache extends CStrikeDisposer {
private static final int FIRST_LAYER_SIZE = 256;
private static final int SECOND_LAYER_SIZE = 16384; // 16384 = 128x128
// rdar://problem/5204197
private final AtomicBoolean disposed = new AtomicBoolean(false);
private final long[] firstLayerCache;
private SparseBitShiftingTwoLayerArray secondLayerCache;
private HashMap<Integer, Long> generalCache;
GlyphInfoCache(final Font2D nativeFont, final FontStrikeDesc desc) {
@@ -381,9 +378,19 @@ public final class CStrike extends PhysicalStrike {
}
public synchronized long get(final int index) {
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
return firstLayerCache[index];
if (index < 0) {
if (-index < SECOND_LAYER_SIZE) {
// catch common unicodes
if (secondLayerCache == null) {
return 0L;
}
return secondLayerCache.get(-index);
}
} else {
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
return firstLayerCache[index];
}
}
if (generalCache == null) {
@@ -397,10 +404,21 @@ public final class CStrike extends PhysicalStrike {
}
public synchronized void put(final int index, final long value) {
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
firstLayerCache[index] = value;
return;
if (index < 0) {
if (-index < SECOND_LAYER_SIZE) {
// catch common unicodes
if (secondLayerCache == null) {
secondLayerCache = new SparseBitShiftingTwoLayerArray(SECOND_LAYER_SIZE, 7); // 128x128
}
secondLayerCache.put(-index, value);
return;
}
} else {
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
firstLayerCache[index] = value;
return;
}
}
if (generalCache == null) {
@@ -423,6 +441,14 @@ public final class CStrike extends PhysicalStrike {
// clean out the first array
disposeLongArray(firstLayerCache);
// clean out the two layer arrays
if (secondLayerCache != null) {
final long[][] secondLayerLongArrayArray = secondLayerCache.cache;
for (final long[] longArray : secondLayerLongArrayArray) {
if (longArray != null) disposeLongArray(longArray);
}
}
// clean up everyone else
if (generalCache != null) {
for (Long aLong : generalCache.values()) {
@@ -459,18 +485,56 @@ public final class CStrike extends PhysicalStrike {
}
}
}
private static class SparseBitShiftingTwoLayerArray {
final long[][] cache;
final int shift;
final int secondLayerLength;
SparseBitShiftingTwoLayerArray(final int size, final int shift) {
this.shift = shift;
this.cache = new long[1 << shift][];
this.secondLayerLength = size >> shift;
}
public long get(final int index) {
final int firstIndex = index >> shift;
final long[] firstLayerRow = cache[firstIndex];
if (firstLayerRow == null) return 0L;
return firstLayerRow[index - (firstIndex * (1 << shift))];
}
public void put(final int index, final long value) {
final int firstIndex = index >> shift;
long[] firstLayerRow = cache[firstIndex];
if (firstLayerRow == null) {
cache[firstIndex] = firstLayerRow = new long[secondLayerLength];
}
firstLayerRow[index - (firstIndex * (1 << shift))] = value;
}
}
}
private static class GlyphAdvanceCache {
private static final int FIRST_LAYER_SIZE = 256;
private static final int SECOND_LAYER_SIZE = 16384; // 16384 = 128x128
private final float[] firstLayerCache = new float[FIRST_LAYER_SIZE];
private SparseBitShiftingTwoLayerArray secondLayerCache;
private HashMap<Integer, Float> generalCache;
public synchronized float get(final int index) {
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
return firstLayerCache[index];
if (index < 0) {
if (-index < SECOND_LAYER_SIZE) {
// catch common unicodes
if (secondLayerCache == null) return 0;
return secondLayerCache.get(-index);
}
} else {
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
return firstLayerCache[index];
}
}
if (generalCache == null) return 0;
@@ -480,10 +544,21 @@ public final class CStrike extends PhysicalStrike {
}
public synchronized void put(final int index, final float value) {
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
firstLayerCache[index] = value;
return;
if (index < 0) {
if (-index < SECOND_LAYER_SIZE) {
// catch common unicodes
if (secondLayerCache == null) {
secondLayerCache = new SparseBitShiftingTwoLayerArray(SECOND_LAYER_SIZE, 7); // 128x128
}
secondLayerCache.put(-index, value);
return;
}
} else {
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
firstLayerCache[index] = value;
return;
}
}
if (generalCache == null) {
@@ -492,5 +567,34 @@ public final class CStrike extends PhysicalStrike {
generalCache.put(Integer.valueOf(index), Float.valueOf(value));
}
private static class SparseBitShiftingTwoLayerArray {
final float[][] cache;
final int shift;
final int secondLayerLength;
SparseBitShiftingTwoLayerArray(final int size, final int shift) {
this.shift = shift;
this.cache = new float[1 << shift][];
this.secondLayerLength = size >> shift;
}
public float get(final int index) {
final int firstIndex = index >> shift;
final float[] firstLayerRow = cache[firstIndex];
if (firstLayerRow == null) return 0L;
return firstLayerRow[index - (firstIndex * (1 << shift))];
}
public void put(final int index, final float value) {
final int firstIndex = index >> shift;
float[] firstLayerRow = cache[firstIndex];
if (firstLayerRow == null) {
cache[firstIndex] = firstLayerRow =
new float[secondLayerLength];
}
firstLayerRow[index - (firstIndex * (1 << shift))] = value;
}
}
}
}

View File

@@ -29,10 +29,13 @@ import sun.java2d.NullSurfaceData;
import sun.java2d.SurfaceData;
import sun.lwawt.LWWindowPeer;
import sun.lwawt.macosx.CFLayer;
import sun.util.logging.PlatformLogger;
import java.awt.GraphicsConfiguration;
import java.awt.Insets;
public class MTLLayer extends CFLayer {
private static final PlatformLogger logger = PlatformLogger.getLogger(MTLLayer.class.getName());
private native long nativeCreateLayer();
private static native void nativeSetScale(long layerPtr, double scale);
@@ -49,6 +52,14 @@ public class MTLLayer extends CFLayer {
setPtr(nativeCreateLayer());
this.peer = peer;
MTLGraphicsConfig gc = (MTLGraphicsConfig)getGraphicsConfiguration();
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("device = " + (gc != null ? gc.getDevice() : "null"));
}
if (gc != null) {
setScale(gc.getDevice().getScaleFactor());
}
}
public SurfaceData replaceSurfaceData() {
@@ -99,6 +110,10 @@ public class MTLLayer extends CFLayer {
private void setScale(final int _scale) {
if (scale != _scale) {
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
MTLGraphicsConfig gc = (MTLGraphicsConfig)getGraphicsConfiguration();
logger.fine("current scale = " + scale + ", new scale = " + _scale + " (device = " + (gc != null ? gc.getDevice() : "null") + ")");
}
scale = _scale;
execute(ptr -> nativeSetScale(ptr, scale));
}

View File

@@ -31,8 +31,10 @@ import sun.java2d.NullSurfaceData;
import sun.lwawt.LWWindowPeer;
import sun.java2d.SurfaceData;
import sun.lwawt.macosx.CFLayer;
import sun.util.logging.PlatformLogger;
public class CGLLayer extends CFLayer {
private static final PlatformLogger logger = PlatformLogger.getLogger(CGLLayer.class.getName());
private native long nativeCreateLayer();
private static native void nativeSetScale(long layerPtr, double scale);
@@ -46,6 +48,14 @@ public class CGLLayer extends CFLayer {
setPtr(nativeCreateLayer());
this.peer = peer;
CGraphicsConfig gc = (CGraphicsConfig)getGraphicsConfiguration();
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("device = " + (gc != null ? gc.getDevice() : "null"));
}
if (gc != null) {
setScale(gc.getDevice().getScaleFactor());
}
}
public SurfaceData replaceSurfaceData() {
@@ -94,8 +104,12 @@ public class CGLLayer extends CFLayer {
super.dispose();
}
private void setScale(final int _scale) {
private void setScale(int _scale) {
if (scale != _scale) {
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
CGraphicsConfig gc = (CGraphicsConfig)getGraphicsConfiguration();
logger.fine("current scale = " + scale + ", new scale = " + _scale + " (device = " + (gc != null ? gc.getDevice() : "null") + ")");
}
scale = _scale;
execute(ptr -> nativeSetScale(ptr, scale));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 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
@@ -59,6 +59,7 @@ import java.awt.peer.KeyboardFocusManagerPeer;
import java.awt.peer.WindowPeer;
import java.util.List;
import java.util.Objects;
import javax.swing.JComponent;
import sun.awt.AWTAccessor;
@@ -283,6 +284,16 @@ public class LWWindowPeer
super.disposeImpl();
}
@Override
public void setBackground(final Color c) {
Color oldBg = getBackground();
if (Objects.equals(oldBg, c)) {
return;
}
super.setBackground(c);
updateOpaque();
}
@Override
protected void setVisibleImpl(final boolean visible) {
if (!visible && warningWindow != null) {
@@ -291,10 +302,6 @@ public class LWWindowPeer
updateFocusableWindowState();
super.setVisibleImpl(visible);
// TODO: update graphicsConfig, see 4868278
if (visible) {
// Set correct background for a window before making it visible
platformWindow.setOpaque(!isTranslucent());
}
platformWindow.setVisible(visible);
}

View File

@@ -38,11 +38,10 @@ import java.beans.PropertyChangeListener;
import java.lang.annotation.Native;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.Arrays;
@@ -76,24 +75,18 @@ import sun.lwawt.LWWindowPeer;
@SuppressWarnings("removal")
class CAccessibility implements PropertyChangeListener {
private static Set<String> ignoredRoles;
private static final int INVOKE_TIMEOUT_SECONDS_DEFAULT = 1;
private static final int INVOKE_TIMEOUT_SECONDS;
static {
AtomicInteger invokeTimeoutSecondsRef = new AtomicInteger();
// Need to load the native library for this code.
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
System.loadLibrary("awt");
invokeTimeoutSecondsRef.set(
// (-1) for the infinite timeout
Integer.getInteger("sun.lwawt.macosx.CAccessibility.invokeTimeoutSeconds",
INVOKE_TIMEOUT_SECONDS_DEFAULT));
return null;
}
// (-1) for the infinite timeout
@SuppressWarnings("removal")
int value = java.security.AccessController.doPrivileged(
(PrivilegedAction<Integer>) () -> {
// Need to load the native library for this code.
System.loadLibrary("awt");
return Integer.getInteger("sun.lwawt.macosx.CAccessibility.invokeTimeoutSeconds", 1);
});
INVOKE_TIMEOUT_SECONDS = invokeTimeoutSecondsRef.get();
INVOKE_TIMEOUT_SECONDS = value;
}
static CAccessibility sAccessibility;

View File

@@ -205,8 +205,10 @@ class CAccessible extends CFRetainedResource implements Accessible {
} else if (oldValue != null &&
((AccessibleState) oldValue) == AccessibleState.VISIBLE) {
execute(ptr -> menuClosed(ptr));
execute(ptr -> unregisterFromCocoaAXSystem(ptr));
}
} else if (thisRole == AccessibleRole.MENU_ITEM) {
} else if (thisRole == AccessibleRole.MENU_ITEM ||
((parentRole == AccessibleRole.POPUP_MENU) && (thisRole == AccessibleRole.MENU))) {
if (newValue != null &&
((AccessibleState) newValue) == AccessibleState.FOCUSED) {
execute(ptr -> menuItemSelected(ptr));

View File

@@ -25,6 +25,7 @@
package sun.lwawt.macosx;
import sun.awt.AWTThreading;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
@@ -64,14 +65,14 @@ public class CMenu extends CMenuItem implements MenuPeer {
LWCToolkit.targetToPeer(getTarget().getParent());
if (parent instanceof CMenu) {
return parent.executeGet(this::nativeCreateSubMenu);
return AWTThreading.executeWaitToolkit(() -> parent.executeGet(this::nativeCreateSubMenu));
}
if (parent instanceof CMenuBar) {
MenuBar parentContainer = (MenuBar)getTarget().getParent();
boolean isHelpMenu = parentContainer.getHelpMenu() == getTarget();
int insertionLocation = ((CMenuBar)parent).getNextInsertionIndex();
return parent.executeGet(ptr -> nativeCreateMenu(ptr, isHelpMenu,
insertionLocation));
return AWTThreading.executeWaitToolkit(() -> parent.executeGet(ptr -> nativeCreateMenu(ptr, isHelpMenu,
insertionLocation)));
}
throw new InternalError("Parent must be CMenu or CMenuBar");
}
@@ -84,7 +85,7 @@ public class CMenu extends CMenuItem implements MenuPeer {
@Override
public final void delItem(final int index) {
execute(ptr -> nativeDeleteItem(ptr, index));
AWTThreading.executeWaitToolkit(() -> execute(ptr -> nativeDeleteItem(ptr, index)));
}
@Override

View File

@@ -33,6 +33,7 @@ import java.awt.event.KeyEvent;
import java.awt.peer.MenuItemPeer;
import java.util.concurrent.atomic.AtomicBoolean;
import sun.awt.AWTThreading;
import sun.awt.SunToolkit;
import sun.lwawt.LWToolkit;
@@ -61,7 +62,7 @@ public class CMenuItem extends CMenuComponent implements MenuItemPeer {
@Override
long createModel() {
CMenuComponent parent = (CMenuComponent)LWToolkit.targetToPeer(getTarget().getParent());
return parent.executeGet(ptr->nativeCreate(ptr, isSeparator()));
return AWTThreading.executeWaitToolkit(() -> parent.executeGet(ptr->nativeCreate(ptr, isSeparator())));
}
@SuppressWarnings("deprecation")
public void setLabel(String label, char keyChar, int keyCode, int modifiers) {

View File

@@ -66,6 +66,7 @@ import sun.awt.AWTAccessor.ComponentAccessor;
import sun.awt.AWTAccessor.WindowAccessor;
import sun.awt.AWTThreading;
import sun.java2d.SurfaceData;
import sun.lwawt.LWComponentPeer;
import sun.lwawt.LWLightweightFramePeer;
import sun.lwawt.LWToolkit;
import sun.lwawt.LWWindowPeer;
@@ -105,6 +106,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
private static native boolean nativeDelayShowing(long nsWindowPtr);
private static native void nativeRaiseLevel(long nsWindowPtr, boolean popup, boolean onlyIfParentIsActive);
private static native void nativeSetTransparentTitleBarHeight(long nsWindowPtr, float height);
private static native void nativeCallDeliverMoveResizeEvent(long nsWindowPtr);
// Loger to report issues happened during execution but that do not affect functionality
private static final PlatformLogger logger = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformWindow");
@@ -290,7 +292,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
new Property<CPlatformWindow>(WINDOW_TRANSPARENT_TITLE_BAR_HEIGHT) {
public void applyProperty(final CPlatformWindow c, final Object value) {
if (value != null && (value instanceof Float)) {
c.execute(ptr -> nativeSetTransparentTitleBarHeight(ptr, (float) value));
c.execute(ptr -> AWTThreading.executeWaitToolkit(wait -> nativeSetTransparentTitleBarHeight(ptr, (float) value)));
}
}
}
@@ -1195,6 +1197,10 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
responder.handleWindowFocusEvent(gained, oppositePeer);
}
public void doDeliverMoveResizeEvent() {
execute(ptr -> nativeCallDeliverMoveResizeEvent(ptr));
}
protected void deliverMoveResizeEvent(int x, int y, int width, int height,
boolean byUser) {
AtomicBoolean ref = new AtomicBoolean();
@@ -1456,28 +1462,20 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
isFullScreenAnimationOn = false;
}
// called from client via reflection
private void setTransparentTitleBarHeight(float height) {
execute(ptr -> {
nativeSetTransparentTitleBarHeight(ptr, height);
});
}
private volatile List<Rectangle> customDecorHitTestSpots;
// called from client via reflection
private void setCustomDecorationHitTestSpots(List<Rectangle> hitTestSpots) {
this.customDecorHitTestSpots = new CopyOnWriteArrayList<>(hitTestSpots);
}
// called from native
private boolean hitTestCustomDecoration(float x, float y) {
List<Rectangle> spots = customDecorHitTestSpots;
if (spots == null) return false;
for (Rectangle spot : spots) {
if (spot.contains(x, y)) return true;
// JBR API internals
private static void setCustomDecorationTitleBarHeight(Window target, ComponentPeer peer, float height) {
if (peer instanceof LWComponentPeer) {
PlatformWindow platformWindow = ((LWComponentPeer<?, ?>) peer).getPlatformWindow();
if (platformWindow instanceof CPlatformWindow) {
((CPlatformWindow) platformWindow).execute(ptr -> {
AWTThreading.executeWaitToolkit(wait -> nativeSetTransparentTitleBarHeight(ptr, height));
});
if (target instanceof javax.swing.RootPaneContainer) {
final javax.swing.JRootPane rootpane = ((javax.swing.RootPaneContainer)target).getRootPane();
if (rootpane != null) rootpane.putClientProperty(WINDOW_TRANSPARENT_TITLE_BAR_HEIGHT, height);
}
}
}
return false;
}
}

View File

@@ -89,6 +89,7 @@ import java.net.URL;
import java.security.*;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@@ -111,6 +112,7 @@ import sun.lwawt.PlatformComponent;
import sun.lwawt.PlatformDropTarget;
import sun.lwawt.PlatformWindow;
import sun.lwawt.SecurityWarningWindow;
import sun.security.action.GetBooleanAction;
import sun.util.logging.PlatformLogger;
@SuppressWarnings("serial") // JDK implementation class
@@ -140,6 +142,13 @@ public final class LWCToolkit extends LWToolkit {
private static CInputMethodDescriptor sInputMethodDescriptor;
// Listens to EDT state in invokeAndWait() and disposes the invocation event
// when EDT becomes free but the invocation event is not yet dispatched (considered lost).
// This prevents a deadlock and makes the invocation return some default result.
@SuppressWarnings("removal")
private static final boolean DISPOSE_INVOCATION_ON_EDT_FREE =
AccessController.doPrivileged(new GetBooleanAction("sun.lwawt.macosx.LWCToolkit.invokeAndWait.disposeOnEDTFree"));
static {
System.err.flush();
@@ -186,7 +195,7 @@ public final class LWCToolkit extends LWToolkit {
*/
private static final boolean inAWT;
private static final PlatformLogger log = PlatformLogger.getLogger("sun.lwawt.macosx.LWCToolkit");
private static final PlatformLogger log = PlatformLogger.getLogger(LWCToolkit.class.getName());
public LWCToolkit() {
final String extraButtons = "sun.awt.enableExtraMouseButtons";
@@ -495,7 +504,8 @@ public final class LWCToolkit extends LWToolkit {
if (!(gd instanceof CGraphicsDevice)) {
return AWTThreading.executeWaitToolkit(() -> super.getScreenInsets(gc));
}
return AWTThreading.executeWaitToolkit(() -> ((CGraphicsDevice)gd).getScreenInsets());
CGraphicsDevice cgd = (CGraphicsDevice) gd;
return cgd.getScreenInsets();
}
@Override
@@ -675,30 +685,12 @@ public final class LWCToolkit extends LWToolkit {
return invokeAndWait(callable, component, -1);
}
static <T> T invokeAndWait(final Callable<T> callable, Component component, int timeoutSeconds) throws Exception {
public static <T> T invokeAndWait(final Callable<T> callable, Component component, int timeoutSeconds) throws Exception {
final CallableWrapper<T> wrapper = new CallableWrapper<>(callable);
invokeAndWait(wrapper, component, false, timeoutSeconds);
return wrapper.getResult();
}
static final class CancelableRunnable implements Runnable {
volatile Runnable runnable;
public CancelableRunnable(Runnable runnable) {
this.runnable = runnable;
}
@Override
public void run() {
Runnable r = runnable;
if (r != null) r.run();
}
public void cancel() {
runnable = null;
}
}
static final class CallableWrapper<T> implements Runnable {
final Callable<T> callable;
T object;
@@ -728,30 +720,6 @@ public final class LWCToolkit extends LWToolkit {
}
}
private static final AtomicInteger blockingRunLoopCounter = new AtomicInteger(0);
private static final AtomicBoolean priorityInvocationPending = new AtomicBoolean(false);
@Override
public void unsafeNonblockingExecute(Runnable runnable) {
if (!EventQueue.isDispatchThread()) {
throw new Error("the method must be called on the Event Dispatching thread");
}
if (runnable == null) return;
synchronized (priorityInvocationPending) {
priorityInvocationPending.set(true);
}
AWTAccessor.getEventQueueAccessor().createSecondaryLoop(
getSystemEventQueue(),
() -> blockingRunLoopCounter.get() > 0).enter();
try {
runnable.run();
} finally {
priorityInvocationPending.set(false);
}
}
/**
* Kicks an event over to the appropriate eventqueue and waits for it to
* finish To avoid deadlocking, we manually run the NSRunLoop while waiting
@@ -776,32 +744,32 @@ public final class LWCToolkit extends LWToolkit {
invokeAndWait(runnable, component, false, -1);
}
static void invokeAndWait(Runnable runnable, Component component, boolean processEvents, int timeoutSeconds)
public static void invokeAndWait(Runnable runnable, Component component, boolean processEvents, int timeoutSeconds)
throws InvocationTargetException
{
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("invokeAndWait started: " + runnable);
}
boolean nonBlockingRunLoop;
CancelableRunnable cancelableRunnable = new CancelableRunnable(runnable);
synchronized (priorityInvocationPending) {
nonBlockingRunLoop = priorityInvocationPending.get();
if (!nonBlockingRunLoop) blockingRunLoopCounter.incrementAndGet();
if (isBlockingEventDispatchThread()) {
String msg = "invokeAndWait is discarded as the EventDispatch thread is currently blocked";
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine(msg, new Throwable());
log.fine(AWTThreading.getInstance(component).printEventDispatchThreadStackTrace().toString());
} else if (log.isLoggable(PlatformLogger.Level.INFO)) {
StackTraceElement[] stack = new Throwable().getStackTrace();
log.info(msg + ". Originated at " + stack[stack.length - 1]);
Thread dispatchThread = AWTThreading.getInstance(component).getEventDispatchThread();
log.info(dispatchThread.getName() + " at: " + dispatchThread.getStackTrace()[0].toString());
}
return;
}
final long mediator = createAWTRunLoopMediator();
AWTThreading.TrackedInvocationEvent invocationEvent =
AWTThreading.createAndTrackInvocationEvent(component, runnable, true);
InvocationEvent invocationEvent =
AWTThreading.createAndTrackInvocationEvent(component,
cancelableRunnable,
() -> {
if (mediator != 0) {
stopAWTRunLoop(mediator);
}
},
true);
long mediator = createAWTRunLoopMediator();
invocationEvent.onDone(() -> stopAWTRunLoop(mediator));
if (component != null) {
AppContext appContext = SunToolkit.targetToAppContext(component);
@@ -815,11 +783,21 @@ public final class LWCToolkit extends LWToolkit {
((LWCToolkit)Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent);
}
if (!doAWTRunLoop(mediator, nonBlockingRunLoop, timeoutSeconds)) {
new Throwable("Invocation timed out (" + timeoutSeconds + "sec)").printStackTrace();
cancelableRunnable.cancel();
if (DISPOSE_INVOCATION_ON_EDT_FREE) {
CompletableFuture<Void> eventDispatchThreadFreeFuture =
AWTThreading.getInstance(component).onEventDispatchThreadFree(() -> {
if (!invocationEvent.isCompleted(true)) {
// EventQueue is now empty but the posted InvocationEvent is still not dispatched,
// consider it lost then.
invocationEvent.dispose("InvocationEvent was lost");
}
});
invocationEvent.onDone(() -> eventDispatchThreadFreeFuture.cancel(false));
}
if (!doAWTRunLoop(mediator, false, timeoutSeconds)) {
invocationEvent.dispose("InvocationEvent has timed out");
}
if (!nonBlockingRunLoop) blockingRunLoopCounter.decrementAndGet();
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("invokeAndWait finished: " + runnable);
@@ -828,6 +806,8 @@ public final class LWCToolkit extends LWToolkit {
checkException(invocationEvent);
}
private static native boolean isBlockingEventDispatchThread();
public static void invokeLater(Runnable event, Component component)
throws InvocationTargetException {
Objects.requireNonNull(component, "Null component provided to invokeLater");
@@ -870,6 +850,11 @@ public final class LWCToolkit extends LWToolkit {
*/
static native void performOnMainThreadAfterDelay(Runnable r, long delay);
/**
* Schedules a {@code Runnable} execution on the Appkit thread and waits for completion.
*/
public static native void performOnMainThreadAndWait(Runnable r);
// DnD support
@Override

View File

@@ -50,6 +50,10 @@
NSWindowTabbingMode javaWindowTabbingMode;
BOOL isEnterFullScreen;
CGFloat _transparentTitleBarHeight;
id<NSObject> _windowWillEnterFullScreenNotification;
id<NSObject> _windowWillExitFullScreenNotification;
id<NSObject> _windowDidExitFullScreenNotification;
NSMutableArray* _transparentTitleBarConstraints;
NSLayoutConstraint *_transparentTitleBarHeightConstraint;
NSMutableArray *_transparentTitleBarButtonCenterXConstraints;
}

View File

@@ -26,6 +26,7 @@
#include <objc/objc-runtime.h>
#import <Cocoa/Cocoa.h>
#include <java_awt_Window_CustomWindowDecoration.h>
#import "sun_lwawt_macosx_CPlatformWindow.h"
#import "com_apple_eawt_event_GestureHandler.h"
#import "com_apple_eawt_FullScreenHandler.h"
@@ -775,7 +776,7 @@ AWT_ASSERT_APPKIT_THREAD;
// NSWindowDelegate methods
- (void) _deliverMoveResizeEvent {
AWT_ASSERT_APPKIT_THREAD;
AWT_ASSERT_APPKIT_THREAD;
// deliver the event if this is a user-initiated live resize or as a side-effect
// of a Java initiated resize, because AppKit can override the bounds and force
@@ -784,10 +785,18 @@ AWT_ASSERT_APPKIT_THREAD;
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
if (platformWindow == NULL) {
// TODO: create generic AWT assert
NSLog(@"[AWTWindow _deliverMoveResizeEvent]: platformWindow == NULL");
return;
}
NSRect frame;
@try {
frame = ConvertNSScreenRect(env, [self.nsWindow frame]);
} @catch (NSException *e) {
NSLog(@"WARNING: suppressed exception from ConvertNSScreenRect() in [AWTWindow _deliverMoveResizeEvent]");
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
[NSApplicationAWT logException:e forProcess:processInfo];
return;
}
NSRect frame = ConvertNSScreenRect(env, [self.nsWindow frame]);
GET_CPLATFORM_WINDOW_CLASS();
DECLARE_METHOD(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIIIZ)V");
@@ -1009,7 +1018,7 @@ AWT_ASSERT_APPKIT_THREAD;
#ifdef DEBUG
NSLog(@"resigned key: %d %@ %@", [self.nsWindow isMainWindow], [self.nsWindow title], [self menuBarForWindow]);
#endif
if (![self.nsWindow isMainWindow]) {
if (![self.nsWindow isMainWindow] || [NSApp keyWindow] == self.nsWindow) {
[self deactivateWindow];
}
}
@@ -1038,7 +1047,9 @@ AWT_ASSERT_APPKIT_THREAD;
NSWindow *keyWindow = [NSApp keyWindow];
AWTWindow *opposite = nil;
if ([AWTWindow isAWTWindow: keyWindow]) {
opposite = (AWTWindow *)[keyWindow delegate];
if (keyWindow != self.nsWindow) {
opposite = (AWTWindow *)[keyWindow delegate];
}
[AWTWindow setLastKeyWindow: self];
} else {
[AWTWindow setLastKeyWindow: nil];
@@ -1294,10 +1305,10 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
NSView* titlebarContainer = titlebar.superview;
NSView* themeFrame = titlebarContainer.superview;
NSMutableArray* newConstraints = [[NSMutableArray alloc] init];
_transparentTitleBarConstraints = [[NSMutableArray alloc] init];
titlebarContainer.translatesAutoresizingMaskIntoConstraints = NO;
_transparentTitleBarHeightConstraint = [titlebarContainer.heightAnchor constraintEqualToConstant:_transparentTitleBarHeight];
[newConstraints addObjectsFromArray:@[
[_transparentTitleBarConstraints addObjectsFromArray:@[
[titlebarContainer.leftAnchor constraintEqualToAnchor:themeFrame.leftAnchor],
[titlebarContainer.widthAnchor constraintEqualToAnchor:themeFrame.widthAnchor],
[titlebarContainer.topAnchor constraintEqualToAnchor:themeFrame.topAnchor],
@@ -1310,7 +1321,7 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
for (NSView* view in @[titlebar, windowDragView])
{
view.translatesAutoresizingMaskIntoConstraints = NO;
[newConstraints addObjectsFromArray:@[
[_transparentTitleBarConstraints addObjectsFromArray:@[
[view.leftAnchor constraintEqualToAnchor:titlebarContainer.leftAnchor],
[view.rightAnchor constraintEqualToAnchor:titlebarContainer.rightAnchor],
[view.topAnchor constraintEqualToAnchor:titlebarContainer.topAnchor],
@@ -1326,7 +1337,7 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
button.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint* buttonCenterXConstraint = [button.centerXAnchor constraintEqualToAnchor:titlebarContainer.leftAnchor constant:(_transparentTitleBarHeight/2.0 + (index * horizontalButtonOffset))];
[_transparentTitleBarButtonCenterXConstraints addObject:buttonCenterXConstraint];
[newConstraints addObjectsFromArray:@[
[_transparentTitleBarConstraints addObjectsFromArray:@[
[button.widthAnchor constraintLessThanOrEqualToAnchor:titlebarContainer.heightAnchor multiplier:0.5],
// Those corrections are required to keep the icons perfectly round because macOS adds a constant 2 px in resulting height to their frame
[button.heightAnchor constraintEqualToAnchor: button.widthAnchor multiplier:14.0/12.0 constant:-2.0],
@@ -1335,7 +1346,7 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
]];
}];
[NSLayoutConstraint activateConstraints:newConstraints];
[NSLayoutConstraint activateConstraints:_transparentTitleBarConstraints];
}
- (void) updateTransparentTitleBarConstraints
@@ -1361,20 +1372,22 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
NSView* titlebarContainer = titlebar.superview;
NSView* themeFrame = titlebarContainer.superview;
[NSLayoutConstraint deactivateConstraints:_transparentTitleBarConstraints];
AWTWindowDragView* windowDragView;
for (NSView* view in titlebar.subviews) {
if ([view isMemberOfClass:[AWTWindowDragView class]]) {
windowDragView = view;
}
if (view.translatesAutoresizingMaskIntoConstraints == NO) {
[view removeConstraints:view.constraints];
view.translatesAutoresizingMaskIntoConstraints = YES;
}
}
[windowDragView removeFromSuperview];
[titlebarContainer removeConstraints:titlebarContainer.constraints];
titlebarContainer.translatesAutoresizingMaskIntoConstraints = YES;
titlebar.translatesAutoresizingMaskIntoConstraints = YES;
_transparentTitleBarConstraints = nil;
_transparentTitleBarHeightConstraint = nil;
_transparentTitleBarButtonCenterXConstraints = nil;
}
@@ -1403,23 +1416,44 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
});
NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
NSOperationQueue* mainQueue = [NSOperationQueue mainQueue];
[defaultCenter addObserverForName:NSWindowWillEnterFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
_windowWillEnterFullScreenNotification = [defaultCenter addObserverForName:NSWindowWillEnterFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
[self resetTitleBar];
}];
[defaultCenter addObserverForName:NSWindowWillExitFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
_windowWillExitFullScreenNotification = [defaultCenter addObserverForName:NSWindowWillExitFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
[self setWindowControlsHidden:YES];
}];
[defaultCenter addObserverForName:NSWindowDidExitFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
_windowDidExitFullScreenNotification = [defaultCenter addObserverForName:NSWindowDidExitFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
[self setUpTransparentTitleBar];
[self setWindowControlsHidden:NO];
}];
}
- (void) configureWindowAndListenersForDefaultTitleBar
{
dispatch_sync(dispatch_get_main_queue(), ^{
[self.nsWindow setTitlebarAppearsTransparent:NO];
[self.nsWindow setTitleVisibility:NSWindowTitleVisible];
[self.nsWindow setStyleMask:[self.nsWindow styleMask]&(~NSWindowStyleMaskFullSizeContentView)];
if (!self.isFullScreen) {
[self resetTitleBar];
}
});
NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
[defaultCenter removeObserver:_windowWillEnterFullScreenNotification];
[defaultCenter removeObserver:_windowWillExitFullScreenNotification];
[defaultCenter removeObserver:_windowDidExitFullScreenNotification];
_windowWillEnterFullScreenNotification = _windowWillExitFullScreenNotification = _windowDidExitFullScreenNotification = nil;
}
- (void) setTransparentTitleBarHeight: (CGFloat) transparentTitleBarHeight
{
if (_transparentTitleBarHeight == transparentTitleBarHeight) return;
if (_transparentTitleBarHeight != 0.0f) {
_transparentTitleBarHeight = transparentTitleBarHeight;
if (_transparentTitleBarHeightConstraint != nil || _transparentTitleBarButtonCenterXConstraints != nil) {
if (transparentTitleBarHeight == 0.0f) {
[self configureWindowAndListenersForDefaultTitleBar];
} else if (_transparentTitleBarHeightConstraint != nil || _transparentTitleBarButtonCenterXConstraints != nil) {
[self updateTransparentTitleBarConstraints];
}
} else {
@@ -1455,11 +1489,18 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
if (platformWindow != NULL) {
GET_CPLATFORM_WINDOW_CLASS_RETURN(YES);
DECLARE_METHOD_RETURN(jm_hitTestCustomDecoration, jc_CPlatformWindow, "hitTestCustomDecoration", "(FF)Z", YES);
NSRect frame = [self.window frame];
float windowHeight = frame.size.height;
returnValue = (*env)->CallBooleanMethod(env, platformWindow, jm_hitTestCustomDecoration, point.x, windowHeight - point.y) == JNI_TRUE ? NO : YES;
CHECK_EXCEPTION_IN_ENV(env);
DECLARE_FIELD_RETURN(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;", YES);
DECLARE_CLASS_RETURN(jc_Window, "java/awt/Window", YES);
DECLARE_METHOD_RETURN(jm_hitTestCustomDecoration, jc_Window, "hitTestCustomDecoration", "(II)I", YES);
jobject awtWindow = (*env)->GetObjectField(env, platformWindow, jf_target);
if (awtWindow != NULL) {
NSRect frame = [self.window frame];
float windowHeight = frame.size.height;
returnValue = (*env)->CallIntMethod(env, awtWindow, jm_hitTestCustomDecoration, (jint) point.x, (jint) (windowHeight - point.y)) ==
(jint) java_awt_Window_CustomWindowDecoration_NO_HIT_SPOT ? YES : NO;
CHECK_EXCEPTION();
(*env)->DeleteLocalRef(env, awtWindow);
}
(*env)->DeleteLocalRef(env, platformWindow);
}
return returnValue;
@@ -1612,7 +1653,15 @@ JNI_COCOA_ENTER(env);
// resets the NSWindow's style mask if the mask intersects any of those bits
if (mask & MASK(_STYLE_PROP_BITMASK)) {
[nsWindow setStyleMask:[AWTWindow styleMaskForStyleBits:newBits]];
NSWindowStyleMask styleMask = [AWTWindow styleMaskForStyleBits:newBits];
@try {
[nsWindow setStyleMask:styleMask];
} @catch (NSException *e) {
NSLog(@"WARNING: suppressed exception from [NSWindow setStyleMask] in CPlatformWindow"
".nativeSetNSWindowStyleBits");
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
[NSApplicationAWT logException:e forProcess:processInfo];
}
}
// calls methods on NSWindow to change other properties, based on the mask
@@ -2300,4 +2349,18 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetTransparen
[window setTransparentTitleBarHeight:((CGFloat) transparentTitleBarHeight)];
JNI_COCOA_EXIT(env);
}
}
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeCallDeliverMoveResizeEvent
(JNIEnv *env, jclass clazz, jlong windowPtr)
{
JNI_COCOA_ENTER(env);
NSWindow *nsWindow = (NSWindow *)jlong_to_ptr(windowPtr);
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
AWTWindow *window = (AWTWindow*)[nsWindow delegate];
[window _deliverMoveResizeEvent];
}];
JNI_COCOA_EXIT(env);
}

View File

@@ -237,7 +237,7 @@ static BOOL sNeedsEnter;
jobject transferer = [self dataTransferer:env];
jbyteArray data = nil;
if (transferer != NULL) {
if (transferer != NULL && fComponent != NULL) {
GET_DT_CLASS_RETURN(NULL);
DECLARE_METHOD_RETURN(convertDataMethod, DataTransfererClass, "convertData", "(Ljava/lang/Object;Ljava/awt/datatransfer/Transferable;JLjava/util/Map;Z)[B", NULL);
data = (*env)->CallObjectMethod(env, transferer, convertDataMethod, fComponent, fTransferable, format, fFormatMap, (jboolean) TRUE);

View File

@@ -69,6 +69,9 @@ static int* gsButtonEventNumber;
static NSTimeInterval gNextKeyEventTime;
static NSTimeInterval safeDelay;
#define KEY_CODE_COUNT 128
static CGEventFlags keyOwnFlags[KEY_CODE_COUNT];
static inline CGKeyCode GetCGKeyCode(jint javaKeyCode);
static void PostMouseEvent(const CGPoint point, CGMouseButton button,
@@ -107,6 +110,20 @@ static inline void autoDelay(BOOL isMove) {
gNextKeyEventTime = [[NSDate date] timeIntervalSinceReferenceDate] + safeDelay;
}
static void initKeyFlags() {
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStatePrivate);
for (CGKeyCode keyCode = 0; keyCode < KEY_CODE_COUNT; keyCode++) {
CGEventRef event = CGEventCreateKeyboardEvent(source, keyCode, true);
if (event != NULL) {
keyOwnFlags[keyCode] = CGEventGetFlags(event);
CFRelease(event);
}
}
if (source != NULL) {
CFRelease(source);
}
}
/*
* Class: sun_lwawt_macosx_CRobot
* Method: initRobot
@@ -155,6 +172,8 @@ Java_sun_lwawt_macosx_CRobot_initRobot
for (i = 0; i < gNumberOfButtons; ++i) {
gsButtonEventNumber[i] = ROBOT_EVENT_NUMBER_START;
}
initKeyFlags();
}];
}
}
@@ -283,6 +302,20 @@ Java_sun_lwawt_macosx_CRobot_mouseWheel
}];
}
// CGEventCreateKeyboardEvent incorrectly handles flags pertinent to non-modifier keys
// (e.g. F1-F12 keys always Fn flag set, while arrow keys always have Fn and NumPad flags set).
// Those flags are not cleared for following key presses automatically, so we need to do it ourselves.
// See JBR-4306 for details.
static void clearStickyFlags(CGEventRef event, CGKeyCode keyCode, CGEventFlags flagToCheck) {
if (keyCode < KEY_CODE_COUNT && (keyOwnFlags[keyCode] & flagToCheck) == 0) {
CGEventFlags flags = CGEventGetFlags(event);
CGEventFlags updatedFlags = flags & ~flagToCheck;
if (updatedFlags != flags) {
CGEventSetFlags(event, updatedFlags);
}
}
}
/*
* Class: sun_lwawt_macosx_CRobot
* Method: keyEvent
@@ -298,6 +331,10 @@ Java_sun_lwawt_macosx_CRobot_keyEvent
CGKeyCode keyCode = GetCGKeyCode(javaKeyCode);
CGEventRef event = CGEventCreateKeyboardEvent(source, keyCode, keyPressed);
if (event != NULL) {
// this assumes Robot isn't used to generate Fn key presses
clearStickyFlags(event, keyCode, kCGEventFlagMaskSecondaryFn);
// there is no NumPad key, so this won't hurt in any case
clearStickyFlags(event, keyCode, kCGEventFlagMaskNumericPad);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
}

View File

@@ -41,6 +41,51 @@ static const CGAffineTransform sInverseTX = { 1, 0, 0, -1, 0, 0 };
#pragma mark --- CoreText Support ---
// Translates a Unicode into a CGGlyph/CTFontRef pair
// Returns the substituted font, and places the appropriate glyph into "glyphRef"
CTFontRef JavaCT_CopyCTFallbackFontAndGlyphForUnicode
(const AWTFont *font, const UTF16Char *charRef, CGGlyph *glyphRef, int count) {
CTFontRef fallback = JRSFontCreateFallbackFontForCharacters((CTFontRef)font->fFont, charRef, count);
if (fallback == NULL)
{
// use the original font if we somehow got duped into trying to fallback something we can't
fallback = (CTFontRef)font->fFont;
CFRetain(fallback);
}
CTFontGetGlyphsForCharacters(fallback, charRef, glyphRef, count);
return fallback;
}
// Translates a Java glyph code int (might be a negative unicode value) into a CGGlyph/CTFontRef pair
// Returns the substituted font, and places the appropriate glyph into "glyph"
CTFontRef JavaCT_CopyCTFallbackFontAndGlyphForJavaGlyphCode
(const AWTFont *font, const jint glyphCode, CGGlyph *glyphRef)
{
// negative glyph codes are really unicodes, which were placed there by the mapper
// to indicate we should use CoreText to substitute the character
if (glyphCode >= 0)
{
*glyphRef = glyphCode;
CFRetain(font->fFont);
return (CTFontRef)font->fFont;
}
UTF16Char character = -glyphCode;
return JavaCT_CopyCTFallbackFontAndGlyphForUnicode(font, &character, glyphRef, 1);
}
// Breakup a 32 bit unicode value into the component surrogate pairs
void JavaCT_BreakupUnicodeIntoSurrogatePairs(int uniChar, UTF16Char charRef[]) {
int value = uniChar - 0x10000;
UTF16Char low_surrogate = (value & 0x3FF) | LO_SURROGATE_START;
UTF16Char high_surrogate = (((int)(value & 0xFFC00)) >> 10) | HI_SURROGATE_START;
charRef[0] = high_surrogate;
charRef[1] = low_surrogate;
}
/*
* Callback for CoreText which uses the CoreTextProviderStruct to feed CT UniChars
* We only use it for one-off lines, and don't attempt to fragment our strings
@@ -84,7 +129,7 @@ static NSDictionary* ctsDictionaryFor(const NSFont *font, BOOL useFractionalMetr
// Itterates though each glyph, and if a transform is present for that glyph, apply it to the CGContext, and strike the glyph.
// If there is no per-glyph transform, just strike the glyph. Advances must also be transformed on-the-spot as well.
void JavaCT_DrawGlyphVector
(const QuartzSDOps *qsdo, const AWTStrike *strike, const CGGlyph glyphs[], CGSize advances[], const jint g_gvTXIndicesAsInts[], const jdouble g_gvTransformsAsDoubles[], const CFIndex length)
(const QuartzSDOps *qsdo, const AWTStrike *strike, const BOOL useSubstituion, const int uniChars[], const CGGlyph glyphs[], CGSize advances[], const jint g_gvTXIndicesAsInts[], const jdouble g_gvTransformsAsDoubles[], const CFIndex length)
{
CGPoint pt = { 0, 0 };
@@ -92,12 +137,49 @@ void JavaCT_DrawGlyphVector
CGContextRef cgRef = qsdo->cgRef;
CGAffineTransform ctmText = CGContextGetTextMatrix(cgRef);
BOOL saved = false;
CGAffineTransform invTx = CGAffineTransformInvert(strike->fTx);
NSInteger i;
for (i = 0; i < length; i++)
{
CGGlyph glyph = glyphs[i];
int uniChar = uniChars[i];
// if we found a unichar instead of a glyph code, get the fallback font,
// find the glyph code for the fallback font, and set the font on the current context
if (uniChar != 0)
{
CTFontRef fallback;
if (uniChar > 0xFFFF) {
UTF16Char charRef[2];
JavaCT_BreakupUnicodeIntoSurrogatePairs(uniChar, charRef);
CGGlyph glyphTmp[2];
fallback = JavaCT_CopyCTFallbackFontAndGlyphForUnicode(strike->fAWTFont, (const UTF16Char *)&charRef, (CGGlyph *)&glyphTmp, 2);
glyph = glyphTmp[0];
} else {
const UTF16Char u = uniChar;
fallback = JavaCT_CopyCTFallbackFontAndGlyphForUnicode(strike->fAWTFont, &u, (CGGlyph *)&glyph, 1);
}
if (fallback) {
const CGFontRef cgFallback = CTFontCopyGraphicsFont(fallback, NULL);
CFRelease(fallback);
if (cgFallback) {
if (!saved) {
CGContextSaveGState(cgRef);
saved = true;
}
CGContextSetFont(cgRef, cgFallback);
CFRelease(cgFallback);
}
}
} else {
if (saved) {
CGContextRestoreGState(cgRef);
saved = false;
}
}
// if we have per-glyph transformations
int tin = (g_gvTXIndicesAsInts == NULL) ? -1 : (g_gvTXIndicesAsInts[i] - 1) * 6;
@@ -132,6 +214,10 @@ void JavaCT_DrawGlyphVector
pt.y += advances[i].height;
}
// reset the font on the context after striking a unicode with CoreText
if (saved) {
CGContextRestoreGState(cgRef);
}
}
// Using the Quartz Surface Data context, draw a hot-substituted character run
@@ -241,16 +327,24 @@ static jclass jc_StandardGlyphVector = NULL;
// Checks the GlyphVector Java object for any transforms that were applied to individual characters. If none are present,
// strike the glyphs immediately in Core Graphics. Otherwise, obtain the arrays, and defer to above.
static inline void doDrawGlyphsPipe_checkForPerGlyphTransforms
(JNIEnv *env, QuartzSDOps *qsdo, const AWTStrike *strike, jobject gVector, CGGlyph *glyphs, CGSize *advances, size_t length)
(JNIEnv *env, QuartzSDOps *qsdo, const AWTStrike *strike, jobject gVector, BOOL useSubstituion, int *uniChars, CGGlyph *glyphs, CGSize *advances, size_t length)
{
// if we have no per-glyph transformations - strike now!
// if we have no character substitution, and no per-glyph transformations - strike now!
GET_SGV_CLASS();
DECLARE_FIELD(jm_StandardGlyphVector_gti, jc_StandardGlyphVector, "gti", "Lsun/font/StandardGlyphVector$GlyphTransformInfo;");
jobject gti = (*env)->GetObjectField(env, gVector, jm_StandardGlyphVector_gti);
if (gti == 0)
{
// fast path, straight to CG without per-glyph transforms
CGContextShowGlyphsWithAdvances(qsdo->cgRef, glyphs, advances, length);
if (useSubstituion)
{
// quasi-simple case, substitution, but no per-glyph transforms
JavaCT_DrawGlyphVector(qsdo, strike, TRUE, uniChars, glyphs, advances, NULL, NULL, length);
}
else
{
// fast path, straight to CG without per-glyph transforms
CGContextShowGlyphsWithAdvances(qsdo->cgRef, glyphs, advances, length);
}
return;
}
@@ -275,8 +369,8 @@ static inline void doDrawGlyphsPipe_checkForPerGlyphTransforms
(*env)->DeleteLocalRef(env, g_gtiTXIndicesArray);
return;
}
// slowest case, we have per-glyph transforms
JavaCT_DrawGlyphVector(qsdo, strike, glyphs, advances, g_gvTXIndicesAsInts, g_gvTransformsAsDoubles, length);
// slowest case, we have per-glyph transforms, and possibly glyph substitution as well
JavaCT_DrawGlyphVector(qsdo, strike, useSubstituion, uniChars, glyphs, advances, g_gvTXIndicesAsInts, g_gvTransformsAsDoubles, length);
(*env)->ReleasePrimitiveArrayCritical(env, g_gtiTransformsArray, g_gvTransformsAsDoubles, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, g_gtiTXIndicesArray, g_gvTXIndicesAsInts, JNI_ABORT);
@@ -285,11 +379,35 @@ static inline void doDrawGlyphsPipe_checkForPerGlyphTransforms
(*env)->DeleteLocalRef(env, g_gtiTXIndicesArray);
}
// Retrieves advances for translated unicodes
// Uses "glyphs" as a temporary buffer for the glyph-to-unicode translation
void JavaCT_GetAdvancesForUnichars
(const NSFont *font, const int uniChars[], CGGlyph glyphs[], const size_t length, CGSize advances[])
{
// cycle over each spot, and if we discovered a unicode to substitute, we have to calculate the advance for it
size_t i;
for (i = 0; i < length; i++)
{
UniChar uniChar = uniChars[i];
if (uniChar == 0) continue;
CGGlyph glyph = 0;
const CTFontRef fallback = JRSFontCreateFallbackFontForCharacters((CTFontRef)font, &uniChar, 1);
if (fallback) {
CTFontGetGlyphsForCharacters(fallback, &uniChar, &glyph, 1);
CTFontGetAdvancesForGlyphs(fallback, kCTFontDefaultOrientation, &glyph, &(advances[i]), 1);
CFRelease(fallback);
}
glyphs[i] = glyph;
}
}
// Fills the glyph buffer with glyphs from the GlyphVector object. Also checks to see if the glyph's positions have been
// already caculated from GlyphVector, or we simply ask Core Graphics to make some advances for us. Pre-calculated positions
// are translated into advances, since CG only understands advances.
static inline void doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers
(JNIEnv *env, QuartzSDOps *qsdo, const AWTStrike *strike, jobject gVector, CGGlyph *glyphs, CGSize *advances, size_t length, jintArray glyphsArray)
(JNIEnv *env, QuartzSDOps *qsdo, const AWTStrike *strike, jobject gVector, CGGlyph *glyphs, int *uniChars, CGSize *advances, size_t length, jintArray glyphsArray)
{
// fill the glyph buffer
jint *glyphsAsInts = (*env)->GetPrimitiveArrayCritical(env, glyphsArray, NULL);
@@ -297,10 +415,24 @@ static inline void doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers
return;
}
// if a glyph code from Java is negative, that means it is really a unicode value
// which we can use in CoreText to strike the character in another font
size_t i;
BOOL complex = NO;
for (i = 0; i < length; i++)
{
glyphs[i] = glyphsAsInts[i];
jint code = glyphsAsInts[i];
if (code < 0)
{
complex = YES;
uniChars[i] = -code;
glyphs[i] = 0;
}
else
{
uniChars[i] = 0;
glyphs[i] = code;
}
}
(*env)->ReleasePrimitiveArrayCritical(env, glyphsArray, glyphsAsInts, JNI_ABORT);
@@ -351,10 +483,15 @@ static inline void doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers
// there were no pre-calculated positions from the glyph buffer on the Java side
AWTFont *awtFont = strike->fAWTFont;
CTFontGetAdvancesForGlyphs((CTFontRef)awtFont->fFont, kCTFontDefaultOrientation, glyphs, advances, length);
if (complex)
{
JavaCT_GetAdvancesForUnichars(awtFont->fFont, uniChars, glyphs, length, advances);
}
}
// continue on to the next stage of the pipe
doDrawGlyphsPipe_checkForPerGlyphTransforms(env, qsdo, strike, gVector, glyphs, advances, length);
doDrawGlyphsPipe_checkForPerGlyphTransforms(env, qsdo, strike, gVector, complex, uniChars, glyphs, advances, length);
}
// Obtains the glyph array to determine the number of glyphs we are dealing with. If we are dealing a large number of glyphs,
@@ -378,16 +515,18 @@ static inline void doDrawGlyphsPipe_getGlyphVectorLengthAndAlloc
{
// if we are small enough, fit everything onto the stack
CGGlyph glyphs[length];
int uniChars[length];
CGSize advances[length];
doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers(env, qsdo, strike, gVector, glyphs, advances, length, glyphsArray);
doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers(env, qsdo, strike, gVector, glyphs, uniChars, advances, length, glyphsArray);
}
else
{
// otherwise, we should malloc and free buffers for this large run
CGGlyph *glyphs = (CGGlyph *)malloc(sizeof(CGGlyph) * length);
int *uniChars = (int *)malloc(sizeof(int) * length);
CGSize *advances = (CGSize *)malloc(sizeof(CGSize) * length);
if (glyphs == NULL || advances == NULL)
if (glyphs == NULL || uniChars == NULL || advances == NULL)
{
(*env)->DeleteLocalRef(env, glyphsArray);
[NSException raise:NSMallocException format:@"%s-%s:%d", __FILE__, __FUNCTION__, __LINE__];
@@ -395,6 +534,10 @@ static inline void doDrawGlyphsPipe_getGlyphVectorLengthAndAlloc
{
free(glyphs);
}
if (uniChars)
{
free(uniChars);
}
if (advances)
{
free(advances);
@@ -402,9 +545,10 @@ static inline void doDrawGlyphsPipe_getGlyphVectorLengthAndAlloc
return;
}
doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers(env, qsdo, strike, gVector, glyphs, advances, length, glyphsArray);
doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers(env, qsdo, strike, gVector, glyphs, uniChars, advances, length, glyphsArray);
free(glyphs);
free(uniChars);
free(advances);
}

View File

@@ -620,6 +620,17 @@ JNI_COCOA_EXIT(env);
return result;
}
/*
* Class: sun_lwawt_macosx_LWCToolkit
* Method: isBlockingEventDispatchThread
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_isBlockingEventDispatchThread
(JNIEnv *env, jclass clz)
{
return ThreadUtilities.blockingEventDispatchThread;
}
/*
* Class: sun_lwawt_macosx_LWCToolkit
* Method: stopAWTRunLoop
@@ -632,6 +643,8 @@ JNI_COCOA_ENTER(env);
AWTRunLoopObject* mediatorObject = (AWTRunLoopObject*)jlong_to_ptr(mediator);
if (mediatorObject == nil) return;
[ThreadUtilities performOnMainThread:@selector(endRunLoop) on:mediatorObject withObject:nil waitUntilDone:NO];
[mediatorObject release];
@@ -657,6 +670,23 @@ JNI_COCOA_ENTER(env);
JNI_COCOA_EXIT(env);
}
/*
* Class: sun_lwawt_macosx_LWCToolkit
* Method: performOnMainThreadAndWait
* Signature: (Ljava/lang/Runnable)V
*/
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_performOnMainThreadAndWait
(JNIEnv *env, jclass clz, jobject runnable)
{
JNI_COCOA_ENTER(env);
jobject gRunnable = (*env)->NewGlobalRef(env, runnable);
CHECK_NULL(gRunnable);
[ThreadUtilities performOnMainThreadWaiting:YES block:^() {
JavaRunnable* performer = [[JavaRunnable alloc] initWithRunnable:gRunnable];
[performer perform];
}];
JNI_COCOA_EXIT(env);
}
/*
* Class: sun_lwawt_macosx_LWCToolkit

View File

@@ -126,7 +126,7 @@ static jobject sAccessibilityClass = NULL;
/*
* Here we should keep all the mapping between the accessibility roles and implementing classes
*/
rolesMap = [[NSMutableDictionary alloc] initWithCapacity:51];
rolesMap = [[NSMutableDictionary alloc] initWithCapacity:50];
[rolesMap setObject:@"ButtonAccessibility" forKey:@"pushbutton"];
[rolesMap setObject:@"ImageAccessibility" forKey:@"icon"];
@@ -158,7 +158,6 @@ static jobject sAccessibilityClass = NULL;
[rolesMap setObject:@"TableAccessibility" forKey:@"table"];
[rolesMap setObject:@"MenuBarAccessibility" forKey:@"menubar"];
[rolesMap setObject:@"MenuAccessibility" forKey:@"menu"];
[rolesMap setObject:@"MenuItemAccessibility" forKey:@"menuitem"];
[rolesMap setObject:@"MenuAccessibility" forKey:@"popupmenu"];
[rolesMap setObject:@"ProgressIndicatorAccessibility" forKey:@"progressbar"];
@@ -186,10 +185,11 @@ static jobject sAccessibilityClass = NULL;
[rolesMap setObject:IgnoreClassName forKey:@"viewport"];
[rolesMap setObject:IgnoreClassName forKey:@"window"];
rowRolesMapForParent = [[NSMutableDictionary alloc] initWithCapacity:2];
rowRolesMapForParent = [[NSMutableDictionary alloc] initWithCapacity:3];
[rowRolesMapForParent setObject:@"ListRowAccessibility" forKey:@"ListAccessibility"];
[rowRolesMapForParent setObject:@"OutlineRowAccessibility" forKey:@"OutlineAccessibility"];
[rowRolesMapForParent setObject:@"MenuItemAccessibility" forKey:@"MenuAccessibility"];
/*
* Initialize CAccessibility instance

View File

@@ -39,7 +39,7 @@
- (BOOL)isAccessibilityElement
{
return YES;
return [[[self accessibilityParent] accessibilityRole] isEqualToString:NSAccessibilityComboBoxRole];
}
@end

View File

@@ -1692,6 +1692,10 @@ static NSDictionary* prebuiltFamilyNames() {
@"SourceCodePro-BoldIt" : @"Source Code Pro",
@"SourceCodePro-It" : @"Source Code Pro",
@"SourceCodePro-Regular" : @"Source Code Pro",
@"Inter-Bold": @"Inter",
@"Inter-BoldItalic": @"Inter",
@"Inter-Italic": @"Inter",
@"Inter-Regular": @"Inter",
};
}
@@ -3342,64 +3346,6 @@ Java_sun_awt_FontDescriptor_initIDs
}
#endif
/*
* Class: sun_font_CFont
* Method: getCascadeList
* Signature: (JLjava/util/ArrayList;)V
*/
JNIEXPORT void JNICALL
Java_sun_font_CFont_getCascadeList
(JNIEnv *env, jclass cls, jlong awtFontPtr, jobject arrayListOfString)
{
JNI_COCOA_ENTER(env);
jclass alc = (*env)->FindClass(env, "java/util/ArrayList");
if (alc == NULL) return;
jmethodID addMID = (*env)->GetMethodID(env, alc, "add", "(Ljava/lang/Object;)Z");
if (addMID == NULL) return;
CFIndex i;
AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
NSFont* nsFont = awtFont->fFont;
#ifdef DEBUG
CFStringRef base = CTFontCopyFullName((CTFontRef)nsFont);
NSLog(@"BaseFont is : %@", (NSString*)base);
CFRelease(base);
#endif
bool anotherBaseFont = false;
if (awtFont->fFallbackBase != nil) {
nsFont = awtFont->fFallbackBase;
anotherBaseFont = true;
}
CTFontRef font = (CTFontRef)nsFont;
CFArrayRef codes = CFLocaleCopyISOLanguageCodes();
CFArrayRef fds = CTFontCopyDefaultCascadeListForLanguages(font, codes);
CFRelease(codes);
CFIndex cnt = CFArrayGetCount(fds);
for (i= anotherBaseFont ? -1 : 0; i<cnt; i++) {
CFStringRef fontname;
if (i < 0) {
fontname = CTFontCopyPostScriptName(font);
} else {
CTFontDescriptorRef ref = CFArrayGetValueAtIndex(fds, i);
fontname = CTFontDescriptorCopyAttribute(ref, kCTFontNameAttribute);
}
#ifdef DEBUG
NSLog(@"Font is : %@", (NSString*)fontname);
#endif
jstring jFontName = (jstring)NSStringToJavaString(env, fontname);
CFRelease(fontname);
(*env)->CallBooleanMethod(env, arrayListOfString, addMID, jFontName);
if ((*env)->ExceptionOccurred(env)) {
CFRelease(fds);
return;
}
(*env)->DeleteLocalRef(env, jFontName);
}
CFRelease(fds);
JNI_COCOA_EXIT(env);
}
static CFStringRef EMOJI_FONT_NAME = CFSTR("Apple Color Emoji");
bool IsEmojiFont(CTFontRef font)

View File

@@ -28,6 +28,7 @@
#import "sun_font_CStrikeDisposer.h"
#import "CGGlyphImages.h"
#import "CGGlyphOutlines.h"
#import "CoreTextSupport.h"
#import "JNIUtilities.h"
#include "fontscalerdefs.h"
#import "LWCToolkit.h"
@@ -159,8 +160,12 @@ JNI_COCOA_ENTER(env);
AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
AWTFont *awtFont = awtStrike->fAWTFont;
CGGlyph glyph = glyphCode;
CGGlyphImages_GetGlyphMetrics((CTFontRef)awtFont->fFont, &awtStrike->fAltTx, awtStrike->fSize, awtStrike->fStyle, &glyph, 1, NULL, &advance, IS_OSX_GT10_14);
// negative glyph codes are really unicodes, which were placed there by the mapper
// to indicate we should use CoreText to substitute the character
CGGlyph glyph;
const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph);
CGGlyphImages_GetGlyphMetrics(fallback, &awtStrike->fAltTx, awtStrike->fSize, awtStrike->fStyle, &glyph, 1, NULL, &advance, IS_OSX_GT10_14);
CFRelease(fallback);
advance = CGSizeApplyAffineTransform(advance, awtStrike->fFontTx);
if (!JRSFontStyleUsesFractionalMetrics(awtStrike->fStyle)) {
advance.width = round(advance.width);
@@ -190,9 +195,14 @@ JNI_COCOA_ENTER(env);
tx.tx += x;
tx.ty += y;
CGGlyph glyph = glyphCode;
// negative glyph codes are really unicodes, which were placed there by the mapper
// to indicate we should use CoreText to substitute the character
CGGlyph glyph;
const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph);
CGRect bbox;
CGGlyphImages_GetGlyphMetrics((CTFontRef)awtFont->fFont, &tx, awtStrike->fSize, awtStrike->fStyle, &glyph, 1, &bbox, NULL, IS_OSX_GT10_14);
CGGlyphImages_GetGlyphMetrics(fallback, &tx, awtStrike->fSize, awtStrike->fStyle, &glyph, 1, &bbox, NULL, IS_OSX_GT10_14);
CFRelease(fallback);
// the origin of this bounding box is relative to the bottom-left corner baseline
CGFloat decender = -bbox.origin.y;
@@ -241,12 +251,14 @@ AWT_FONT_CLEANUP_CHECK(awtfont);
tx.tx += xPos;
tx.ty += yPos;
CGGlyph glyph = glyphCode;
NSFont *font = awtfont->fFont;
// get the right font and glyph for this "Java GlyphCode"
CGGlyph glyph;
const CTFontRef font = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtfont, glyphCode, &glyph);
// get the advance of this glyph
CGSize advance;
CTFontGetAdvancesForGlyphs((CTFontRef)font, kCTFontDefaultOrientation, &glyph, &advance, 1);
CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, &glyph, &advance, 1);
// Create AWTPath
path = AWTPathCreate(CGSizeMake(xPos, yPos));
@@ -255,7 +267,8 @@ AWT_FONT_CLEANUP_CHECK(path);
// Get the paths
tx = awtStrike->fTx;
tx = CGAffineTransformConcat(tx, sInverseTX);
AWTGetGlyphOutline(&glyph, font, &advance, &tx, 0, 1, &path);
AWTGetGlyphOutline(&glyph, (NSFont *)font, &advance, &tx, 0, 1, &path);
CFRelease(font);
pointCoords = (*env)->NewFloatArray(env, path->fNumberOfDataElements);
AWT_FONT_CLEANUP_CHECK(pointCoords);
@@ -309,14 +322,19 @@ JNIEXPORT void JNICALL Java_sun_font_CStrike_getNativeGlyphOutlineBounds
AWT_FONT_CLEANUP_SETUP;
AWT_FONT_CLEANUP_CHECK(awtfont);
CGGlyph glyph = glyphCode;
// get the right font and glyph for this "Java GlyphCode"
CGGlyph glyph;
const CTFontRef font = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(
awtfont, glyphCode, &glyph);
CGRect bbox = CTFontGetBoundingRectsForGlyphs(
(CTFontRef)awtfont->fFont, kCTFontOrientationDefault, &glyph, NULL, 1);
font, kCTFontOrientationDefault, &glyph, NULL, 1);
CGAffineTransform tx = CGAffineTransformConcat(awtStrike->fTx,
sInverseTX);
bbox = CGRectApplyAffineTransform (bbox, tx);
CFRelease(font);
jfloat *rawRectData =
(*env)->GetPrimitiveArrayCritical(env, rectData, NULL);

View File

@@ -29,6 +29,7 @@
#import "CoreTextSupport.h"
#import "sun_font_CCharToGlyphMapper.h"
#import "sun_font_CCompositeGlyphMapper.h"
/*
* Class: sun_font_CCharToGlyphMapper
@@ -113,3 +114,28 @@ JNI_COCOA_ENTER(env);
JNI_COCOA_EXIT(env);
}
/*
* Class: sun_font_CCompositeGlyphMapper
* Method: nativeCodePointToGlyph
* Signature: (JI[Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL
Java_sun_font_CCompositeGlyphMapper_nativeCodePointToGlyph
(JNIEnv *env, jclass clazz, jlong awtFontPtr, jint codePoint, jobjectArray resultArray)
{
JNI_COCOA_ENTER(env);
AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
CFStringRef fontNames[] = {NULL, NULL};
CGGlyph glyph = CTS_CopyGlyphAndFontNamesForCodePoint(awtFont, (UnicodeScalarValue)codePoint, fontNames);
if (glyph > 0) {
jstring fontName = NSStringToJavaString(env, (NSString *)fontNames[0]);
(*env)->SetObjectArrayElement(env, resultArray, 0, fontName);
jstring fontFamilyName = NSStringToJavaString(env, (NSString *)fontNames[1]);
(*env)->SetObjectArrayElement(env, resultArray, 1, fontFamilyName);
}
if (fontNames[0]) CFRelease(fontNames[0]);
if (fontNames[1]) CFRelease(fontNames[1]);
return glyph;
JNI_COCOA_EXIT(env);
}

View File

@@ -27,6 +27,7 @@
#import "JNIUtilities.h"
#import "CGGlyphImages.h"
#import "CoreTextSupport.h"
#import "fontscalerdefs.h" // contains the definition of GlyphInfo struct
#import "sun_awt_SunHints.h"
@@ -646,6 +647,16 @@ CGGI_CreateNewGlyphInfoFrom(CGSize advance, CGRect bbox,
#define RENDER_GLYPH_BATCH_SIZE 16
#define RENDER_GLYPH_ARRAY_INIT_8 glyph,glyph,glyph,glyph,glyph,glyph,glyph,glyph
#define RENDER_GLYPH_ARRAY_INIT RENDER_GLYPH_ARRAY_INIT_8,RENDER_GLYPH_ARRAY_INIT_8
static CTFontRef CopyFontWithSize(CTFontRef originalFont, CGFloat size) {
CTFontDescriptorRef descriptor = NULL;
CGFontRef cgFont = CTFontCopyGraphicsFont(originalFont, &descriptor);
CTFontRef result = CTFontCreateWithGraphicsFont(cgFont, size, NULL, descriptor);
if (cgFont) CFRelease(cgFont);
if (descriptor) CFRelease(descriptor);
return result;
}
/*
* Clears the canvas, strikes the glyph with CoreGraphics, and then
* copies the struck pixels into the GlyphInfo image.
@@ -686,7 +697,7 @@ CGGI_CreateImageForGlyph
// Set actual font size from transformation matrix for color glyphs
CGFloat fontSize = glyphDescriptor != &argb ? strike->fSize :
sqrt(fabs(matrix.a * matrix.d - matrix.b * matrix.c));
CTFontRef sizedFont = CTFontCreateCopyWithSymbolicTraits(font, fontSize, NULL, 0, 0);
CTFontRef sizedFont = CopyFontWithSize(font, fontSize);
CGFloat normFactor = 1.0 / fontSize;
CGAffineTransform normalizedMatrix = CGAffineTransformScale(matrix, normFactor, normFactor);
@@ -738,6 +749,78 @@ CGGI_CreateImageForGlyph
/*
* CoreText path...
*/
static inline GlyphInfo *
CGGI_CreateImageForUnicode
(CGGI_GlyphCanvas *canvas, const AWTStrike *strike,
const CGGI_RenderingMode *mode, const UnicodeScalarValue uniChar,
const bool isCatalinaOrAbove)
{
// save the graphics state
CGContextSaveGState(canvas->context);
// text matrix is not considered part of graphics state
CGAffineTransform originalTx = CGContextGetTextMatrix(canvas->context);
// get the glyph, measure it using CG
CGGlyph glyph;
CTFontRef fallback;
if (uniChar > 0xFFFF) {
UTF16Char charRef[2];
CTS_BreakupUnicodeIntoSurrogatePairs(uniChar, charRef);
CGGlyph glyphTmp[2];
fallback = CTS_CopyCTFallbackFontAndGlyphForUnicode(strike->fAWTFont, (const UTF16Char *)&charRef, (CGGlyph *)&glyphTmp, 2);
glyph = glyphTmp[0];
} else {
UTF16Char charRef;
charRef = (UTF16Char) uniChar; // truncate.
fallback = CTS_CopyCTFallbackFontAndGlyphForUnicode(strike->fAWTFont, (const UTF16Char *)&charRef, &glyph, 1);
}
JRSFontRenderingStyle style = JRSFontAlignStyleForFractionalMeasurement(strike->fStyle);
CGGI_GlyphInfoDescriptor *glyphDescriptor = CGGI_GetGlyphInfoDescriptor(mode, fallback);
bool subpixelResolution = mode->subpixelResolution && glyphDescriptor == &grey;
CGRect bbox;
CGSize advance;
CGGlyphImages_GetGlyphMetrics(fallback, &strike->fTx, strike->fSize, style, &glyph, 1, &bbox, &advance, isCatalinaOrAbove);
// create the Sun2D GlyphInfo we are going to strike into
GlyphInfo *info = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, glyphDescriptor, subpixelResolution);
// fix the context size, just in case the substituted character is unexpectedly large
CGGI_SizeCanvas(canvas, info->width * info->subpixelResolutionX, info->height * info->subpixelResolutionY, mode);
// align the transform for the real CoreText strike
CGContextSetTextMatrix(canvas->context, strike->fAltTx);
const CGFontRef cgFallback = CTFontCopyGraphicsFont(fallback, NULL);
CGContextSetFont(canvas->context, cgFallback);
CFRelease(cgFallback);
// clean the canvas - align, strike, and copy the glyph from the canvas into the info
CGGI_CreateImageForGlyph(canvas, glyph, info, glyphDescriptor, strike, fallback, isCatalinaOrAbove);
// restore graphics state
CGContextRestoreGState(canvas->context);
CGContextSetTextMatrix(canvas->context, originalTx);
CFRelease(fallback);
#ifdef CGGI_DEBUG
DUMP_GLYPHINFO(info);
#endif
#ifdef CGGI_DEBUG_DUMP
DUMP_IMG_PIXELS("CGGI Canvas", canvas->image);
#if 0
PRINT_CGSTATES_INFO(NULL);
#endif
#endif
return info;
}
#pragma mark --- GlyphInfo Filling and Canvas Managment ---
@@ -752,6 +835,7 @@ CGGI_FillImagesForGlyphsWithSizedCanvas(CGGI_GlyphCanvas *canvas,
const AWTStrike *strike,
const CGGI_RenderingMode *mode,
jlong glyphInfos[],
const UnicodeScalarValue uniChars[],
const CGGlyph glyphs[],
const CFIndex len)
{
@@ -764,8 +848,13 @@ CGGI_FillImagesForGlyphsWithSizedCanvas(CGGI_GlyphCanvas *canvas,
CFIndex i;
for (i = 0; i < len; i++) {
GlyphInfo *info = (GlyphInfo *)jlong_to_ptr(glyphInfos[i]);
CGGI_CreateImageForGlyph(canvas, glyphs[i], info, mode->mainFontDescriptor,
strike, (CTFontRef)strike->fAWTFont->fFont, isMojaveOrAbove);
if (info != NULL) {
CGGI_CreateImageForGlyph(canvas, glyphs[i], info, mode->mainFontDescriptor,
strike, (CTFontRef)strike->fAWTFont->fFont, isMojaveOrAbove);
} else {
info = CGGI_CreateImageForUnicode(canvas, strike, mode, uniChars[i], isMojaveOrAbove);
glyphInfos[i] = ptr_to_jlong(info);
}
#ifdef CGGI_DEBUG
DUMP_GLYPHINFO(info);
#endif
@@ -800,7 +889,7 @@ static NSString *threadLocalLCDCanvasKey =
static inline void
CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
const CGGI_RenderingMode *mode,
const CGGlyph glyphs[],
const UnicodeScalarValue uniChars[], const CGGlyph glyphs[],
const size_t maxWidth, const size_t maxHeight,
const CFIndex len)
{
@@ -810,7 +899,8 @@ CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
CGGI_GlyphCanvas *tmpCanvas = [[CGGI_GlyphCanvas alloc] init];
CGGI_InitCanvas(tmpCanvas, maxWidth, maxHeight, mode);
CGGI_FillImagesForGlyphsWithSizedCanvas(tmpCanvas, strike,
mode, glyphInfos, glyphs, len);
mode, glyphInfos, uniChars,
glyphs, len);
CGGI_FreeCanvas(tmpCanvas);
[tmpCanvas release];
@@ -830,7 +920,7 @@ CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
CGGI_SizeCanvas(canvas, maxWidth, maxHeight, mode);
CGGI_FillImagesForGlyphsWithSizedCanvas(canvas, strike, mode,
glyphInfos, glyphs, len);
glyphInfos, uniChars, glyphs, len);
}
/*
@@ -846,7 +936,7 @@ CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
static inline void
CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike,
const CGGI_RenderingMode *mode,
const CGGlyph glyphs[],
const UnicodeScalarValue uniChars[], const CGGlyph glyphs[],
CGSize advances[], CGRect bboxes[], const CFIndex len)
{
AWTFont *font = strike->fAWTFont;
@@ -861,6 +951,12 @@ CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike,
CFIndex i;
for (i = 0; i < len; i++)
{
if (uniChars[i] != 0)
{
glyphInfos[i] = 0L;
continue; // will be handled later
}
CGSize advance = advances[i];
CGRect bbox = bboxes[i];
@@ -877,29 +973,41 @@ CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike,
glyphInfos[i] = ptr_to_jlong(glyphInfo);
}
CGGI_FillImagesForGlyphs(glyphInfos, strike, mode,
CGGI_FillImagesForGlyphs(glyphInfos, strike, mode, uniChars,
glyphs, maxWidth, maxHeight, len);
}
#pragma mark --- Temporary Buffer Allocations and Initialization ---
/*
* This stage separates the already valid glyph codes from the unicode values
* that need special handling - the rawGlyphCodes array is no longer used
* after this stage.
*/
static void
CGGI_CreateGlyphs(jlong *glyphInfos,
const AWTStrike *strike,
const CGGI_RenderingMode *mode,
jint rawGlyphCodes[],
CGGlyph glyphs[],
CGSize advances[], CGRect bboxes[],
const CFIndex len)
CGGI_CreateGlyphsAndScanForComplexities(jlong *glyphInfos,
const AWTStrike *strike,
const CGGI_RenderingMode *mode,
jint rawGlyphCodes[],
UnicodeScalarValue uniChars[], CGGlyph glyphs[],
CGSize advances[], CGRect bboxes[],
const CFIndex len)
{
CFIndex i;
for (i = 0; i < len; i++) {
glyphs[i] = rawGlyphCodes[i];
jint code = rawGlyphCodes[i];
if (code < 0) {
glyphs[i] = 0;
uniChars[i] = -code;
} else {
glyphs[i] = code;
uniChars[i] = 0;
}
}
CGGI_CreateGlyphInfos(glyphInfos, strike, mode,
glyphs, advances, bboxes, len);
uniChars, glyphs, advances, bboxes, len);
#ifdef CGGI_DEBUG_HIT_COUNT
static size_t hitCount = 0;
@@ -925,29 +1033,31 @@ CGGlyphImages_GetGlyphImagePtrs(jlong glyphInfos[],
CGRect bboxes[len];
CGSize advances[len];
CGGlyph glyphs[len];
UnicodeScalarValue uniChars[len];
CGGI_CreateGlyphs(glyphInfos, strike, &mode,
rawGlyphCodes, glyphs,
advances, bboxes, len);
CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode,
rawGlyphCodes, uniChars, glyphs,
advances, bboxes, len);
return;
}
// just do one malloc, and carve it up for all the buffers
void *buffer = malloc((sizeof(CGRect) + sizeof(CGSize) + sizeof(CGGlyph)) *
len);
void *buffer = malloc(sizeof(CGRect) * sizeof(CGSize) *
sizeof(CGGlyph) * sizeof(UnicodeScalarValue) * len);
if (buffer == NULL) {
[[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 + len);
CGGlyph *glyphs = (CGGlyph *)(advances + len);
CGSize *advances = (CGSize *)(bboxes + sizeof(CGRect) * len);
CGGlyph *glyphs = (CGGlyph *)(advances + sizeof(CGGlyph) * len);
UnicodeScalarValue *uniChars = (UnicodeScalarValue *)(glyphs + sizeof(UnicodeScalarValue) * len);
CGGI_CreateGlyphs(glyphInfos, strike, &mode,
rawGlyphCodes, glyphs,
advances, bboxes, len);
CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode,
rawGlyphCodes, uniChars, glyphs,
advances, bboxes, len);
free(buffer);
}
@@ -971,7 +1081,7 @@ CGGlyphImages_GetGlyphMetrics(const CTFontRef font,
// The logic here must match the logic in CGGI_CreateImageForGlyph,
// which performs glyph drawing.
CTFontRef sizedFont = CTFontCreateCopyWithSymbolicTraits(font, fontSize, NULL, 0, 0);
CTFontRef sizedFont = CopyFontWithSize(font, fontSize);
if (bboxes) {
// JRSFontGetBoundingBoxesForGlyphsAndStyle works incorrectly for AppleColorEmoji font:

View File

@@ -31,13 +31,37 @@
#pragma mark --- CoreText Support ---
#define HI_SURROGATE_START 0xD800
#define HI_SURROGATE_END 0xDBFF
#define LO_SURROGATE_START 0xDC00
#define LO_SURROGATE_END 0xDFFF
/*
* Transform Unicode characters into glyphs.
*
* Fills the "glyphsAsInts" array with the glyph codes for the current font.
* Fills the "glyphsAsInts" array with the glyph codes for the current font,
* or the negative unicode value if we know the character can be hot-substituted.
*
* This is the heart of "Universal Font Substitution" in Java.
*/
void CTS_GetGlyphsAsIntsForCharacters(const AWTFont *font, const UniChar unicodes[], CGGlyph glyphs[], jint glyphsAsInts[], const size_t count);
// Translates a Java glyph code int (might be a negative unicode value) into a CGGlyph/CTFontRef pair
// Returns the substituted font, and places the appropriate glyph into "glyph"
CTFontRef CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(const AWTFont *font, const jint glyphCode, CGGlyph *glyphRef);
// Translates a Unicode into a CGGlyph/CTFontRef pair
// Returns the substituted font, and places the appropriate glyph into "glyphRef"
CTFontRef CTS_CopyCTFallbackFontAndGlyphForUnicode(const AWTFont *font, const UTF16Char *charRef, CGGlyph *glyphRef, int count);
// Transform a single Unicode character code into glyph code.
// Names of the relevant font are also returned, if the substitution is used.
// Non-null components of fontNames array should always be released by the calling code, regardless of the returned value.
CGGlyph CTS_CopyGlyphAndFontNamesForCodePoint(const AWTFont *font, const UnicodeScalarValue codePoint, CFStringRef fontNames[]);
// Breakup a 32 bit unicode value into the component surrogate pairs
void CTS_BreakupUnicodeIntoSurrogatePairs(int uniChar, UTF16Char charRef[]);
// Basic struct that holds everything CoreText is interested in
typedef struct CTS_ProviderStruct {

View File

@@ -88,18 +88,161 @@ ReleaseCTStateDictionary(CFDictionaryRef ctStateDict)
CFRelease(ctStateDict); // GC
}
void GetFontsAndGlyphsForCharacters(CTFontRef font, CTFontRef fallbackBase,
const UniChar unicodes[], CGGlyph glyphs[], jint glyphsAsInts[],
CTFontRef actualFonts[], const size_t count)
{
CTFontGetGlyphsForCharacters(font, unicodes, glyphs, count);
if (!fallbackBase) fallbackBase = font;
size_t i;
for (i = 0; i < count; i++) {
UniChar unicode = unicodes[i];
UniChar nextUnicode = (i+1) < count ? unicodes[i+1] : 0;
bool surrogatePair = unicode >= HI_SURROGATE_START && unicode <= HI_SURROGATE_END
&& nextUnicode >= LO_SURROGATE_START && nextUnicode <= LO_SURROGATE_END;
CGGlyph glyph = glyphs[i];
if (glyph > 0) {
glyphsAsInts[i] = glyph;
if (surrogatePair) i++;
continue;
}
const CTFontRef fallback = JRSFontCreateFallbackFontForCharacters(fallbackBase, &unicodes[i], surrogatePair ? 2 : 1);
if (fallback) {
CTFontGetGlyphsForCharacters(fallback, &unicodes[i], &glyphs[i], surrogatePair ? 2 : 1);
glyph = glyphs[i];
if (actualFonts && glyph > 0) {
actualFonts[i] = fallback;
} else {
CFRelease(fallback);
}
}
if (glyph > 0) {
int codePoint = surrogatePair ? (((int)(unicode - HI_SURROGATE_START)) << 10)
+ nextUnicode - LO_SURROGATE_START + 0x10000 : unicode;
glyphsAsInts[i] = -codePoint; // set the glyph code to the negative unicode value
} else {
glyphsAsInts[i] = 0; // CoreText couldn't find a glyph for this character either
}
if (surrogatePair) i++;
}
}
/*
* Transform Unicode characters into glyphs.
*
* Fills the "glyphsAsInts" array with the glyph codes for the current font.
* Fills the "glyphsAsInts" array with the glyph codes for the current font,
* or the negative unicode value if we know the character can be hot-substituted.
*
* This is the heart of "Universal Font Substitution" in Java.
*/
void CTS_GetGlyphsAsIntsForCharacters
(const AWTFont *font, const UniChar unicodes[], CGGlyph glyphs[], jint glyphsAsInts[], const size_t count)
{
CTFontGetGlyphsForCharacters((CTFontRef)font->fFont, unicodes, glyphs, count);
GetFontsAndGlyphsForCharacters((CTFontRef)font->fFont, (CTFontRef)font->fFallbackBase,
unicodes, glyphs, glyphsAsInts, NULL, count);
}
size_t i;
for (i = 0; i < count; i++) {
glyphsAsInts[i] = glyphs[i];
/*
* Returns glyph code for a given Unicode character.
* Names of the corresponding substituted font are also returned if substitution is performed.
*/
CGGlyph CTS_CopyGlyphAndFontNamesForCodePoint
(const AWTFont *font, const UnicodeScalarValue codePoint, CFStringRef fontNames[])
{
CTFontRef fontRef = (CTFontRef)font->fFont;
CTFontRef fallbackBase = (CTFontRef)font->fFallbackBase;
int count = codePoint >= 0x10000 ? 2 : 1;
UTF16Char unicodes[count];
if (count == 1) {
unicodes[0] = (UTF16Char)codePoint;
} else {
CTS_BreakupUnicodeIntoSurrogatePairs(codePoint, unicodes);
}
CGGlyph glyphs[count];
jint glyphsAsInts[count];
CTFontRef actualFonts[count];
GetFontsAndGlyphsForCharacters(fontRef, fallbackBase, unicodes, glyphs, glyphsAsInts, actualFonts, count);
CGGlyph glyph = glyphs[0];
bool substitutionHappened = glyphsAsInts[0] < 0;
if (glyph > 0 && substitutionHappened) {
CTFontRef actualFont = actualFonts[0];
CFStringRef fontName = CTFontCopyPostScriptName(actualFont);
CFStringRef familyName = CTFontCopyFamilyName(actualFont);
CFRelease(actualFont);
fontNames[0] = fontName;
fontNames[1] = familyName;
if (!fontName || !familyName) glyph = 0;
}
return glyph;
}
/*
* Translates a Unicode into a CGGlyph/CTFontRef pair
* Returns the substituted font, and places the appropriate glyph into "glyphRef"
*/
CTFontRef CTS_CopyCTFallbackFontAndGlyphForUnicode
(const AWTFont *font, const UTF16Char *charRef, CGGlyph *glyphRef, int count) {
CTFontRef primary = (CTFontRef)font->fFont;
CTFontRef fallbackBase = (CTFontRef)font->fFallbackBase;
if (fallbackBase) {
CTFontGetGlyphsForCharacters(primary, charRef, glyphRef, count);
if (glyphRef[0] > 0) {
CFRetain(primary);
return primary;
}
} else {
fallbackBase = primary;
}
CTFontRef fallback = JRSFontCreateFallbackFontForCharacters(fallbackBase, charRef, count);
if (fallback == NULL)
{
// use the original font if we somehow got duped into trying to fallback something we can't
fallback = (CTFontRef)font->fFont;
CFRetain(fallback);
}
CTFontGetGlyphsForCharacters(fallback, charRef, glyphRef, count);
return fallback;
}
/*
* Translates a Java glyph code int (might be a negative unicode value) into a CGGlyph/CTFontRef pair
* Returns the substituted font, and places the appropriate glyph into "glyphRef"
*/
CTFontRef CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode
(const AWTFont *font, const jint glyphCode, CGGlyph *glyphRef)
{
// negative glyph codes are really unicodes, which were placed there by the mapper
// to indicate we should use CoreText to substitute the character
if (glyphCode >= 0)
{
*glyphRef = glyphCode;
CFRetain(font->fFont);
return (CTFontRef)font->fFont;
}
int codePoint = -glyphCode;
if (codePoint >= 0x10000) {
UTF16Char chars[2];
CGGlyph glyphs[2];
CTS_BreakupUnicodeIntoSurrogatePairs(codePoint, chars);
CTFontRef result = CTS_CopyCTFallbackFontAndGlyphForUnicode(font, chars, glyphs, 2);
*glyphRef = glyphs[0];
return result;
} else {
UTF16Char character = codePoint;
return CTS_CopyCTFallbackFontAndGlyphForUnicode(font, &character, glyphRef, 1);
}
}
// Breakup a 32 bit unicode value into the component surrogate pairs
void CTS_BreakupUnicodeIntoSurrogatePairs(int uniChar, UTF16Char charRef[]) {
int value = uniChar - 0x10000;
UTF16Char low_surrogate = (value & 0x3FF) | LO_SURROGATE_START;
UTF16Char high_surrogate = (((int)(value & 0xFFC00)) >> 10) | HI_SURROGATE_START;
charRef[0] = high_surrogate;
charRef[1] = low_surrogate;
}

View File

@@ -127,6 +127,13 @@ do { \
__attribute__((visibility("default")))
@interface ThreadUtilities : NSObject { } /* Extend NSObject so can call performSelectorOnMainThread */
/*
* When a blocking performSelectorOnMainThread is executed from the EventDispatch thread,
* and the executed code triggers an opposite blocking a11y call (via LWCToolkit.invokeAndWait)
* this is a deadlock case, and then this property is used to discard LWCToolkit.invokeAndWait.
*/
@property (class, nonatomic, readonly) BOOL blockingEventDispatchThread;
+ (JNIEnv*)getJNIEnv;
+ (JNIEnv*)getJNIEnvUncached;
+ (void)detachCurrentThread;

View File

@@ -50,6 +50,24 @@ static inline void attachCurrentThread(void** env) {
@implementation ThreadUtilities
static BOOL _blockingEventDispatchThread = NO;
static long eventDispatchThreadPtr = (long)nil;
static BOOL isEventDispatchThread() {
return (long)[NSThread currentThread] == eventDispatchThreadPtr;
}
// The [blockingEventDispatchThread] property is readonly, so we implement a private setter
static void setBlockingEventDispatchThread(BOOL value) {
assert([NSThread isMainThread]);
_blockingEventDispatchThread = value;
}
+ (BOOL) blockingEventDispatchThread {
assert([NSThread isMainThread]);
return _blockingEventDispatchThread;
}
+ (void)initialize {
/* All the standard modes plus ours */
javaModes = [[NSArray alloc] initWithObjects:NSDefaultRunLoopMode,
@@ -81,13 +99,6 @@ AWT_ASSERT_APPKIT_THREAD;
appkitThreadGroup = group;
}
/* This is needed because we can't directly pass a block to
* performSelectorOnMainThreadWaiting .. since it expects a selector
*/
+ (void)invokeBlock:(void (^)())block {
block();
}
/*
* When running a block where either we don't wait, or it needs to run on another thread
* we need to copy it from stack to heap, use the copy in the call and release after use.
@@ -103,12 +114,7 @@ AWT_ASSERT_APPKIT_THREAD;
if ([NSThread isMainThread] && wait == YES) {
block();
} else {
if (wait == YES) {
[self performOnMainThread:@selector(invokeBlock:) on:self withObject:block waitUntilDone:YES];
} else {
void (^blockCopy)(void) = Block_copy(block);
[self performOnMainThread:@selector(invokeBlockCopy:) on:self withObject:blockCopy waitUntilDone:NO];
}
[self performOnMainThread:@selector(invokeBlockCopy:) on:self withObject:Block_copy(block) waitUntilDone:wait];
}
}
@@ -116,7 +122,19 @@ AWT_ASSERT_APPKIT_THREAD;
if ([NSThread isMainThread] && wait == YES) {
[target performSelector:aSelector withObject:arg];
} else {
[target performSelectorOnMainThread:aSelector withObject:arg waitUntilDone:wait modes:javaModes];
if (wait && isEventDispatchThread()) {
void (^blockCopy)(void) = Block_copy(^(){
setBlockingEventDispatchThread(YES);
@try {
[target performSelector:aSelector withObject:arg];
} @finally {
setBlockingEventDispatchThread(NO);
}
});
[self performSelectorOnMainThread:@selector(invokeBlockCopy:) withObject:blockCopy waitUntilDone:YES modes:javaModes];
} else {
[target performSelectorOnMainThread:aSelector withObject:arg waitUntilDone:wait modes:javaModes];
}
}
}
@@ -143,3 +161,16 @@ JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CThreading_isMainThread
return [NSThread isMainThread];
}
/*
* Class: sun_awt_AWTThreading
* Method: notifyEventDispatchThreadStartedNative
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_awt_AWTThreading_notifyEventDispatchThreadStartedNative
(JNIEnv *env, jclass c)
{
@synchronized([ThreadUtilities class]) {
eventDispatchThreadPtr = (long)[NSThread currentThread];
}
}

View File

@@ -30,6 +30,7 @@ public class JBRApiModule {
.withStatic("getSubpixelResolution", "sun.font.FontUtilities")
.service("com.jetbrains.JBRFileDialogService", null)
.withStatic("getFileDialog", "com.jetbrains.desktop.JBRFileDialog", "get")
.proxy("com.jetbrains.JBRFileDialog", "com.jetbrains.desktop.JBRFileDialog");
.proxy("com.jetbrains.JBRFileDialog", "com.jetbrains.desktop.JBRFileDialog")
.service("com.jetbrains.CustomWindowDecoration", "java.awt.Window$CustomWindowDecoration");
}
}

View File

@@ -31,6 +31,7 @@ import java.awt.event.WindowEvent;
import java.util.ArrayList;
import sun.awt.AWTThreading;
import sun.util.logging.PlatformLogger;
import sun.awt.dnd.SunDragSourceContextPeer;
@@ -86,6 +87,7 @@ class EventDispatchThread extends Thread {
}
public void run() {
AWTThreading.getInstance(Thread.currentThread()).notifyEventDispatchThreadStarted();
try {
pumpEvents(new Conditional() {
public boolean evaluate() {
@@ -97,6 +99,8 @@ class EventDispatchThread extends Thread {
}
}
private static native void registerEventDispatchThread();
void pumpEvents(Conditional cond) {
pumpEvents(ANY_EVENT, cond);
}

View File

@@ -358,6 +358,7 @@ public class EventQueue {
if (shouldNotify) {
if (theEvent.getSource() != AWTAutoShutdown.getInstance()) {
AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
AWTThreading.getInstance(dispatchThread).notifyEventDispatchThreadBusy();
}
pushPopCond.signalAll();
} else if (notifyID) {
@@ -570,6 +571,7 @@ public class EventQueue {
return event;
}
AWTAutoShutdown.getInstance().notifyThreadFree(dispatchThread);
AWTThreading.getInstance(dispatchThread).notifyEventDispatchThreadFree();
pushPopCond.await();
} finally {
pushPopLock.unlock();
@@ -1128,6 +1130,7 @@ public class EventQueue {
t.setPriority(Thread.NORM_PRIORITY + 1);
t.setDaemon(false);
AWTAutoShutdown.getInstance().notifyThreadBusy(t);
AWTThreading.getInstance(t).notifyEventDispatchThreadBusy();
return t;
}
}
@@ -1158,6 +1161,7 @@ public class EventQueue {
dispatchThread = null;
}
AWTAutoShutdown.getInstance().notifyThreadFree(edt);
AWTThreading.getInstance(edt).notifyEventDispatchThreadFree();
/*
* Event was posted after EDT events pumping had stopped, so start
* another EDT to handle this event

View File

@@ -67,7 +67,6 @@ import sun.font.FontDesignMetrics;
import sun.font.FontLineMetrics;
import sun.font.FontManager;
import sun.font.FontManagerFactory;
import sun.font.FontSubstitution;
import sun.font.FontUtilities;
import sun.font.GlyphLayout;
import sun.font.StandardGlyphVector;
@@ -267,11 +266,6 @@ public class Font implements java.io.Serializable
return font.getFont2D();
}
@Override
public Font2D getFont2DWithSubstitution(Font font) {
return font.getFont2DWithSubstitution();
}
public void setFont2D(Font font, Font2DHandle handle) {
font.font2DHandle = handle;
}
@@ -549,11 +543,6 @@ public class Font implements java.io.Serializable
return font2DHandle.font2D;
}
private Font2D getFont2DWithSubstitution() {
Font2D font2D = getFont2D();
return font2D instanceof FontSubstitution ? ((FontSubstitution) font2D).getCompositeFont2D() : font2D;
}
/**
* Creates a new {@code Font} from the specified name, style and
* point size.
@@ -2252,7 +2241,7 @@ public class Font implements java.io.Serializable
* @since 1.2
*/
public boolean canDisplay(char c){
return getFont2DWithSubstitution().canDisplay(c);
return getFont2D().canDisplay(c);
}
/**
@@ -2273,7 +2262,7 @@ public class Font implements java.io.Serializable
throw new IllegalArgumentException("invalid code point: " +
Integer.toHexString(codePoint));
}
return getFont2DWithSubstitution().canDisplay(codePoint);
return getFont2D().canDisplay(codePoint);
}
/**
@@ -2294,7 +2283,7 @@ public class Font implements java.io.Serializable
* @since 1.2
*/
public int canDisplayUpTo(String str) {
Font2D font2d = getFont2DWithSubstitution();
Font2D font2d = getFont2D();
int len = str.length();
for (int i = 0; i < len; i++) {
char c = str.charAt(i);
@@ -2332,7 +2321,7 @@ public class Font implements java.io.Serializable
* @since 1.2
*/
public int canDisplayUpTo(char[] text, int start, int limit) {
Font2D font2d = getFont2DWithSubstitution();
Font2D font2d = getFont2D();
for (int i = start; i < limit; i++) {
char c = text[i];
if (font2d.canDisplay(c)) {
@@ -2367,7 +2356,7 @@ public class Font implements java.io.Serializable
* @since 1.2
*/
public int canDisplayUpTo(CharacterIterator iter, int start, int limit) {
Font2D font2d = getFont2DWithSubstitution();
Font2D font2d = getFont2D();
char c = iter.setIndex(start);
for (int i = start; i < limit; i++, c = iter.next()) {
if (font2d.canDisplay(c)) {

View File

@@ -46,13 +46,17 @@ import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serial;
import java.io.Serializable;
import java.lang.annotation.Native;
import java.lang.invoke.MethodHandles;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EventListener;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.Vector;
@@ -64,6 +68,7 @@ import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;
import com.jetbrains.internal.JBRApi;
import sun.awt.AWTAccessor;
import sun.awt.AWTPermissions;
import sun.awt.AppContext;
@@ -4007,7 +4012,66 @@ public class Window extends Container implements Accessible {
}
private volatile boolean hasCustomDecoration;
private volatile List<Map.Entry<Shape, Integer>> customDecorHitTestSpots;
private volatile int customDecorTitleBarHeight = -1; // 0 can be a legal value when no title bar is expected
// called from native
private int hitTestCustomDecoration(int x, int y) {
var spots = customDecorHitTestSpots;
if (spots == null) return CustomWindowDecoration.NO_HIT_SPOT;
for (var spot : spots) {
if (spot.getKey().contains(x, y)) return spot.getValue();
}
return CustomWindowDecoration.NO_HIT_SPOT;
}
private static class CustomWindowDecoration {
@Native public static final int
NO_HIT_SPOT = 0,
OTHER_HIT_SPOT = 1,
MINIMIZE_BUTTON = 2,
MAXIMIZE_BUTTON = 3,
CLOSE_BUTTON = 4,
MENU_BAR = 5;
void setCustomDecorationEnabled(Window window, boolean enabled) {
window.hasCustomDecoration = enabled;
if (MacOS.INSTANCE != null && window.customDecorTitleBarHeight > 0f) {
MacOS.INSTANCE.setTitleBarHeight(window, window.peer, enabled ? window.customDecorTitleBarHeight : 0);
}
}
boolean isCustomDecorationEnabled(Window window) {
return window.hasCustomDecoration;
}
void setCustomDecorationHitTestSpots(Window window, List<Map.Entry<Shape, Integer>> spots) {
window.customDecorHitTestSpots = List.copyOf(spots);
}
List<Map.Entry<Shape, Integer>> getCustomDecorationHitTestSpots(Window window) {
return window.customDecorHitTestSpots;
}
void setCustomDecorationTitleBarHeight(Window window, int height) {
if (height >= 0) {
window.customDecorTitleBarHeight = height;
if (MacOS.INSTANCE != null && window.hasCustomDecoration) {
MacOS.INSTANCE.setTitleBarHeight(window, window.peer, height);
}
}
}
int getCustomDecorationTitleBarHeight(Window window) {
return window.customDecorTitleBarHeight;
}
private interface MacOS {
MacOS INSTANCE = (MacOS) JBRApi.internalServiceBuilder(MethodHandles.lookup(), null)
.withStatic("setTitleBarHeight", "sun.lwawt.macosx.CPlatformWindow", "setCustomDecorationTitleBarHeight").build();
void setTitleBarHeight(Window target, ComponentPeer peer, float height);
}
}
@Deprecated
boolean hasCustomDecoration() {
return hasCustomDecoration;
}
@@ -4015,6 +4079,7 @@ public class Window extends Container implements Accessible {
/**
* Set via reflection (JB JdkEx API).
*/
@Deprecated
void setHasCustomDecoration() {
hasCustomDecoration = true;
}

View File

@@ -5,18 +5,33 @@ import sun.util.logging.PlatformLogger;
import java.awt.*;
import java.awt.event.InvocationEvent;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Map;
import java.util.Stack;
import java.util.*;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.function.Consumer;
/**
* Used to perform a cross threads (EventDispatch, Toolkit) execution so that the execution does not cause a deadlock.
*
* Note: the log messages are tested by jdk/jb/java/awt/Toolkit/LWCToolkitInvokeAndWaitTest.java
*/
public class AWTThreading {
private static final PlatformLogger logger = PlatformLogger.getLogger("sun.awt.AWTThreading");
private static final PlatformLogger logger = PlatformLogger.getLogger(AWTThreading.class.getName());
private static final Runnable EMPTY_RUNNABLE = () -> {};
private static final AtomicReference<Function<Thread, AWTThreading>> theAWTThreadingFactory =
new AtomicReference<>(AWTThreading::new);
private final Thread eventDispatchThread;
private ExecutorService executor;
// every invokeAndWait() pushes a queue of invocations
@@ -24,13 +39,21 @@ public class AWTThreading {
private int level; // re-entrance level
private final List<CompletableFuture<Void>> eventDispatchThreadStateNotifiers = new ArrayList<>();
private volatile boolean isEventDispatchThreadFree;
// invocations should be dispatched on proper EDT (per AppContext)
private static final Map<Thread, AWTThreading> EDT_TO_INSTANCE_MAP = new ConcurrentHashMap<>();
@SuppressWarnings("serial")
private static class TrackingQueue extends LinkedBlockingQueue<InvocationEvent> {}
private AWTThreading() {}
/**
* WARNING: for testing purpose, use {@link AWTThreading#getInstance(Thread)} instead.
*/
public AWTThreading(Thread edt) {
eventDispatchThread = edt;
}
/**
* Executes a callable from EventDispatch thread (EDT). It's assumed the callable either performs a blocking execution on Toolkit
@@ -55,14 +78,25 @@ public class AWTThreading {
}
/**
* Same as {@link #executeWaitToolkit(Callable)}, but without returning a value. If requested (as indicated by
* the passed parameter), the invoked native method is supposed to wait for the result of invocation on AppKit
* thread, and vice versa.
* A boolean value passed to the consumer indicates whether the consumer should perform
* a synchronous invocation on the Toolkit thread and wait, or return immediately.
*
* @see #executeWaitToolkit(Callable).
*/
public static void executeWaitToolkit(Task runnable) {
public static void executeWaitToolkit(Consumer<Boolean> consumer) {
boolean wait = EventQueue.isDispatchThread();
executeWaitToolkit(() -> {
runnable.run(wait);
consumer.accept(wait);
return null;
});
}
/**
* @see #executeWaitToolkit(Callable).
*/
public static void executeWaitToolkit(Runnable runnable) {
executeWaitToolkit(() -> {
runnable.run();
return null;
});
}
@@ -82,12 +116,6 @@ public class AWTThreading {
}
}
if (!isEDT && logger.isLoggable(PlatformLogger.Level.FINE)) {
// this can cause deadlock if calling thread is holding a lock which EDT might require (e.g. AWT tree lock)
logger.fine("AWTThreading.executeWaitToolkit invoked from non-EDT thread", new Throwable());
}
// fallback to default
try {
return callable.call();
} catch (Exception e) {
@@ -178,8 +206,15 @@ public class AWTThreading {
* <li>If the event is first dispatched from EventQueue - it gets removed from the tracking queue.
* <li>If the event is first dispatched from the tracking queue - its dispatching on EventQueue will be noop.
* <ul>
*
* @param source the source of the event
* @param onDispatched called back on event dispatching
* @param catchThrowables should catch Throwable's or propagate to the EventDispatch thread's loop
*/
public static InvocationEvent createAndTrackInvocationEvent(Object source, Runnable runnable, Runnable listener, boolean catchThrowables) {
public static TrackedInvocationEvent createAndTrackInvocationEvent(Object source,
Runnable onDispatched,
boolean catchThrowables)
{
AWTThreading instance = getInstance(source);
if (instance != null) {
synchronized (instance.invocations) {
@@ -187,68 +222,239 @@ public class AWTThreading {
instance.invocations.push(new TrackingQueue());
}
final TrackingQueue queue = instance.invocations.peek();
final InvocationEvent[] eventRef = new InvocationEvent[1];
final AtomicReference<TrackedInvocationEvent> eventRef = new AtomicReference<>();
queue.add(eventRef[0] = new InvocationEvent(
source,
runnable,
// Wrap the original completion listener so that it:
// - guarantees a single run either from dispatch or dispose
// - removes the invocation event from the tracking queue
new Runnable() {
WeakReference<TrackingQueue> queueRef = new WeakReference<>(queue);
eventRef.set(TrackedInvocationEvent.create(
source,
onDispatched,
new Runnable() {
final WeakReference<TrackingQueue> queueRef = new WeakReference<>(queue);
@Override
public void run() {
if (queueRef != null) {
if (listener != null) {
listener.run();
}
TrackingQueue q = queueRef.get();
if (q != null) {
q.remove(eventRef[0]);
}
queueRef = null;
}
@Override
public void run() {
TrackingQueue queue = queueRef.get();
queueRef.clear();
if (queue != null) {
queue.remove(eventRef.get());
}
},
catchThrowables)
{
@Override
public void dispatch() {
if (!isDispatched()) {
super.dispatch();
}
}
});
return eventRef[0];
},
catchThrowables));
queue.add(eventRef.get());
return eventRef.get();
}
}
return new InvocationEvent(source, runnable, listener, catchThrowables);
return TrackedInvocationEvent.create(source, onDispatched, () -> {}, catchThrowables);
}
private static AWTThreading getInstance(Object obj) {
if (obj == null) return null;
@SuppressWarnings("serial")
public static class TrackedInvocationEvent extends InvocationEvent {
private final long creationTime = System.currentTimeMillis();
private final Throwable throwable = new Throwable();
private final CompletableFuture<Void> futureResult = new CompletableFuture<>();
// dispatch or dispose has been started or already completed
private final AtomicBoolean isCompletionStarted = new AtomicBoolean(false);
static TrackedInvocationEvent create(Object source,
Runnable onDispatch,
Runnable onDone,
boolean catchThrowables)
{
final AtomicReference<TrackedInvocationEvent> eventRef = new AtomicReference<>();
eventRef.set(new TrackedInvocationEvent(
source,
onDispatch,
() -> {
if (onDone != null) {
onDone.run();
}
TrackedInvocationEvent thisEvent = eventRef.get();
if (!thisEvent.isDispatched()) {
// If we're here - this {onDone} is being disposed.
thisEvent.completeIfNotYet(() ->
// If we're here - this {onDone} is called by the outer AWTAccessor.getInvocationEventAccessor().dispose()
// which we do not control, so complete here.
thisEvent.futureResult.completeExceptionally(new Throwable("InvocationEvent was disposed"))
);
}
},
catchThrowables));
return eventRef.get();
}
protected TrackedInvocationEvent(Object source, Runnable onDispatched, Runnable onDone, boolean catchThrowables) {
super(source,
Optional.of(onDispatched).orElse(EMPTY_RUNNABLE),
Optional.of(onDone).orElse(EMPTY_RUNNABLE),
catchThrowables);
futureResult.whenComplete((r, ex) -> {
if (ex != null) {
String message = ex.getMessage() + " (awaiting " + (System.currentTimeMillis() - creationTime) + " ms)";
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
ex.initCause(throwable);
logger.fine(message, ex);
} else if (logger.isLoggable(PlatformLogger.Level.INFO)) {
StackTraceElement[] stack = throwable.getStackTrace();
logger.info(message + ". Originated at " + stack[stack.length - 1]);
}
}
});
}
@Override
public void dispatch() {
// Should not complete if competion has already started.
if (completeIfNotYet(super::dispatch)) {
futureResult.complete(null);
}
}
public void dispose(String reason) {
completeIfNotYet(() -> AWTAccessor.getInvocationEventAccessor().dispose(this));
// Should complete exceptionally regardless of whether completetion has alredy started or hasn't.
futureResult.completeExceptionally(new Throwable(reason));
}
private boolean completeIfNotYet(Runnable competeRunnable) {
if (!isCompletionStarted.getAndSet(true)) {
competeRunnable.run();
return true;
}
return false;
}
/**
* Returns whether the event is dispatched or disposed.
*/
public boolean isCompleted() {
return futureResult.isDone();
}
/**
* Returns whether the event is dispatched or disposed.
* If {@code isCompletionInProgress} is true then also checks whether the event
* dispatching or disposal is in progress and if so returns true.
*/
public boolean isCompleted(boolean isCompletionInProgress) {
return isCompleted() || (isCompletionInProgress && isCompletionStarted.get());
}
/**
* Calls the runnable when it's done (immediately if it's done).
*/
public void onDone(Runnable runnable) {
futureResult.whenComplete((r, ex) -> Optional.of(runnable).orElse(EMPTY_RUNNABLE).run());
}
}
public static AWTThreading getInstance(Object obj) {
if (obj == null) {
return getInstance(Toolkit.getDefaultToolkit().getSystemEventQueue());
}
AppContext appContext = SunToolkit.targetToAppContext(obj);
if (appContext == null) return null;
if (appContext == null) {
return getInstance(Toolkit.getDefaultToolkit().getSystemEventQueue());
}
return getInstance((EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY));
}
private static AWTThreading getInstance(EventQueue eq) {
public static AWTThreading getInstance(EventQueue eq) {
if (eq == null) return null;
return getInstance(AWTAccessor.getEventQueueAccessor().getDispatchThread(eq));
}
private static AWTThreading getInstance(Thread edt) {
if (edt == null) return null;
public static AWTThreading getInstance(Thread edt) {
assert edt != null;
return EDT_TO_INSTANCE_MAP.computeIfAbsent(edt, key -> new AWTThreading());
return EDT_TO_INSTANCE_MAP.computeIfAbsent(edt, key -> theAWTThreadingFactory.get().apply(edt));
}
public interface Task {
void run(boolean wait);
public Thread getEventDispatchThread() {
return eventDispatchThread;
}
public StringWriter printEventDispatchThreadStackTrace() {
return printEventDispatchThreadStackTrace(new StringWriter());
}
public StringWriter printEventDispatchThreadStackTrace(StringWriter writer) {
assert writer != null;
var printer = new PrintWriter(writer);
Thread dispatchThread = getEventDispatchThread();
printer.println(dispatchThread.getName());
Arrays.asList(dispatchThread.getStackTrace()).forEach(frame -> printer.append("\tat ").println(frame));
return writer;
}
/**
* Sets {@code AWTThreading} instance factory.
* WARNING: for testing purpose.
*/
public static void setAWTThreadingFactory(Function<Thread, AWTThreading> factory) {
theAWTThreadingFactory.set(factory);
}
/**
* Must be called on the EventDispatch thread.
*/
public void notifyEventDispatchThreadStarted() {
if (FontUtilities.isMacOSX) notifyEventDispatchThreadStartedNative();
}
private static native void notifyEventDispatchThreadStartedNative();
public void notifyEventDispatchThreadFree() {
List<CompletableFuture<Void>> notifiers = Collections.emptyList();
synchronized (eventDispatchThreadStateNotifiers) {
isEventDispatchThreadFree = true;
if (eventDispatchThreadStateNotifiers.size() > 0) {
notifiers = List.copyOf(eventDispatchThreadStateNotifiers);
}
}
if (logger.isLoggable(PlatformLogger.Level.FINER)) {
logger.finer("notifyEventDispatchThreadFree");
}
// notify callbacks out of the synchronization block
notifiers.forEach(f -> f.complete(null));
}
public void notifyEventDispatchThreadBusy() {
synchronized (eventDispatchThreadStateNotifiers) {
isEventDispatchThreadFree = false;
}
if (logger.isLoggable(PlatformLogger.Level.FINER)) {
logger.finer("notifyEventDispatchThreadBusy");
}
}
/**
* Sets a callback and returns a {@code CompletableFuture} reporting the case when the associated EventDispatch thread
* has gone sleeping and stopped dispatching events because of empty EventQueue. If the EventDispatch thread is free
* at the moment then the callback is called immediately on the caller's thread and the future completes.
*/
public CompletableFuture<Void> onEventDispatchThreadFree(Runnable runnable) {
CompletableFuture<Void> future = new CompletableFuture<>();
future.thenRun(Optional.of(runnable).orElse(EMPTY_RUNNABLE));
if (!isEventDispatchThreadFree) {
synchronized (eventDispatchThreadStateNotifiers) {
if (!isEventDispatchThreadFree) {
eventDispatchThreadStateNotifiers.add(future);
future.whenComplete((r, ex) -> eventDispatchThreadStateNotifiers.remove(future));
return future;
}
}
}
if (logger.isLoggable(PlatformLogger.Level.FINER)) {
logger.finer("onEventDispatchThreadFree: free at the moment");
}
future.complete(null);
return future;
}
}

View File

@@ -38,7 +38,7 @@ import java.awt.Font;
* But its probably OK to include it so long as only composites include
* fallbacks. If physicals do then it would be really confusing ..
*/
public final class CompositeFont extends Font2D {
public class CompositeFont extends Font2D {
private boolean[] deferredInitialisation;
String[] componentFileNames;

View File

@@ -108,7 +108,7 @@ public class CompositeGlyphMapper extends CharToGlyphMapper {
return mapper;
}
private int convertToGlyph(int unicode) {
protected int convertToGlyph(int unicode) {
for (int slot = 0; slot < font.numSlots; slot++) {
if (!hasExcludes || !font.isExcludedChar(slot, unicode)) {

View File

@@ -335,7 +335,7 @@ public abstract class Font2D {
return getStrike(desc, true);
}
private FontStrike getStrike(FontStrikeDesc desc, boolean copy) {
FontStrike getStrike(FontStrikeDesc desc, boolean copy) {
/* Before looking in the map, see if the descriptor matches the
* last strike returned from this Font2D. This should often be a win
* since its common for the same font, in the same size to be

View File

@@ -43,7 +43,6 @@ public abstract class FontAccess {
}
public abstract Font2D getFont2D(Font f);
public abstract Font2D getFont2DWithSubstitution(Font f);
public abstract void setFont2D(Font f, Font2DHandle h);
public abstract void setWithFallback(Font f);
public abstract boolean isCreatedFont(Font f);

View File

@@ -356,7 +356,7 @@ public final class FontDesignMetrics extends FontMetrics {
private void initMatrixAndMetrics() {
Font2D font2D = FontUtilities.getFont2DWithSubstitution(font);
Font2D font2D = FontUtilities.getFont2D(font);
fontStrike = font2D.getStrike(font, frc);
StrikeMetrics metrics = fontStrike.getFontMetrics();
this.ascent = metrics.getAscent();

View File

@@ -266,12 +266,12 @@ public class FontFamily {
doSetFont(fontAndStyle.font, fontAndStyle.style);
}
if (italic == null && plain instanceof FontWithDerivedItalic) {
italic = ((FontWithDerivedItalic)plain).createItalicVariant();
italic = ((FontWithDerivedItalic)plain).createItalic();
}
if (bolditalic == null) {
Font2D boldItalicPrototype = bold != null ? bold : plain;
if (boldItalicPrototype instanceof FontWithDerivedItalic) {
bolditalic = ((FontWithDerivedItalic)boldItalicPrototype).createItalicVariant();
bolditalic = ((FontWithDerivedItalic)boldItalicPrototype).createItalic();
}
}
fontSequence.clear();

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