mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-25 10:49:41 +01:00
Compare commits
84 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2cbcbeeef | ||
|
|
aba2a258bb | ||
|
|
53c9198350 | ||
|
|
e27b2fbf84 | ||
|
|
a5c9a208ed | ||
|
|
86b93a57af | ||
|
|
c838f55dd9 | ||
|
|
8d188ad27f | ||
|
|
d87fc06c41 | ||
|
|
b17c748949 | ||
|
|
03783189d0 | ||
|
|
05fbf8507c | ||
|
|
80de7efe15 | ||
|
|
6d1add0393 | ||
|
|
f57241bcf8 | ||
|
|
3fca5bee90 | ||
|
|
60330c9b3e | ||
|
|
4a16c3b8c8 | ||
|
|
2ece56c057 | ||
|
|
c3a506172b | ||
|
|
c81d4030eb | ||
|
|
32fb930e85 | ||
|
|
0ef1d9a4a9 | ||
|
|
07ee0a2471 | ||
|
|
c4cb87ff06 | ||
|
|
6b36a9227d | ||
|
|
83ca27f8b2 | ||
|
|
c539ca4ddf | ||
|
|
51ec2c610e | ||
|
|
2b8ee942e0 | ||
|
|
9b17148ef4 | ||
|
|
02289f478f | ||
|
|
2f0eb2bba8 | ||
|
|
740bf2b3e5 | ||
|
|
88d7361bd9 | ||
|
|
87c6482c0e | ||
|
|
b2a9372d70 | ||
|
|
d0d8a63e0b | ||
|
|
09c200ccfd | ||
|
|
42a22e0cc4 | ||
|
|
71d54051d2 | ||
|
|
d4fc6bc380 | ||
|
|
1e1f71f907 | ||
|
|
6d26c9353f | ||
|
|
adabf8c677 | ||
|
|
5e0ec47ce9 | ||
|
|
9ec9457d8b | ||
|
|
e1a1b6814d | ||
|
|
944797005c | ||
|
|
507f4d716a | ||
|
|
67c24c9b88 | ||
|
|
2ef4de692d | ||
|
|
f20b2dca0f | ||
|
|
0b9397cf4c | ||
|
|
392cf1c31a | ||
|
|
b269750318 | ||
|
|
0676b50884 | ||
|
|
4df6fbd251 | ||
|
|
006cd74964 | ||
|
|
57289a0ad5 | ||
|
|
4916d26f47 | ||
|
|
2daed21814 | ||
|
|
d99872c962 | ||
|
|
ae5963a094 | ||
|
|
9d8433f220 | ||
|
|
2f4a7f66ab | ||
|
|
28289bcf00 | ||
|
|
71597c1b0e | ||
|
|
80efac6e25 | ||
|
|
641688b88a | ||
|
|
b6699ce7a2 | ||
|
|
cf7d0ecb1f | ||
|
|
93fe26f579 | ||
|
|
f4ecc22b1b | ||
|
|
290f700127 | ||
|
|
acdb9fccbd | ||
|
|
1e79cf4924 | ||
|
|
00ce50d5d9 | ||
|
|
17acd28d7c | ||
|
|
c6f3522d16 | ||
|
|
8b35a7e88c | ||
|
|
6e15088b7e | ||
|
|
3a0d06b873 | ||
|
|
531f97d905 |
@@ -11,7 +11,7 @@ can be found on the [releases page](https://github.com/JetBrains/JetBrainsRuntim
|
||||
|
||||
| IDE Version | Latest JBR | Date Released |
|
||||
| --- | --- | --- |
|
||||
| 2021.3 | [17-b106.1](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr17b106.1) | 28-Sep-2021 |
|
||||
| 2021.3 | [17_0_1-b164.8](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr17_0_1b164.8) | 15-Nov-2021 |
|
||||
|
||||
## Contents
|
||||
- [Welcome to JetBrains Runtime](#jetbrains-runtime)
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
<li><a href="#specific-build-issues">Specific Build Issues</a></li>
|
||||
<li><a href="#getting-help">Getting Help</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#reproducible-builds">Reproducible Builds</a></li>
|
||||
<li><a href="#hints-and-suggestions-for-advanced-users">Hints and Suggestions for Advanced Users</a><ul>
|
||||
<li><a href="#bash-completion">Bash Completion</a></li>
|
||||
<li><a href="#using-multiple-configurations">Using Multiple Configurations</a></li>
|
||||
@@ -884,6 +885,32 @@ spawn failed</code></pre>
|
||||
<h3 id="getting-help">Getting Help</h3>
|
||||
<p>If none of the suggestions in this document helps you, or if you find what you believe is a bug in the build system, please contact the Build Group by sending a mail to <a href="mailto:build-dev@openjdk.java.net">build-dev@openjdk.java.net</a>. Please include the relevant parts of the configure and/or build log.</p>
|
||||
<p>If you need general help or advice about developing for the JDK, you can also contact the Adoption Group. See the section on <a href="#contributing-to-openjdk">Contributing to OpenJDK</a> for more information.</p>
|
||||
<h2 id="reproducible-builds">Reproducible Builds</h2>
|
||||
<p>Build reproducibility is the property of getting exactly the same bits out when building, every time, independent on who builds the product, or where. This is for many reasons a harder goal than it initially appears, but it is an important goal, for security reasons and others. Please see <a href="https://reproducible-builds.org">Reproducible Builds</a> for more information about the background and reasons for reproducible builds.</p>
|
||||
<p>Currently, it is not possible to build OpenJDK fully reproducibly, but getting there is an ongoing effort. There are some things you can do to minimize non-determinism and make a larger part of the build reproducible:</p>
|
||||
<ul>
|
||||
<li>Turn on build system support for reproducible builds</li>
|
||||
</ul>
|
||||
<p>Add the flag <code>--enable-reproducible-build</code> to your <code>configure</code> command line. This will turn on support for reproducible builds where it could otherwise be lacking.</p>
|
||||
<ul>
|
||||
<li>Do not rely on <code>configure</code>'s default adhoc version strings</li>
|
||||
</ul>
|
||||
<p>Default adhoc version strings OPT segment include user name, source directory and timestamp. You can either override just the OPT segment using <code>--with-version-opt=<any fixed string></code>, or you can specify the entire version string using <code>--with-version-string=<your version></code>.</p>
|
||||
<ul>
|
||||
<li>Specify how the build sets <code>SOURCE_DATE_EPOCH</code></li>
|
||||
</ul>
|
||||
<p>The JDK build system will set the <code>SOURCE_DATE_EPOCH</code> environment variable during building, depending on the value of the <code>--with-source-date</code> option for <code>configure</code>. The default value is <code>updated</code>, which means that <code>SOURCE_DATE_EPOCH</code> will be set to the current time each time you are running <code>make</code>.</p>
|
||||
<p>The <a href="https://reproducible-builds.org/docs/source-date-epoch/"><code>SOURCE_DATE_EPOCH</code> environment variable</a> is an industry standard, that many tools, such as gcc, recognize, and use in place of the current time when generating output.</p>
|
||||
<p>For reproducible builds, you need to set this to a fixed value. You can use the special value <code>version</code> which will use the nominal release date for the current JDK version, or a value describing a date, either an epoch based timestamp as an integer, or a valid ISO-8601 date.</p>
|
||||
<p><strong>Hint:</strong> If your build environment already sets <code>SOURCE_DATE_EPOCH</code>, you can propagate this using <code>--with-source-date=$SOURCE_DATE_EPOCH</code>.</p>
|
||||
<ul>
|
||||
<li>Specify a hotspot build time</li>
|
||||
</ul>
|
||||
<p>Set a fixed hotspot build time. This will be included in the hotspot library (<code>libjvm.so</code> or <code>jvm.dll</code>) and defaults to the current time when building hotspot. Use <code>--with-hotspot-build-time=<any fixed string></code> for reproducible builds. It's a string so you don't need to format it specifically, so e.g. <code>n/a</code> will do. Another solution is to use the <code>SOURCE_DATE_EPOCH</code> variable, e.g. <code>--with-hotspot-build-time=$(date --date=@$SOURCE_DATE_EPOCH)</code>.</p>
|
||||
<ul>
|
||||
<li>Copyright year</li>
|
||||
</ul>
|
||||
<p>The copyright year in some generated text files are normally set to the current year. This can be overridden by <code>--with-copyright-year=<year></code>. For fully reproducible builds, this needs to be set to a fixed value.</p>
|
||||
<h2 id="hints-and-suggestions-for-advanced-users">Hints and Suggestions for Advanced Users</h2>
|
||||
<h3 id="bash-completion">Bash Completion</h3>
|
||||
<p>The <code>configure</code> and <code>make</code> commands tries to play nice with bash command-line completion (using <code><tab></code> or <code><tab><tab></code>). To use this functionality, make sure you enable completion in your <code>~/.bashrc</code> (see instructions for bash in your operating system).</p>
|
||||
|
||||
@@ -1503,6 +1503,68 @@ If you need general help or advice about developing for the JDK, you can also
|
||||
contact the Adoption Group. See the section on [Contributing to OpenJDK](
|
||||
#contributing-to-openjdk) for more information.
|
||||
|
||||
## Reproducible Builds
|
||||
|
||||
Build reproducibility is the property of getting exactly the same bits out when
|
||||
building, every time, independent on who builds the product, or where. This is
|
||||
for many reasons a harder goal than it initially appears, but it is an important
|
||||
goal, for security reasons and others. Please see [Reproducible Builds](
|
||||
https://reproducible-builds.org) for more information about the background and
|
||||
reasons for reproducible builds.
|
||||
|
||||
Currently, it is not possible to build OpenJDK fully reproducibly, but getting
|
||||
there is an ongoing effort. There are some things you can do to minimize
|
||||
non-determinism and make a larger part of the build reproducible:
|
||||
|
||||
* Turn on build system support for reproducible builds
|
||||
|
||||
Add the flag `--enable-reproducible-build` to your `configure` command line.
|
||||
This will turn on support for reproducible builds where it could otherwise be
|
||||
lacking.
|
||||
|
||||
* Do not rely on `configure`'s default adhoc version strings
|
||||
|
||||
Default adhoc version strings OPT segment include user name, source directory
|
||||
and timestamp. You can either override just the OPT segment using
|
||||
`--with-version-opt=<any fixed string>`, or you can specify the entire version
|
||||
string using `--with-version-string=<your version>`.
|
||||
|
||||
* Specify how the build sets `SOURCE_DATE_EPOCH`
|
||||
|
||||
The JDK build system will set the `SOURCE_DATE_EPOCH` environment variable
|
||||
during building, depending on the value of the `--with-source-date` option for
|
||||
`configure`. The default value is `updated`, which means that
|
||||
`SOURCE_DATE_EPOCH` will be set to the current time each time you are running
|
||||
`make`.
|
||||
|
||||
The [`SOURCE_DATE_EPOCH` environment variable](
|
||||
https://reproducible-builds.org/docs/source-date-epoch/) is an industry
|
||||
standard, that many tools, such as gcc, recognize, and use in place of the
|
||||
current time when generating output.
|
||||
|
||||
For reproducible builds, you need to set this to a fixed value. You can use the
|
||||
special value `version` which will use the nominal release date for the current
|
||||
JDK version, or a value describing a date, either an epoch based timestamp as an
|
||||
integer, or a valid ISO-8601 date.
|
||||
|
||||
**Hint:** If your build environment already sets `SOURCE_DATE_EPOCH`, you can
|
||||
propagate this using `--with-source-date=$SOURCE_DATE_EPOCH`.
|
||||
|
||||
* Specify a hotspot build time
|
||||
|
||||
Set a fixed hotspot build time. This will be included in the hotspot library
|
||||
(`libjvm.so` or `jvm.dll`) and defaults to the current time when building
|
||||
hotspot. Use `--with-hotspot-build-time=<any fixed string>` for reproducible
|
||||
builds. It's a string so you don't need to format it specifically, so e.g. `n/a`
|
||||
will do. Another solution is to use the `SOURCE_DATE_EPOCH` variable, e.g.
|
||||
`--with-hotspot-build-time=$(date --date=@$SOURCE_DATE_EPOCH)`.
|
||||
|
||||
* Copyright year
|
||||
|
||||
The copyright year in some generated text files are normally set to the current
|
||||
year. This can be overridden by `--with-copyright-year=<year>`. For fully
|
||||
reproducible builds, this needs to be set to a fixed value.
|
||||
|
||||
## Hints and Suggestions for Advanced Users
|
||||
|
||||
### Bash Completion
|
||||
|
||||
47
jb/project/docker/Dockerfile.aarch64
Normal file
47
jb/project/docker/Dockerfile.aarch64
Normal file
@@ -0,0 +1,47 @@
|
||||
# NOTE: This Dockerfile is meant to be used from the mkdocker_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/ubuntu:focal-20211006
|
||||
|
||||
# Install the necessary build tools
|
||||
RUN export DEBIAN_FRONTEND=noninteractive \
|
||||
export DEBCONF_NONINTERACTIVE_SEEN=true && \
|
||||
echo 'tzdata tzdata/Areas select Etc' | debconf-set-selections; \
|
||||
echo 'tzdata tzdata/Zones/Etc select UTC' | debconf-set-selections; \
|
||||
apt-get update -qy && \
|
||||
apt-get install -qy \
|
||||
autoconf \
|
||||
build-essential \
|
||||
bzip2 \
|
||||
file \
|
||||
g++-10=10.3.0-1ubuntu1~20.04 \
|
||||
gcc-10=10.3.0-1ubuntu1~20.04 \
|
||||
git \
|
||||
libasound2-dev \
|
||||
libcups2-dev \
|
||||
libfontconfig1-dev \
|
||||
libx11-dev \
|
||||
libxext-dev \
|
||||
libxrandr-dev \
|
||||
libxrender-dev \
|
||||
libxt-dev \
|
||||
libxtst-dev \
|
||||
make \
|
||||
tar \
|
||||
unzip \
|
||||
zip && \
|
||||
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 && \
|
||||
apt-get clean -qy && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Set up boot JDK for building
|
||||
COPY boot_jdk.tar.gz /jdk17/
|
||||
RUN cd /jdk17 && tar --strip-components=1 -xzf boot_jdk.tar.gz && rm /jdk17/boot_jdk.tar.gz
|
||||
ENV BOOT_JDK=/jdk17
|
||||
|
||||
RUN git config --global user.email "teamcity@jetbrains.com" && \
|
||||
git config --global user.name "builduser"
|
||||
26
jb/project/docker/mkdocker_aarch64.sh
Executable file
26
jb/project/docker/mkdocker_aarch64.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# This script creates a Docker image suitable for building AArch64 variant
|
||||
# of the JetBrains Runtime version 17.
|
||||
|
||||
BOOT_JDK_REMOTE_FILE=zulu17.30.15-ca-jdk17.0.1-linux_aarch64.tar.gz
|
||||
BOOT_JDK_SHA=4d9c9116eb0cdd2d7fb220d6d27059f4bf1b7e95cc93d5512bd8ce3791af86c7
|
||||
BOOT_JDK_LOCAL_FILE=boot_jdk.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.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.
|
||||
@@ -6,6 +6,38 @@ do_reset_changes=0
|
||||
do_reset_dcevm=0
|
||||
HEAD_REVISION=0
|
||||
|
||||
OS_NAME=$(uname -s)
|
||||
# Enable reproducible builds
|
||||
TZ=UTC
|
||||
export TZ
|
||||
SOURCE_DATE_EPOCH="$(git log -1 --pretty=%ct)"
|
||||
export SOURCE_DATE_EPOCH
|
||||
USER=builduser
|
||||
export USER
|
||||
|
||||
case "$OS_NAME" in
|
||||
Linux)
|
||||
COPYRIGHT_YEAR="$(date --utc --date=@$SOURCE_DATE_EPOCH +%Y)"
|
||||
BUILD_TIME="$(date --utc --date=@$SOURCE_DATE_EPOCH +%F)"
|
||||
REPRODUCIBLE_TAR_OPTS="--mtime=@$SOURCE_DATE_EPOCH --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime"
|
||||
;;
|
||||
Darwin)
|
||||
COPYRIGHT_YEAR="$(date -u -r $SOURCE_DATE_EPOCH +%Y)"
|
||||
BUILD_TIME="$(date -u -r $SOURCE_DATE_EPOCH +%F)"
|
||||
TOUCH_TIME="$(date -u -r $SOURCE_DATE_EPOCH +%Y%m%d%H%M.%S)"
|
||||
REPRODUCIBLE_TAR_OPTS="--uid 0 --gid 0 --numeric-owner"
|
||||
;;
|
||||
*)
|
||||
# TODO: Windows
|
||||
;;
|
||||
esac
|
||||
|
||||
REPRODUCIBLE_BUILD_OPTS="--enable-reproducible-build
|
||||
--with-source-date=$SOURCE_DATE_EPOCH
|
||||
--with-hotspot-build-time=$BUILD_TIME
|
||||
--with-copyright-year=$COPYRIGHT_YEAR
|
||||
--with-native-debug-symbols=none"
|
||||
|
||||
function do_exit() {
|
||||
exit_code=$1
|
||||
[ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java
|
||||
|
||||
@@ -24,8 +24,6 @@ source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
|
||||
[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?)
|
||||
|
||||
sh configure \
|
||||
--with-debug-level=release \
|
||||
--with-vendor-name="${VENDOR_NAME}" \
|
||||
@@ -35,7 +33,9 @@ sh configure \
|
||||
--with-version-build="${JDK_BUILD_NUMBER}" \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-boot-jdk=${BOOT_JDK} \
|
||||
--enable-cds=yes || exit $?
|
||||
--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 $?
|
||||
|
||||
@@ -54,9 +54,11 @@ echo Creating $JBSDK.tar.gz ...
|
||||
sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release
|
||||
mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release
|
||||
|
||||
tar -pcf $JBSDK.tar \
|
||||
# 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 $?
|
||||
|
||||
JBR_BUNDLE=jbr
|
||||
@@ -75,10 +77,11 @@ echo Modifying release info ...
|
||||
grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${BASE_DIR}/${JBR_BUNDLE}/release
|
||||
|
||||
echo Creating $JBR.tar.gz ...
|
||||
tar -pcf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE} || exit $?
|
||||
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 $?
|
||||
gzip $JBRSDK_TEST.tar || exit $?
|
||||
|
||||
@@ -50,7 +50,9 @@ function do_configure {
|
||||
--with-version-build="$JDK_BUILD_NUMBER" \
|
||||
--with-version-opt=b"$build_number" \
|
||||
--with-boot-jdk="$BOOT_JDK" \
|
||||
--enable-cds=yes || do_exit $?
|
||||
--enable-cds=yes \
|
||||
$REPRODUCIBLE_BUILD_OPTS \
|
||||
|| do_exit $?
|
||||
}
|
||||
|
||||
function create_image_bundle {
|
||||
@@ -79,8 +81,14 @@ function create_image_bundle {
|
||||
[ -f "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper
|
||||
|
||||
echo Creating "$JBR".tar.gz ...
|
||||
tar -pcf "$JBR".tar -C "$IMAGES_DIR" "$__arch_name" || do_exit $?
|
||||
|
||||
(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"
|
||||
}
|
||||
@@ -150,4 +158,4 @@ if [ -z "$bundle_type" ]; then
|
||||
gzip "$JBRSDK_TEST".tar || do_exit $?
|
||||
fi
|
||||
|
||||
do_exit 0
|
||||
do_exit 0
|
||||
|
||||
@@ -47,18 +47,14 @@ BOOT_JDK=${BOOT_JDK:=$(/usr/libexec/java_home -v 16)}
|
||||
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
function copyJNF {
|
||||
__contents_dir=$1
|
||||
mkdir -p ${__contents_dir}/Frameworks
|
||||
cp -Rp Frameworks/JavaNativeFoundation.framework ${__contents_dir}/Frameworks
|
||||
}
|
||||
|
||||
function do_configure {
|
||||
if [[ "${architecture}" == *aarch64* ]]; then
|
||||
sh configure \
|
||||
$WITH_DEBUG_LEVEL \
|
||||
--with-vendor-name="${VENDOR_NAME}" \
|
||||
--with-vendor-version-string="${VENDOR_VERSION_STRING}" \
|
||||
--with-macosx-bundle-name-base=${VENDOR_VERSION_STRING} \
|
||||
--with-macosx-bundle-id-base="com.jetbrains.jbr" \
|
||||
--with-jvm-features=shenandoahgc \
|
||||
--with-version-pre= \
|
||||
--with-version-build="${JDK_BUILD_NUMBER}" \
|
||||
@@ -69,19 +65,25 @@ function do_configure {
|
||||
--enable-cds=no \
|
||||
--with-extra-cflags="-F$(pwd)/Frameworks" \
|
||||
--with-extra-cxxflags="-F$(pwd)/Frameworks" \
|
||||
--with-extra-ldflags="-F$(pwd)/Frameworks" || do_exit $?
|
||||
--with-extra-ldflags="-F$(pwd)/Frameworks" \
|
||||
$REPRODUCIBLE_BUILD_OPTS \
|
||||
|| do_exit $?
|
||||
else
|
||||
sh configure \
|
||||
$WITH_DEBUG_LEVEL \
|
||||
--with-vendor-name="$VENDOR_NAME" \
|
||||
--with-vendor-version-string="$VENDOR_VERSION_STRING" \
|
||||
--with-macosx-bundle-name-base=${VENDOR_VERSION_STRING} \
|
||||
--with-macosx-bundle-id-base="com.jetbrains.jbr" \
|
||||
--with-jvm-features=shenandoahgc \
|
||||
--with-version-pre= \
|
||||
--with-version-build="$JDK_BUILD_NUMBER" \
|
||||
--with-version-opt=b"$build_number" \
|
||||
--with-boot-jdk="$BOOT_JDK" \
|
||||
--with-macosx-version-max="${MACOSX_VERSION_MAX:="10.12.00"}" \
|
||||
--enable-cds=yes || do_exit $?
|
||||
--enable-cds=yes \
|
||||
$REPRODUCIBLE_BUILD_OPTS \
|
||||
|| do_exit $?
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -115,16 +117,17 @@ function create_image_bundle {
|
||||
cp -R "$JSDK"/../MacOS "$JRE_CONTENTS"
|
||||
cp "$JSDK"/../Info.plist "$JRE_CONTENTS"
|
||||
|
||||
if [[ "${architecture}" == *aarch64* ]]; then
|
||||
# we can't notarize this library as usual framework (with headers and tbd-file)
|
||||
# but single library notarizes correctly
|
||||
copyJNF $JRE_CONTENTS
|
||||
fi
|
||||
|
||||
[ -n "$bundle_type" ] && (cp -a $JCEF_PATH/Frameworks "$JRE_CONTENTS" || do_exit $?)
|
||||
|
||||
echo Creating "$JBR".tar.gz ...
|
||||
COPYFILE_DISABLE=1 tar -pczf "$JBR".tar.gz --exclude='*.dSYM' --exclude='man' -C "$tmp" "$__arch_name" || do_exit $?
|
||||
# Normalize timestamp
|
||||
find "$tmp"/"$__arch_name" -print0 | xargs -0 touch -c -h -t "$TOUCH_TIME"
|
||||
|
||||
(cd "$tmp" &&
|
||||
find "$__arch_name" -print0 | LC_ALL=C sort -z | \
|
||||
COPYFILE_DISABLE=1 tar $REPRODUCIBLE_TAR_OPTS --no-recursion --null -T - \
|
||||
-czf "$JBR".tar.gz --exclude='*.dSYM' --exclude='man') || do_exit $?
|
||||
mv "$tmp"/"$JBR".tar.gz "$JBR".tar.gz
|
||||
rm -rf "$tmp"
|
||||
}
|
||||
|
||||
@@ -198,4 +201,4 @@ if [ -z "$bundle_type" ]; then
|
||||
COPYFILE_DISABLE=1 tar -pczf "$JBRSDK_TEST".tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $?
|
||||
fi
|
||||
|
||||
do_exit 0
|
||||
do_exit 0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/bin/bash -x
|
||||
|
||||
APP_DIRECTORY=$1
|
||||
APPL_USER=$2
|
||||
@@ -54,17 +54,15 @@ function altool-upload() {
|
||||
#immediately exit script with an error if a command fails
|
||||
set -euo pipefail
|
||||
|
||||
file="$APP_NAME.zip"
|
||||
#file="$APP_NAME.zip"
|
||||
|
||||
log "Zipping $file..."
|
||||
rm -rf "$file"
|
||||
ditto -c -k --sequesterRsrc --keepParent "$APP_DIRECTORY" "$file"
|
||||
#log "Zipping $file..."
|
||||
#rm -rf "$file"
|
||||
#ditto -c -k --sequesterRsrc --keepParent "$APP_DIRECTORY" "$file"
|
||||
|
||||
log "Notarizing $file..."
|
||||
log "Notarizing $APP_NAME..."
|
||||
rm -rf "altool.init.out" "altool.check.out"
|
||||
altool-upload "$file"
|
||||
|
||||
rm -rf "$file"
|
||||
altool-upload "$APP_NAME"
|
||||
|
||||
notarization_info="$(grep -e "RequestUUID" "altool.init.out" | grep -oE '([0-9a-f-]{36})')"
|
||||
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
#!/bin/bash
|
||||
#!/bin/bash -x
|
||||
|
||||
APP_DIRECTORY=$1
|
||||
JB_CERT=$2
|
||||
APPLICATION_PATH=$1
|
||||
APP_NAME=$2
|
||||
BUNDLE_ID=$3
|
||||
JB_DEVELOPER_CERT=$4
|
||||
JB_INSTALLER_CERT=$5
|
||||
|
||||
if [[ -z "$APP_DIRECTORY" ]] || [[ -z "$JB_CERT" ]]; then
|
||||
if [[ -z "$APPLICATION_PATH" ]] || [[ -z "$JB_DEVELOPER_CERT" ]]; then
|
||||
echo "Usage: $0 AppDirectory CertificateID"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -d "$APP_DIRECTORY" ]]; then
|
||||
echo "AppDirectory '$APP_DIRECTORY' does not exist or not a directory"
|
||||
if [[ ! -d "$APPLICATION_PATH" ]]; then
|
||||
echo "AppDirectory '$APPLICATION_PATH' does not exist or not a directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -20,43 +23,30 @@ function log() {
|
||||
set -euo pipefail
|
||||
|
||||
# Cleanup files left from previous sign attempt (if any)
|
||||
find "$APP_DIRECTORY" -name '*.cstemp' -exec rm '{}' \;
|
||||
find "$APPLICATION_PATH" -name '*.cstemp' -exec rm '{}' \;
|
||||
|
||||
log "Signing libraries and executables..."
|
||||
# -perm +111 searches for executables
|
||||
for f in \
|
||||
"Contents/Home/bin" \
|
||||
"Contents/Home/lib"; do
|
||||
if [ -d "$APP_DIRECTORY/$f" ]; then
|
||||
find "$APP_DIRECTORY/$f" \
|
||||
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \
|
||||
-exec codesign --timestamp --force \
|
||||
-v -s "$JB_CERT" --options=runtime \
|
||||
"Contents/Home/lib" "Contents/MacOS" \
|
||||
"Contents/Home/Frameworks" \
|
||||
"Contents/Frameworks"; do
|
||||
if [ -d "$APPLICATION_PATH/$f" ]; then
|
||||
find "$APPLICATION_PATH/$f" \
|
||||
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "*.tbd" -o -name "*.node" -o -perm +111 \) \
|
||||
-exec codesign --timestamp \
|
||||
-v -s "$JB_DEVELOPER_CERT" --options=runtime --force \
|
||||
--entitlements entitlements.xml {} \;
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -d "$APP_DIRECTORY/Contents/Frameworks" ]; then
|
||||
log "Signing frameworks..."
|
||||
for f in $APP_DIRECTORY/Contents/Frameworks/*; do
|
||||
find "$f" \
|
||||
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" \) \
|
||||
-exec codesign --timestamp --force \
|
||||
-v -s "$JB_CERT" \
|
||||
--entitlements entitlements.xml {} \;
|
||||
codesign --timestamp --force \
|
||||
-v -s "$JB_CERT" --options=runtime \
|
||||
--entitlements entitlements.xml "$f"
|
||||
done
|
||||
fi
|
||||
|
||||
log "Signing libraries in jars in $PWD"
|
||||
|
||||
# todo: add set -euo pipefail; into the inner sh -c
|
||||
# `-e` prevents `grep -q && printf` loginc
|
||||
# with `-o pipefail` there's no input for 'while' loop
|
||||
find "$APP_DIRECTORY" -name '*.jar' \
|
||||
-exec sh -c "set -u; unzip -l \"\$0\" | grep -q -e '\.dylib\$' -e '\.jnilib\$' -e '\.so\$' -e '^jattach\$' && printf \"\$0\0\" " {} \; |
|
||||
find "$APPLICATION_PATH" -name '*.jar' \
|
||||
-exec sh -c "set -u; unzip -l \"\$0\" | grep -q -e '\.dylib\$' -e '\.jnilib\$' -e '\.so\$' -e '\.tbd\$' -e '^jattach\$' && printf \"\$0\0\" " {} \; |
|
||||
while IFS= read -r -d $'\0' file; do
|
||||
log "Processing libraries in $file"
|
||||
|
||||
@@ -67,12 +57,13 @@ find "$APP_DIRECTORY" -name '*.jar' \
|
||||
cp "$file" jarfolder && (cd jarfolder && jar xf "$filename" && rm "$filename")
|
||||
|
||||
find jarfolder \
|
||||
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "jattach" \) \
|
||||
-exec codesign --timestamp --force \
|
||||
-v -s "$JB_CERT" --options=runtime \
|
||||
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "*.tbd" -o -name "jattach" \) \
|
||||
-exec codesign --timestamp \
|
||||
--force \
|
||||
-v -s "$JB_DEVELOPER_CERT" --options=runtime \
|
||||
--entitlements entitlements.xml {} \;
|
||||
|
||||
(cd jarfolder; zip -q -r -o ../jar.jar .)
|
||||
(cd jarfolder; zip -q -r -o -0 ../jar.jar .)
|
||||
mv jar.jar "$file"
|
||||
done
|
||||
|
||||
@@ -80,28 +71,41 @@ rm -rf jarfolder jar.jar
|
||||
|
||||
log "Signing other files..."
|
||||
for f in \
|
||||
"Contents/MacOS"; do
|
||||
if [ -d "$APP_DIRECTORY/$f" ]; then
|
||||
find "$APP_DIRECTORY/$f" \
|
||||
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \
|
||||
-exec codesign --timestamp --force \
|
||||
-v -s "$JB_CERT" --options=runtime \
|
||||
"Contents/Home/bin"; do
|
||||
if [ -d "$APPLICATION_PATH/$f" ]; then
|
||||
find "$APPLICATION_PATH/$f" \
|
||||
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "*.tbd" -o -perm +111 \) \
|
||||
-exec codesign --timestamp \
|
||||
-v -s "$JB_DEVELOPER_CERT" --options=runtime --force \
|
||||
--entitlements entitlements.xml {} \;
|
||||
fi
|
||||
done
|
||||
|
||||
#log "Signing executable..."
|
||||
#codesign --timestamp \
|
||||
# -v -s "$JB_CERT" --options=runtime \
|
||||
# -v -s "$JB_DEVELOPER_CERT" --options=runtime \
|
||||
# --force \
|
||||
# --entitlements entitlements.xml "$APP_DIRECTORY/Contents/MacOS/idea"
|
||||
# --entitlements entitlements.xml "$APPLICATION_PATH/Contents/MacOS/idea"
|
||||
|
||||
log "Signing whole app..."
|
||||
codesign --timestamp \
|
||||
-v -s "$JB_CERT" --options=runtime \
|
||||
-v -s "$JB_DEVELOPER_CERT" --options=runtime \
|
||||
--force \
|
||||
--entitlements entitlements.xml "$APP_DIRECTORY"
|
||||
--entitlements entitlements.xml "$APPLICATION_PATH"
|
||||
|
||||
BUILD_NAME=$(echo $APPLICATION_PATH | awk -F"/" '{ print $2 }')
|
||||
|
||||
log "Creating $APP_NAME.pkg..."
|
||||
rm -rf "$APP_NAME.pkg"
|
||||
pkgbuild --identifier $BUNDLE_ID --sign "$JB_INSTALLER_CERT" --root $APPLICATION_PATH \
|
||||
--install-location /Library/Java/JavaVirtualMachines/${BUILD_NAME} ${APP_NAME}.pkg
|
||||
|
||||
#log "Signing whole app..."
|
||||
#codesign --timestamp \
|
||||
# -v -s "$JB_DEVELOPER_CERT" --options=runtime \
|
||||
# --force \
|
||||
# --entitlements entitlements.xml $APP_NAME.pkg
|
||||
|
||||
log "Verifying java is not broken"
|
||||
find "$APP_DIRECTORY" \
|
||||
find "$APPLICATION_PATH" \
|
||||
-type f -name 'java' -perm +111 -exec {} -version \;
|
||||
|
||||
@@ -12,8 +12,9 @@ BACKUP_JMODS=$2.backup
|
||||
USERNAME=$3
|
||||
PASSWORD=$4
|
||||
CODESIGN_STRING=$5
|
||||
NOTARIZE=$6
|
||||
BUNDLE_ID=$7
|
||||
JB_INSTALLER_CERT=$6
|
||||
NOTARIZE=$7
|
||||
BUNDLE_ID=$8
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
@@ -33,7 +34,7 @@ mkdir "$BACKUP_JMODS"
|
||||
log "Unzipping $INPUT_FILE to $EXPLODED ..."
|
||||
tar -xzvf "$INPUT_FILE" --directory $EXPLODED
|
||||
BUILD_NAME="$(ls "$EXPLODED")"
|
||||
sed -i '' s/BNDL/APPL/ $EXPLODED/$BUILD_NAME/Contents/Info.plist
|
||||
#sed -i '' s/BNDL/APPL/ $EXPLODED/$BUILD_NAME/Contents/Info.plist
|
||||
rm -f $EXPLODED/$BUILD_NAME/Contents/CodeResources
|
||||
rm "$INPUT_FILE"
|
||||
if test -d $EXPLODED/$BUILD_NAME/Contents/Home/jmods; then
|
||||
@@ -42,7 +43,9 @@ fi
|
||||
|
||||
log "$INPUT_FILE extracted and removed"
|
||||
|
||||
APPLICATION_PATH="$EXPLODED/$BUILD_NAME"
|
||||
APP_NAME=$(echo ${INPUT_FILE} | awk -F".tar" '{ print $1 }')
|
||||
APPLICATION_PATH=$(sed "s/osx-//" <<< "$EXPLODED/$APP_NAME")
|
||||
mv $EXPLODED/$BUILD_NAME $APPLICATION_PATH
|
||||
|
||||
find "$APPLICATION_PATH/Contents/Home/bin" \
|
||||
-maxdepth 1 -type f -name '*.jnilib' -print0 |
|
||||
@@ -79,7 +82,7 @@ limit=3
|
||||
set +e
|
||||
while [[ $attempt -le $limit ]]; do
|
||||
log "Signing (attempt $attempt) $APPLICATION_PATH ..."
|
||||
./sign.sh "$APPLICATION_PATH" "$CODESIGN_STRING"
|
||||
./sign.sh "$APPLICATION_PATH" "$APP_NAME" "$BUNDLE_ID" "$CODESIGN_STRING" "$JB_INSTALLER_CERT"
|
||||
ec=$?
|
||||
if [[ $ec -ne 0 ]]; then
|
||||
((attempt += 1))
|
||||
@@ -92,6 +95,7 @@ while [[ $attempt -le $limit ]]; do
|
||||
log "Signing done"
|
||||
codesign -v "$APPLICATION_PATH" -vvvvv
|
||||
log "Check sign done"
|
||||
spctl -a -v $APPLICATION_PATH
|
||||
((attempt += limit))
|
||||
fi
|
||||
done
|
||||
@@ -102,13 +106,12 @@ if [ "$NOTARIZE" = "yes" ]; then
|
||||
log "Notarizing..."
|
||||
# shellcheck disable=SC1090
|
||||
source "$HOME/.notarize_token"
|
||||
APP_NAME=$(echo ${INPUT_FILE} | awk -F"." '{ print $1 }')
|
||||
# Since notarization tool uses same file for upload token we have to trick it into using different folders, hence fake root
|
||||
# Also it leaves copy of zip file in TMPDIR, so notarize.sh overrides it and uses FAKE_ROOT as location for temp TMPDIR
|
||||
FAKE_ROOT="$(pwd)/fake-root"
|
||||
mkdir -p "$FAKE_ROOT"
|
||||
echo "Notarization will use fake root: $FAKE_ROOT"
|
||||
./notarize.sh "$APPLICATION_PATH" "$APPLE_USERNAME" "$APPLE_PASSWORD" "$APP_NAME" "$BUNDLE_ID" "$FAKE_ROOT"
|
||||
./notarize.sh "$APPLICATION_PATH" "$APPLE_USERNAME" "$APPLE_PASSWORD" "$APP_NAME.pkg" "$BUNDLE_ID" "$FAKE_ROOT"
|
||||
rm -rf "$FAKE_ROOT"
|
||||
|
||||
set +e
|
||||
@@ -124,10 +127,11 @@ log "Zipping $BUILD_NAME to $INPUT_FILE ..."
|
||||
#cd "$EXPLODED"
|
||||
#ditto -c -k --sequesterRsrc --keepParent "$BUILD_NAME" "../$INPUT_FILE"
|
||||
if test -d $BACKUP_JMODS/jmods; then
|
||||
mv $BACKUP_JMODS/jmods $EXPLODED/$BUILD_NAME/Contents/Home
|
||||
mv $BACKUP_JMODS/jmods $APPLICATION_PATH/Contents/Home
|
||||
fi
|
||||
mv $APPLICATION_PATH $EXPLODED/$BUILD_NAME
|
||||
|
||||
tar -pczvf $INPUT_FILE --exclude='*.dSYM' --exclude='man' -C $EXPLODED $BUILD_NAME
|
||||
tar -pczvf $INPUT_FILE --exclude='man' -C $EXPLODED $BUILD_NAME
|
||||
log "Finished zipping"
|
||||
)
|
||||
rm -rf "$EXPLODED"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2016, 2021, 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
|
||||
@@ -88,7 +88,10 @@ $(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXECUTABLE_SUFFIX) $(CLASSLIST
|
||||
$(CAT) $(LINK_OPT_DIR)/stderr $(JLI_TRACE_FILE) ; \
|
||||
exit $$exitcode \
|
||||
)
|
||||
$(GREP) -v HelloClasslist $@.raw.2 > $@
|
||||
$(GREP) -v HelloClasslist $@.raw.2 > $@.raw.3
|
||||
$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java \
|
||||
-cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
|
||||
build.tools.classlist.SortClasslist $@.raw.3 > $@
|
||||
|
||||
# The jli trace is created by the same recipe as classlist. By declaring these
|
||||
# dependencies, make will correctly rebuild both jli trace and classlist
|
||||
|
||||
@@ -324,7 +324,7 @@ $(eval $(call SetupTarget, vscode-project-ccls, \
|
||||
# aren't built until after libjava and libjvm are available to link to.
|
||||
$(eval $(call SetupTarget, demos-jdk, \
|
||||
MAKEFILE := CompileDemos, \
|
||||
DEPS := java.base-libs exploded-image, \
|
||||
DEPS := java.base-libs exploded-image buildtools-jdk, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupTarget, test-image-demos-jdk, \
|
||||
@@ -383,12 +383,12 @@ bootcycle-images:
|
||||
|
||||
$(eval $(call SetupTarget, zip-security, \
|
||||
MAKEFILE := ZipSecurity, \
|
||||
DEPS := java.base-java java.security.jgss-java java.security.jgss-libs, \
|
||||
DEPS := buildtools-jdk java.base-java java.security.jgss-java java.security.jgss-libs, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupTarget, zip-source, \
|
||||
MAKEFILE := ZipSource, \
|
||||
DEPS := gensrc, \
|
||||
DEPS := buildtools-jdk gensrc, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupTarget, jrtfs-jar, \
|
||||
@@ -508,13 +508,13 @@ $(eval $(call SetupTarget, docs-jdk-index, \
|
||||
$(eval $(call SetupTarget, docs-zip, \
|
||||
MAKEFILE := Docs, \
|
||||
TARGET := docs-zip, \
|
||||
DEPS := docs-jdk, \
|
||||
DEPS := docs-jdk buildtools-jdk, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupTarget, docs-specs-zip, \
|
||||
MAKEFILE := Docs, \
|
||||
TARGET := docs-specs-zip, \
|
||||
DEPS := docs-jdk-specs, \
|
||||
DEPS := docs-jdk-specs buildtools-jdk, \
|
||||
))
|
||||
|
||||
$(eval $(call SetupTarget, update-build-docs, \
|
||||
|
||||
@@ -80,6 +80,8 @@ TOOL_GENERATECACERTS = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_class
|
||||
TOOL_GENERATEEMOJIDATA = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
||||
build.tools.generateemojidata.GenerateEmojiData
|
||||
|
||||
TOOL_MAKEZIPREPRODUCIBLE = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
||||
build.tools.makezipreproducible.MakeZipReproducible
|
||||
|
||||
# TODO: There are references to the jdwpgen.jar in jdk/make/netbeans/jdwpgen/build.xml
|
||||
# and nbproject/project.properties in the same dir. Needs to be looked at.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@@ -94,11 +94,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_PATHS],
|
||||
|
||||
# Locate the directory of this script.
|
||||
AUTOCONF_DIR=$TOPDIR/make/autoconf
|
||||
|
||||
# Setup username (for use in adhoc version strings etc)
|
||||
# Outer [ ] to quote m4.
|
||||
[ USERNAME=`$ECHO "$USER" | $TR -d -c '[a-z][A-Z][0-9]'` ]
|
||||
AC_SUBST(USERNAME)
|
||||
])
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -356,6 +356,14 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS],
|
||||
fi
|
||||
AC_SUBST(IS_GNU_TIME)
|
||||
|
||||
# Check if it's GNU date
|
||||
check_date=`$DATE --version 2>&1 | $GREP GNU`
|
||||
if test "x$check_date" != x; then
|
||||
IS_GNU_DATE=yes
|
||||
else
|
||||
IS_GNU_DATE=no
|
||||
fi
|
||||
|
||||
if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then
|
||||
UTIL_REQUIRE_PROGS(DSYMUTIL, dsymutil)
|
||||
UTIL_REQUIRE_PROGS(MIG, mig)
|
||||
|
||||
@@ -199,6 +199,12 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS],
|
||||
AC_MSG_ERROR([Copyright year must have a value])
|
||||
elif test "x$with_copyright_year" != x; then
|
||||
COPYRIGHT_YEAR="$with_copyright_year"
|
||||
elif test "x$SOURCE_DATE_EPOCH" != x; then
|
||||
if test "x$IS_GNU_DATE" = xyes; then
|
||||
COPYRIGHT_YEAR=`date --date=@$SOURCE_DATE_EPOCH +%Y`
|
||||
else
|
||||
COPYRIGHT_YEAR=`date -j -f %s $SOURCE_DATE_EPOCH +%Y`
|
||||
fi
|
||||
else
|
||||
COPYRIGHT_YEAR=`$DATE +'%Y'`
|
||||
fi
|
||||
@@ -735,7 +741,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_REPRODUCIBLE_BUILD],
|
||||
if test "x$OPENJDK_BUILD_OS" = xwindows && \
|
||||
test "x$ALLOW_ABSOLUTE_PATHS_IN_OUTPUT" = xfalse && \
|
||||
test "x$ENABLE_REPRODUCIBLE_BUILD" = xfalse; then
|
||||
AC_MSG_NOTICE([On Windows it is not possible to combine --disable-reproducible-builds])
|
||||
AC_MSG_NOTICE([On Windows it is not possible to combine --disable-reproducible-build])
|
||||
AC_MSG_NOTICE([with --disable-absolute-paths-in-output.])
|
||||
AC_MSG_ERROR([Cannot continue])
|
||||
fi
|
||||
|
||||
@@ -69,6 +69,17 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS],
|
||||
AC_SUBST(JDK_RC_PLATFORM_NAME)
|
||||
AC_SUBST(HOTSPOT_VM_DISTRO)
|
||||
|
||||
# Setup username (for use in adhoc version strings etc)
|
||||
AC_ARG_WITH([build-user], [AS_HELP_STRING([--with-build-user],
|
||||
[build username to use in version strings])])
|
||||
if test "x$with_build_user" != x; then
|
||||
USERNAME="$with_build_user"
|
||||
else
|
||||
# Outer [ ] to quote m4.
|
||||
[ USERNAME=`$ECHO "$USER" | $TR -d -c '[a-z][A-Z][0-9]'` ]
|
||||
fi
|
||||
AC_SUBST(USERNAME)
|
||||
|
||||
# Set the JDK RC name
|
||||
AC_ARG_WITH(jdk-rc-name, [AS_HELP_STRING([--with-jdk-rc-name],
|
||||
[Set JDK RC name. This is used for FileDescription and ProductName properties
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@@ -26,6 +26,9 @@
|
||||
ifndef _ZIP_ARCHIVE_GMK
|
||||
_ZIP_ARCHIVE_GMK := 1
|
||||
|
||||
# Depends on build tools for MakeZipReproducible
|
||||
include ../ToolsJdk.gmk
|
||||
|
||||
ifeq (,$(_MAKEBASE_GMK))
|
||||
$(error You must include MakeBase.gmk prior to including ZipArchive.gmk)
|
||||
endif
|
||||
@@ -51,6 +54,8 @@ endif
|
||||
# FOLLOW_SYMLINKS - Set to explicitly follow symlinks. Affects performance of
|
||||
# finding files.
|
||||
# ZIP_OPTIONS extra options to pass to zip
|
||||
# REPRODUCIBLE override ENABLE_REPRODUCIBLE_BUILD (to make zip reproducible or not)
|
||||
|
||||
SetupZipArchive = $(NamedParamsMacroTemplate)
|
||||
define SetupZipArchiveBody
|
||||
|
||||
@@ -124,6 +129,10 @@ define SetupZipArchiveBody
|
||||
) \
|
||||
)
|
||||
|
||||
ifeq ($$($1_REPRODUCIBLE), )
|
||||
$1_REPRODUCIBLE := $$(ENABLE_REPRODUCIBLE_BUILD)
|
||||
endif
|
||||
|
||||
# Use a slightly shorter name for logging, but with enough path to identify this zip.
|
||||
$1_NAME:=$$(subst $$(OUTPUTDIR)/,,$$($1_ZIP))
|
||||
|
||||
@@ -134,6 +143,8 @@ define SetupZipArchiveBody
|
||||
# dir is very small.
|
||||
# If zip has nothing to do, it returns 12 and would fail the build. Check for 12
|
||||
# and only fail if it's not.
|
||||
# For reproducible builds set the zip access & modify times to SOURCE_DATE_EPOCH
|
||||
# by using a ziptmp folder to generate final zip from using MakeZipReproducible.
|
||||
$$($1_ZIP) : $$($1_ALL_SRCS) $$($1_EXTRA_DEPS)
|
||||
$$(call LogWarn, Updating $$($1_NAME))
|
||||
$$(call MakeTargetDir)
|
||||
@@ -163,7 +174,18 @@ define SetupZipArchiveBody
|
||||
$$($1_ZIP_EXCLUDES_$$s) \
|
||||
|| test "$$$$?" = "12" \
|
||||
))$$(NEWLINE) \
|
||||
) true \
|
||||
) true
|
||||
ifeq ($$($1_REPRODUCIBLE), true)
|
||||
$$(call ExecuteWithLog, \
|
||||
$$(SUPPORT_OUTPUTDIR)/makezipreproducible/$$(patsubst $$(OUTPUTDIR)/%,%, $$@), \
|
||||
($(RM) $$(SUPPORT_OUTPUTDIR)/ziptmp/$1/tmp.zip && \
|
||||
$(MKDIR) -p $$(SUPPORT_OUTPUTDIR)/ziptmp/$1 && \
|
||||
$(TOOL_MAKEZIPREPRODUCIBLE) -f $$(SUPPORT_OUTPUTDIR)/ziptmp/$1/tmp.zip \
|
||||
-t $(SOURCE_DATE_EPOCH) $$@ && \
|
||||
$(RM) $$@ && \
|
||||
$(MV) $$(SUPPORT_OUTPUTDIR)/ziptmp/$1/tmp.zip $$@ \
|
||||
))
|
||||
endif
|
||||
$(TOUCH) $$@
|
||||
|
||||
# Add zip to target list
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This application is meant to be run to create a classlist file representing
|
||||
* common use.
|
||||
*
|
||||
* The classlist is produced by adding -XX:DumpLoadedClassList=classlist
|
||||
*/
|
||||
package build.tools.classlist;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* The classlist generated by build.tools.classlist.HelloClasslist
|
||||
* may have non-deterministic contents, affected by Java thread execution order.
|
||||
* SortClasslist sorts the file to make the JDK image's contents more deterministic.
|
||||
*/
|
||||
public class SortClasslist {
|
||||
public static void main(String args[]) throws FileNotFoundException {
|
||||
ArrayList<String> classes = new ArrayList<>();
|
||||
ArrayList<String> lambdas = new ArrayList<>();
|
||||
|
||||
FileInputStream fis = new FileInputStream(args[0]);
|
||||
Scanner scanner = new Scanner(fis);
|
||||
while (scanner.hasNextLine()) {
|
||||
String line = scanner.nextLine();
|
||||
if (line.startsWith("#")) {
|
||||
// Comments -- print them first without sorting. These appear only at the top
|
||||
// of the file.
|
||||
System.out.println(line);
|
||||
} else if (line.startsWith("@")) {
|
||||
// @lambda-form-invoker, @lambda-proxy, etc.
|
||||
lambdas.add(line);
|
||||
} else {
|
||||
// We should find a pattern like this:
|
||||
//
|
||||
// <beginning of line>java/lang/Object<end of line>
|
||||
final String className = line;
|
||||
classes.add(className);
|
||||
}
|
||||
}
|
||||
|
||||
Collections.sort(classes);
|
||||
Collections.sort(lambdas);
|
||||
|
||||
for (String s : classes) {
|
||||
System.out.println(s);
|
||||
}
|
||||
for (String s : lambdas) {
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,6 +114,7 @@ public class CLDRConverter {
|
||||
ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT);
|
||||
|
||||
private static Set<String> AVAILABLE_TZIDS;
|
||||
static int copyrightYear;
|
||||
private static String zoneNameTempFile;
|
||||
private static String tzDataDir;
|
||||
private static final Map<String, String> canonicalTZMap = new HashMap<>();
|
||||
@@ -217,6 +218,10 @@ public class CLDRConverter {
|
||||
verbose = true;
|
||||
break;
|
||||
|
||||
case "-year":
|
||||
copyrightYear = Integer.parseInt(args[++i]);
|
||||
break;
|
||||
|
||||
case "-zntempfile":
|
||||
zoneNameTempFile = args[++i];
|
||||
break;
|
||||
@@ -235,7 +240,7 @@ public class CLDRConverter {
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
severe("unknown or imcomplete arg(s): " + currentArg);
|
||||
severe("unknown or incomplete arg(s): " + currentArg);
|
||||
usage();
|
||||
System.exit(1);
|
||||
}
|
||||
@@ -260,6 +265,10 @@ public class CLDRConverter {
|
||||
setupBaseLocales("en-US");
|
||||
}
|
||||
|
||||
if (copyrightYear == 0) {
|
||||
copyrightYear = ZonedDateTime.now(ZoneId.of("America/Los_Angeles")).getYear();
|
||||
}
|
||||
|
||||
bundleGenerator = new ResourceBundleGenerator();
|
||||
|
||||
// Parse data independent of locales
|
||||
@@ -292,6 +301,7 @@ public class CLDRConverter {
|
||||
+ "\t-basemodule generates bundles that go into java.base module%n"
|
||||
+ "\t-baselocales loc(,loc)* locales that go into the base module%n"
|
||||
+ "\t-o dir output directory (default: ./build/gensrc)%n"
|
||||
+ "\t-year year copyright year in output%n"
|
||||
+ "\t-zntempfile template file for java.time.format.ZoneName.java%n"
|
||||
+ "\t-tzdatadir tzdata directory for java.time.format.ZoneName.java%n"
|
||||
+ "\t-utf8 use UTF-8 rather than \\uxxxx (for debug)%n");
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
package build.tools.cldrconverter;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
@@ -131,8 +132,7 @@ class CopyrightHeaders {
|
||||
" * questions.\n" +
|
||||
" */\n";
|
||||
|
||||
static String getOracleCopyright() {
|
||||
int year = getYear();
|
||||
static String getOracleCopyright(int year) {
|
||||
return String.format(year > 2012 ? ORACLE_AFTER2012 : ORACLE2012, year);
|
||||
}
|
||||
|
||||
@@ -140,16 +140,10 @@ class CopyrightHeaders {
|
||||
return UNICODE;
|
||||
}
|
||||
|
||||
static String getOpenJDKCopyright() {
|
||||
int year = getYear();
|
||||
static String getOpenJDKCopyright(int year) {
|
||||
return String.format(year > 2012 ? OPENJDK_AFTER2012 : OPENJDK2012, year);
|
||||
}
|
||||
|
||||
private static int getYear() {
|
||||
return new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles"),
|
||||
Locale.US).get(Calendar.YEAR);
|
||||
}
|
||||
|
||||
// no instantiation
|
||||
private CopyrightHeaders() {
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ class ResourceBundleGenerator implements BundleGenerator {
|
||||
|
||||
try (PrintWriter out = new PrintWriter(file, encoding)) {
|
||||
// Output copyright headers
|
||||
out.println(CopyrightHeaders.getOpenJDKCopyright());
|
||||
out.println(CopyrightHeaders.getOpenJDKCopyright(CLDRConverter.copyrightYear));
|
||||
out.println(CopyrightHeaders.getUnicodeCopyright());
|
||||
|
||||
if (useJava) {
|
||||
@@ -266,7 +266,7 @@ class ResourceBundleGenerator implements BundleGenerator {
|
||||
CLDRConverter.info("Generating file " + file);
|
||||
|
||||
try (PrintWriter out = new PrintWriter(file, "us-ascii")) {
|
||||
out.printf(CopyrightHeaders.getOpenJDKCopyright());
|
||||
out.printf(CopyrightHeaders.getOpenJDKCopyright(CLDRConverter.copyrightYear));
|
||||
|
||||
out.printf((CLDRConverter.isBaseModule ? "package sun.util.cldr;\n\n" :
|
||||
"package sun.util.resources.cldr.provider;\n\n")
|
||||
|
||||
@@ -30,13 +30,15 @@ import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.TreeMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -52,17 +54,19 @@ import java.util.stream.Collectors;
|
||||
public class EquivMapsGenerator {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length != 2) {
|
||||
if (args.length != 3) {
|
||||
System.err.println("Usage: java EquivMapsGenerator"
|
||||
+ " language-subtag-registry.txt LocaleEquivalentMaps.java");
|
||||
+ " language-subtag-registry.txt LocaleEquivalentMaps.java copyrightYear");
|
||||
System.exit(1);
|
||||
}
|
||||
copyrightYear = Integer.parseInt(args[2]);
|
||||
readLSRfile(args[0]);
|
||||
generateEquivalentMap();
|
||||
generateSourceCode(args[1]);
|
||||
}
|
||||
|
||||
private static String LSRrevisionDate;
|
||||
private static int copyrightYear;
|
||||
private static Map<String, StringBuilder> initialLanguageMap =
|
||||
new TreeMap<>();
|
||||
private static Map<String, StringBuilder> initialRegionVariantMap =
|
||||
@@ -246,9 +250,7 @@ public class EquivMapsGenerator {
|
||||
+ "}";
|
||||
|
||||
private static String getOpenJDKCopyright() {
|
||||
int year = ZonedDateTime.now(ZoneId
|
||||
.of("America/Los_Angeles")).getYear();
|
||||
return String.format(Locale.US, COPYRIGHT, year);
|
||||
return String.format(Locale.US, COPYRIGHT, copyrightYear);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package build.tools.makezipreproducible;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.*;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipException;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* Generate a zip file in a "reproducible" manner from the input zip file.
|
||||
* Standard zip tools rely on OS file list querying whose ordering can vary
|
||||
* by platform architecture, this class ensures the zip entries are ordered
|
||||
* and also supports SOURCE_DATE_EPOCH timestamps.
|
||||
*/
|
||||
public class MakeZipReproducible {
|
||||
String input_file = null;
|
||||
String fname = null;
|
||||
String zname = "";
|
||||
long timestamp = -1L;
|
||||
boolean verbose = false;
|
||||
|
||||
// Keep a sorted Set of ZipEntrys to be processed, so that the zip is reproducible
|
||||
SortedMap<String, ZipEntry> entries = new TreeMap<String, ZipEntry>();
|
||||
|
||||
private boolean ok;
|
||||
|
||||
public MakeZipReproducible() {
|
||||
}
|
||||
|
||||
public synchronized boolean run(String args[]) {
|
||||
ok = true;
|
||||
if (!parseArgs(args)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
zname = fname.replace(File.separatorChar, '/');
|
||||
if (zname.startsWith("./")) {
|
||||
zname = zname.substring(2);
|
||||
}
|
||||
|
||||
if (verbose) System.out.println("Input zip file: " + input_file);
|
||||
|
||||
File inFile = new File(input_file);
|
||||
if (!inFile.exists()) {
|
||||
error("Input zip file does not exist");
|
||||
ok = false;
|
||||
} else {
|
||||
File zipFile = new File(fname);
|
||||
// Check archive to create does not exist
|
||||
if (!zipFile.exists()) {
|
||||
// Process input ZipEntries
|
||||
ok = processInputEntries(inFile);
|
||||
if (ok) {
|
||||
try (FileOutputStream out = new FileOutputStream(fname)) {
|
||||
ok = create(inFile, new BufferedOutputStream(out, 4096));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
error("Target zip file "+fname+" already exists.");
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
fatalError(e);
|
||||
ok = false;
|
||||
} catch (Error ee) {
|
||||
ee.printStackTrace();
|
||||
ok = false;
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
ok = false;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
boolean parseArgs(String args[]) {
|
||||
try {
|
||||
boolean parsingIncludes = false;
|
||||
boolean parsingExcludes = false;
|
||||
int count = 0;
|
||||
while(count < args.length) {
|
||||
if (args[count].startsWith("-")) {
|
||||
String flag = args[count].substring(1);
|
||||
switch (flag.charAt(0)) {
|
||||
case 'f':
|
||||
fname = args[++count];
|
||||
break;
|
||||
case 't':
|
||||
// SOURCE_DATE_EPOCH timestamp specified
|
||||
timestamp = Long.parseLong(args[++count]) * 1000;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
default:
|
||||
error(String.format("Illegal option -%s", String.valueOf(flag.charAt(0))));
|
||||
usageError();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// input zip file
|
||||
if (input_file != null) {
|
||||
error("Input zip file already specified");
|
||||
usageError();
|
||||
return false;
|
||||
}
|
||||
input_file = args[count];
|
||||
}
|
||||
count++;
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
usageError();
|
||||
return false;
|
||||
} catch (NumberFormatException e) {
|
||||
usageError();
|
||||
return false;
|
||||
}
|
||||
if (fname == null) {
|
||||
error("-f <outputArchiveName> must be specified");
|
||||
usageError();
|
||||
return false;
|
||||
}
|
||||
// If no files specified then default to current directory
|
||||
if (input_file == null) {
|
||||
error("No input zip file specified");
|
||||
usageError();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Process input zip file and add to sorted entries set
|
||||
boolean processInputEntries(File inFile) throws IOException {
|
||||
ZipFile zipFile = new ZipFile(inFile);
|
||||
zipFile.stream().forEach(entry -> entries.put(entry.getName(), entry));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create new zip from entries
|
||||
boolean create(File inFile, OutputStream out) throws IOException
|
||||
{
|
||||
try (ZipFile zipFile = new ZipFile(inFile);
|
||||
ZipOutputStream zos = new ZipOutputStream(out)) {
|
||||
for (Map.Entry<String, ZipEntry> entry : entries.entrySet()) {
|
||||
ZipEntry zipEntry = entry.getValue();
|
||||
if (zipEntry.getSize() > 0) {
|
||||
try (InputStream eis = zipFile.getInputStream(zipEntry)) {
|
||||
addEntry(zos, zipEntry, eis);
|
||||
}
|
||||
} else {
|
||||
addEntry(zos, zipEntry, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add Entry and data to Zip
|
||||
void addEntry(ZipOutputStream zos, ZipEntry entry, InputStream entryInputStream) throws IOException {
|
||||
if (verbose) {
|
||||
System.out.println("Adding: "+entry.getName());
|
||||
}
|
||||
|
||||
// Set to specified timestamp if set otherwise leave as original lastModified time
|
||||
if (timestamp != -1L) {
|
||||
entry.setTime(timestamp);
|
||||
}
|
||||
|
||||
zos.putNextEntry(entry);
|
||||
if (entry.getSize() > 0 && entryInputStream != null) {
|
||||
entryInputStream.transferTo(zos);
|
||||
}
|
||||
zos.closeEntry();
|
||||
}
|
||||
|
||||
void usageError() {
|
||||
error(
|
||||
"Usage: MakeZipReproducible [-v] [-t <SOURCE_DATE_EPOCH>] -f <output_zip_file> <input_zip_file>\n" +
|
||||
"Options:\n" +
|
||||
" -v verbose output\n" +
|
||||
" -f specify archive file name to create\n" +
|
||||
" -t specific SOURCE_DATE_EPOCH value to use for timestamps\n" +
|
||||
" input_zip_file re-written as a reproducible zip output_zip_file.\n");
|
||||
}
|
||||
|
||||
void fatalError(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
protected void error(String s) {
|
||||
System.err.println(s);
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
MakeZipReproducible z = new MakeZipReproducible();
|
||||
System.exit(z.run(args) ? 0 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ $(CLDR_GEN_DONE): $(wildcard $(CLDR_DATA_DIR)/dtd/*.dtd) \
|
||||
-baselocales "en-US" \
|
||||
-o $(GENSRC_DIR) \
|
||||
-basemodule \
|
||||
-year $(COPYRIGHT_YEAR) \
|
||||
-zntempfile $(ZONENAME_TEMPLATE) \
|
||||
-tzdatadir $(TZ_DATA_DIR))
|
||||
$(TOUCH) $@
|
||||
@@ -99,7 +100,7 @@ GENSRC_LSREQUIVMAPS := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/util/locale/Loc
|
||||
|
||||
$(GENSRC_LSREQUIVMAPS): $(TOPDIR)/make/data/lsrdata/language-subtag-registry.txt $(BUILD_TOOLS_JDK)
|
||||
$(call MakeDir, $(@D))
|
||||
$(TOOL_GENERATELSREQUIVMAPS) $< $@
|
||||
$(TOOL_GENERATELSREQUIVMAPS) $< $@ $(COPYRIGHT_YEAR)
|
||||
|
||||
TARGETS += $(GENSRC_LSREQUIVMAPS)
|
||||
|
||||
|
||||
@@ -837,6 +837,19 @@ endif
|
||||
|
||||
################################################################################
|
||||
|
||||
# MACOSX_METAL_VERSION_MIN specifies the lowest version of Macosx
|
||||
# that should be used to compile Metal shaders. We support Metal
|
||||
# pipeline only on Macosx >=10.14. For Macosx versions <10.14 even if
|
||||
# we enable Metal pipeline using -Dsun.java2d.metal=true, at
|
||||
# runtime we force it to use OpenGL pipeline. And MACOSX_VERSION_MIN
|
||||
# for aarch64 has always been >10.14 so we use continue to use
|
||||
# MACOSX_VERSION_MIN for aarch64.
|
||||
ifeq ($(OPENJDK_TARGET_CPU_ARCH), xaarch64)
|
||||
MACOSX_METAL_VERSION_MIN=$(MACOSX_VERSION_MIN)
|
||||
else
|
||||
MACOSX_METAL_VERSION_MIN=10.14.0
|
||||
endif
|
||||
|
||||
ifeq ($(call isTargetOs, macosx), true)
|
||||
SHADERS_SRC := $(TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/shaders.metal
|
||||
SHADERS_SUPPORT_DIR := $(SUPPORT_OUTPUTDIR)/native/java.desktop/libosxui
|
||||
@@ -848,7 +861,9 @@ ifeq ($(call isTargetOs, macosx), true)
|
||||
DEPS := $(SHADERS_SRC), \
|
||||
OUTPUT_FILE := $(SHADERS_AIR), \
|
||||
SUPPORT_DIR := $(SHADERS_SUPPORT_DIR), \
|
||||
COMMAND := $(METAL) -c -std=osx-metal2.0 -o $(SHADERS_AIR) $(SHADERS_SRC), \
|
||||
COMMAND := $(METAL) -c -std=osx-metal2.0 \
|
||||
-mmacosx-version-min=$(MACOSX_METAL_VERSION_MIN) \
|
||||
-o $(SHADERS_AIR) $(SHADERS_SRC), \
|
||||
))
|
||||
|
||||
$(eval $(call SetupExecute, metallib_shaders, \
|
||||
|
||||
@@ -72,7 +72,9 @@ $(JDK_JAVADOC_DIR)/_element_lists.marker: \
|
||||
$(MODULE_INFOS)
|
||||
$(call MakeTargetDir)
|
||||
$(call LogInfo, Creating javadoc element lists)
|
||||
$(RM) -r $(ELEMENT_LISTS_DIR)
|
||||
$(RM) $(ELEMENT_LISTS_DIR)/element-list-{$(call CommaList, \
|
||||
$(call sequence, $(GENERATE_SYMBOLS_FROM_JDK_VERSION), \
|
||||
$(JDK_SOURCE_TARGET_VERSION)))}.txt
|
||||
# Generate element-list files for JDK 11 to current-1
|
||||
$(call ExecuteWithLog, $@_historic, \
|
||||
$(JAVA_SMALL) $(INTERIM_LANGTOOLS_ARGS) \
|
||||
|
||||
@@ -46,6 +46,7 @@ $(CLDR_GEN_DONE): $(wildcard $(CLDR_DATA_DIR)/dtd/*.dtd) \
|
||||
$(call ExecuteWithLog, $@, \
|
||||
$(TOOL_CLDRCONVERTER) -base $(CLDR_DATA_DIR) \
|
||||
-baselocales "en-US" \
|
||||
-year $(COPYRIGHT_YEAR) \
|
||||
-o $(GENSRC_DIR))
|
||||
$(TOUCH) $@
|
||||
|
||||
|
||||
@@ -356,8 +356,8 @@ compare_general_files() {
|
||||
"
|
||||
$CAT $OTHER_DIR/$f | eval "$SVG_FILTER" > $OTHER_FILE
|
||||
$CAT $THIS_DIR/$f | eval "$SVG_FILTER" > $THIS_FILE
|
||||
elif [[ "$f" = *"/lib/classlist" ]] || [ "$SUFFIX" = "jar_contents" ]; then
|
||||
# The classlist files may have some lines in random order
|
||||
elif [ "$SUFFIX" = "jar_contents" ]; then
|
||||
# The jar_contents files may have some lines in random order
|
||||
OTHER_FILE=$WORK_DIR/$f.other
|
||||
THIS_FILE=$WORK_DIR/$f.this
|
||||
$MKDIR -p $(dirname $OTHER_FILE) $(dirname $THIS_FILE)
|
||||
|
||||
@@ -1885,7 +1885,11 @@ int os::fork_and_exec(const char* cmd, bool prefer_vfork) {
|
||||
// Use always vfork on AIX, since its safe and helps with analyzing OOM situations.
|
||||
// Otherwise leave it up to the caller.
|
||||
AIX_ONLY(prefer_vfork = true;)
|
||||
#ifdef __APPLE__
|
||||
pid = ::fork();
|
||||
#else
|
||||
pid = prefer_vfork ? ::vfork() : ::fork();
|
||||
#endif
|
||||
|
||||
if (pid < 0) {
|
||||
// fork failed
|
||||
|
||||
@@ -839,6 +839,19 @@ bool BlockBegin::try_merge(ValueStack* new_state) {
|
||||
}
|
||||
}
|
||||
|
||||
for_each_stack_value(existing_state, index, existing_value) {
|
||||
if ( !(existing_value->as_Phi() != NULL && existing_value->as_Phi()->block() == this)) {
|
||||
TRACE_PHI(tty->print_cr("Re-entered loop head without existing phi for stack - bailout"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for_each_local_value(existing_state, index, existing_value) {
|
||||
if (!(existing_value == new_state->local_at(index) || (existing_value->as_Phi() != NULL && existing_value->as_Phi()->as_Phi()->block() == this))) {
|
||||
TRACE_PHI(tty->print_cr("Re-entered loop head without existing phi for modified local - bailout"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
// check that all necessary phi functions are present
|
||||
for_each_stack_value(existing_state, index, existing_value) {
|
||||
|
||||
@@ -113,10 +113,12 @@ class JfrNetworkInterfaceName : public JfrSerializer {
|
||||
void serialize(JfrCheckpointWriter& writer) {} // we write each constant lazily
|
||||
|
||||
void on_rotation() {
|
||||
for (int i = 0; i < _interfaces->length(); ++i) {
|
||||
const InterfaceEntry& entry = _interfaces->at(i);
|
||||
if (entry.written) {
|
||||
entry.written = false;
|
||||
if (_interfaces != NULL) {
|
||||
for (int i = 0; i < _interfaces->length(); ++i) {
|
||||
const InterfaceEntry &entry = _interfaces->at(i);
|
||||
if (entry.written) {
|
||||
entry.written = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ public class ModuleDescriptor
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = name.hashCode() * 43 + mods.hashCode();
|
||||
int hash = name.hashCode() * 43 + modsHashCode(mods);
|
||||
if (compiledVersion != null)
|
||||
hash = hash * 43 + compiledVersion.hashCode();
|
||||
if (rawCompiledVersion != null)
|
||||
@@ -505,7 +505,7 @@ public class ModuleDescriptor
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = mods.hashCode();
|
||||
int hash = modsHashCode(mods);
|
||||
hash = hash * 43 + source.hashCode();
|
||||
return hash * 43 + targets.hashCode();
|
||||
}
|
||||
@@ -708,7 +708,7 @@ public class ModuleDescriptor
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = mods.hashCode();
|
||||
int hash = modsHashCode(mods);
|
||||
hash = hash * 43 + source.hashCode();
|
||||
return hash * 43 + targets.hashCode();
|
||||
}
|
||||
@@ -2261,7 +2261,7 @@ public class ModuleDescriptor
|
||||
int hc = hash;
|
||||
if (hc == 0) {
|
||||
hc = name.hashCode();
|
||||
hc = hc * 43 + Objects.hashCode(modifiers);
|
||||
hc = hc * 43 + modsHashCode(modifiers);
|
||||
hc = hc * 43 + requires.hashCode();
|
||||
hc = hc * 43 + Objects.hashCode(packages);
|
||||
hc = hc * 43 + exports.hashCode();
|
||||
@@ -2546,6 +2546,18 @@ public class ModuleDescriptor
|
||||
.collect(Collectors.joining(" "));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates and returns a hashcode for the enum instances. The returned hashcode
|
||||
* is a value based on the {@link Enum#name() name} of each enum instance.
|
||||
*/
|
||||
private static int modsHashCode(Iterable<? extends Enum<?>> enums) {
|
||||
int h = 0;
|
||||
for (Enum<?> e : enums) {
|
||||
h = h * 43 + Objects.hashCode(e.name());
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
private static <T extends Object & Comparable<? super T>>
|
||||
int compare(T obj1, T obj2) {
|
||||
if (obj1 != null) {
|
||||
|
||||
@@ -46,6 +46,7 @@ import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
import jdk.internal.util.StaticProperty;
|
||||
import sun.nio.cs.ISO_8859_1;
|
||||
import sun.nio.cs.UTF_8;
|
||||
|
||||
@@ -807,17 +808,25 @@ public class Properties extends Hashtable<Object,Object> {
|
||||
* If the comments argument is not null, then an ASCII {@code #}
|
||||
* character, the comments string, and a line separator are first written
|
||||
* to the output stream. Thus, the {@code comments} can serve as an
|
||||
* identifying comment. Any one of a line feed ('\n'), a carriage
|
||||
* return ('\r'), or a carriage return followed immediately by a line feed
|
||||
* in comments is replaced by a line separator generated by the {@code Writer}
|
||||
* and if the next character in comments is not character {@code #} or
|
||||
* character {@code !} then an ASCII {@code #} is written out
|
||||
* after that line separator.
|
||||
* identifying comment. Any one of a line feed ({@code \n}), a carriage
|
||||
* return ({@code \r}), or a carriage return followed immediately by a line feed
|
||||
* ({@code \r\n}) in comments is replaced by a
|
||||
* {@link System#lineSeparator() line separator} and if the next
|
||||
* character in comments is not character {@code #} or character {@code !} then
|
||||
* an ASCII {@code #} is written out after that line separator.
|
||||
* <p>
|
||||
* Next, a comment line is always written, consisting of an ASCII
|
||||
* {@code #} character, the current date and time (as if produced
|
||||
* by the {@code toString} method of {@code Date} for the
|
||||
* current time), and a line separator as generated by the {@code Writer}.
|
||||
* If the {@systemProperty java.properties.date} is set on the command line
|
||||
* and is non-empty (as determined by {@link String#isEmpty() String.isEmpty}),
|
||||
* a comment line is written as follows.
|
||||
* First, a {@code #} character is written, followed by the contents
|
||||
* of the property, followed by a line separator. Any line terminator characters
|
||||
* in the value of the system property are treated the same way as noted above
|
||||
* for the comments argument.
|
||||
* If the system property is not set or is empty, a comment line is written
|
||||
* as follows.
|
||||
* First, a {@code #} character is written, followed by the current date and time
|
||||
* formatted as if by the {@link Date#toString() Date.toString} method,
|
||||
* followed by a line separator.
|
||||
* <p>
|
||||
* Then every entry in this {@code Properties} table is
|
||||
* written out, one per line. For each entry the key string is
|
||||
@@ -833,6 +842,10 @@ public class Properties extends Hashtable<Object,Object> {
|
||||
* After the entries have been written, the output stream is flushed.
|
||||
* The output stream remains open after this method returns.
|
||||
*
|
||||
* @implSpec The keys and elements are written in the natural sort order
|
||||
* of the keys in the {@code entrySet()} unless {@code entrySet()} is
|
||||
* overridden by a subclass to return a different value than {@code super.entrySet()}.
|
||||
*
|
||||
* @param writer an output character stream writer.
|
||||
* @param comments a description of the property list.
|
||||
* @throws IOException if writing this property list to the specified
|
||||
@@ -903,12 +916,25 @@ public class Properties extends Hashtable<Object,Object> {
|
||||
if (comments != null) {
|
||||
writeComments(bw, comments);
|
||||
}
|
||||
bw.write("#" + new Date().toString());
|
||||
bw.newLine();
|
||||
writeDateComment(bw);
|
||||
|
||||
synchronized (this) {
|
||||
for (Map.Entry<Object, Object> e : entrySet()) {
|
||||
String key = (String)e.getKey();
|
||||
String val = (String)e.getValue();
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<Map.Entry<String, String>> entries = (Set<Map.Entry<String, String>>) (Set) entrySet();
|
||||
// entrySet() can be overridden by subclasses. Here we check to see if
|
||||
// the returned instance type is the one returned by the Properties.entrySet()
|
||||
// implementation. If yes, then we sort those entries in the natural order
|
||||
// of their key. Else, we consider that the subclassed implementation may
|
||||
// potentially have returned a differently ordered entries and so we just
|
||||
// use the iteration order of the returned instance.
|
||||
if (entries instanceof Collections.SynchronizedSet<?> ss
|
||||
&& ss.c instanceof EntrySet) {
|
||||
entries = new ArrayList<>(entries);
|
||||
((List<Map.Entry<String, String>>) entries).sort(Map.Entry.comparingByKey());
|
||||
}
|
||||
for (Map.Entry<String, String> e : entries) {
|
||||
String key = e.getKey();
|
||||
String val = e.getValue();
|
||||
key = saveConvert(key, true, escUnicode);
|
||||
/* No need to escape embedded and trailing spaces for value, hence
|
||||
* pass false to flag.
|
||||
@@ -921,6 +947,19 @@ public class Properties extends Hashtable<Object,Object> {
|
||||
bw.flush();
|
||||
}
|
||||
|
||||
private static void writeDateComment(BufferedWriter bw) throws IOException {
|
||||
// value of java.properties.date system property isn't sensitive
|
||||
// and so doesn't need any security manager checks to make the value accessible
|
||||
// to the callers
|
||||
String sysPropVal = StaticProperty.javaPropertiesDate();
|
||||
if (sysPropVal != null && !sysPropVal.isEmpty()) {
|
||||
writeComments(bw, sysPropVal);
|
||||
} else {
|
||||
bw.write("#" + new Date());
|
||||
bw.newLine();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all of the properties represented by the XML document on the
|
||||
* specified input stream into this properties table.
|
||||
|
||||
@@ -50,6 +50,7 @@ public final class StaticProperty {
|
||||
private static final String JDK_SERIAL_FILTER_FACTORY;
|
||||
private static final String JAVA_IO_TMPDIR;
|
||||
private static final String NATIVE_ENCODING;
|
||||
private static final String JAVA_PROPERTIES_DATE;
|
||||
|
||||
private StaticProperty() {}
|
||||
|
||||
@@ -65,6 +66,7 @@ public final class StaticProperty {
|
||||
JDK_SERIAL_FILTER = getProperty(props, "jdk.serialFilter", null);
|
||||
JDK_SERIAL_FILTER_FACTORY = getProperty(props, "jdk.serialFilterFactory", null);
|
||||
NATIVE_ENCODING = getProperty(props, "native.encoding");
|
||||
JAVA_PROPERTIES_DATE = getProperty(props, "java.properties.date", null);
|
||||
}
|
||||
|
||||
private static String getProperty(Properties props, String key) {
|
||||
@@ -212,4 +214,16 @@ public final class StaticProperty {
|
||||
public static String nativeEncoding() {
|
||||
return NATIVE_ENCODING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@code java.properties.date} system property.
|
||||
*
|
||||
* <strong>{@link SecurityManager#checkPropertyAccess} is NOT checked
|
||||
* in this method.</strong>
|
||||
*
|
||||
* @return the {@code java.properties.date} system property
|
||||
*/
|
||||
public static String javaPropertiesDate() {
|
||||
return JAVA_PROPERTIES_DATE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,12 +129,12 @@ module java.base {
|
||||
exports javax.security.auth.spi;
|
||||
exports javax.security.auth.x500;
|
||||
exports javax.security.cert;
|
||||
exports com.jetbrains.bootstrap;
|
||||
|
||||
|
||||
// additional qualified exports may be inserted at build time
|
||||
// see make/gensrc/GenModuleInfo.gmk
|
||||
|
||||
opens com.jetbrains.bootstrap;
|
||||
|
||||
exports com.jetbrains.internal to
|
||||
java.desktop;
|
||||
exports com.sun.crypto.provider to
|
||||
|
||||
@@ -139,6 +139,8 @@ class UnixDomainSockets {
|
||||
return UnixDomainSocketAddress.of(path);
|
||||
} catch (InvalidPathException e) {
|
||||
throw new BindException("Invalid temporary directory");
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new UnsupportedOperationException("Unix Domain Sockets not supported on non-default file system");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -444,7 +444,8 @@ static int copystrings(char *buf, int offset, const char * const *arg) {
|
||||
__attribute_noinline__
|
||||
#endif
|
||||
|
||||
/* vfork(2) is deprecated on Solaris */
|
||||
/* vfork(2) is deprecated on Darwin */
|
||||
#ifndef __APPLE__
|
||||
static pid_t
|
||||
vforkChild(ChildStuff *c) {
|
||||
volatile pid_t resultPid;
|
||||
@@ -463,6 +464,7 @@ vforkChild(ChildStuff *c) {
|
||||
assert(resultPid != 0); /* childProcess never returns */
|
||||
return resultPid;
|
||||
}
|
||||
#endif
|
||||
|
||||
static pid_t
|
||||
forkChild(ChildStuff *c) {
|
||||
@@ -573,9 +575,11 @@ spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath)
|
||||
static pid_t
|
||||
startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
|
||||
switch (c->mode) {
|
||||
/* vfork(2) is deprecated on Solaris */
|
||||
/* vfork(2) is deprecated on Darwin*/
|
||||
#ifndef __APPLE__
|
||||
case MODE_VFORK:
|
||||
return vforkChild(c);
|
||||
#endif
|
||||
case MODE_FORK:
|
||||
return forkChild(c);
|
||||
case MODE_POSIX_SPAWN:
|
||||
|
||||
@@ -43,6 +43,7 @@ final class GestureHandler {
|
||||
@Native static final int ROTATE = 2;
|
||||
@Native static final int MAGNIFY = 3;
|
||||
@Native static final int SWIPE = 4;
|
||||
@Native static final int PRESSURE = 5;
|
||||
|
||||
// installs a private instance of GestureHandler, if necessary
|
||||
static void addGestureListenerTo(final JComponent component, final GestureListener listener) {
|
||||
@@ -97,6 +98,9 @@ final class GestureHandler {
|
||||
case SWIPE:
|
||||
firstNotifier.recursivelyHandleSwipe(a, b, new SwipeEvent());
|
||||
return;
|
||||
case PRESSURE:
|
||||
firstNotifier.recursivelyHandlePressure(new PressureEvent(a,b));
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -107,6 +111,7 @@ final class GestureHandler {
|
||||
final List<RotationListener> rotaters = new LinkedList<RotationListener>();
|
||||
final List<MagnificationListener> magnifiers = new LinkedList<MagnificationListener>();
|
||||
final List<SwipeListener> swipers = new LinkedList<SwipeListener>();
|
||||
final List<PressureListener> pressures = new LinkedList<PressureListener>();
|
||||
|
||||
GestureHandler() { }
|
||||
|
||||
@@ -115,6 +120,7 @@ final class GestureHandler {
|
||||
if (listener instanceof RotationListener) rotaters.add((RotationListener)listener);
|
||||
if (listener instanceof MagnificationListener) magnifiers.add((MagnificationListener)listener);
|
||||
if (listener instanceof SwipeListener) swipers.add((SwipeListener)listener);
|
||||
if (listener instanceof PressureListener) pressures.add((PressureListener)listener);
|
||||
}
|
||||
|
||||
void removeListener(final GestureListener listener) {
|
||||
@@ -169,6 +175,16 @@ final class GestureHandler {
|
||||
if (next != null) next.recursivelyHandleMagnify(e);
|
||||
}
|
||||
|
||||
void recursivelyHandlePressure(final PressureEvent e) {
|
||||
for (final PressureListener listener : handler.pressures) {
|
||||
listener.pressure(e);
|
||||
if (e.isConsumed()) return;
|
||||
}
|
||||
|
||||
final PerComponentNotifier next = getNextNotifierForComponent(component.getParent());
|
||||
if (next != null) next.recursivelyHandlePressure(e);
|
||||
}
|
||||
|
||||
void recursivelyHandleSwipe(final double x, final double y, final SwipeEvent e) {
|
||||
for (final SwipeListener listener : handler.swipers) {
|
||||
if (x < 0) listener.swipedLeft(e);
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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 com.apple.eawt.event;
|
||||
|
||||
/**
|
||||
* Event indicating a swipe was performed by the user.
|
||||
*
|
||||
* @see PressureListener
|
||||
*
|
||||
* @since Java for Mac OS X 10.10 Update 3, JDK 8
|
||||
*/
|
||||
public class PressureEvent extends GestureEvent {
|
||||
|
||||
public double getPressure() {
|
||||
return pressure;
|
||||
}
|
||||
|
||||
public double getStage() {
|
||||
return stage;
|
||||
}
|
||||
|
||||
private double pressure;
|
||||
private double stage;
|
||||
|
||||
PressureEvent(double pressure, double stage) {
|
||||
this.pressure = pressure;
|
||||
this.stage = stage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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 com.apple.eawt.event;
|
||||
|
||||
/**
|
||||
* Listener interface for receiving pressure events.
|
||||
*
|
||||
* @see PressureEvent
|
||||
* @see GestureUtilities
|
||||
*
|
||||
* @since Java for Mac OS X 10.5 Update 7, Java for Mac OS X 10.6 Update 2
|
||||
*/
|
||||
public interface PressureListener extends GestureListener {
|
||||
public void pressure(final PressureEvent e);
|
||||
}
|
||||
@@ -128,12 +128,8 @@ public class CCharToGlyphMapper extends CharToGlyphMapper {
|
||||
};
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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);
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* 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++;
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
@@ -31,6 +31,9 @@ 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
|
||||
@@ -175,14 +178,12 @@ public final class CFont extends PhysicalFont implements FontSubstitution, FontW
|
||||
isFakeItalic = other.isFakeItalic;
|
||||
}
|
||||
|
||||
public CFont createItalicVariant(boolean updateStyle) {
|
||||
public CFont createItalicVariant() {
|
||||
CFont font = new CFont(this, familyName);
|
||||
font.nativeFontName = fullName;
|
||||
font.fullName =
|
||||
fullName + (style == Font.BOLD ? "" : "-") + "Italic-Derived";
|
||||
if (updateStyle) {
|
||||
font.style |= Font.ITALIC;
|
||||
}
|
||||
font.style |= Font.ITALIC;
|
||||
font.isFakeItalic = true;
|
||||
return font;
|
||||
}
|
||||
@@ -204,11 +205,51 @@ 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 = new CCompositeFont(this);
|
||||
compFont = createCompositeFont();
|
||||
}
|
||||
return compFont;
|
||||
}
|
||||
@@ -236,14 +277,6 @@ 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;
|
||||
@@ -276,8 +309,4 @@ public final class CFont extends PhysicalFont implements FontSubstitution, FontW
|
||||
", familyName: " + familyName + ", style: " + style +
|
||||
" } aka: " + super.toString();
|
||||
}
|
||||
|
||||
public Font2D createItalic() {
|
||||
return this.createItalicVariant(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,20 +30,27 @@ 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() {
|
||||
@@ -230,6 +237,7 @@ public final class CFontManager extends SunFontManager {
|
||||
public Object run() {
|
||||
if (!loadedAllFonts) {
|
||||
loadNativeFonts();
|
||||
collectAdditionalFallbackVariants();
|
||||
loadedAllFonts = true;
|
||||
}
|
||||
return null;
|
||||
@@ -337,4 +345,40 @@ 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,18 +358,14 @@ public final class CStrike extends PhysicalStrike {
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
// This class stores glyph pointers, and is indexed based on glyph codes.
|
||||
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) {
|
||||
@@ -378,19 +374,9 @@ public final class CStrike extends PhysicalStrike {
|
||||
}
|
||||
|
||||
public synchronized long get(final int 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 (index < FIRST_LAYER_SIZE) {
|
||||
// catch common glyphcodes
|
||||
return firstLayerCache[index];
|
||||
}
|
||||
|
||||
if (generalCache == null) {
|
||||
@@ -404,21 +390,10 @@ public final class CStrike extends PhysicalStrike {
|
||||
}
|
||||
|
||||
public synchronized void put(final int index, final long value) {
|
||||
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 (index < FIRST_LAYER_SIZE) {
|
||||
// catch common glyphcodes
|
||||
firstLayerCache[index] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
if (generalCache == null) {
|
||||
@@ -441,14 +416,6 @@ 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()) {
|
||||
@@ -485,56 +452,18 @@ 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 < 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 (index < FIRST_LAYER_SIZE) {
|
||||
// catch common glyphcodes
|
||||
return firstLayerCache[index];
|
||||
}
|
||||
|
||||
if (generalCache == null) return 0;
|
||||
@@ -544,21 +473,10 @@ public final class CStrike extends PhysicalStrike {
|
||||
}
|
||||
|
||||
public synchronized void put(final int index, final float value) {
|
||||
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 (index < FIRST_LAYER_SIZE) {
|
||||
// catch common glyphcodes
|
||||
firstLayerCache[index] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
if (generalCache == null) {
|
||||
@@ -567,34 +485,5 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,13 +25,14 @@
|
||||
|
||||
package sun.lwawt.macosx;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.*;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import javax.accessibility.Accessible;
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.*;
|
||||
|
||||
import static javax.accessibility.AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY;
|
||||
import static javax.accessibility.AccessibleContext.ACCESSIBLE_CARET_PROPERTY;
|
||||
@@ -48,6 +49,20 @@ import sun.awt.AWTAccessor;
|
||||
|
||||
|
||||
class CAccessible extends CFRetainedResource implements Accessible {
|
||||
private static Timer timer = null;
|
||||
private final static int SELECTED_CHILDREN_MILLISECONDS_DEFAULT = 100;
|
||||
private static int SELECTED_CHILDREN_MILLISECONDS;
|
||||
|
||||
static {
|
||||
@SuppressWarnings("removal") int scms = java.security.AccessController.doPrivileged(new PrivilegedAction<Integer>() {
|
||||
@Override
|
||||
public Integer run() {
|
||||
return Integer.getInteger("sun.lwawt.macosx.CAccessible.selectedChildrenMilliSeconds",
|
||||
SELECTED_CHILDREN_MILLISECONDS_DEFAULT);
|
||||
}
|
||||
});
|
||||
SELECTED_CHILDREN_MILLISECONDS = scms >= 0 ? scms : SELECTED_CHILDREN_MILLISECONDS_DEFAULT;
|
||||
}
|
||||
|
||||
public static CAccessible getCAccessible(final Accessible a) {
|
||||
if (a == null) return null;
|
||||
@@ -112,19 +127,25 @@ class CAccessible extends CFRetainedResource implements Accessible {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent e) {
|
||||
assert EventQueue.isDispatchThread();
|
||||
String name = e.getPropertyName();
|
||||
if ( ptr != 0 ) {
|
||||
Object newValue = e.getNewValue();
|
||||
Object oldValue = e.getOldValue();
|
||||
if (name.compareTo(ACCESSIBLE_CARET_PROPERTY) == 0) {
|
||||
selectedTextChanged(ptr);
|
||||
} else if (name.compareTo(ACCESSIBLE_TEXT_PROPERTY) == 0) {
|
||||
valueChanged(ptr);
|
||||
} else if (name.compareTo(ACCESSIBLE_SELECTION_PROPERTY) == 0) {
|
||||
selectionChanged(ptr);
|
||||
} else if (name.compareTo(ACCESSIBLE_TABLE_MODEL_CHANGED) == 0) {
|
||||
valueChanged(ptr);
|
||||
} else if (name.compareTo(ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY) == 0 ) {
|
||||
if (name.equals(ACCESSIBLE_CARET_PROPERTY)) {
|
||||
execute(ptr -> selectedTextChanged(ptr));
|
||||
} else if (name.equals(ACCESSIBLE_TEXT_PROPERTY)) {
|
||||
execute(ptr -> valueChanged(ptr));
|
||||
} else if (name.equals(ACCESSIBLE_SELECTION_PROPERTY)) {
|
||||
if (timer != null) {
|
||||
timer.stop();
|
||||
}
|
||||
timer = new Timer(SELECTED_CHILDREN_MILLISECONDS, actionEvent -> execute(ptr -> selectionChanged(ptr)));
|
||||
timer.setRepeats(false);
|
||||
timer.start();
|
||||
} else if (name.equals(ACCESSIBLE_TABLE_MODEL_CHANGED)) {
|
||||
execute(ptr -> valueChanged(ptr));
|
||||
} else if (name.equals(ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY)) {
|
||||
if (newValue == null || newValue instanceof AccessibleContext) {
|
||||
activeDescendant = (AccessibleContext)newValue;
|
||||
if (newValue instanceof Accessible) {
|
||||
@@ -135,7 +156,7 @@ class CAccessible extends CFRetainedResource implements Accessible {
|
||||
if (p != null) {
|
||||
AccessibleContext pac = p.getAccessibleContext();
|
||||
if ((pac != null) && (pac.getAccessibleRole() == AccessibleRole.TABLE)) {
|
||||
selectedCellsChanged(ptr);
|
||||
execute(ptr -> selectedCellsChanged(ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,47 +172,54 @@ class CAccessible extends CFRetainedResource implements Accessible {
|
||||
}
|
||||
|
||||
if (newValue == AccessibleState.EXPANDED) {
|
||||
treeNodeExpanded(ptr);
|
||||
execute(ptr -> treeNodeExpanded(ptr));
|
||||
} else if (newValue == AccessibleState.COLLAPSED) {
|
||||
treeNodeCollapsed(ptr);
|
||||
execute(ptr -> treeNodeCollapsed(ptr));
|
||||
}
|
||||
|
||||
// At least for now don't handle combo box menu state changes.
|
||||
// This may change when later fixing issues which currently
|
||||
// exist for combo boxes, but for now the following is only
|
||||
// for JPopupMenus, not for combobox menus.
|
||||
if (parentRole != AccessibleRole.COMBO_BOX) {
|
||||
if (thisRole == AccessibleRole.POPUP_MENU) {
|
||||
if ( newValue != null &&
|
||||
((AccessibleState)newValue) == AccessibleState.VISIBLE ) {
|
||||
menuOpened(ptr);
|
||||
} else if ( oldValue != null &&
|
||||
((AccessibleState)oldValue) == AccessibleState.VISIBLE ) {
|
||||
menuClosed(ptr);
|
||||
}
|
||||
} else if (thisRole == AccessibleRole.MENU_ITEM) {
|
||||
if ( newValue != null &&
|
||||
((AccessibleState)newValue) == AccessibleState.FOCUSED ) {
|
||||
menuItemSelected(ptr);
|
||||
}
|
||||
if (thisRole == AccessibleRole.COMBO_BOX) {
|
||||
if (timer != null) {
|
||||
timer.stop();
|
||||
}
|
||||
timer = new Timer(SELECTED_CHILDREN_MILLISECONDS, actionEvent -> execute(ptr -> selectionChanged(ptr)));
|
||||
timer.setRepeats(false);
|
||||
timer.start();
|
||||
}
|
||||
|
||||
if (thisRole == AccessibleRole.POPUP_MENU) {
|
||||
if (newValue != null &&
|
||||
((AccessibleState) newValue) == AccessibleState.VISIBLE) {
|
||||
execute(ptr -> menuOpened(ptr));
|
||||
} else if (oldValue != null &&
|
||||
((AccessibleState) oldValue) == AccessibleState.VISIBLE) {
|
||||
execute(ptr -> menuClosed(ptr));
|
||||
}
|
||||
} else if (thisRole == AccessibleRole.MENU_ITEM) {
|
||||
if (newValue != null &&
|
||||
((AccessibleState) newValue) == AccessibleState.FOCUSED) {
|
||||
execute(ptr -> menuItemSelected(ptr));
|
||||
}
|
||||
}
|
||||
|
||||
// Do send check box state changes to native side
|
||||
if (thisRole == AccessibleRole.CHECK_BOX) {
|
||||
valueChanged(ptr);
|
||||
execute(ptr -> valueChanged(ptr));
|
||||
}
|
||||
} else if (name.compareTo(ACCESSIBLE_NAME_PROPERTY) == 0) {
|
||||
//for now trigger only for JTabbedPane.
|
||||
if (e.getSource() instanceof JTabbedPane) {
|
||||
titleChanged(ptr);
|
||||
execute(ptr -> titleChanged(ptr));
|
||||
}
|
||||
} else if (name.compareTo(ACCESSIBLE_VALUE_PROPERTY) == 0) {
|
||||
AccessibleRole thisRole = accessible.getAccessibleContext()
|
||||
.getAccessibleRole();
|
||||
if (thisRole == AccessibleRole.SLIDER ||
|
||||
thisRole == AccessibleRole.PROGRESS_BAR) {
|
||||
valueChanged(ptr);
|
||||
execute(ptr -> valueChanged(ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,6 +231,15 @@ AWT_NS_WINDOW_IMPLEMENTATION
|
||||
b:[event deltaY]];
|
||||
}
|
||||
|
||||
- (void)pressureChangeWithEvent:(NSEvent *)event {
|
||||
float pressure = event.pressure;
|
||||
[self postGesture:event
|
||||
as:com_apple_eawt_event_GestureHandler_PRESSURE
|
||||
a:pressure
|
||||
b:(([event respondsToSelector:@selector(stage)]) ? ((NSInteger)[event stage]) : -1)
|
||||
];
|
||||
}
|
||||
|
||||
- (void)moveTabToNewWindow:(id)sender {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
|
||||
|
||||
@@ -125,11 +125,35 @@ canChooseDirectories:(BOOL)inChooseDirectories
|
||||
}
|
||||
|
||||
[thePanel setDelegate:self];
|
||||
|
||||
NSMenuItem *editMenuItem = nil;
|
||||
NSMenu *menu = [NSApp mainMenu];
|
||||
if (menu != nil) {
|
||||
if (menu.numberOfItems > 0) {
|
||||
NSMenu *submenu = [[menu itemAtIndex:0] submenu];
|
||||
if (submenu != nil) {
|
||||
menu = submenu;
|
||||
}
|
||||
}
|
||||
|
||||
editMenuItem = [self createEditMenu];
|
||||
if (menu.numberOfItems > 0) {
|
||||
[menu insertItem:editMenuItem atIndex:0];
|
||||
} else {
|
||||
[menu addItem:editMenuItem];
|
||||
}
|
||||
[editMenuItem release];
|
||||
}
|
||||
|
||||
fPanelResult = [thePanel runModalForDirectory:fDirectory file:fFile];
|
||||
[thePanel setDelegate:nil];
|
||||
CMenuBar *menuBar = [[ApplicationDelegate sharedDelegate] defaultMenuBar];
|
||||
[CMenuBar activate:menuBar modallyDisabled:NO];
|
||||
|
||||
if (editMenuItem != nil) {
|
||||
[menu removeItem:editMenuItem];
|
||||
}
|
||||
|
||||
if ([self userClickedOK]) {
|
||||
if (fMode == java_awt_FileDialog_LOAD) {
|
||||
NSOpenPanel *openPanel = (NSOpenPanel *)thePanel;
|
||||
@@ -144,6 +168,33 @@ canChooseDirectories:(BOOL)inChooseDirectories
|
||||
[self disposer];
|
||||
}
|
||||
|
||||
- (NSMenuItem *) createEditMenu {
|
||||
NSMenu *editMenu = [[NSMenu alloc] initWithTitle:@"Edit"];
|
||||
|
||||
NSMenuItem *cutItem = [[NSMenuItem alloc] initWithTitle:@"Cut" action:@selector(cut:) keyEquivalent:@"x"];
|
||||
[editMenu addItem:cutItem];
|
||||
[cutItem release];
|
||||
|
||||
NSMenuItem *copyItem = [[NSMenuItem alloc] initWithTitle:@"Copy" action:@selector(copy:) keyEquivalent:@"c"];
|
||||
[editMenu addItem:copyItem];
|
||||
[copyItem release];
|
||||
|
||||
NSMenuItem *pasteItem = [[NSMenuItem alloc] initWithTitle:@"Paste" action:@selector(paste:) keyEquivalent:@"v"];
|
||||
[editMenu addItem:pasteItem];
|
||||
[pasteItem release];
|
||||
|
||||
NSMenuItem *selectAllItem = [[NSMenuItem alloc] initWithTitle:@"Select All" action:@selector(selectAll:) keyEquivalent:@"a"];
|
||||
[editMenu addItem:selectAllItem];
|
||||
[selectAllItem release];
|
||||
|
||||
NSMenuItem *editMenuItem = [NSMenuItem new];
|
||||
[editMenuItem setTitle:@"Edit"];
|
||||
[editMenuItem setSubmenu:editMenu];
|
||||
[editMenu release];
|
||||
|
||||
return editMenuItem;
|
||||
}
|
||||
|
||||
- (BOOL) askFilenameFilter:(NSString *)filename {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jstring jString = NormalizedPathJavaStringFromNSString(env, filename);
|
||||
|
||||
@@ -41,51 +41,6 @@ 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
|
||||
@@ -129,7 +84,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 BOOL useSubstituion, const int uniChars[], const CGGlyph glyphs[], CGSize advances[], const jint g_gvTXIndicesAsInts[], const jdouble g_gvTransformsAsDoubles[], const CFIndex length)
|
||||
(const QuartzSDOps *qsdo, const AWTStrike *strike, const CGGlyph glyphs[], CGSize advances[], const jint g_gvTXIndicesAsInts[], const jdouble g_gvTransformsAsDoubles[], const CFIndex length)
|
||||
{
|
||||
CGPoint pt = { 0, 0 };
|
||||
|
||||
@@ -137,49 +92,12 @@ 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;
|
||||
@@ -214,10 +132,6 @@ 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
|
||||
@@ -327,24 +241,16 @@ 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, BOOL useSubstituion, int *uniChars, CGGlyph *glyphs, CGSize *advances, size_t length)
|
||||
(JNIEnv *env, QuartzSDOps *qsdo, const AWTStrike *strike, jobject gVector, CGGlyph *glyphs, CGSize *advances, size_t length)
|
||||
{
|
||||
// if we have no character substitution, and no per-glyph transformations - strike now!
|
||||
// if we have 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
// fast path, straight to CG without per-glyph transforms
|
||||
CGContextShowGlyphsWithAdvances(qsdo->cgRef, glyphs, advances, length);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -369,8 +275,8 @@ static inline void doDrawGlyphsPipe_checkForPerGlyphTransforms
|
||||
(*env)->DeleteLocalRef(env, g_gtiTXIndicesArray);
|
||||
return;
|
||||
}
|
||||
// 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);
|
||||
// slowest case, we have per-glyph transforms
|
||||
JavaCT_DrawGlyphVector(qsdo, strike, 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);
|
||||
@@ -379,35 +285,11 @@ 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, int *uniChars, CGSize *advances, size_t length, jintArray glyphsArray)
|
||||
(JNIEnv *env, QuartzSDOps *qsdo, const AWTStrike *strike, jobject gVector, CGGlyph *glyphs, CGSize *advances, size_t length, jintArray glyphsArray)
|
||||
{
|
||||
// fill the glyph buffer
|
||||
jint *glyphsAsInts = (*env)->GetPrimitiveArrayCritical(env, glyphsArray, NULL);
|
||||
@@ -415,24 +297,10 @@ 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++)
|
||||
{
|
||||
jint code = glyphsAsInts[i];
|
||||
if (code < 0)
|
||||
{
|
||||
complex = YES;
|
||||
uniChars[i] = -code;
|
||||
glyphs[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uniChars[i] = 0;
|
||||
glyphs[i] = code;
|
||||
}
|
||||
glyphs[i] = glyphsAsInts[i];
|
||||
}
|
||||
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, glyphsArray, glyphsAsInts, JNI_ABORT);
|
||||
@@ -483,15 +351,10 @@ 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, complex, uniChars, glyphs, advances, length);
|
||||
doDrawGlyphsPipe_checkForPerGlyphTransforms(env, qsdo, strike, gVector, 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,
|
||||
@@ -515,18 +378,16 @@ 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, uniChars, advances, length, glyphsArray);
|
||||
doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers(env, qsdo, strike, gVector, glyphs, 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 || uniChars == NULL || advances == NULL)
|
||||
if (glyphs == NULL || advances == NULL)
|
||||
{
|
||||
(*env)->DeleteLocalRef(env, glyphsArray);
|
||||
[NSException raise:NSMallocException format:@"%s-%s:%d", __FILE__, __FUNCTION__, __LINE__];
|
||||
@@ -534,10 +395,6 @@ static inline void doDrawGlyphsPipe_getGlyphVectorLengthAndAlloc
|
||||
{
|
||||
free(glyphs);
|
||||
}
|
||||
if (uniChars)
|
||||
{
|
||||
free(uniChars);
|
||||
}
|
||||
if (advances)
|
||||
{
|
||||
free(advances);
|
||||
@@ -545,10 +402,9 @@ static inline void doDrawGlyphsPipe_getGlyphVectorLengthAndAlloc
|
||||
return;
|
||||
}
|
||||
|
||||
doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers(env, qsdo, strike, gVector, glyphs, uniChars, advances, length, glyphsArray);
|
||||
doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers(env, qsdo, strike, gVector, glyphs, advances, length, glyphsArray);
|
||||
|
||||
free(glyphs);
|
||||
free(uniChars);
|
||||
free(advances);
|
||||
}
|
||||
|
||||
|
||||
@@ -1008,7 +1008,7 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
point.y += size.height;
|
||||
|
||||
// Now make it into Cocoa screen coords.
|
||||
point.y = [[[[self view] window] screen] frame].size.height - point.y;
|
||||
point.y = [[NSScreen screens][0] frame].size.height - point.y;
|
||||
|
||||
return [NSValue valueWithPoint:point];
|
||||
}
|
||||
@@ -1385,7 +1385,7 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
"(Ljava/awt/Container;FF)Ljavax/accessibility/Accessible;", nil);
|
||||
|
||||
// Make it into java screen coords
|
||||
point.y = [[[[self view] window] screen] frame].size.height - point.y;
|
||||
point.y = [[NSScreen screens][0] frame].size.height - point.y;
|
||||
|
||||
jobject jparent = fComponent;
|
||||
|
||||
|
||||
@@ -43,9 +43,8 @@ static jmethodID sjm_getAccessibleSelection = NULL;
|
||||
|
||||
@implementation ComboBoxAccessibility
|
||||
|
||||
// NSAccessibilityElement protocol methods
|
||||
|
||||
- (id)accessibilityValue {
|
||||
- (CommonComponentAccessibility *)accessibleSelection
|
||||
{
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject axContext = [self axContextWithEnv:env];
|
||||
if (axContext == NULL) return nil;
|
||||
@@ -64,17 +63,19 @@ static jmethodID sjm_getAccessibleSelection = NULL;
|
||||
if (axSelectedChild == NULL) {
|
||||
return nil;
|
||||
}
|
||||
GET_ACCESSIBLENAME_METHOD_RETURN(nil);
|
||||
jobject childName = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getAccessibleName, axSelectedChild, fComponent);
|
||||
CHECK_EXCEPTION();
|
||||
if (childName == NULL) {
|
||||
(*env)->DeleteLocalRef(env, axSelectedChild);
|
||||
return nil;
|
||||
}
|
||||
NSString *selectedText = JavaStringToNSString(env, childName);
|
||||
(*env)->DeleteLocalRef(env, axSelectedChild);
|
||||
(*env)->DeleteLocalRef(env, childName);
|
||||
return selectedText;
|
||||
return [CommonComponentAccessibility createWithAccessible:axSelectedChild withEnv:env withView:fView];
|
||||
}
|
||||
|
||||
// NSAccessibilityElement protocol methods
|
||||
|
||||
- (id)accessibilityValue
|
||||
{
|
||||
return [[self accessibleSelection] accessibilityLabel];
|
||||
}
|
||||
|
||||
- (NSArray *)accessibilitySelectedChildren
|
||||
{
|
||||
return [NSArray arrayWithObject:[self accessibleSelection]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -83,10 +83,11 @@ static NSString* uiBoldName = nil;
|
||||
(uiBoldName != nil && [name isEqualTo:uiBoldName])) {
|
||||
if (style & java_awt_Font_BOLD) {
|
||||
nsFont = [NSFont boldSystemFontOfSize:1.0];
|
||||
nsFallbackBase = [NSFont fontWithName:@"LucidaGrande-Bold" size:1.0];
|
||||
} else {
|
||||
nsFont = [NSFont systemFontOfSize:1.0];
|
||||
nsFallbackBase = [NSFont fontWithName:@"LucidaGrande" size:1.0];
|
||||
}
|
||||
nsFallbackBase = [NSFont fontWithName:@"Lucida Grande" size:1.0];
|
||||
#ifdef DEBUG
|
||||
NSLog(@"nsFont-name is : %@", nsFont.familyName);
|
||||
NSLog(@"nsFont-family is : %@", nsFont.fontName);
|
||||
@@ -3341,6 +3342,64 @@ 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)
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#import "sun_font_CStrikeDisposer.h"
|
||||
#import "CGGlyphImages.h"
|
||||
#import "CGGlyphOutlines.h"
|
||||
#import "CoreTextSupport.h"
|
||||
#import "JNIUtilities.h"
|
||||
#include "fontscalerdefs.h"
|
||||
#import "LWCToolkit.h"
|
||||
@@ -160,12 +159,8 @@ JNI_COCOA_ENTER(env);
|
||||
AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
|
||||
AWTFont *awtFont = awtStrike->fAWTFont;
|
||||
|
||||
// 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);
|
||||
CGGlyph glyph = glyphCode;
|
||||
CGGlyphImages_GetGlyphMetrics((CTFontRef)awtFont->fFont, &awtStrike->fAltTx, awtStrike->fSize, awtStrike->fStyle, &glyph, 1, NULL, &advance, IS_OSX_GT10_14);
|
||||
advance = CGSizeApplyAffineTransform(advance, awtStrike->fFontTx);
|
||||
if (!JRSFontStyleUsesFractionalMetrics(awtStrike->fStyle)) {
|
||||
advance.width = round(advance.width);
|
||||
@@ -195,14 +190,9 @@ JNI_COCOA_ENTER(env);
|
||||
tx.tx += x;
|
||||
tx.ty += y;
|
||||
|
||||
// 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);
|
||||
|
||||
CGGlyph glyph = glyphCode;
|
||||
CGRect bbox;
|
||||
CGGlyphImages_GetGlyphMetrics(fallback, &tx, awtStrike->fSize, awtStrike->fStyle, &glyph, 1, &bbox, NULL, IS_OSX_GT10_14);
|
||||
CFRelease(fallback);
|
||||
CGGlyphImages_GetGlyphMetrics((CTFontRef)awtFont->fFont, &tx, awtStrike->fSize, awtStrike->fStyle, &glyph, 1, &bbox, NULL, IS_OSX_GT10_14);
|
||||
|
||||
// the origin of this bounding box is relative to the bottom-left corner baseline
|
||||
CGFloat decender = -bbox.origin.y;
|
||||
@@ -251,14 +241,12 @@ AWT_FONT_CLEANUP_CHECK(awtfont);
|
||||
tx.tx += xPos;
|
||||
tx.ty += yPos;
|
||||
|
||||
// get the right font and glyph for this "Java GlyphCode"
|
||||
|
||||
CGGlyph glyph;
|
||||
const CTFontRef font = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtfont, glyphCode, &glyph);
|
||||
CGGlyph glyph = glyphCode;
|
||||
NSFont *font = awtfont->fFont;
|
||||
|
||||
// get the advance of this glyph
|
||||
CGSize advance;
|
||||
CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, &glyph, &advance, 1);
|
||||
CTFontGetAdvancesForGlyphs((CTFontRef)font, kCTFontDefaultOrientation, &glyph, &advance, 1);
|
||||
|
||||
// Create AWTPath
|
||||
path = AWTPathCreate(CGSizeMake(xPos, yPos));
|
||||
@@ -267,8 +255,7 @@ AWT_FONT_CLEANUP_CHECK(path);
|
||||
// Get the paths
|
||||
tx = awtStrike->fTx;
|
||||
tx = CGAffineTransformConcat(tx, sInverseTX);
|
||||
AWTGetGlyphOutline(&glyph, (NSFont *)font, &advance, &tx, 0, 1, &path);
|
||||
CFRelease(font);
|
||||
AWTGetGlyphOutline(&glyph, font, &advance, &tx, 0, 1, &path);
|
||||
|
||||
pointCoords = (*env)->NewFloatArray(env, path->fNumberOfDataElements);
|
||||
AWT_FONT_CLEANUP_CHECK(pointCoords);
|
||||
@@ -322,19 +309,14 @@ JNIEXPORT void JNICALL Java_sun_font_CStrike_getNativeGlyphOutlineBounds
|
||||
AWT_FONT_CLEANUP_SETUP;
|
||||
AWT_FONT_CLEANUP_CHECK(awtfont);
|
||||
|
||||
// get the right font and glyph for this "Java GlyphCode"
|
||||
CGGlyph glyph;
|
||||
const CTFontRef font = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(
|
||||
awtfont, glyphCode, &glyph);
|
||||
|
||||
CGGlyph glyph = glyphCode;
|
||||
CGRect bbox = CTFontGetBoundingRectsForGlyphs(
|
||||
font, kCTFontOrientationDefault, &glyph, NULL, 1);
|
||||
(CTFontRef)awtfont->fFont, kCTFontOrientationDefault, &glyph, NULL, 1);
|
||||
|
||||
CGAffineTransform tx = CGAffineTransformConcat(awtStrike->fTx,
|
||||
sInverseTX);
|
||||
|
||||
bbox = CGRectApplyAffineTransform (bbox, tx);
|
||||
CFRelease(font);
|
||||
jfloat *rawRectData =
|
||||
(*env)->GetPrimitiveArrayCritical(env, rectData, NULL);
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#import "CoreTextSupport.h"
|
||||
|
||||
#import "sun_font_CCharToGlyphMapper.h"
|
||||
#import "sun_font_CCompositeGlyphMapper.h"
|
||||
|
||||
/*
|
||||
* Class: sun_font_CCharToGlyphMapper
|
||||
@@ -114,28 +113,3 @@ 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);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
|
||||
#import "JNIUtilities.h"
|
||||
#import "CGGlyphImages.h"
|
||||
#import "CoreTextSupport.h"
|
||||
#import "fontscalerdefs.h" // contains the definition of GlyphInfo struct
|
||||
|
||||
#import "sun_awt_SunHints.h"
|
||||
@@ -627,6 +626,7 @@ CGGI_CreateNewGlyphInfoFrom(CGSize advance, CGRect bbox,
|
||||
glyphInfo->cellInfo = NULL;
|
||||
glyphInfo->subpixelResolutionX = subpixelResX;
|
||||
glyphInfo->subpixelResolutionY = subpixelResY;
|
||||
glyphInfo->format = (UInt8) pixelSize;
|
||||
|
||||
#ifdef USE_IMAGE_ALIGNED_MEMORY
|
||||
glyphInfo->image = image;
|
||||
@@ -683,9 +683,12 @@ CGGI_CreateImageForGlyph
|
||||
// which calculates glyph metrics.
|
||||
|
||||
CGAffineTransform matrix = CGContextGetTextMatrix(canvas->context);
|
||||
CTFontRef sizedFont = CTFontCreateCopyWithSymbolicTraits(font, strike->fSize, NULL, 0, 0);
|
||||
// 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);
|
||||
|
||||
CGFloat normFactor = 1.0 / strike->fSize;
|
||||
CGFloat normFactor = 1.0 / fontSize;
|
||||
CGAffineTransform normalizedMatrix = CGAffineTransformScale(matrix, normFactor, normFactor);
|
||||
CGContextSetTextMatrix(canvas->context, normalizedMatrix);
|
||||
|
||||
@@ -735,78 +738,6 @@ 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 ---
|
||||
|
||||
@@ -821,7 +752,6 @@ CGGI_FillImagesForGlyphsWithSizedCanvas(CGGI_GlyphCanvas *canvas,
|
||||
const AWTStrike *strike,
|
||||
const CGGI_RenderingMode *mode,
|
||||
jlong glyphInfos[],
|
||||
const UnicodeScalarValue uniChars[],
|
||||
const CGGlyph glyphs[],
|
||||
const CFIndex len)
|
||||
{
|
||||
@@ -834,13 +764,8 @@ CGGI_FillImagesForGlyphsWithSizedCanvas(CGGI_GlyphCanvas *canvas,
|
||||
CFIndex i;
|
||||
for (i = 0; i < len; i++) {
|
||||
GlyphInfo *info = (GlyphInfo *)jlong_to_ptr(glyphInfos[i]);
|
||||
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);
|
||||
}
|
||||
CGGI_CreateImageForGlyph(canvas, glyphs[i], info, mode->mainFontDescriptor,
|
||||
strike, (CTFontRef)strike->fAWTFont->fFont, isMojaveOrAbove);
|
||||
#ifdef CGGI_DEBUG
|
||||
DUMP_GLYPHINFO(info);
|
||||
#endif
|
||||
@@ -875,7 +800,7 @@ static NSString *threadLocalLCDCanvasKey =
|
||||
static inline void
|
||||
CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
|
||||
const CGGI_RenderingMode *mode,
|
||||
const UnicodeScalarValue uniChars[], const CGGlyph glyphs[],
|
||||
const CGGlyph glyphs[],
|
||||
const size_t maxWidth, const size_t maxHeight,
|
||||
const CFIndex len)
|
||||
{
|
||||
@@ -885,8 +810,7 @@ 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, uniChars,
|
||||
glyphs, len);
|
||||
mode, glyphInfos, glyphs, len);
|
||||
CGGI_FreeCanvas(tmpCanvas);
|
||||
|
||||
[tmpCanvas release];
|
||||
@@ -906,7 +830,7 @@ CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
|
||||
|
||||
CGGI_SizeCanvas(canvas, maxWidth, maxHeight, mode);
|
||||
CGGI_FillImagesForGlyphsWithSizedCanvas(canvas, strike, mode,
|
||||
glyphInfos, uniChars, glyphs, len);
|
||||
glyphInfos, glyphs, len);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -922,7 +846,7 @@ CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
|
||||
static inline void
|
||||
CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike,
|
||||
const CGGI_RenderingMode *mode,
|
||||
const UnicodeScalarValue uniChars[], const CGGlyph glyphs[],
|
||||
const CGGlyph glyphs[],
|
||||
CGSize advances[], CGRect bboxes[], const CFIndex len)
|
||||
{
|
||||
AWTFont *font = strike->fAWTFont;
|
||||
@@ -937,12 +861,6 @@ 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];
|
||||
|
||||
@@ -959,41 +877,29 @@ CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike,
|
||||
glyphInfos[i] = ptr_to_jlong(glyphInfo);
|
||||
}
|
||||
|
||||
CGGI_FillImagesForGlyphs(glyphInfos, strike, mode, uniChars,
|
||||
CGGI_FillImagesForGlyphs(glyphInfos, strike, mode,
|
||||
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_CreateGlyphsAndScanForComplexities(jlong *glyphInfos,
|
||||
const AWTStrike *strike,
|
||||
const CGGI_RenderingMode *mode,
|
||||
jint rawGlyphCodes[],
|
||||
UnicodeScalarValue uniChars[], CGGlyph glyphs[],
|
||||
CGSize advances[], CGRect bboxes[],
|
||||
const CFIndex len)
|
||||
CGGI_CreateGlyphs(jlong *glyphInfos,
|
||||
const AWTStrike *strike,
|
||||
const CGGI_RenderingMode *mode,
|
||||
jint rawGlyphCodes[],
|
||||
CGGlyph glyphs[],
|
||||
CGSize advances[], CGRect bboxes[],
|
||||
const CFIndex len)
|
||||
{
|
||||
CFIndex i;
|
||||
for (i = 0; i < len; i++) {
|
||||
jint code = rawGlyphCodes[i];
|
||||
if (code < 0) {
|
||||
glyphs[i] = 0;
|
||||
uniChars[i] = -code;
|
||||
} else {
|
||||
glyphs[i] = code;
|
||||
uniChars[i] = 0;
|
||||
}
|
||||
glyphs[i] = rawGlyphCodes[i];
|
||||
}
|
||||
|
||||
CGGI_CreateGlyphInfos(glyphInfos, strike, mode,
|
||||
uniChars, glyphs, advances, bboxes, len);
|
||||
glyphs, advances, bboxes, len);
|
||||
|
||||
#ifdef CGGI_DEBUG_HIT_COUNT
|
||||
static size_t hitCount = 0;
|
||||
@@ -1019,31 +925,29 @@ CGGlyphImages_GetGlyphImagePtrs(jlong glyphInfos[],
|
||||
CGRect bboxes[len];
|
||||
CGSize advances[len];
|
||||
CGGlyph glyphs[len];
|
||||
UnicodeScalarValue uniChars[len];
|
||||
|
||||
CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode,
|
||||
rawGlyphCodes, uniChars, glyphs,
|
||||
advances, bboxes, len);
|
||||
CGGI_CreateGlyphs(glyphInfos, strike, &mode,
|
||||
rawGlyphCodes, 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) * sizeof(UnicodeScalarValue) * len);
|
||||
void *buffer = malloc((sizeof(CGRect) + sizeof(CGSize) + sizeof(CGGlyph)) *
|
||||
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 + sizeof(CGRect) * len);
|
||||
CGGlyph *glyphs = (CGGlyph *)(advances + sizeof(CGGlyph) * len);
|
||||
UnicodeScalarValue *uniChars = (UnicodeScalarValue *)(glyphs + sizeof(UnicodeScalarValue) * len);
|
||||
CGSize *advances = (CGSize *)(bboxes + len);
|
||||
CGGlyph *glyphs = (CGGlyph *)(advances + len);
|
||||
|
||||
CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode,
|
||||
rawGlyphCodes, uniChars, glyphs,
|
||||
advances, bboxes, len);
|
||||
CGGI_CreateGlyphs(glyphInfos, strike, &mode,
|
||||
rawGlyphCodes, glyphs,
|
||||
advances, bboxes, len);
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
@@ -31,37 +31,13 @@
|
||||
|
||||
#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,
|
||||
* or the negative unicode value if we know the character can be hot-substituted.
|
||||
*
|
||||
* This is the heart of "Universal Font Substitution" in Java.
|
||||
* Fills the "glyphsAsInts" array with the glyph codes for the current font.
|
||||
*/
|
||||
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 {
|
||||
|
||||
@@ -88,161 +88,18 @@ 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,
|
||||
* or the negative unicode value if we know the character can be hot-substituted.
|
||||
*
|
||||
* This is the heart of "Universal Font Substitution" in Java.
|
||||
* Fills the "glyphsAsInts" array with the glyph codes for the current font.
|
||||
*/
|
||||
void CTS_GetGlyphsAsIntsForCharacters
|
||||
(const AWTFont *font, const UniChar unicodes[], CGGlyph glyphs[], jint glyphsAsInts[], const size_t count)
|
||||
{
|
||||
GetFontsAndGlyphsForCharacters((CTFontRef)font->fFont, (CTFontRef)font->fFallbackBase,
|
||||
unicodes, glyphs, glyphsAsInts, NULL, count);
|
||||
}
|
||||
CTFontGetGlyphsForCharacters((CTFontRef)font->fFont, unicodes, glyphs, count);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
size_t i;
|
||||
for (i = 0; i < count; i++) {
|
||||
glyphsAsInts[i] = glyphs[i];
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -40,12 +40,10 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE };
|
||||
- (id)init;
|
||||
- (void)dealloc;
|
||||
|
||||
- (void) reset:(id<MTLTexture>)destination
|
||||
isDstOpaque:(jboolean)isDstOpaque
|
||||
isDstPremultiplied:(jboolean)isDstPremultiplied
|
||||
isAA:(jboolean)isAA
|
||||
isGMCText:(jboolean)isGMCText
|
||||
isLCD:(jboolean)isLCD;
|
||||
- (void)reset:(id<MTLTexture>)destination
|
||||
isAA:(jboolean)isAA
|
||||
isGMCText:(jboolean)isGMCText
|
||||
isLCD:(jboolean)isLCD;
|
||||
|
||||
- (void)updateEncoder:(id<MTLRenderCommandEncoder>)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
@@ -63,7 +61,6 @@ isDstPremultiplied:(jboolean)isDstPremultiplied
|
||||
|
||||
// Persistent encoder properties
|
||||
id<MTLTexture> _destination;
|
||||
SurfaceRasterFlags _dstFlags;
|
||||
|
||||
jboolean _isAA;
|
||||
jboolean _isGMCText;
|
||||
@@ -121,14 +118,10 @@ isDstPremultiplied:(jboolean)isDstPremultiplied
|
||||
}
|
||||
|
||||
- (void)reset:(id<MTLTexture>)destination
|
||||
isDstOpaque:(jboolean)isDstOpaque
|
||||
isDstPremultiplied:(jboolean)isDstPremultiplied
|
||||
isAA:(jboolean)isAA
|
||||
isGMCText:(jboolean)isGMCText
|
||||
isLCD:(jboolean)isLCD {
|
||||
isAA:(jboolean)isAA
|
||||
isGMCText:(jboolean)isGMCText
|
||||
isLCD:(jboolean)isLCD {
|
||||
_destination = destination;
|
||||
_dstFlags.isOpaque = isDstOpaque;
|
||||
_dstFlags.isPremultiplied = isDstPremultiplied;
|
||||
_isAA = isAA;
|
||||
_isGMCText = isGMCText;
|
||||
_isLCD = isLCD;
|
||||
@@ -286,20 +279,20 @@ isDstPremultiplied:(jboolean)isDstPremultiplied
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull)getAARenderEncoder:(const BMTLSDOps * _Nonnull)dstOps {
|
||||
id<MTLTexture> dstTxt = dstOps->pTexture;
|
||||
RenderOptions roptions = {JNI_FALSE, JNI_TRUE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, {dstOps->isOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE};
|
||||
RenderOptions roptions = {JNI_FALSE, JNI_TRUE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, JNI_FALSE, JNI_FALSE, JNI_FALSE};
|
||||
return [self getEncoder:dstTxt renderOptions:&roptions];
|
||||
}
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull)getAAShaderRenderEncoder:(const BMTLSDOps * _Nonnull)dstOps
|
||||
{
|
||||
RenderOptions roptions = {JNI_FALSE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, {dstOps->isOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_TRUE};
|
||||
RenderOptions roptions = {JNI_FALSE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, JNI_FALSE, JNI_FALSE, JNI_TRUE};
|
||||
return [self getEncoder:dstOps->pTexture renderOptions:&roptions];
|
||||
}
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull)getRenderEncoder:(id<MTLTexture> _Nonnull)dest
|
||||
isDstOpaque:(bool)isOpaque
|
||||
{
|
||||
RenderOptions roptions = {JNI_FALSE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, {isOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE};
|
||||
RenderOptions roptions = {JNI_FALSE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, JNI_FALSE, JNI_FALSE, JNI_FALSE};
|
||||
return [self getEncoder:dest renderOptions:&roptions];
|
||||
}
|
||||
|
||||
@@ -327,7 +320,7 @@ isDstPremultiplied:(jboolean)isDstPremultiplied
|
||||
isSrcOpaque:(bool)isSrcOpaque
|
||||
isDstOpaque:(bool)isDstOpaque
|
||||
{
|
||||
RenderOptions roptions = {JNI_TRUE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, {isSrcOpaque, JNI_TRUE }, {isDstOpaque, JNI_TRUE}, JNI_FALSE, JNI_TRUE, JNI_FALSE};
|
||||
RenderOptions roptions = {JNI_TRUE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, {isSrcOpaque, JNI_TRUE }, JNI_FALSE, JNI_TRUE, JNI_FALSE};
|
||||
return [self getEncoder:dest renderOptions:&roptions];
|
||||
}
|
||||
|
||||
@@ -337,7 +330,7 @@ isDstPremultiplied:(jboolean)isDstPremultiplied
|
||||
interpolation:(int)interpolation
|
||||
isAA:(jboolean)isAA
|
||||
{
|
||||
RenderOptions roptions = {JNI_TRUE, isAA, interpolation, { isSrcOpaque, JNI_TRUE }, {isDstOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE};
|
||||
RenderOptions roptions = {JNI_TRUE, isAA, interpolation, { isSrcOpaque, JNI_TRUE }, JNI_FALSE, JNI_FALSE, JNI_FALSE};
|
||||
return [self getEncoder:dest renderOptions:&roptions];
|
||||
}
|
||||
|
||||
@@ -354,7 +347,7 @@ isDstPremultiplied:(jboolean)isDstPremultiplied
|
||||
gammaCorrection:(bool)gmc
|
||||
{
|
||||
RenderOptions roptions = {JNI_TRUE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, { isSrcOpaque, JNI_TRUE },
|
||||
{dstOps->isOpaque, JNI_TRUE}, gmc, JNI_FALSE, JNI_FALSE};
|
||||
gmc, JNI_FALSE, JNI_FALSE};
|
||||
return [self getEncoder:dstOps->pTexture renderOptions:&roptions];
|
||||
}
|
||||
|
||||
@@ -437,8 +430,6 @@ isDstPremultiplied:(jboolean)isDstPremultiplied
|
||||
_encoder = [[cbw getCommandBuffer] renderCommandEncoderWithDescriptor:rpd];
|
||||
|
||||
[_encoderStates reset:dest
|
||||
isDstOpaque:renderOptions->dstFlags.isOpaque
|
||||
isDstPremultiplied:YES
|
||||
isAA:renderOptions->isAA
|
||||
isGMCText:renderOptions->isGMCText
|
||||
isLCD:renderOptions->isLCD];
|
||||
|
||||
@@ -595,8 +595,9 @@ MTLBlitLoops_Blit(JNIEnv *env,
|
||||
}
|
||||
|
||||
#ifdef TRACE_BLIT
|
||||
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_FALSE,
|
||||
"MTLBlitLoops_Blit [tx=%d, xf=%d, AC=%s]: bdst=%s, src=%p (%dx%d) O=%d premul=%d | (%d, %d, %d, %d)->(%1.2f, %1.2f, %1.2f, %1.2f)",
|
||||
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE,
|
||||
"MTLBlitLoops_Blit srctype=%d [tx=%d, xf=%d, AC=%s]: bdst=%s, src=%p (%dx%d) O=%d premul=%d | (%d, "
|
||||
"%d, %d, %d)->(%1.2f, %1.2f, %1.2f, %1.2f)", srctype,
|
||||
texture, xform, [mtlc getCompositeDescription].cString,
|
||||
getSurfaceDescription(dstOps).cString, srcOps,
|
||||
sx2 - sx1, sy2 - sy1,
|
||||
|
||||
@@ -58,7 +58,6 @@ static void initTemplatePipelineDescriptors() {
|
||||
BMTLSDOps* _dstOps;
|
||||
BOOL _stencilMaskGenerationInProgress;
|
||||
BOOL _stencilMaskGenerationStarted;
|
||||
BOOL _clipReady;
|
||||
MTLOrigin _clipShapeOrigin;
|
||||
MTLSize _clipShapeSize;
|
||||
}
|
||||
@@ -73,7 +72,6 @@ static void initTemplatePipelineDescriptors() {
|
||||
_dstOps = NULL;
|
||||
_stencilMaskGenerationInProgress = NO;
|
||||
_stencilMaskGenerationStarted = NO;
|
||||
_clipReady = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -189,7 +187,6 @@ static void initTemplatePipelineDescriptors() {
|
||||
_stencilMaskGenerationStarted = NO;
|
||||
_dstOps = dstOps;
|
||||
_clipType = SHAPE_CLIP;
|
||||
_clipReady = NO;
|
||||
}
|
||||
|
||||
- (void)setMaskGenerationPipelineState:(id<MTLRenderCommandEncoder>)encoder
|
||||
|
||||
@@ -56,8 +56,7 @@ static MTLRenderPipelineDescriptor * templateLCDPipelineDesc = nil;
|
||||
static MTLRenderPipelineDescriptor * templateAAPipelineDesc = nil;
|
||||
static void
|
||||
setTxtUniforms(MTLContext *mtlc, int color, id <MTLRenderCommandEncoder> encoder, int interpolation, bool repeat,
|
||||
jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, const SurfaceRasterFlags *dstFlags, int mode,
|
||||
bool gmcText);
|
||||
jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, int mode, bool gmcText);
|
||||
|
||||
static void initTemplatePipelineDescriptors() {
|
||||
if (templateRenderPipelineDesc != nil && templateTexturePipelineDesc != nil &&
|
||||
@@ -211,7 +210,7 @@ jint _color;
|
||||
}
|
||||
setTxtUniforms(mtlc, _color, encoder,
|
||||
renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha], &renderOptions->srcFlags,
|
||||
&renderOptions->dstFlags, 1, gmcText);
|
||||
1, gmcText);
|
||||
} else if (renderOptions->isAAShader) {
|
||||
vertShader = @"vert_col_aa";
|
||||
fragShader = @"frag_col_aa";
|
||||
@@ -254,7 +253,7 @@ jint _color;
|
||||
|
||||
setTxtUniforms(mtlc, col, encoder,
|
||||
renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha],
|
||||
&renderOptions->srcFlags, &renderOptions->dstFlags, 1, NO);
|
||||
&renderOptions->srcFlags, 1, NO);
|
||||
[encoder setFragmentBytes:&xorColor length:sizeof(xorColor) atIndex:0];
|
||||
|
||||
[encoder setFragmentTexture:dstOps->pTexture atIndex:1];
|
||||
@@ -793,9 +792,8 @@ jint _color;
|
||||
[encoder setFragmentTexture:_paintTexture atIndex:0];
|
||||
}
|
||||
const SurfaceRasterFlags srcFlags = {_isOpaque, renderOptions->srcFlags.isPremultiplied};
|
||||
setTxtUniforms(mtlc, 0, encoder,
|
||||
renderOptions->interpolation, YES, [mtlc.composite getExtraAlpha],
|
||||
&srcFlags, &renderOptions->dstFlags, 0, NO);
|
||||
setTxtUniforms(mtlc, 0, encoder, renderOptions->interpolation, YES, [mtlc.composite getExtraAlpha],
|
||||
&srcFlags, 0, NO);
|
||||
|
||||
id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc
|
||||
vertexShaderId:vertShader
|
||||
@@ -877,8 +875,7 @@ jint _color;
|
||||
|
||||
static void
|
||||
setTxtUniforms(MTLContext *mtlc, int color, id <MTLRenderCommandEncoder> encoder, int interpolation, bool repeat,
|
||||
jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, const SurfaceRasterFlags *dstFlags, int mode,
|
||||
bool gmcText)
|
||||
jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, int mode, bool gmcText)
|
||||
{
|
||||
if (gmcText) {
|
||||
float ca = (((color) >> 24) & 0xFF)/255.0f;
|
||||
@@ -915,7 +912,7 @@ setTxtUniforms(MTLContext *mtlc, int color, id <MTLRenderCommandEncoder> encoder
|
||||
[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];
|
||||
} else {
|
||||
struct TxtFrameUniforms uf =
|
||||
{RGBA_TO_V4(color), mode, srcFlags->isOpaque, dstFlags->isOpaque, extraAlpha};
|
||||
{RGBA_TO_V4(color), mode, srcFlags->isOpaque, extraAlpha};
|
||||
[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];
|
||||
}
|
||||
[mtlc.samplerManager setSamplerWithEncoder:encoder interpolation:interpolation repeat:repeat];
|
||||
@@ -978,8 +975,7 @@ setTxtUniforms(MTLContext *mtlc, int color, id <MTLRenderCommandEncoder> encoder
|
||||
} else {
|
||||
setTxtUniforms(mtlc, 0, encoder,
|
||||
renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha],
|
||||
&renderOptions->srcFlags,
|
||||
&renderOptions->dstFlags, 0, NO);
|
||||
&renderOptions->srcFlags, 0, NO);
|
||||
|
||||
}
|
||||
id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc
|
||||
@@ -1010,7 +1006,7 @@ setTxtUniforms(MTLContext *mtlc, int color, id <MTLRenderCommandEncoder> encoder
|
||||
const int col = 0 ^ xorColor;
|
||||
setTxtUniforms(mtlc, col, encoder,
|
||||
renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha],
|
||||
&renderOptions->srcFlags, &renderOptions->dstFlags, 0, NO);
|
||||
&renderOptions->srcFlags, 0, NO);
|
||||
[encoder setFragmentBytes:&xorColor length:sizeof(xorColor) atIndex: 0];
|
||||
|
||||
BMTLSDOps *dstOps = MTLRenderQueue_GetCurrentDestination();
|
||||
@@ -1018,8 +1014,7 @@ setTxtUniforms(MTLContext *mtlc, int color, id <MTLRenderCommandEncoder> encoder
|
||||
|
||||
setTxtUniforms(mtlc, 0, encoder,
|
||||
renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha],
|
||||
&renderOptions->srcFlags,
|
||||
&renderOptions->dstFlags, 0, NO);
|
||||
&renderOptions->srcFlags, 0, NO);
|
||||
|
||||
id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc
|
||||
vertexShaderId:vertShader
|
||||
|
||||
@@ -84,7 +84,7 @@ static void setBlendingFactors(
|
||||
vertexShaderId:(NSString *)vertexShaderId
|
||||
fragmentShaderId:(NSString *)fragmentShaderId
|
||||
{
|
||||
RenderOptions defaultOptions = {JNI_FALSE, JNI_FALSE, 0/*unused*/, {JNI_FALSE, JNI_TRUE}, {JNI_FALSE, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE};
|
||||
RenderOptions defaultOptions = {JNI_FALSE, JNI_FALSE, 0/*unused*/, {JNI_FALSE, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE};
|
||||
return [self getPipelineState:pipelineDescriptor
|
||||
vertexShaderId:vertexShaderId
|
||||
fragmentShaderId:fragmentShaderId
|
||||
@@ -98,7 +98,7 @@ static void setBlendingFactors(
|
||||
fragmentShaderId:(NSString *)fragmentShaderId
|
||||
stencilNeeded:(bool)stencilNeeded
|
||||
{
|
||||
RenderOptions defaultOptions = {JNI_FALSE, JNI_FALSE, 0/*unused*/, {JNI_FALSE, JNI_TRUE}, {JNI_FALSE, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE};
|
||||
RenderOptions defaultOptions = {JNI_FALSE, JNI_FALSE, 0/*unused*/, {JNI_FALSE, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE};
|
||||
return [self getPipelineState:pipelineDescriptor
|
||||
vertexShaderId:vertexShaderId
|
||||
fragmentShaderId:fragmentShaderId
|
||||
@@ -107,6 +107,19 @@ static void setBlendingFactors(
|
||||
stencilNeeded:stencilNeeded];
|
||||
}
|
||||
|
||||
// Pipeline state index
|
||||
union StateIndex {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t srcPremultiplied : 1,
|
||||
srcOpaque : 1,
|
||||
stencil : 1,
|
||||
aa : 1,
|
||||
extAlpha : 1,
|
||||
compositeRule : 27;
|
||||
} bits;
|
||||
};
|
||||
|
||||
// Base method to obtain MTLRenderPipelineState.
|
||||
// NOTE: parameters compositeRule, srcFlags, dstFlags are used to set MTLRenderPipelineColorAttachmentDescriptor multipliers
|
||||
- (id<MTLRenderPipelineState>) getPipelineState:(MTLRenderPipelineDescriptor *) pipelineDescriptor
|
||||
@@ -123,45 +136,31 @@ static void setBlendingFactors(
|
||||
|
||||
// Calculate index by flags and compositeRule
|
||||
// TODO: reimplement, use map with convenient key (calculated by all arguments)
|
||||
int subIndex = 0;
|
||||
union StateIndex index;
|
||||
index.value = 0;
|
||||
if (useXorComposite) {
|
||||
// compositeRule value is already XOR_COMPOSITE_RULE
|
||||
}
|
||||
else {
|
||||
if (useComposite) {
|
||||
if (!renderOptions->srcFlags.isPremultiplied)
|
||||
subIndex |= 1;
|
||||
if (renderOptions->srcFlags.isOpaque)
|
||||
subIndex |= 1 << 1;
|
||||
if (!renderOptions->dstFlags.isPremultiplied)
|
||||
subIndex |= 1 << 2;
|
||||
if (renderOptions->dstFlags.isOpaque)
|
||||
subIndex |= 1 << 3;
|
||||
index.bits.srcPremultiplied = renderOptions->srcFlags.isPremultiplied;
|
||||
index.bits.srcOpaque = renderOptions->srcFlags.isOpaque;
|
||||
} else
|
||||
compositeRule = RULE_Src;
|
||||
}
|
||||
|
||||
if (stencilNeeded) {
|
||||
subIndex |= 1 << 4;
|
||||
}
|
||||
|
||||
if (renderOptions->isAA) {
|
||||
subIndex |= 1 << 5;
|
||||
}
|
||||
|
||||
if ((composite != nil && FLT_LT([composite getExtraAlpha], 1.0f))) {
|
||||
subIndex |= 1 << 6;
|
||||
}
|
||||
|
||||
int index = compositeRule*128 + subIndex;
|
||||
index.bits.stencil = stencilNeeded;
|
||||
index.bits.aa = renderOptions->isAA;
|
||||
index.bits.extAlpha = composite != nil && FLT_LT([composite getExtraAlpha], 1.0f);
|
||||
index.bits.compositeRule = compositeRule;
|
||||
|
||||
NSPointerArray * subStates = [self getSubStates:vertexShaderId fragmentShader:fragmentShaderId];
|
||||
|
||||
if (index >= subStates.count) {
|
||||
subStates.count = (NSUInteger) (index + 1);
|
||||
if (index.value >= subStates.count) {
|
||||
subStates.count = index.value + 1;
|
||||
}
|
||||
|
||||
id<MTLRenderPipelineState> result = [subStates pointerAtIndex:index];
|
||||
id<MTLRenderPipelineState> result = [subStates pointerAtIndex:index.value];
|
||||
if (result == nil) {
|
||||
@autoreleasepool {
|
||||
id <MTLFunction> vertexShader = [self getShader:vertexShaderId];
|
||||
@@ -222,7 +221,7 @@ static void setBlendingFactors(
|
||||
exit(0);
|
||||
}
|
||||
|
||||
[subStates insertPointer:result atIndex:index];
|
||||
[subStates replacePointerAtIndex:index.value withPointer:result];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -714,7 +714,7 @@ MTLTR_DrawGlyphList(JNIEnv *env, MTLContext *mtlc, BMTLSDOps *dstOps,
|
||||
|
||||
J2dTraceLn2(J2D_TRACE_INFO, "Glyph width = %d height = %d", ginfo->width, ginfo->height);
|
||||
J2dTraceLn1(J2D_TRACE_INFO, "rowBytes = %d", ginfo->rowBytes);
|
||||
if (ginfo->rowBytes == ginfo->width) {
|
||||
if (ginfo->format == sun_font_StrikeCache_PIXEL_FORMAT_GREYSCALE) {
|
||||
// grayscale or monochrome glyph data
|
||||
if (ginfo->width <= MTLTR_CACHE_CELL_WIDTH &&
|
||||
ginfo->height <= MTLTR_CACHE_CELL_HEIGHT)
|
||||
@@ -725,7 +725,7 @@ MTLTR_DrawGlyphList(JNIEnv *env, MTLContext *mtlc, BMTLSDOps *dstOps,
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_DrawGlyphList Grayscale no cache");
|
||||
ok = MTLTR_DrawGrayscaleGlyphNoCache(mtlc, ginfo, x, y, dstOps);
|
||||
}
|
||||
} else if (ginfo->rowBytes == ginfo->width * 4) {
|
||||
} else if (ginfo->format == sun_font_StrikeCache_PIXEL_FORMAT_BGRA) {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_DrawGlyphList color glyph no cache");
|
||||
ok = MTLTR_DrawColorGlyphNoCache(mtlc, ginfo, x, y, dstOps);
|
||||
flushBeforeLCD = JNI_FALSE;
|
||||
|
||||
@@ -44,7 +44,6 @@ static jint vertexCacheIndex = 0;
|
||||
|
||||
static MTLPooledTextureHandle * maskCacheTex = NULL;
|
||||
static jint maskCacheIndex = 0;
|
||||
static bool gammaCorrection = NO;
|
||||
static id<MTLRenderCommandEncoder> encoder = NULL;
|
||||
|
||||
#define MTLVC_ADD_VERTEX(TX, TY, DX, DY, DZ) \
|
||||
@@ -144,9 +143,12 @@ MTLVertexCache_InitMaskCache(MTLContext *mtlc) {
|
||||
}
|
||||
// init special fully opaque tile in the upper-right corner of
|
||||
// the mask cache texture
|
||||
|
||||
char tile[MTLVC_MASK_CACHE_TILE_SIZE];
|
||||
memset(tile, 0xff, MTLVC_MASK_CACHE_TILE_SIZE);
|
||||
static char tile[MTLVC_MASK_CACHE_TILE_SIZE];
|
||||
static char* pTile = NULL;
|
||||
if (!pTile) {
|
||||
memset(tile, 0xff, MTLVC_MASK_CACHE_TILE_SIZE);
|
||||
pTile = tile;
|
||||
}
|
||||
|
||||
jint texx = MTLVC_MASK_CACHE_TILE_WIDTH * (MTLVC_MASK_CACHE_WIDTH_IN_TILES - 1);
|
||||
|
||||
@@ -183,7 +185,7 @@ MTLVertexCache_EnableMaskCache(MTLContext *mtlc, BMTLSDOps *dstOps)
|
||||
return;
|
||||
}
|
||||
}
|
||||
MTLVertexCache_CreateSamplingEncoder(mtlc, dstOps, gammaCorrection);
|
||||
MTLVertexCache_CreateSamplingEncoder(mtlc, dstOps, NO);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -195,7 +197,6 @@ MTLVertexCache_DisableMaskCache(MTLContext *mtlc)
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_DisableMaskCache");
|
||||
MTLVertexCache_FlushVertexCache(mtlc);
|
||||
maskCacheIndex = 0;
|
||||
gammaCorrection = NO;
|
||||
free(vertexCache);
|
||||
vertexCache = NULL;
|
||||
}
|
||||
@@ -203,7 +204,6 @@ MTLVertexCache_DisableMaskCache(MTLContext *mtlc)
|
||||
void
|
||||
MTLVertexCache_CreateSamplingEncoder(MTLContext *mtlc, BMTLSDOps *dstOps, bool gmc) {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_CreateSamplingEncoder");
|
||||
gammaCorrection = gmc;
|
||||
encoder = [mtlc.encoderManager getTextEncoder:dstOps
|
||||
isSrcOpaque:NO
|
||||
gammaCorrection:gmc];
|
||||
|
||||
@@ -35,7 +35,6 @@ typedef struct {
|
||||
jboolean isAA;
|
||||
int interpolation;
|
||||
SurfaceRasterFlags srcFlags;
|
||||
SurfaceRasterFlags dstFlags;
|
||||
jboolean isGMCText;
|
||||
jboolean isLCD;
|
||||
jboolean isAAShader;
|
||||
|
||||
@@ -114,7 +114,6 @@ struct TxtFrameUniforms {
|
||||
vector_float4 color;
|
||||
int mode; // NOTE: consider to use bit fields
|
||||
int isSrcOpaque;
|
||||
int isDstOpaque;
|
||||
float extraAlpha;
|
||||
};
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ 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;
|
||||
@@ -266,6 +267,11 @@ 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;
|
||||
}
|
||||
@@ -537,6 +543,11 @@ 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.
|
||||
@@ -2223,7 +2234,7 @@ public class Font implements java.io.Serializable
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean canDisplay(char c){
|
||||
return getFont2D().canDisplay(c);
|
||||
return getFont2DWithSubstitution().canDisplay(c);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2244,7 +2255,7 @@ public class Font implements java.io.Serializable
|
||||
throw new IllegalArgumentException("invalid code point: " +
|
||||
Integer.toHexString(codePoint));
|
||||
}
|
||||
return getFont2D().canDisplay(codePoint);
|
||||
return getFont2DWithSubstitution().canDisplay(codePoint);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2265,7 +2276,7 @@ public class Font implements java.io.Serializable
|
||||
* @since 1.2
|
||||
*/
|
||||
public int canDisplayUpTo(String str) {
|
||||
Font2D font2d = getFont2D();
|
||||
Font2D font2d = getFont2DWithSubstitution();
|
||||
int len = str.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = str.charAt(i);
|
||||
@@ -2303,7 +2314,7 @@ public class Font implements java.io.Serializable
|
||||
* @since 1.2
|
||||
*/
|
||||
public int canDisplayUpTo(char[] text, int start, int limit) {
|
||||
Font2D font2d = getFont2D();
|
||||
Font2D font2d = getFont2DWithSubstitution();
|
||||
for (int i = start; i < limit; i++) {
|
||||
char c = text[i];
|
||||
if (font2d.canDisplay(c)) {
|
||||
@@ -2338,7 +2349,7 @@ public class Font implements java.io.Serializable
|
||||
* @since 1.2
|
||||
*/
|
||||
public int canDisplayUpTo(CharacterIterator iter, int start, int limit) {
|
||||
Font2D font2d = getFont2D();
|
||||
Font2D font2d = getFont2DWithSubstitution();
|
||||
char c = iter.setIndex(start);
|
||||
for (int i = start; i < limit; i++, c = iter.next()) {
|
||||
if (font2d.canDisplay(c)) {
|
||||
@@ -2909,12 +2920,6 @@ public class Font implements java.io.Serializable
|
||||
*/
|
||||
public static final int LAYOUT_NO_LIMIT_CONTEXT = 4;
|
||||
|
||||
/**
|
||||
* A flag to layoutGlyphVector requesting to disable detection of paired characters
|
||||
* when splitting text into scripts.
|
||||
*/
|
||||
public static final int LAYOUT_NO_PAIRED_CHARS_AT_SCRIPT_SPLIT = 8;
|
||||
|
||||
private static void applyTransform(AffineTransform trans, AttributeValues values) {
|
||||
if (trans == null) {
|
||||
throw new IllegalArgumentException("transform must not be null");
|
||||
|
||||
@@ -32,6 +32,8 @@ import java.util.Locale;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
import sun.swing.SwingUtilities2;
|
||||
import sun.swing.text.GlyphViewAccessor;
|
||||
|
||||
import static sun.swing.SwingUtilities2.IMPLIED_CR;
|
||||
|
||||
/**
|
||||
@@ -787,6 +789,16 @@ public class GlyphView extends View implements TabableView, Cloneable {
|
||||
return breakSpot;
|
||||
}
|
||||
|
||||
static {
|
||||
GlyphViewAccessor.setAccessor(new GlyphViewAccessor() {
|
||||
@Override
|
||||
public int[] calcBreakSpots(GlyphView glyphView, BreakIterator breaker) {
|
||||
return glyphView.calcBreakSpots(breaker);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: convert to protected method (removing accessor) when upstreaming the fix
|
||||
/**
|
||||
* Collects all possible breaking positions in the element,
|
||||
* generated by the provided breaker.
|
||||
@@ -794,7 +806,7 @@ public class GlyphView extends View implements TabableView, Cloneable {
|
||||
* @param breaker provider of break positions
|
||||
* @return possible break positions in the element
|
||||
*/
|
||||
protected int[] calcBreakSpots(BreakIterator breaker) {
|
||||
int[] calcBreakSpots(BreakIterator breaker) {
|
||||
int start = getStartOffset();
|
||||
int end = getEndOffset();
|
||||
int[] bs = new int[end + 1 - start];
|
||||
|
||||
@@ -495,8 +495,10 @@ public class CSS implements Serializable {
|
||||
|
||||
/**
|
||||
* CSS attribute "overflow-wrap".
|
||||
*
|
||||
* TODO: make public when upstreaming the fix
|
||||
*/
|
||||
public static final Attribute OVERFLOW_WRAP =
|
||||
static final Attribute OVERFLOW_WRAP =
|
||||
new Attribute("overflow-wrap", "normal", true);
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
*/
|
||||
package javax.swing.text.html;
|
||||
|
||||
import sun.swing.text.GlyphViewAccessor;
|
||||
|
||||
import java.awt.*;
|
||||
import java.text.BreakIterator;
|
||||
import java.util.Locale;
|
||||
@@ -242,7 +244,7 @@ public class InlineView extends LabelView {
|
||||
Container c = getContainer();
|
||||
Locale locale = (c == null ? Locale.getDefault() : c.getLocale());
|
||||
BreakIterator breaker = BreakIterator.getCharacterInstance(locale);
|
||||
int[] breakSpots = calcBreakSpots(breaker);
|
||||
int[] breakSpots = GlyphViewAccessor.getAccessor().calcBreakSpots(this, breaker);
|
||||
int lastBreak = endOffset;
|
||||
for (int breakSpot : breakSpots) {
|
||||
wrapAnywhereMinimumSpan = Math.max(wrapAnywhereMinimumSpan,
|
||||
|
||||
@@ -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 class CompositeFont extends Font2D {
|
||||
public final class CompositeFont extends Font2D {
|
||||
|
||||
private boolean[] deferredInitialisation;
|
||||
String[] componentFileNames;
|
||||
|
||||
@@ -108,7 +108,7 @@ public class CompositeGlyphMapper extends CharToGlyphMapper {
|
||||
return mapper;
|
||||
}
|
||||
|
||||
protected int convertToGlyph(int unicode) {
|
||||
private int convertToGlyph(int unicode) {
|
||||
|
||||
for (int slot = 0; slot < font.numSlots; slot++) {
|
||||
if (!hasExcludes || !font.isExcludedChar(slot, unicode)) {
|
||||
|
||||
@@ -307,7 +307,8 @@ public class FileFontStrike extends PhysicalStrike {
|
||||
intPtSize = (int) pts;
|
||||
useNatives = (rotation == 0 || rotation > 0 && useNativesForRotatedText) && pts >= 3.0 && pts <= 100.0 &&
|
||||
(getImageWithAdvance || desc.fmHint == INTVAL_FRACTIONALMETRICS_ON) &&
|
||||
!((TrueTypeFont)fileFont).useEmbeddedBitmapsForSize(intPtSize);
|
||||
!((TrueTypeFont)fileFont).useEmbeddedBitmapsForSize(intPtSize) &&
|
||||
!((TrueTypeFont)fileFont).hasCOLRTable();
|
||||
}
|
||||
if (FontUtilities.isLogging() && FontUtilities.isWindows) {
|
||||
FontUtilities.logInfo("Strike for " + fileFont + " at size = " + intPtSize +
|
||||
@@ -839,15 +840,13 @@ public class FileFontStrike extends PhysicalStrike {
|
||||
|
||||
private int getGlyphImageMinX(long ptr, int origMinX) {
|
||||
|
||||
int width = StrikeCache.unsafe.getChar(ptr+StrikeCache.widthOffset);
|
||||
byte format = StrikeCache.unsafe.getByte(ptr+StrikeCache.formatOffset);
|
||||
if (format != StrikeCache.PIXEL_FORMAT_LCD) return origMinX;
|
||||
|
||||
int height = StrikeCache.unsafe.getChar(ptr+StrikeCache.heightOffset);
|
||||
int rowBytes =
|
||||
StrikeCache.unsafe.getChar(ptr+StrikeCache.rowBytesOffset);
|
||||
|
||||
if (rowBytes == width) {
|
||||
return origMinX;
|
||||
}
|
||||
|
||||
long pixelData =
|
||||
StrikeCache.unsafe.getAddress(ptr + StrikeCache.pixelDataOffset);
|
||||
|
||||
|
||||
@@ -335,7 +335,7 @@ public abstract class Font2D {
|
||||
return getStrike(desc, true);
|
||||
}
|
||||
|
||||
FontStrike getStrike(FontStrikeDesc desc, boolean copy) {
|
||||
private 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
|
||||
|
||||
@@ -43,6 +43,7 @@ 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 setCreatedFont(Font f);
|
||||
public abstract boolean isCreatedFont(Font f);
|
||||
|
||||
@@ -356,7 +356,7 @@ public final class FontDesignMetrics extends FontMetrics {
|
||||
|
||||
private void initMatrixAndMetrics() {
|
||||
|
||||
Font2D font2D = FontUtilities.getFont2D(font);
|
||||
Font2D font2D = FontUtilities.getFont2DWithSubstitution(font);
|
||||
fontStrike = font2D.getStrike(font, frc);
|
||||
StrikeMetrics metrics = fontStrike.getFontMetrics();
|
||||
this.ascent = metrics.getAscent();
|
||||
|
||||
@@ -266,12 +266,12 @@ public class FontFamily {
|
||||
doSetFont(fontAndStyle.font, fontAndStyle.style);
|
||||
}
|
||||
if (italic == null && plain instanceof FontWithDerivedItalic) {
|
||||
italic = ((FontWithDerivedItalic)plain).createItalic();
|
||||
italic = ((FontWithDerivedItalic)plain).createItalicVariant();
|
||||
}
|
||||
if (bolditalic == null) {
|
||||
Font2D boldItalicPrototype = bold != null ? bold : plain;
|
||||
if (boldItalicPrototype instanceof FontWithDerivedItalic) {
|
||||
bolditalic = ((FontWithDerivedItalic)boldItalicPrototype).createItalic();
|
||||
bolditalic = ((FontWithDerivedItalic)boldItalicPrototype).createItalicVariant();
|
||||
}
|
||||
}
|
||||
fontSequence.clear();
|
||||
|
||||
@@ -168,6 +168,10 @@ public final class FontUtilities {
|
||||
return FontAccess.getFontAccess().getFont2D(font);
|
||||
}
|
||||
|
||||
public static Font2D getFont2DWithSubstitution(Font font) {
|
||||
return FontAccess.getFontAccess().getFont2DWithSubstitution(font);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if there any characters which would trigger layout.
|
||||
* This method considers supplementary characters to be simple,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package sun.font;
|
||||
|
||||
interface FontWithDerivedItalic {
|
||||
Font2D createItalic();
|
||||
Font2D createItalicVariant();
|
||||
}
|
||||
@@ -81,6 +81,14 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import static java.lang.Character.*;
|
||||
|
||||
public final class GlyphLayout {
|
||||
/**
|
||||
* A flag to layoutGlyphVector requesting to disable detection of paired characters
|
||||
* when splitting text into scripts.
|
||||
*
|
||||
* TODO: move to java.awt.Font when upstreaming the fix
|
||||
*/
|
||||
private static final int LAYOUT_NO_PAIRED_CHARS_AT_SCRIPT_SPLIT = 8;
|
||||
|
||||
// data for glyph vector
|
||||
private GVData _gvdata;
|
||||
|
||||
@@ -360,7 +368,7 @@ public final class GlyphLayout {
|
||||
|
||||
init(count);
|
||||
|
||||
boolean handlePairedChars = (flags & Font.LAYOUT_NO_PAIRED_CHARS_AT_SCRIPT_SPLIT) == 0;
|
||||
boolean handlePairedChars = (flags & LAYOUT_NO_PAIRED_CHARS_AT_SCRIPT_SPLIT) == 0;
|
||||
|
||||
// need to set after init
|
||||
// go through the back door for this
|
||||
@@ -402,10 +410,7 @@ public final class GlyphLayout {
|
||||
|
||||
int lang = -1; // default for now
|
||||
|
||||
Font2D font2D = FontUtilities.getFont2D(font);
|
||||
if (font2D instanceof FontSubstitution) {
|
||||
font2D = ((FontSubstitution)font2D).getCompositeFont2D();
|
||||
}
|
||||
Font2D font2D = FontUtilities.getFont2DWithSubstitution(font);
|
||||
|
||||
_textRecord.init(text, offset, lim, min, max);
|
||||
int start = offset;
|
||||
|
||||
@@ -505,12 +505,17 @@ public final class GlyphList {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link StrikeCache#PIXEL_FORMAT_GREYSCALE} for greyscale,
|
||||
* {@link StrikeCache#PIXEL_FORMAT_LCD} for LCD and {@link StrikeCache#PIXEL_FORMAT_BGRA} for BGRA glyph
|
||||
*/
|
||||
public byte getPixelFormat(int glyphIndex) {
|
||||
return StrikeCache.unsafe.getByte(images[glyphIndex] +
|
||||
StrikeCache.formatOffset);
|
||||
}
|
||||
|
||||
public boolean isColorGlyph(int glyphIndex) {
|
||||
int width = StrikeCache.unsafe.getChar(images[glyphIndex] +
|
||||
StrikeCache.widthOffset);
|
||||
int rowBytes = StrikeCache.unsafe.getChar(images[glyphIndex] +
|
||||
StrikeCache.rowBytesOffset);
|
||||
return rowBytes == width * 4;
|
||||
return getPixelFormat(glyphIndex) == StrikeCache.PIXEL_FORMAT_BGRA;
|
||||
}
|
||||
|
||||
public SurfaceData getColorGlyphData() {
|
||||
|
||||
@@ -197,8 +197,7 @@ public class StandardGlyphVector extends GlyphVector {
|
||||
|
||||
// how do we know its a base glyph
|
||||
// for now, it is if the natural advance of the glyph is non-zero
|
||||
Font2D f2d = FontUtilities.getFont2D(font);
|
||||
FontStrike strike = f2d.getStrike(font, frc);
|
||||
FontStrike strike = font2D.getStrike(font, frc);
|
||||
|
||||
float[] deltas = { trackPt.x, trackPt.y };
|
||||
for (int j = 0; j < deltas.length; ++j) {
|
||||
@@ -1106,10 +1105,7 @@ public class StandardGlyphVector extends GlyphVector {
|
||||
}
|
||||
|
||||
private void initFontData() {
|
||||
font2D = FontUtilities.getFont2D(font);
|
||||
if (font2D instanceof FontSubstitution) {
|
||||
font2D = ((FontSubstitution)font2D).getCompositeFont2D();
|
||||
}
|
||||
font2D = FontUtilities.getFont2DWithSubstitution(font);
|
||||
float s = font.getSize2D();
|
||||
if (font.isTransformed()) {
|
||||
ftx = font.getTransform();
|
||||
@@ -1728,12 +1724,7 @@ public class StandardGlyphVector extends GlyphVector {
|
||||
aa, fm);
|
||||
// Get the strike via the handle. Shouldn't matter
|
||||
// if we've invalidated the font but its an extra precaution.
|
||||
// do we want the CompFont from CFont here ?
|
||||
Font2D f2d = sgv.font2D;
|
||||
if (f2d instanceof FontSubstitution) {
|
||||
f2d = ((FontSubstitution)f2d).getCompositeFont2D();
|
||||
}
|
||||
FontStrike strike = f2d.handle.font2D.getStrike(desc); // !!! getStrike(desc, false)
|
||||
FontStrike strike = sgv.font2D.handle.font2D.getStrike(desc); // !!! getStrike(desc, false)
|
||||
|
||||
return new GlyphStrike(sgv, strike, dx, dy);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ package sun.font;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.lang.annotation.Native;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
@@ -117,8 +118,14 @@ public final class StrikeCache {
|
||||
static int managedOffset;
|
||||
static int subpixelResolutionXOffset;
|
||||
static int subpixelResolutionYOffset;
|
||||
static int formatOffset;
|
||||
static long invisibleGlyphPtr;
|
||||
|
||||
@Native public static final byte PIXEL_FORMAT_UNKNOWN = -1;
|
||||
@Native public static final byte PIXEL_FORMAT_GREYSCALE = 1;
|
||||
@Native public static final byte PIXEL_FORMAT_LCD = 3;
|
||||
@Native public static final byte PIXEL_FORMAT_BGRA = 4;
|
||||
|
||||
/* Native method used to return information used for unsafe
|
||||
* access to native data.
|
||||
* return values as follows:-
|
||||
@@ -137,12 +144,13 @@ public final class StrikeCache {
|
||||
* arr[12] = offset of managed
|
||||
* arr[13] = offset of subpixelResolutionX
|
||||
* arr[14] = offset of subpixelResolutionY
|
||||
* arr[15] = offset of format
|
||||
*/
|
||||
static native void getGlyphCacheDescription(long[] infoArray);
|
||||
|
||||
static {
|
||||
|
||||
long[] nativeInfo = new long[15];
|
||||
long[] nativeInfo = new long[16];
|
||||
getGlyphCacheDescription(nativeInfo);
|
||||
//Can also get address size from Unsafe class :-
|
||||
//nativeAddressSize = unsafe.addressSize();
|
||||
@@ -161,6 +169,7 @@ public final class StrikeCache {
|
||||
managedOffset = (int) nativeInfo[12];
|
||||
subpixelResolutionXOffset = (int) nativeInfo[13];
|
||||
subpixelResolutionYOffset = (int) nativeInfo[14];
|
||||
formatOffset = (int) nativeInfo[15];
|
||||
|
||||
if (nativeAddressSize < 4) {
|
||||
throw new InternalError("Unexpected address size for font data: " +
|
||||
|
||||
@@ -98,6 +98,7 @@ public class TrueTypeFont extends FileFont {
|
||||
public static final int v1ttTag = 0x00010000; // 'v1tt' - Version 1 TT font
|
||||
public static final int trueTag = 0x74727565; // 'true' - Version 2 TT font
|
||||
public static final int ottoTag = 0x4f54544f; // 'otto' - OpenType font
|
||||
public static final int COLRTag = 0x434f4c52; // 'COLR'
|
||||
|
||||
/* -- ID's used in the 'name' table */
|
||||
public static final int MAC_PLATFORM_ID = 1;
|
||||
@@ -884,6 +885,10 @@ public class TrueTypeFont extends FileFont {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean hasCOLRTable() {
|
||||
return getDirectoryEntry(COLRTag) != null;
|
||||
}
|
||||
|
||||
/* Used to determine if this size has embedded bitmaps, which
|
||||
* for CJK fonts should be used in preference to LCD glyphs.
|
||||
*/
|
||||
|
||||
@@ -670,7 +670,7 @@ public final class SunGraphics2D
|
||||
info.nonInvertibleTx =
|
||||
(Math.abs(textAt.getDeterminant()) <= Double.MIN_VALUE);
|
||||
|
||||
info.font2D = FontUtilities.getFont2D(font);
|
||||
info.font2D = FontUtilities.getFont2DWithSubstitution(font);
|
||||
|
||||
int fmhint = fractionalMetricsHint;
|
||||
if (fmhint == SunHints.INTVAL_FRACTIONALMETRICS_DEFAULT) {
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
package sun.java2d.pipe;
|
||||
|
||||
import sun.awt.SunHints;
|
||||
import sun.font.StrikeCache;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.font.GlyphList;
|
||||
|
||||
@@ -41,50 +42,49 @@ public abstract class GlyphListLoopPipe extends GlyphListPipe
|
||||
protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl,
|
||||
int aaHint) {
|
||||
int prevLimit = 0;
|
||||
boolean isColor = false;
|
||||
byte pixelFormat = StrikeCache.PIXEL_FORMAT_UNKNOWN;
|
||||
int len = gl.getNumGlyphs();
|
||||
gl.startGlyphIteration();
|
||||
if (GlyphList.canContainColorGlyphs()) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
boolean newIsColor = gl.isColorGlyph(i);
|
||||
if (newIsColor != isColor) {
|
||||
drawGlyphListSegment(sg2d, gl, prevLimit, i, aaHint,
|
||||
isColor);
|
||||
byte newFormat = gl.getPixelFormat(i);
|
||||
if (newFormat != pixelFormat) {
|
||||
drawGlyphListSegment(sg2d, gl,
|
||||
prevLimit, i, aaHint, pixelFormat);
|
||||
prevLimit = i;
|
||||
isColor = newIsColor;
|
||||
pixelFormat = newFormat;
|
||||
}
|
||||
}
|
||||
}
|
||||
drawGlyphListSegment(sg2d, gl, prevLimit, len, aaHint, isColor);
|
||||
drawGlyphListSegment(sg2d, gl, prevLimit, len, aaHint, pixelFormat);
|
||||
}
|
||||
|
||||
private void drawGlyphListSegment(SunGraphics2D sg2d, GlyphList gl,
|
||||
int fromglyph, int toGlyph,
|
||||
int aaHint, boolean isColor) {
|
||||
int aaHint, byte pixelFormat) {
|
||||
if (fromglyph >= toGlyph) return;
|
||||
if (isColor) {
|
||||
sg2d.loops.drawGlyphListColorLoop.
|
||||
DrawGlyphListColor(sg2d, sg2d.surfaceData,
|
||||
gl, fromglyph, toGlyph);
|
||||
} else {
|
||||
switch (aaHint) {
|
||||
case SunHints.INTVAL_TEXT_ANTIALIAS_OFF:
|
||||
switch (pixelFormat) {
|
||||
case StrikeCache.PIXEL_FORMAT_GREYSCALE:
|
||||
if (aaHint == SunHints.INTVAL_TEXT_ANTIALIAS_OFF) {
|
||||
sg2d.loops.drawGlyphListLoop.
|
||||
DrawGlyphList(sg2d, sg2d.surfaceData,
|
||||
gl, fromglyph, toGlyph);
|
||||
return;
|
||||
case SunHints.INTVAL_TEXT_ANTIALIAS_ON:
|
||||
} else {
|
||||
sg2d.loops.drawGlyphListAALoop.
|
||||
DrawGlyphListAA(sg2d, sg2d.surfaceData,
|
||||
gl, fromglyph, toGlyph);
|
||||
return;
|
||||
case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB:
|
||||
case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB:
|
||||
sg2d.loops.drawGlyphListLCDLoop.
|
||||
DrawGlyphListLCD(sg2d, sg2d.surfaceData,
|
||||
gl, fromglyph, toGlyph);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
case StrikeCache.PIXEL_FORMAT_LCD:
|
||||
sg2d.loops.drawGlyphListLCDLoop.
|
||||
DrawGlyphListLCD(sg2d, sg2d.surfaceData,
|
||||
gl, fromglyph, toGlyph);
|
||||
return;
|
||||
case StrikeCache.PIXEL_FORMAT_BGRA:
|
||||
sg2d.loops.drawGlyphListColorLoop.
|
||||
DrawGlyphListColor(sg2d, sg2d.surfaceData,
|
||||
gl, fromglyph, toGlyph);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -698,7 +698,7 @@ public abstract class PathGraphics extends ProxyGraphics2D {
|
||||
}
|
||||
|
||||
Font font = g.getFont();
|
||||
Font2D font2D = FontUtilities.getFont2D(font);
|
||||
Font2D font2D = FontUtilities.getFont2DWithSubstitution(font);
|
||||
if (font2D.handle.font2D != font2D) {
|
||||
/* suspicious, may be a bad font. lets bail */
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2021 JetBrains s.r.o.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.swing.text;
|
||||
|
||||
import javax.swing.text.GlyphView;
|
||||
import java.text.BreakIterator;
|
||||
|
||||
public abstract class GlyphViewAccessor {
|
||||
private static GlyphViewAccessor accessor;
|
||||
|
||||
public static void setAccessor(GlyphViewAccessor a) {
|
||||
accessor = a;
|
||||
}
|
||||
|
||||
public static GlyphViewAccessor getAccessor() {
|
||||
return accessor;
|
||||
}
|
||||
|
||||
public abstract int[] calcBreakSpots(GlyphView glyphView, BreakIterator breaker);
|
||||
}
|
||||
@@ -27,6 +27,7 @@
|
||||
#define FontScalerDefsIncludesDefined
|
||||
|
||||
#include "AccelGlyphCache.h"
|
||||
#include "sun_font_StrikeCache.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -74,7 +75,8 @@ typedef struct GlyphInfo {
|
||||
UInt16 width;
|
||||
UInt16 height;
|
||||
UInt16 rowBytes;
|
||||
UInt8 managed;
|
||||
UInt8 managed;
|
||||
UInt8 format; // sun_font_StrikeCache_PIXEL_FORMAT_*
|
||||
UInt8 subpixelResolutionX;
|
||||
UInt8 subpixelResolutionY;
|
||||
float topLeftX;
|
||||
|
||||
@@ -1309,7 +1309,7 @@ OGLTR_DrawGlyphList(JNIEnv *env, OGLContext *oglc, OGLSDOps *dstOps,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ginfo->rowBytes == ginfo->width) {
|
||||
if (ginfo->format == sun_font_StrikeCache_PIXEL_FORMAT_GREYSCALE) {
|
||||
if (oglc->grayRenderHints == NULL) {
|
||||
OGLContext_InitGrayRenderHints(env, oglc);
|
||||
}
|
||||
@@ -1329,7 +1329,7 @@ OGLTR_DrawGlyphList(JNIEnv *env, OGLContext *oglc, OGLSDOps *dstOps,
|
||||
} else {
|
||||
ok = OGLTR_DrawGrayscaleGlyphNoCache(oglc, ginfo, x, y, subimage);
|
||||
}
|
||||
} else if (ginfo->rowBytes == ginfo->width * 4) {
|
||||
} else if (ginfo->format == sun_font_StrikeCache_PIXEL_FORMAT_BGRA) {
|
||||
// color glyph data
|
||||
ok = OGLTR_DrawColorGlyphNoCache(oglc, ginfo, x, y);
|
||||
} else {
|
||||
|
||||
@@ -578,8 +578,7 @@ GlyphBlitVector* setupLCDBlitVector(JNIEnv *env, jobject glyphlist,
|
||||
free(gbv);
|
||||
return (GlyphBlitVector*)NULL;
|
||||
}
|
||||
/* rowBytes==width tests if its a B&W or LCD glyph */
|
||||
if (ginfo->width == ginfo->rowBytes) {
|
||||
if (ginfo->format != sun_font_StrikeCache_PIXEL_FORMAT_LCD) {
|
||||
subPixPos = JNI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1850,6 +1850,11 @@ static jlong
|
||||
glyphInfo->subpixelResolutionX = subpixelResolutionX;
|
||||
glyphInfo->subpixelResolutionY = subpixelResolutionY;
|
||||
|
||||
if (ftglyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) glyphInfo->format = sun_font_StrikeCache_PIXEL_FORMAT_BGRA;
|
||||
else if (ftglyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD ||
|
||||
ftglyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V) glyphInfo->format = sun_font_StrikeCache_PIXEL_FORMAT_LCD;
|
||||
else glyphInfo->format = sun_font_StrikeCache_PIXEL_FORMAT_GREYSCALE;
|
||||
|
||||
if (renderImage) {
|
||||
if (ftglyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD && width > 0) {
|
||||
glyphInfo->width = width/3;
|
||||
|
||||
@@ -314,7 +314,7 @@ Java_sun_font_StrikeCache_getGlyphCacheDescription
|
||||
GlyphInfo *info;
|
||||
size_t baseAddr;
|
||||
|
||||
if ((*env)->GetArrayLength(env, results) < 15) {
|
||||
if ((*env)->GetArrayLength(env, results) < 16) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -343,6 +343,7 @@ Java_sun_font_StrikeCache_getGlyphCacheDescription
|
||||
nresults[12] = (size_t)&(info->managed)-baseAddr;
|
||||
nresults[13] = (size_t)&(info->subpixelResolutionX)-baseAddr;
|
||||
nresults[14] = (size_t)&(info->subpixelResolutionY)-baseAddr;
|
||||
nresults[15] = (size_t)&(info->format)-baseAddr;
|
||||
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import sun.awt.IconInfo;
|
||||
import sun.awt.PeerEvent;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
@@ -1306,7 +1307,7 @@ abstract class XDecoratedPeer extends XWindowPeer {
|
||||
* WM_TAKE_FOCUS (when FocusIn is generated via XSetInputFocus call) but
|
||||
* definetely before the Frame gets FocusIn event (when this method is called).
|
||||
*/
|
||||
postEvent(new InvocationEvent(target, new Runnable() {
|
||||
postEvent(new PeerEvent(target, new Runnable() {
|
||||
public void run() {
|
||||
XWindowPeer fw = null;
|
||||
synchronized (getStateLock()) {
|
||||
@@ -1318,7 +1319,7 @@ abstract class XDecoratedPeer extends XWindowPeer {
|
||||
}
|
||||
fw.handleWindowFocusIn_Dispatch();
|
||||
}
|
||||
}));
|
||||
}, PeerEvent.ULTIMATE_PRIORITY_EVENT));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ public class XKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
|
||||
{
|
||||
return KeyboardFocusManagerPeerImpl.deliverFocus(lightweightChild,
|
||||
target,
|
||||
false,
|
||||
true,
|
||||
cause,
|
||||
getInstance().getCurrentFocusOwner());
|
||||
}
|
||||
|
||||
@@ -149,6 +149,8 @@ final class XWM
|
||||
return "XMonad";
|
||||
case AWESOME_WM:
|
||||
return "Awesome";
|
||||
case XWM.I3_WM:
|
||||
return "I3WM";
|
||||
case UNDETERMINED_WM:
|
||||
default:
|
||||
return "Undetermined WM";
|
||||
@@ -1466,6 +1468,8 @@ final class XWM
|
||||
case XWM.ENLIGHTEN_WM:
|
||||
/* At least E16 is buggy. */
|
||||
return true;
|
||||
case XWM.I3_WM:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user