mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-25 02:39:43 +01:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
761239703b | ||
|
|
c75d75b84d | ||
|
|
59dde04f10 | ||
|
|
730e5d9e01 | ||
|
|
4fde082d53 | ||
|
|
a953db1c0e | ||
|
|
a155760e94 | ||
|
|
51dc9aeb99 | ||
|
|
d69eac67d5 | ||
|
|
2a398ebb24 | ||
|
|
9e959b0043 | ||
|
|
653123737c | ||
|
|
3c34696d27 | ||
|
|
aa0b61cb75 | ||
|
|
1002eff4f3 | ||
|
|
f20a3d8679 | ||
|
|
961e036158 | ||
|
|
cafb374afc | ||
|
|
32def2fd42 | ||
|
|
224f78ca62 | ||
|
|
b775b37bd3 | ||
|
|
bd366e24b1 | ||
|
|
25e087d269 | ||
|
|
23bf121a1e | ||
|
|
b224bef5a3 | ||
|
|
d0600837ed | ||
|
|
77be5ba45f | ||
|
|
4af628cefe |
@@ -1,6 +1,7 @@
|
||||
[](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
|
||||
|
||||
# Welcome to JetBrains Runtime!
|
||||
# Welcome to JetBrains Runtime!
|
||||
<a name="jetbrains-runtime"></a>
|
||||
|
||||
JetBrains Runtime is a fork of [OpenJDK](https://github.com/openjdk/jdk) available for Windows, Mac OS X, and Linux.
|
||||
It includes a number enhancements in font rendering, HiDPI support, ligatures, performance improvements, and bugfixes.
|
||||
@@ -11,8 +12,8 @@ can be found on the [releases page](https://github.com/JetBrains/JetBrainsRuntim
|
||||
|
||||
| IDE Version | Latest JBR | Date Released |
|
||||
| --- | --- | --- |
|
||||
| 2021.3 | [11_0_13-b1751.16](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr11_0_13b1751.16) | 2-Nov-2021 |
|
||||
| 2021.2 | [11_0_12-b1504.40](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jb11_0_12-b1504.40) | 28-Sep-2021 |
|
||||
| 2021.3 | [11_0_13-b1751.19](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr11_0_13b1751.19) | 9-Nov-2021 |
|
||||
| 2021.2 | [11_0_13-b1504.49](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jb11_0_13-b1504.49) | 15-Nov-2021 |
|
||||
| 2021.1 | [11.0.11+9-b1341.60](https://confluence.jetbrains.com/pages/viewpage.action?pageId=218857477) | 15-Jun-2021 |
|
||||
| 2020.3 | [11_0_11-b1145.115](https://confluence.jetbrains.com/pages/viewpage.action?pageId=219349001) | 21-Jun-2021 |
|
||||
|
||||
|
||||
@@ -47,12 +47,6 @@ architecture=${architecture:=x64}
|
||||
|
||||
source jb/project/tools/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
|
||||
# NOTE: aot, cds aren't supported yet
|
||||
@@ -84,6 +78,7 @@ function do_configure {
|
||||
$WITH_DEBUG_LEVEL \
|
||||
--with-vendor-name="${VENDOR_NAME}" \
|
||||
--with-vendor-version-string="${VENDOR_VERSION_STRING}" \
|
||||
--with-jvm-features=shenandoahgc \
|
||||
--with-version-pre= \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
@@ -134,11 +129,6 @@ function create_jbr {
|
||||
cp ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Info.plist ${JRE_CONTENTS}
|
||||
|
||||
rm -rf ${JRE_CONTENTS}/Frameworks || do_exit $?
|
||||
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
|
||||
if [[ "${bundle_type}" == *jcef* ]] || [[ "${bundle_type}" == *dcevm* ]] || [[ "${bundle_type}" == fd ]]; then
|
||||
cp -a ${JCEF_PATH}/Frameworks ${JRE_CONTENTS} || do_exit $?
|
||||
fi
|
||||
@@ -206,9 +196,6 @@ if [[ "${bundle_type}" == *jcef* ]] || [[ "${bundle_type}" == *dcevm* ]] || [[ "
|
||||
fi
|
||||
if [ "${bundle_type}" == "jcef" ] || [ "${bundle_type}" == "fd" ]; then
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
if [[ "${architecture}" == *aarch64* ]]; then
|
||||
copyJNF $BASE_DIR/$JBRSDK_BUNDLE/Contents
|
||||
fi
|
||||
sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release > release
|
||||
mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release
|
||||
[ -f "${JBSDK}.tar.gz" ] && rm "${JBSDK}.tar.gz"
|
||||
|
||||
@@ -52,6 +52,7 @@ jdk.sctp,
|
||||
jdk.security.auth,
|
||||
jdk.security.jgss,
|
||||
jdk.unsupported,
|
||||
jdk.unsupported.desktop,
|
||||
jdk.xml.dom,
|
||||
jdk.zipfs,
|
||||
jdk.hotspot.agent,
|
||||
|
||||
@@ -840,6 +840,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) {
|
||||
|
||||
@@ -127,12 +127,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
|
||||
|
||||
@@ -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, 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,45 @@ 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;
|
||||
for (String s : components) {
|
||||
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 +271,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 +303,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() {
|
||||
@@ -226,6 +233,7 @@ public final class CFontManager extends SunFontManager {
|
||||
public Object run() {
|
||||
if (!loadedAllFonts) {
|
||||
loadNativeFonts();
|
||||
collectAdditionalFallbackVariants();
|
||||
loadedAllFonts = true;
|
||||
}
|
||||
return null;
|
||||
@@ -322,4 +330,39 @@ 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) {}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,18 +360,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) {
|
||||
@@ -380,19 +376,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) {
|
||||
@@ -406,21 +392,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) {
|
||||
@@ -443,14 +418,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()) {
|
||||
@@ -492,42 +459,12 @@ 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;
|
||||
|
||||
// Empty non private constructor was added because access to this
|
||||
@@ -537,17 +474,9 @@ public final class CStrike extends PhysicalStrike {
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -557,21 +486,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) {
|
||||
@@ -580,34 +498,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1245,23 +1245,6 @@ public class LWWindowPeer
|
||||
return false;
|
||||
}
|
||||
|
||||
AppContext targetAppContext = AWTAccessor.getComponentAccessor().getAppContext(getTarget());
|
||||
KeyboardFocusManager kfm = AWTAccessor.getKeyboardFocusManagerAccessor()
|
||||
.getCurrentKeyboardFocusManager(targetAppContext);
|
||||
Window currentActive = kfm.getActiveWindow();
|
||||
|
||||
|
||||
Window opposite = LWKeyboardFocusManagerPeer.getInstance().
|
||||
getCurrentFocusedWindow();
|
||||
|
||||
// In case the toplevel is active but not focused, change focus directly,
|
||||
// as requesting native focus on it will not have effect.
|
||||
if (getTarget() == currentActive && !getTarget().hasFocus()) {
|
||||
|
||||
changeFocusedWindow(true, opposite);
|
||||
return true;
|
||||
}
|
||||
|
||||
return platformWindow.requestWindowFocus();
|
||||
}
|
||||
|
||||
|
||||
@@ -25,14 +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.JProgressBar;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
@@ -48,6 +48,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 {
|
||||
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;
|
||||
@@ -120,23 +134,29 @@ 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);
|
||||
execute(ptr -> selectedTextChanged(ptr));
|
||||
} else if (name.compareTo(ACCESSIBLE_TEXT_PROPERTY) == 0 ) {
|
||||
valueChanged(ptr);
|
||||
execute(ptr -> valueChanged(ptr));
|
||||
} else if (name.compareTo(ACCESSIBLE_SELECTION_PROPERTY) == 0 ) {
|
||||
selectionChanged(ptr);
|
||||
if (timer != null) {
|
||||
timer.stop();
|
||||
}
|
||||
timer = new Timer(SELECTED_CHILDREN_MILLISECONDS, actionEvent -> execute(ptr -> selectionChanged(ptr)));
|
||||
timer.setRepeats(false);
|
||||
timer.start();
|
||||
} else if (name.compareTo(ACCESSIBLE_TABLE_MODEL_CHANGED) == 0) {
|
||||
valueChanged(ptr);
|
||||
execute(ptr -> valueChanged(ptr));
|
||||
if (CAccessible.getSwingAccessible(CAccessible.this) != null) {
|
||||
Accessible a = CAccessible.getSwingAccessible(CAccessible.this);
|
||||
AccessibleContext ac = a.getAccessibleContext();
|
||||
if ((ac != null) && (ac.getAccessibleRole() == AccessibleRole.TABLE)) {
|
||||
tableContentCacheClear(ptr);
|
||||
execute(ptr -> tableContentCacheClear(ptr));
|
||||
}
|
||||
}
|
||||
} else if (name.compareTo(ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY) == 0 ) {
|
||||
@@ -151,25 +171,33 @@ class CAccessible extends CFRetainedResource implements Accessible {
|
||||
if (parentAccessible != null) {
|
||||
parentRole = parentAccessible.getAccessibleContext().getAccessibleRole();
|
||||
}
|
||||
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();
|
||||
}
|
||||
// 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 (parentRole != AccessibleRole.COMBO_BOX) {
|
||||
if (thisRole == AccessibleRole.POPUP_MENU) {
|
||||
if ( newValue != null &&
|
||||
((AccessibleState)newValue) == AccessibleState.VISIBLE ) {
|
||||
menuOpened(ptr);
|
||||
execute(ptr -> menuOpened(ptr));
|
||||
} else if ( oldValue != null &&
|
||||
((AccessibleState)oldValue) == AccessibleState.VISIBLE ) {
|
||||
menuClosed(ptr);
|
||||
execute(ptr -> menuClosed(ptr));
|
||||
}
|
||||
} else if (thisRole == AccessibleRole.MENU_ITEM) {
|
||||
if ( newValue != null &&
|
||||
((AccessibleState)newValue) == AccessibleState.FOCUSED ) {
|
||||
menuItemSelected(ptr);
|
||||
execute(ptr -> menuItemSelected(ptr));
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +109,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
private static native void nativeExitFullScreenMode(long nsWindowPtr);
|
||||
static native CPlatformWindow nativeGetTopmostPlatformWindowUnderMouse();
|
||||
private static native boolean nativeDelayShowing(long nsWindowPtr);
|
||||
private static native void nativeRaiseLevel(long nsWindowPtr, boolean popup, boolean onlyIfParentIsActive);
|
||||
|
||||
// Loger to report issues happened during execution but that do not affect functionality
|
||||
private static final PlatformLogger logger = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformWindow");
|
||||
@@ -1432,10 +1433,10 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
}
|
||||
|
||||
protected void applyWindowLevel(Window target) {
|
||||
if (target.isAlwaysOnTop() && target.getType() != Window.Type.POPUP) {
|
||||
execute(ptr->CWrapper.NSWindow.setLevel(ptr, CWrapper.NSWindow.NSFloatingWindowLevel));
|
||||
} else if (target.getType() == Window.Type.POPUP) {
|
||||
execute(ptr->CWrapper.NSWindow.setLevel(ptr, CWrapper.NSWindow.NSPopUpMenuWindowLevel));
|
||||
boolean popup = target.getType() == Window.Type.POPUP;
|
||||
boolean alwaysOnTop = target.isAlwaysOnTop();
|
||||
if (popup || alwaysOnTop || owner != null) {
|
||||
execute(ptr -> nativeRaiseLevel(ptr, popup, !popup && !alwaysOnTop));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1961,6 +1961,29 @@ JNI_COCOA_ENTER(env);
|
||||
JNI_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeRaiseLevel
|
||||
(JNIEnv *env, jclass clazz, jlong windowPtr, jboolean popup, jboolean onlyIfParentIsActive)
|
||||
{
|
||||
JNI_COCOA_ENTER(env);
|
||||
|
||||
NSWindow *nsWindow = OBJC(windowPtr);
|
||||
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
|
||||
AWTWindow *window = (AWTWindow*)[nsWindow delegate];
|
||||
if (onlyIfParentIsActive) {
|
||||
AWTWindow *parent = window;
|
||||
do {
|
||||
parent = parent.ownerWindow;
|
||||
} while (parent != nil && !parent.nsWindow.isMainWindow);
|
||||
if (parent == nil) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
[nsWindow setLevel: popup ? NSPopUpMenuWindowLevel : NSFloatingWindowLevel];
|
||||
}];
|
||||
|
||||
JNI_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_CPlatformWindow
|
||||
* Method: nativeDelayShowing
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,7 @@ static jmethodID sjm_getAccessibleSelection = NULL;
|
||||
|
||||
@implementation JavaComboBoxAccessibility
|
||||
|
||||
// NSAccessibilityElement protocol methods
|
||||
|
||||
- (id)accessibilityValue {
|
||||
- (JavaComponentAccessibility *)accessibleSelection {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject axContext = [self axContextWithEnv:env];
|
||||
if (axContext == NULL) return nil;
|
||||
@@ -42,17 +40,17 @@ 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 [JavaComponentAccessibility createWithAccessible:axSelectedChild withEnv:env withView:fView];
|
||||
}
|
||||
|
||||
// NSAccessibilityElement protocol methods
|
||||
|
||||
- (id)accessibilityValue {
|
||||
return [[self accessibleSelection] accessibilityLabel];
|
||||
}
|
||||
|
||||
- (NSArray *)accessibilitySelectedChildren {
|
||||
return [NSArray arrayWithObject:[self accessibleSelection]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -528,7 +528,11 @@ static NSString* parentRole(NSAccessibilityRole nsRole)
|
||||
return NO;
|
||||
}
|
||||
|
||||
return isChildSelected(env, ((JavaComponentAccessibility *)[self parent])->fAccessible, fIndex, fComponent);
|
||||
id parent = [self parent];
|
||||
if ([parent isKindOfClass:[JavaComponentAccessibility class]]) {
|
||||
return isChildSelected(env, ((JavaComponentAccessibility *)parent)->fAccessible, fIndex, fComponent);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)isSelectable:(JNIEnv *)env
|
||||
@@ -764,7 +768,7 @@ static NSString* parentRole(NSAccessibilityRole nsRole)
|
||||
|
||||
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 NSMakeRect(point.x, point.y, size.width, size.height);
|
||||
}
|
||||
@@ -1081,7 +1085,7 @@ static NSNumber* JavaNumberToNSNumber(JNIEnv *env, jobject jnumber) {
|
||||
"(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;
|
||||
|
||||
|
||||
@@ -26,10 +26,13 @@ static BOOL javaObjectEquals(JNIEnv *env, jobject a, jobject b, jobject componen
|
||||
- (jobject)tabGroup {
|
||||
if (fTabGroupAxContext == NULL) {
|
||||
JNIEnv* env = [ThreadUtilities getJNIEnv];
|
||||
jobject tabGroupAxContext = [(JavaComponentAccessibility *)[self parent] axContextWithEnv:env];
|
||||
fTabGroupAxContext = (*env)->NewWeakGlobalRef(env, tabGroupAxContext);
|
||||
CHECK_EXCEPTION();
|
||||
(*env)->DeleteLocalRef(env, tabGroupAxContext);
|
||||
id parent = [self parent];
|
||||
if ([parent isKindOfClass:[JavaComponentAccessibility class]]) {
|
||||
jobject tabGroupAxContext = [(JavaComponentAccessibility *)parent axContextWithEnv:env];
|
||||
fTabGroupAxContext = (*env)->NewWeakGlobalRef(env, tabGroupAxContext);
|
||||
CHECK_EXCEPTION();
|
||||
(*env)->DeleteLocalRef(env, tabGroupAxContext);
|
||||
}
|
||||
}
|
||||
return fTabGroupAxContext;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -3350,3 +3351,61 @@ 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);
|
||||
}
|
||||
|
||||
@@ -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,24 +159,19 @@ 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);
|
||||
const CGFontRef cgFallback = CTFontCopyGraphicsFont(fallback, NULL);
|
||||
if (IS_OSX_GT10_13 || CGGI_IsColorFont(cgFallback)) {
|
||||
CGGlyph glyph = glyphCode;
|
||||
const CGFontRef cgFont = awtFont->fNativeCGFont;
|
||||
if (IS_OSX_GT10_13 || CGGI_IsColorFont(cgFont)) {
|
||||
CGAffineTransform matrix = awtStrike->fAltTx;
|
||||
CGFloat fontSize = sqrt(fabs(matrix.a * matrix.d - matrix.b * matrix.c));
|
||||
CTFontRef font = CTFontCreateWithGraphicsFont(cgFallback, fontSize, NULL, NULL);
|
||||
CTFontRef font = CTFontCreateWithGraphicsFont(cgFont, fontSize, NULL, NULL);
|
||||
CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, &glyph, &advance, 1);
|
||||
CFRelease(font);
|
||||
advance.width /= fontSize;
|
||||
advance.height /= fontSize;
|
||||
} else {
|
||||
CTFontGetAdvancesForGlyphs(fallback, kCTFontDefaultOrientation, &glyph, &advance, 1);
|
||||
CTFontGetAdvancesForGlyphs((CTFontRef)awtFont->fFont, kCTFontDefaultOrientation, &glyph, &advance, 1);
|
||||
}
|
||||
CFRelease(cgFallback);
|
||||
CFRelease(fallback);
|
||||
advance = CGSizeApplyAffineTransform(advance, awtStrike->fFontTx);
|
||||
if (!JRSFontStyleUsesFractionalMetrics(awtStrike->fStyle)) {
|
||||
advance.width = round(advance.width);
|
||||
@@ -207,14 +201,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;
|
||||
JRSFontGetBoundingBoxesForGlyphsAndStyle(fallback, &tx, awtStrike->fStyle, &glyph, 1, &bbox);
|
||||
CFRelease(fallback);
|
||||
JRSFontGetBoundingBoxesForGlyphsAndStyle((CTFontRef)awtFont->fFont, &tx, awtStrike->fStyle, &glyph, 1, &bbox);
|
||||
|
||||
// the origin of this bounding box is relative to the bottom-left corner baseline
|
||||
CGFloat decender = -bbox.origin.y;
|
||||
@@ -263,14 +252,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));
|
||||
@@ -279,8 +266,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);
|
||||
@@ -334,19 +320,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 = (jstring)NSStringToJavaString(env, (NSString *)fontNames[0]);
|
||||
(*env)->SetObjectArrayElement(env, resultArray, 0, fontName);
|
||||
jstring fontFamilyName = (jstring)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"
|
||||
@@ -687,6 +686,7 @@ CGGI_CreateImageForGlyph
|
||||
|
||||
// clean the canvas
|
||||
CGGI_ClearCanvas(canvas, info, glyphDescriptor == &argb);
|
||||
CGContextSetShouldAntialias(canvas->context, strike->fAAStyle != sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_OFF);
|
||||
|
||||
// strike the glyph in the upper right corner
|
||||
CGFloat x = -info->topLeftX;
|
||||
@@ -758,80 +758,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);
|
||||
|
||||
const CGFontRef cgFallback = CTFontCopyGraphicsFont(fallback, NULL);
|
||||
CGGI_GlyphInfoDescriptor *glyphDescriptor = CGGI_GetGlyphInfoDescriptor(mode, cgFallback);
|
||||
|
||||
bool subpixelResolution = mode->subpixelResolution && glyphDescriptor == &grey;
|
||||
|
||||
CGRect bbox;
|
||||
JRSFontGetBoundingBoxesForGlyphsAndStyle(fallback, &strike->fTx, style, &glyph, 1, &bbox);
|
||||
|
||||
CGSize advance;
|
||||
CTFontGetAdvancesForGlyphs(fallback, kCTFontDefaultOrientation, &glyph, &advance, 1);
|
||||
|
||||
|
||||
// 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);
|
||||
|
||||
CGContextSetFont(canvas->context, cgFallback);
|
||||
CFRelease(cgFallback);
|
||||
|
||||
// clean the canvas - align, strike, and copy the glyph from the canvas into the info
|
||||
CGGI_CreateImageForGlyph(cgFallback, canvas, glyph, info, glyphDescriptor, strike, 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 ---
|
||||
|
||||
@@ -846,7 +772,6 @@ CGGI_FillImagesForGlyphsWithSizedCanvas(CGGI_GlyphCanvas *canvas,
|
||||
const AWTStrike *strike,
|
||||
const CGGI_RenderingMode *mode,
|
||||
jlong glyphInfos[],
|
||||
const UnicodeScalarValue uniChars[],
|
||||
const CGGlyph glyphs[],
|
||||
const CFIndex len)
|
||||
{
|
||||
@@ -859,13 +784,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(strike->fAWTFont->fNativeCGFont,
|
||||
canvas, glyphs[i], info, mode->mainFontDescriptor, strike, isMojaveOrAbove);
|
||||
} else {
|
||||
info = CGGI_CreateImageForUnicode(canvas, strike, mode, uniChars[i], isMojaveOrAbove);
|
||||
glyphInfos[i] = ptr_to_jlong(info);
|
||||
}
|
||||
CGGI_CreateImageForGlyph(strike->fAWTFont->fNativeCGFont,
|
||||
canvas, glyphs[i], info, mode->mainFontDescriptor, strike, isMojaveOrAbove);
|
||||
#ifdef CGGI_DEBUG
|
||||
DUMP_GLYPHINFO(info);
|
||||
#endif
|
||||
@@ -900,7 +820,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)
|
||||
{
|
||||
@@ -910,8 +830,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];
|
||||
@@ -931,7 +850,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);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -947,7 +866,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;
|
||||
@@ -962,12 +881,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];
|
||||
|
||||
@@ -984,41 +897,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;
|
||||
@@ -1044,31 +945,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;
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ import sun.font.FontAccess;
|
||||
import sun.font.FontDesignMetrics;
|
||||
import sun.font.FontManager;
|
||||
import sun.font.FontManagerFactory;
|
||||
import sun.font.FontSubstitution;
|
||||
import sun.font.FontUtilities;
|
||||
import sun.font.GlyphLayout;
|
||||
import sun.font.FontLineMetrics;
|
||||
@@ -234,6 +235,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;
|
||||
}
|
||||
@@ -510,6 +516,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.
|
||||
@@ -2187,7 +2198,7 @@ public class Font implements java.io.Serializable
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean canDisplay(char c){
|
||||
return getFont2D().canDisplay(c);
|
||||
return getFont2DWithSubstitution().canDisplay(c);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2208,7 +2219,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2229,7 +2240,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);
|
||||
@@ -2267,7 +2278,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)) {
|
||||
@@ -2302,7 +2313,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)) {
|
||||
@@ -2873,12 +2884,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,7 +789,17 @@ public class GlyphView extends View implements TabableView, Cloneable {
|
||||
return breakSpot;
|
||||
}
|
||||
|
||||
protected int[] calcBreakSpots(BreakIterator breaker) {
|
||||
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
|
||||
int[] calcBreakSpots(BreakIterator breaker) {
|
||||
int start = getStartOffset();
|
||||
int end = getEndOffset();
|
||||
int[] bs = new int[end + 1 - start];
|
||||
|
||||
@@ -494,8 +494,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)) {
|
||||
|
||||
@@ -878,8 +878,8 @@ public class FileFontStrike extends PhysicalStrike {
|
||||
|
||||
private int getGlyphImageMinX(long ptr, int origMinX) {
|
||||
|
||||
int format = StrikeCache.unsafe.getByte(ptr+StrikeCache.formatOffset);
|
||||
if (format != 3) return origMinX;
|
||||
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 =
|
||||
|
||||
@@ -71,8 +71,6 @@ public abstract class Font2D {
|
||||
private static final FontRenderContext DEFAULT_FRC =
|
||||
new FontRenderContext(null, false, false);
|
||||
|
||||
static final boolean fontSubstitutionEnabled = !Boolean.getBoolean("disable.font.substitution");
|
||||
|
||||
public Font2DHandle handle;
|
||||
protected String familyName; /* Family font name (english) */
|
||||
protected String fullName; /* Full font name (english) */
|
||||
@@ -337,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);
|
||||
|
||||
@@ -355,7 +355,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();
|
||||
|
||||
@@ -111,14 +111,13 @@ public class FontStrikeDesc {
|
||||
*/
|
||||
public static int getAAHintIntVal(Object aa, Font2D font2D, int ptSize) {
|
||||
|
||||
if (FontUtilities.isMacOSX16 ||
|
||||
(FontUtilities.isMacOSX14 &&
|
||||
(aa == VALUE_TEXT_ANTIALIAS_OFF ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_DEFAULT ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_ON ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_GASP)))
|
||||
if (FontUtilities.isMacOSX14 &&
|
||||
(aa == VALUE_TEXT_ANTIALIAS_LCD_HBGR ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_LCD_HRGB ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_LCD_VBGR ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_LCD_VRGB))
|
||||
{
|
||||
return INTVAL_TEXT_ANTIALIAS_ON;
|
||||
return INTVAL_TEXT_ANTIALIAS_ON;
|
||||
}
|
||||
|
||||
if (aa == VALUE_TEXT_ANTIALIAS_OFF ||
|
||||
@@ -154,14 +153,13 @@ public class FontStrikeDesc {
|
||||
FontRenderContext frc) {
|
||||
Object aa = frc.getAntiAliasingHint();
|
||||
|
||||
if (FontUtilities.isMacOSX16 ||
|
||||
(FontUtilities.isMacOSX14 &&
|
||||
(aa == VALUE_TEXT_ANTIALIAS_OFF ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_DEFAULT ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_ON ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_GASP)))
|
||||
if (FontUtilities.isMacOSX14 &&
|
||||
(aa == VALUE_TEXT_ANTIALIAS_LCD_HBGR ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_LCD_HRGB ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_LCD_VBGR ||
|
||||
aa == VALUE_TEXT_ANTIALIAS_LCD_VRGB))
|
||||
{
|
||||
return INTVAL_TEXT_ANTIALIAS_ON;
|
||||
return INTVAL_TEXT_ANTIALIAS_ON;
|
||||
}
|
||||
|
||||
if (aa == VALUE_TEXT_ANTIALIAS_OFF ||
|
||||
|
||||
@@ -190,6 +190,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;
|
||||
|
||||
@@ -369,7 +377,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
|
||||
@@ -411,10 +419,7 @@ public final class GlyphLayout {
|
||||
|
||||
int lang = -1; // default for now
|
||||
|
||||
Font2D font2D = FontUtilities.getFont2D(font);
|
||||
if (Font2D.fontSubstitutionEnabled && font2D instanceof FontSubstitution) {
|
||||
font2D = ((FontSubstitution)font2D).getCompositeFont2D();
|
||||
}
|
||||
Font2D font2D = FontUtilities.getFont2DWithSubstitution(font);
|
||||
|
||||
_textRecord.init(text, offset, lim, min, max);
|
||||
int start = offset;
|
||||
|
||||
@@ -509,14 +509,15 @@ public final class GlyphList {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 1 for greyscale, 3 for LCD and 4 for BGRA glyph
|
||||
* @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 int getPixelFormat(int glyphIndex) {
|
||||
public byte getPixelFormat(int glyphIndex) {
|
||||
return StrikeCache.unsafe.getByte(images[glyphIndex] + StrikeCache.formatOffset);
|
||||
}
|
||||
|
||||
public boolean isColorGlyph(int glyphIndex) {
|
||||
return getPixelFormat(glyphIndex) == 4;
|
||||
return getPixelFormat(glyphIndex) == StrikeCache.PIXEL_FORMAT_BGRA;
|
||||
}
|
||||
|
||||
public SurfaceData getColorGlyphData() {
|
||||
|
||||
@@ -195,8 +195,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) {
|
||||
@@ -1127,10 +1126,7 @@ public class StandardGlyphVector extends GlyphVector {
|
||||
}
|
||||
|
||||
private void initFontData() {
|
||||
font2D = FontUtilities.getFont2D(font);
|
||||
if (Font2D.fontSubstitutionEnabled && font2D instanceof FontSubstitution) {
|
||||
font2D = ((FontSubstitution)font2D).getCompositeFont2D();
|
||||
}
|
||||
font2D = FontUtilities.getFont2DWithSubstitution(font);
|
||||
float s = font.getSize2D();
|
||||
if (font.isTransformed()) {
|
||||
ftx = font.getTransform();
|
||||
@@ -1749,12 +1745,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;
|
||||
@@ -119,6 +120,11 @@ public final class StrikeCache {
|
||||
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:-
|
||||
|
||||
@@ -668,7 +668,7 @@ public final class SunGraphics2D
|
||||
}
|
||||
}
|
||||
|
||||
info.font2D = FontUtilities.getFont2D(font);
|
||||
info.font2D = FontUtilities.getFont2DWithSubstitution(font);
|
||||
|
||||
int fmhint = fractionalMetricsHint;
|
||||
if (fmhint == SunHints.INTVAL_FRACTIONALMETRICS_DEFAULT) {
|
||||
@@ -772,12 +772,6 @@ public final class SunGraphics2D
|
||||
}
|
||||
}
|
||||
}
|
||||
if (FontUtilities.isMacOSX16 ||
|
||||
(FontUtilities.isMacOSX14 &&
|
||||
aahint == SunHints.INTVAL_TEXT_ANTIALIAS_OFF))
|
||||
{
|
||||
aahint = SunHints.INTVAL_TEXT_ANTIALIAS_ON;
|
||||
}
|
||||
info.aaHint = aahint;
|
||||
info.fontStrike = info.font2D.getStrike(font, devAt, textAt,
|
||||
aahint, fmhint);
|
||||
|
||||
@@ -450,13 +450,9 @@ public abstract class SurfaceData
|
||||
colorPrimitives = new LoopPipe();
|
||||
|
||||
outlineTextRenderer = new OutlineTextRenderer();
|
||||
solidTextRenderer = new SolidTextRenderer();
|
||||
aaTextRenderer = new AATextRenderer();
|
||||
if (FontUtilities.isMacOSX14) {
|
||||
solidTextRenderer = aaTextRenderer;
|
||||
} else {
|
||||
solidTextRenderer = new SolidTextRenderer();
|
||||
}
|
||||
if (FontUtilities.isMacOSX16) {
|
||||
lcdTextRenderer = aaTextRenderer;
|
||||
} else {
|
||||
lcdTextRenderer = new LCDTextRenderer();
|
||||
|
||||
@@ -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,13 +42,13 @@ public abstract class GlyphListLoopPipe extends GlyphListPipe
|
||||
protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl,
|
||||
int aaHint) {
|
||||
int prevBorder = 0;
|
||||
int pixelFormat = -1;
|
||||
byte pixelFormat = StrikeCache.PIXEL_FORMAT_UNKNOWN;
|
||||
int len = gl.getNumGlyphs();
|
||||
gl.startGlyphIteration();
|
||||
for (int i = 0; i < len; i++) {
|
||||
int newFormat = gl.getPixelFormat(i);
|
||||
byte newFormat = gl.getPixelFormat(i);
|
||||
if (newFormat != pixelFormat) {
|
||||
if (pixelFormat != -1) drawGlyphListSegment(sg2d, gl, prevBorder, i, aaHint, pixelFormat);
|
||||
drawGlyphListSegment(sg2d, gl, prevBorder, i, aaHint, pixelFormat);
|
||||
prevBorder = i;
|
||||
pixelFormat = newFormat;
|
||||
}
|
||||
@@ -56,10 +57,10 @@ public abstract class GlyphListLoopPipe extends GlyphListPipe
|
||||
}
|
||||
|
||||
private void drawGlyphListSegment(SunGraphics2D sg2d, GlyphList gl, int fromglyph, int toGlyph,
|
||||
int aaHint, int pixelFormat) {
|
||||
int aaHint, byte pixelFormat) {
|
||||
if (fromglyph >= toGlyph) return;
|
||||
switch (pixelFormat) {
|
||||
case 1:
|
||||
case StrikeCache.PIXEL_FORMAT_GREYSCALE:
|
||||
if (aaHint == SunHints.INTVAL_TEXT_ANTIALIAS_OFF) {
|
||||
sg2d.loops.drawGlyphListLoop.
|
||||
DrawGlyphList(sg2d, sg2d.surfaceData, gl, fromglyph, toGlyph);
|
||||
@@ -68,11 +69,11 @@ public abstract class GlyphListLoopPipe extends GlyphListPipe
|
||||
DrawGlyphListAA(sg2d, sg2d.surfaceData, gl, fromglyph, toGlyph);
|
||||
}
|
||||
return;
|
||||
case 3:
|
||||
case StrikeCache.PIXEL_FORMAT_LCD:
|
||||
sg2d.loops.drawGlyphListLCDLoop.
|
||||
DrawGlyphListLCD(sg2d, sg2d.surfaceData, gl, fromglyph, toGlyph);
|
||||
return;
|
||||
case 4:
|
||||
case StrikeCache.PIXEL_FORMAT_BGRA:
|
||||
sg2d.loops.drawGlyphListColorLoop.
|
||||
DrawGlyphListColor(sg2d, sg2d.surfaceData, gl, fromglyph, toGlyph);
|
||||
return;
|
||||
|
||||
@@ -696,7 +696,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" {
|
||||
@@ -75,7 +76,7 @@ typedef struct GlyphInfo {
|
||||
UInt16 height;
|
||||
UInt16 rowBytes;
|
||||
UInt8 managed;
|
||||
UInt8 format; // 1-Grayscale, 3-LCD, 4-BGRA
|
||||
UInt8 format; // sun_font_StrikeCache_PIXEL_FORMAT_*
|
||||
UInt8 subpixelResolutionX;
|
||||
UInt8 subpixelResolutionY;
|
||||
float topLeftX;
|
||||
|
||||
@@ -337,7 +337,10 @@ static const char *grayGammaTextShaderSource =
|
||||
"{"
|
||||
"float a = src_adj.a;"
|
||||
"vec3 col = src_adj.rgb;"
|
||||
|
||||
// Convert from ARGB_PRE
|
||||
"if (a > 0.0) {"
|
||||
"col = col/a;"
|
||||
"}"
|
||||
// calculate brightness of the fragment
|
||||
"float b = dot(col, vec3(1.0/3.0, 1.0/3.0, 1.0/3.0))*a;"
|
||||
|
||||
@@ -1436,7 +1439,7 @@ OGLTR_DrawGlyphList(JNIEnv *env, OGLContext *oglc, OGLSDOps *dstOps,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ginfo->format == 1) {
|
||||
if (ginfo->format == sun_font_StrikeCache_PIXEL_FORMAT_GREYSCALE) {
|
||||
OGLMTVertexCache_disable();
|
||||
// grayscale or monochrome glyph data
|
||||
int rx = ginfo->subpixelResolutionX;
|
||||
@@ -1454,7 +1457,7 @@ OGLTR_DrawGlyphList(JNIEnv *env, OGLContext *oglc, OGLSDOps *dstOps,
|
||||
} else {
|
||||
ok = OGLTR_DrawGrayscaleGlyphNoCache(oglc, ginfo, x, y, subimage);
|
||||
}
|
||||
} else if (ginfo->format == 4) {
|
||||
} else if (ginfo->format == sun_font_StrikeCache_PIXEL_FORMAT_BGRA) {
|
||||
OGLMTVertexCache_disable();
|
||||
// color glyph data
|
||||
ok = OGLTR_DrawColorGlyphNoCache(oglc, ginfo, x, y);
|
||||
|
||||
@@ -572,7 +572,7 @@ GlyphBlitVector* setupLCDBlitVector(JNIEnv *env, jobject glyphlist, jint fromGly
|
||||
free(gbv);
|
||||
return (GlyphBlitVector*)NULL;
|
||||
}
|
||||
if (ginfo->format != 3) { // Not LCD glyph
|
||||
if (ginfo->format != sun_font_StrikeCache_PIXEL_FORMAT_LCD) {
|
||||
subPixPos = JNI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1768,10 +1768,10 @@ static jlong
|
||||
glyphInfo->subpixelResolutionX = subpixelResolutionX;
|
||||
glyphInfo->subpixelResolutionY = subpixelResolutionY;
|
||||
|
||||
if (ftglyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) glyphInfo->format = 4;
|
||||
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 = 3;
|
||||
else glyphInfo->format = 1;
|
||||
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) {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -154,6 +154,8 @@ final class XWM
|
||||
return "Awesome";
|
||||
case DWM_WM:
|
||||
return "DWM";
|
||||
case XWM.I3_WM:
|
||||
return "I3WM";
|
||||
case UNDETERMINED_WM:
|
||||
default:
|
||||
return "Undetermined WM";
|
||||
@@ -1484,6 +1486,8 @@ final class XWM
|
||||
case XWM.ENLIGHTEN_WM:
|
||||
/* At least E16 is buggy. */
|
||||
return true;
|
||||
case XWM.I3_WM:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -627,20 +627,13 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
// NOTE: This method may be called by privileged threads.
|
||||
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
|
||||
public void handleWindowFocusIn(long serial) {
|
||||
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS);
|
||||
/* wrap in Sequenced, then post*/
|
||||
XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow((Window) target);
|
||||
postEvent(wrapInSequenced((AWTEvent) we));
|
||||
handleWindowFocusInSync(serial, () -> {});
|
||||
}
|
||||
|
||||
// NOTE: This method may be called by privileged threads.
|
||||
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
|
||||
public void handleWindowFocusOut(Window oppositeWindow, long serial) {
|
||||
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow);
|
||||
XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow(null);
|
||||
XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(null);
|
||||
/* wrap in Sequenced, then post*/
|
||||
postEvent(wrapInSequenced((AWTEvent) we));
|
||||
handleWindowFocusOutSync(oppositeWindow, serial);
|
||||
}
|
||||
public void handleWindowFocusOutSync(Window oppositeWindow, long serial) {
|
||||
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow);
|
||||
|
||||
@@ -199,10 +199,10 @@ public class XRGlyphCacheEntry {
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
int format = StrikeCache.unsafe.getByte(glyphInfoPtr + StrikeCache.formatOffset);
|
||||
if (format == 1) return Type.GRAYSCALE;
|
||||
else if (format == 3) return Type.LCD;
|
||||
else if (format == 4) return Type.BGRA;
|
||||
byte format = StrikeCache.unsafe.getByte(glyphInfoPtr + StrikeCache.formatOffset);
|
||||
if (format == StrikeCache.PIXEL_FORMAT_GREYSCALE) return Type.GRAYSCALE;
|
||||
else if (format == StrikeCache.PIXEL_FORMAT_LCD) return Type.LCD;
|
||||
else if (format == StrikeCache.PIXEL_FORMAT_BGRA) return Type.BGRA;
|
||||
else throw new IllegalStateException("Unknown glyph format: " + format);
|
||||
}
|
||||
|
||||
|
||||
@@ -291,7 +291,7 @@ JNIEXPORT jlong JNICALL AWTFontGenerateImage(AWTFont pFont, AWTChar2b* xChar) {
|
||||
glyphInfo->height = height;
|
||||
glyphInfo->subpixelResolutionX = 1;
|
||||
glyphInfo->subpixelResolutionY = 1;
|
||||
glyphInfo->format = 1;
|
||||
glyphInfo->format = sun_font_StrikeCache_PIXEL_FORMAT_GREYSCALE;
|
||||
glyphInfo->topLeftX = xcs.lbearing;
|
||||
glyphInfo->topLeftY = -xcs.ascent;
|
||||
glyphInfo->advanceX = xcs.width;
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.awt.peer.FramePeer;
|
||||
import java.security.AccessController;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.SunToolkit;
|
||||
import sun.awt.im.InputMethodManager;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
@@ -124,15 +125,16 @@ class WFramePeer extends WWindowPeer implements FramePeer {
|
||||
@Override
|
||||
public void displayChanged() {
|
||||
super.displayChanged();
|
||||
updateIcon();
|
||||
SunToolkit.executeOnEventHandlerThread(target, this::updateIcon);
|
||||
if (!screenChangedFlag &&
|
||||
(getExtendedState() & Frame.MAXIMIZED_BOTH) != 0 &&
|
||||
(getExtendedState() & Frame.ICONIFIED) == 0)
|
||||
{
|
||||
(getExtendedState() & Frame.ICONIFIED) == 0) {
|
||||
// A workaround to update the maximized state of the frame
|
||||
int state = getExtendedState();
|
||||
setState(Frame.NORMAL);
|
||||
setState(state);
|
||||
SunToolkit.executeOnEventHandlerThread(target, ()->{
|
||||
int state = getExtendedState();
|
||||
setState(Frame.NORMAL);
|
||||
setState(state);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ import java.awt.Graphics;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.IllegalComponentStateException;
|
||||
import java.awt.Image;
|
||||
import java.awt.Insets;
|
||||
import java.awt.KeyboardFocusManager;
|
||||
@@ -89,7 +90,7 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
|
||||
|
||||
private TranslucentWindowPainter painter;
|
||||
|
||||
private int screenNum;
|
||||
private int screenNum = 0;
|
||||
protected boolean screenChangedFlag;
|
||||
|
||||
/*
|
||||
@@ -215,6 +216,13 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
|
||||
super(target);
|
||||
// update GC based on the current bounds
|
||||
updateGC();
|
||||
try {
|
||||
screenNum = getScreenImOn();
|
||||
} catch (IllegalComponentStateException e) {
|
||||
if (log.isLoggable(PlatformLogger.Level.WARNING)) {
|
||||
log.warning(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -630,9 +638,6 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
|
||||
|
||||
public void updateGC() {
|
||||
int scrn = getScreenImOn();
|
||||
screenChangedFlag = scrn != screenNum;
|
||||
screenNum = scrn;
|
||||
|
||||
if (screenLog.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
log.finer("Screen number: " + scrn);
|
||||
}
|
||||
@@ -701,6 +706,9 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
|
||||
*/
|
||||
@Override
|
||||
public void displayChanged() {
|
||||
int scrn = getScreenImOn();
|
||||
screenChangedFlag = scrn != screenNum;
|
||||
screenNum = scrn;
|
||||
SunToolkit.executeOnEventHandlerThread(target, ()->{
|
||||
updateGC();
|
||||
adjustBoundsOnDPIChange();
|
||||
|
||||
@@ -792,7 +792,7 @@ D3DTR_DrawGlyphList(D3DContext *d3dc, D3DSDOps *dstOps,
|
||||
break;
|
||||
}
|
||||
|
||||
grayscale = (ginfo->format == 1);
|
||||
grayscale = (ginfo->format == sun_font_StrikeCache_PIXEL_FORMAT_GREYSCALE);
|
||||
|
||||
if (usePositions) {
|
||||
jfloat posx = NEXT_FLOAT(positions);
|
||||
|
||||
@@ -94,7 +94,6 @@ HWND AwtComponent::sm_focusOwner = NULL;
|
||||
HWND AwtComponent::sm_focusedWindow = NULL;
|
||||
BOOL AwtComponent::sm_bMenuLoop = FALSE;
|
||||
BOOL AwtComponent::sm_inSynthesizeFocus = FALSE;
|
||||
BOOL AwtComponent::sm_priorityFocusEvents = FALSE;
|
||||
|
||||
/************************************************************************/
|
||||
// Struct for _Reshape() and ReshapeNoCheck() methods
|
||||
@@ -981,8 +980,8 @@ void AwtComponent::ReshapeNoScale(int x, int y, int w, int h)
|
||||
int usrY = y;
|
||||
|
||||
AwtWin32GraphicsDevice* device = UGetDeviceByBounds(URectBounds(x, y, w, h, USER_SPACE), this);
|
||||
x = device->ScaleUpX(x, RELATIVITY_FOR_COMP_XY(this));
|
||||
y = device->ScaleUpY(y, RELATIVITY_FOR_COMP_XY(this));
|
||||
x = device->ScaleUpX(x);
|
||||
y = device->ScaleUpY(y);
|
||||
w = device->ScaleUpX(w);
|
||||
h = device->ScaleUpY(h);
|
||||
|
||||
@@ -2027,38 +2026,28 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
* there.
|
||||
*/
|
||||
case WM_AWT_COMPONENT_SHOW:
|
||||
sm_priorityFocusEvents = TRUE;
|
||||
Show();
|
||||
sm_priorityFocusEvents = FALSE;
|
||||
mr = mrConsume;
|
||||
break;
|
||||
case WM_AWT_COMPONENT_HIDE:
|
||||
sm_priorityFocusEvents = TRUE;
|
||||
Hide();
|
||||
sm_priorityFocusEvents = FALSE;
|
||||
mr = mrConsume;
|
||||
break;
|
||||
|
||||
case WM_AWT_COMPONENT_SETFOCUS:
|
||||
sm_priorityFocusEvents = TRUE;
|
||||
if ((BOOL)wParam) {
|
||||
retValue = SynthesizeWmSetFocus(GetHWnd(), NULL);
|
||||
} else {
|
||||
retValue = SynthesizeWmKillFocus(GetHWnd(), NULL);
|
||||
}
|
||||
sm_priorityFocusEvents = FALSE;
|
||||
mr = mrConsume;
|
||||
break;
|
||||
case WM_AWT_WINDOW_SETACTIVE:
|
||||
sm_priorityFocusEvents = TRUE;
|
||||
retValue = (LRESULT)((AwtWindow*)this)->AwtSetActiveWindow((BOOL)wParam);
|
||||
sm_priorityFocusEvents = FALSE;
|
||||
mr = mrConsume;
|
||||
break;
|
||||
case WM_AWT_WINDOW_TOFRONT:
|
||||
sm_priorityFocusEvents = TRUE;
|
||||
((AwtWindow*)this)->ToFront();
|
||||
sm_priorityFocusEvents = FALSE;
|
||||
mr = mrConsume;
|
||||
break;
|
||||
|
||||
@@ -2484,7 +2473,7 @@ void AwtComponent::WmTouchHandler(const TOUCHINPUT& touchInput)
|
||||
const jint scrollModifiers = modifiers & ~java_awt_event_InputEvent_SHIFT_DOWN_MASK;
|
||||
SendMouseWheelEventFromTouch(p, scrollModifiers, sun_awt_event_TouchEvent_TOUCH_UPDATE, deltaY);
|
||||
}
|
||||
|
||||
|
||||
const jint deltaX = ScaleDownX(static_cast<int>(m_lastTouchPoint.x - p.x));
|
||||
if (deltaX != 0) {
|
||||
const jint scrollModifiers = modifiers | java_awt_event_InputEvent_SHIFT_DOWN_MASK;
|
||||
|
||||
@@ -699,7 +699,6 @@ public:
|
||||
static void *GetNativeFocusOwner();
|
||||
|
||||
static BOOL sm_inSynthesizeFocus;
|
||||
static BOOL sm_priorityFocusEvents;
|
||||
|
||||
// Execute on Toolkit only.
|
||||
INLINE static LRESULT SynthesizeWmSetFocus(HWND targetHWnd, HWND oppositeHWnd) {
|
||||
|
||||
@@ -519,9 +519,7 @@ MsgRouting AwtDialog::WmEndModal()
|
||||
jobject peer = GetPeer(env);
|
||||
jobject target = GetTarget(env);
|
||||
if (::GetForegroundWindow() == GetHWnd()) {
|
||||
sm_priorityFocusEvents = TRUE;
|
||||
ModalActivateNextWindow(GetHWnd(), target, peer);
|
||||
sm_priorityFocusEvents = FALSE;
|
||||
}
|
||||
// hide the dialog
|
||||
SendMessage(WM_AWT_COMPONENT_HIDE);
|
||||
|
||||
@@ -1251,7 +1251,7 @@ MsgRouting AwtFrame::WmSysCommand(UINT uCmdType, int xPos, int yPos)
|
||||
}
|
||||
|
||||
MsgRouting AwtFrame::WmDPIChanged(UINT xDPI, UINT yDPI, RECT* bounds) {
|
||||
if (isZoomed()) {
|
||||
if (isZoomed() && !m_maxBoundsSet) {
|
||||
Devices::InstanceAccess devices;
|
||||
AwtWin32GraphicsDevice* device = devices->GetDevice(AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd()));
|
||||
if (device) {
|
||||
|
||||
@@ -84,9 +84,10 @@ RECT AwtWin32GraphicsConfig::getMonitorBounds(int screen, const UCoordSpace& spa
|
||||
AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
|
||||
|
||||
if (TRUE == MonitorBounds(AwtWin32GraphicsDevice::GetMonitor(screen), &rRW)) {
|
||||
// don't scale xy to avoid overlapping of the multi-dpi-monitors bounds in the user space
|
||||
int x = rRW.left;
|
||||
int y = rRW.top;
|
||||
int x = (device == NULL || space == DEVICE_SPACE) ? rRW.left
|
||||
: device->ScaleDownX(rRW.left);
|
||||
int y = (device == NULL || space == DEVICE_SPACE) ? rRW.top
|
||||
: device->ScaleDownY(rRW.top);
|
||||
int w = (device == NULL || space == DEVICE_SPACE) ? rRW.right - rRW.left
|
||||
: device->ScaleDownX(rRW.right - rRW.left);
|
||||
int h = (device == NULL || space == DEVICE_SPACE) ? rRW.bottom - rRW.top
|
||||
|
||||
@@ -1725,9 +1725,8 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite,
|
||||
env->DeleteLocalRef(target); target = NULL;
|
||||
CHECK_NULL(event);
|
||||
|
||||
if (AwtComponent::sm_priorityFocusEvents &&
|
||||
(id == java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS ||
|
||||
id == java_awt_event_WindowEvent_WINDOW_LOST_FOCUS))
|
||||
if (id == java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS ||
|
||||
id == java_awt_event_WindowEvent_WINDOW_LOST_FOCUS)
|
||||
{
|
||||
SendPriorityEvent(event);
|
||||
} else {
|
||||
@@ -1920,8 +1919,8 @@ MsgRouting AwtWindow::WmMove(int x, int y)
|
||||
URectBounds rect = UGetWindowRectBounds(GetHWnd());
|
||||
AwtWin32GraphicsDevice* device = UGetDeviceByBounds(rect, this);
|
||||
|
||||
int usrX = device->ScaleDownDX(rect.x);
|
||||
int usrY = device->ScaleDownDY(rect.y);
|
||||
int usrX = device->ScaleDownX(rect.x);
|
||||
int usrY = device->ScaleDownY(rect.y);
|
||||
|
||||
// [tav] Convert x/y to user space, asymmetrically to AwtComponent::Reshape.
|
||||
AwtComponent* parent = GetParent();
|
||||
|
||||
@@ -457,7 +457,7 @@ Java_sun_font_FileFontStrike__1getGlyphImageFromWindows
|
||||
glyphInfo->height = height;
|
||||
glyphInfo->subpixelResolutionX = 1;
|
||||
glyphInfo->subpixelResolutionY = 1;
|
||||
glyphInfo->format = 3;
|
||||
glyphInfo->format = sun_font_StrikeCache_PIXEL_FORMAT_LCD;
|
||||
glyphInfo->advanceX = advanceX;
|
||||
glyphInfo->advanceY = advanceY;
|
||||
glyphInfo->topLeftX = (float)(topLeftX-1);
|
||||
|
||||
@@ -266,7 +266,7 @@ Java_sun_font_FileFontStrike__1getGlyphImageFromWindowsUsingDirectWrite
|
||||
glyphInfo->height = glyphHeight;
|
||||
glyphInfo->subpixelResolutionX = 1;
|
||||
glyphInfo->subpixelResolutionY = 1;
|
||||
glyphInfo->format = 3;
|
||||
glyphInfo->format = sun_font_StrikeCache_PIXEL_FORMAT_LCD;
|
||||
glyphInfo->advanceX = rotation == 0 ? advance : rotation == 2 ? -advance : 0;
|
||||
glyphInfo->advanceY = rotation == 3 ? advance : rotation == 1 ? -advance : 0;
|
||||
glyphInfo->topLeftX = bbRect.left - xTransformed;
|
||||
|
||||
74
test/hotspot/jtreg/runtime/JBR-3923/Test.java
Normal file
74
test/hotspot/jtreg/runtime/JBR-3923/Test.java
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2021, JetBrains s.r.o.. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Verify that C1 compiler does not crash on a particular
|
||||
* Kotlin suspend fun
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* java.management
|
||||
* @compile Test.java
|
||||
* @run main Test
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import java.util.*;
|
||||
|
||||
public class Test {
|
||||
public static void main(String[] args) throws Exception {
|
||||
String jarFile = System.getProperty("test.src") + "/testcase.jar";
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-cp", jarFile,
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-Xcomp",
|
||||
"-XX:CompileCommand=compileonly,MainKt::test",
|
||||
"MainKt");
|
||||
|
||||
new OutputAnalyzer(pb.start())
|
||||
.shouldContain("Success")
|
||||
.shouldNotContain("Internal Error")
|
||||
.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The code in testcase.jar is produced by running
|
||||
* $ kotlinc Main.kt -include-runtime -d testcase.jar
|
||||
* on this Kotlin code:
|
||||
suspend fun yield(s: String) {
|
||||
println("Success");
|
||||
System.exit(0)
|
||||
}
|
||||
|
||||
suspend fun test(s: String) {
|
||||
while (true) {
|
||||
yield(s)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun main() {
|
||||
test("")
|
||||
}
|
||||
*/
|
||||
BIN
test/hotspot/jtreg/runtime/JBR-3923/testcase.jar
Normal file
BIN
test/hotspot/jtreg/runtime/JBR-3923/testcase.jar
Normal file
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
###########################################################################
|
||||
#
|
||||
# Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2009, 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
|
||||
@@ -42,10 +42,11 @@
|
||||
# List items are testnames followed by labels, all MUST BE commented
|
||||
# as to why they are here and use a label:
|
||||
# generic-all Problems on all platforms
|
||||
# generic-ARCH Where ARCH is one of: x64, i586, ppc64, ppc64le, s390x, aarch64 etc.
|
||||
# OSNAME-all Where OSNAME is one of: linux, windows, macosx, aix
|
||||
# OSNAME-ARCH Specific on to one OSNAME and ARCH, e.g. macosx-x64
|
||||
# OSNAME-REV Specific on to one OSNAME and REV, e.g. macosx-10.7.4
|
||||
# generic-ARCH Where ARCH is one of: sparc, sparcv9, x64, i586, ppc64,
|
||||
# ppc64le, s390x etc.
|
||||
# OSNAME-all Where OSNAME is one of: solaris, linux, windows, macosx, aix
|
||||
# OSNAME-ARCH Specific on to one OSNAME and ARCH, e.g. solaris-amd64
|
||||
# OSNAME-REV Specific on to one OSNAME and REV, e.g. solaris-5.8
|
||||
#
|
||||
# More than one label is allowed but must be on the same line comma seperated,
|
||||
# without spaces.
|
||||
@@ -685,8 +686,6 @@ sun/security/pkcs11/KeyStore/SecretKeysBasic.sh 8209398 generic-
|
||||
security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java 8224768 generic-all
|
||||
security/infra/java/security/cert/CertPathValidator/certification/BuypassCA.java 8243543 generic-all
|
||||
security/infra/java/security/cert/CertPathValidator/certification/ComodoCA.java 8263059 generic-all
|
||||
security/infra/java/security/cert/CertPathValidator/certification/QuoVadisCA.java 8248899 generic-all
|
||||
security/infra/java/security/cert/CertPathValidator/certification/LetsEncryptCA.java 8270280 generic-all
|
||||
|
||||
sun/security/smartcardio/TestChannel.java 8039280 generic-all
|
||||
sun/security/smartcardio/TestConnect.java 8039280 generic-all
|
||||
|
||||
111
test/jdk/jb/java/awt/Focus/ActivationEventsOrder.java
Normal file
111
test/jdk/jb/java/awt/Focus/ActivationEventsOrder.java
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Regression test for JBR-3989 Broken focus state after a quick succession of activation/deactivation events
|
||||
* on Windows
|
||||
* @key headful
|
||||
*/
|
||||
|
||||
public class ActivationEventsOrder {
|
||||
private static final CompletableFuture<Boolean> success = new CompletableFuture<>();
|
||||
|
||||
private static Robot robot;
|
||||
private static JFrame frame1;
|
||||
private static JFrame frame2;
|
||||
private static JTextField field1;
|
||||
private static JTextField field2;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
robot = new Robot();
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(ActivationEventsOrder::initUI);
|
||||
robot.delay(1000); // wait for windows to appear
|
||||
SwingUtilities.invokeLater(ActivationEventsOrder::delayedFocusRequest);
|
||||
robot.delay(1000); // wait for EDT to be frozen in Thread.sleep
|
||||
clickOn(field1);
|
||||
robot.delay(2000); // wait for freeze to be over
|
||||
clickOn(field2);
|
||||
robot.delay(1000); // wait for focus to settle down
|
||||
pressAndRelease(KeyEvent.VK_ENTER);
|
||||
success.get(5, TimeUnit.SECONDS);
|
||||
}
|
||||
finally {
|
||||
SwingUtilities.invokeAndWait(ActivationEventsOrder::disposeUI);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initUI() {
|
||||
frame1 = new JFrame("ActivationEventsOrder 1");
|
||||
field1 = new JTextField();
|
||||
frame1.add(field1);
|
||||
frame1.setBounds(100, 100, 200, 100);
|
||||
frame1.setVisible(true);
|
||||
|
||||
frame2 = new JFrame("ActivationEventsOrder 2");
|
||||
field2 = new JTextField();
|
||||
frame2.add(field2);
|
||||
frame2.setBounds(100, 300, 200, 100);
|
||||
frame2.setVisible(true);
|
||||
|
||||
field2.addActionListener(e -> success.complete(true));
|
||||
}
|
||||
|
||||
private static void disposeUI() {
|
||||
if (frame1 != null) frame1.dispose();
|
||||
if (frame2 != null) frame2.dispose();
|
||||
}
|
||||
|
||||
private static void delayedFocusRequest() {
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
frame2.toFront();
|
||||
}
|
||||
|
||||
private static void pressAndRelease(int keyCode) {
|
||||
robot.keyPress(keyCode);
|
||||
robot.keyRelease(keyCode);
|
||||
}
|
||||
|
||||
private static void clickAt(int x, int y) {
|
||||
robot.mouseMove(x, y);
|
||||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
}
|
||||
|
||||
private static void clickOn(Component component) {
|
||||
Point location = component.getLocationOnScreen();
|
||||
clickAt(location.x + component.getWidth() / 2, location.y + component.getHeight() / 2);
|
||||
}
|
||||
}
|
||||
103
test/jdk/jb/java/awt/Focus/EventsOnPopupShowing.java
Normal file
103
test/jdk/jb/java/awt/Focus/EventsOnPopupShowing.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Regression test for JBR-4021 Unexpected focus event order on window showing
|
||||
* @key headful
|
||||
*/
|
||||
|
||||
public class EventsOnPopupShowing {
|
||||
private static final AtomicInteger gainedCount = new AtomicInteger();
|
||||
|
||||
private static Robot robot;
|
||||
private static JFrame frame;
|
||||
private static JButton button;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
robot = new Robot();
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(EventsOnPopupShowing::initUI);
|
||||
robot.delay(1000);
|
||||
clickOn(button);
|
||||
robot.delay(3000);
|
||||
if (gainedCount.get() != 1) {
|
||||
throw new RuntimeException("Unexpected 'focus gained' count: " + gainedCount);
|
||||
}
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(EventsOnPopupShowing::disposeUI);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initUI() {
|
||||
frame = new JFrame("EventsOnPopupShowing");
|
||||
button = new JButton("Start");
|
||||
button.addActionListener(e -> {
|
||||
JDialog d = new JDialog(frame, "Dialog", true);
|
||||
d.setBounds(300, 300, 200, 200);
|
||||
new Timer(1000, ee -> d.dispose()) {{ setRepeats(false); }}.start();
|
||||
d.setVisible(true);
|
||||
|
||||
JWindow w = new JWindow(frame);
|
||||
w.add(new JTextField());
|
||||
w.addWindowFocusListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowGainedFocus(WindowEvent e) {
|
||||
gainedCount.incrementAndGet();
|
||||
}
|
||||
});
|
||||
w.setBounds(300, 300, 200, 200);
|
||||
w.setVisible(true);
|
||||
try {
|
||||
Thread.sleep(1000); // make sure all native events are processed
|
||||
} catch (InterruptedException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
});
|
||||
frame.add(button);
|
||||
frame.setBounds(200, 200, 200, 200);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static void disposeUI() {
|
||||
if (frame != null) frame.dispose();
|
||||
}
|
||||
|
||||
private static void clickAt(int x, int y) {
|
||||
robot.mouseMove(x, y);
|
||||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
}
|
||||
|
||||
private static void clickOn(Component component) {
|
||||
Point location = component.getLocationOnScreen();
|
||||
clickAt(location.x + component.getWidth() / 2, location.y + component.getHeight() / 2);
|
||||
}
|
||||
}
|
||||
97
test/jdk/jb/java/awt/Focus/RequestFocusInParent.java
Normal file
97
test/jdk/jb/java/awt/Focus/RequestFocusInParent.java
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Regression test for JBR-3979 Focus is not transferred to parent window
|
||||
* @key headful
|
||||
*/
|
||||
|
||||
public class RequestFocusInParent {
|
||||
private static CompletableFuture<Boolean> result;
|
||||
|
||||
private static Robot robot;
|
||||
private static JFrame frame;
|
||||
private static JButton button1;
|
||||
private static JButton button2;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
robot = new Robot();
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(RequestFocusInParent::initUI);
|
||||
robot.delay(1000); // wait for frame to appear
|
||||
clickOn(button1);
|
||||
robot.delay(1000); // wait for popup to appear
|
||||
SwingUtilities.invokeAndWait(() -> result = new CompletableFuture<>());
|
||||
clickOn(button2);
|
||||
result.get(5, TimeUnit.SECONDS);
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(RequestFocusInParent::disposeUI);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initUI() {
|
||||
frame = new JFrame("RequestFocusInParent");
|
||||
button1 = new JButton("Open popup");
|
||||
button1.addActionListener(e -> {
|
||||
JWindow popup = new JWindow(frame);
|
||||
button2 = new JButton("Return focus");
|
||||
button2.addActionListener(ee -> button1.requestFocus());
|
||||
popup.add(button2);
|
||||
popup.setSize(100, 100);
|
||||
popup.setLocation(100, 400);
|
||||
popup.setVisible(true);
|
||||
});
|
||||
button1.addFocusListener(new FocusAdapter() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
if (result != null) result.complete(true);
|
||||
}
|
||||
});
|
||||
frame.add(button1);
|
||||
frame.setSize(100, 100);
|
||||
frame.setLocation(100, 100);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static void disposeUI() {
|
||||
if (frame != null) frame.dispose();
|
||||
}
|
||||
|
||||
private static void clickAt(int x, int y) {
|
||||
robot.mouseMove(x, y);
|
||||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
}
|
||||
|
||||
private static void clickOn(Component component) {
|
||||
Point location = component.getLocationOnScreen();
|
||||
clickAt(location.x + component.getWidth() / 2, location.y + component.getHeight() / 2);
|
||||
}
|
||||
}
|
||||
158
test/jdk/jb/java/awt/Graphics2D/TextRender/AlphaTextRender.java
Normal file
158
test/jdk/jb/java/awt/Graphics2D/TextRender/AlphaTextRender.java
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import javax.imageio.ImageIO;
|
||||
import static java.awt.Color.*;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @key headful
|
||||
* @summary Check that increasing alpha of text on white background produces letters with decreasing brightness.
|
||||
* @run main AlphaTextRender
|
||||
*/
|
||||
|
||||
public class AlphaTextRender {
|
||||
final static int WIDTH = 150;
|
||||
final static int HEIGHT = 200;
|
||||
final static File img = new File("t-alpha.png");
|
||||
|
||||
public static void main(final String[] args) throws IOException {
|
||||
|
||||
GraphicsEnvironment ge =
|
||||
GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
GraphicsConfiguration gc =
|
||||
ge.getDefaultScreenDevice().getDefaultConfiguration();
|
||||
|
||||
VolatileImage vi = gc.createCompatibleVolatileImage(WIDTH, HEIGHT);
|
||||
BufferedImage bi = gc.createCompatibleImage(WIDTH, HEIGHT);
|
||||
BufferedImage br = gc.createCompatibleImage(WIDTH, HEIGHT);
|
||||
Color[] colors = {
|
||||
WHITE, LIGHT_GRAY, GRAY, DARK_GRAY, BLACK, RED, PINK, ORANGE, YELLOW, MAGENTA,
|
||||
CYAN, BLUE
|
||||
};
|
||||
|
||||
int c = 10;
|
||||
int maxAscent;
|
||||
do {
|
||||
Graphics2D g2d = vi.createGraphics();
|
||||
maxAscent = g2d.getFontMetrics().getMaxAscent();
|
||||
Font font = new Font("Serif", Font.PLAIN, 10);
|
||||
g2d.setFont(font);
|
||||
g2d.setColor(Color.WHITE);
|
||||
g2d.fillRect(0, 0, WIDTH, HEIGHT);
|
||||
int posy = maxAscent;
|
||||
for (Color col : colors) {
|
||||
g2d.setColor(col);
|
||||
int posx = 10;
|
||||
for (int j = 0; j < 20; j++) {
|
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, j/(float)20));
|
||||
g2d.drawString(String.valueOf('|'), posx, posy);
|
||||
posx += g2d.getFontMetrics().charWidth('|') + 1;
|
||||
}
|
||||
posy += maxAscent;
|
||||
}
|
||||
g2d.dispose();
|
||||
} while (vi.contentsLost() && (--c > 0));
|
||||
|
||||
Graphics2D g2d = bi.createGraphics();
|
||||
g2d.drawImage(vi, 0, 0, null);
|
||||
g2d.dispose();
|
||||
|
||||
g2d = br.createGraphics();
|
||||
g2d.drawImage(vi, 0, 0, null);
|
||||
g2d.dispose();
|
||||
|
||||
int posy = 0;
|
||||
int errors = 0;
|
||||
for (Color color : colors) {
|
||||
int r0 = 255;
|
||||
int g0 = 255;
|
||||
int b0 = 255;
|
||||
int lmr = 0;
|
||||
int lmg = 0;
|
||||
int lmb = 0;
|
||||
|
||||
int curErrors = 0;
|
||||
boolean spike = false;
|
||||
for (int j = 0; j < WIDTH; j++) {
|
||||
Color c1 = new Color(bi.getRGB(j, posy + maxAscent / 2));
|
||||
int dr = Math.abs(c1.getRed() - WHITE.getRed());
|
||||
int dg = Math.abs(c1.getGreen() - WHITE.getGreen());
|
||||
int db = Math.abs(c1.getBlue() - WHITE.getBlue());
|
||||
|
||||
// Skip background and pick color with maximal local brightness
|
||||
if (dr + dg + db > 0) {
|
||||
if (!spike) {
|
||||
lmr = c1.getRed();
|
||||
lmg = c1.getGreen();
|
||||
lmb = c1.getBlue();
|
||||
spike = true;
|
||||
} else {
|
||||
lmr = Math.max(lmr, c1.getRed());
|
||||
lmg = Math.max(lmg, c1.getGreen());
|
||||
lmb = Math.max(lmb, c1.getBlue());
|
||||
}
|
||||
} else if (spike) { // Compare current spike with the previous one
|
||||
if (getColorValue(r0, g0, b0) < getColorValue(lmr, lmg, lmb)) {
|
||||
curErrors++;
|
||||
br.setRGB(j, posy + maxAscent / 2 - 2, BLACK.getRGB());
|
||||
br.setRGB(j, posy + maxAscent / 2 - 1, BLACK.getRGB());
|
||||
br.setRGB(j, posy + maxAscent / 2, BLACK.getRGB());
|
||||
br.setRGB(j, posy + maxAscent / 2 + 1, BLACK.getRGB());
|
||||
br.setRGB(j, posy + maxAscent / 2 + 2, BLACK.getRGB());
|
||||
}
|
||||
r0 = lmr;
|
||||
g0 = lmg;
|
||||
b0 = lmb;
|
||||
spike = false;
|
||||
}
|
||||
}
|
||||
if (curErrors > 0) {
|
||||
System.err.println("Error with color:" + color);
|
||||
errors += curErrors;
|
||||
}
|
||||
|
||||
posy += maxAscent;
|
||||
}
|
||||
|
||||
if (errors > 0) {
|
||||
ImageIO.write(br, "png", img);
|
||||
throw new RuntimeException("Translucent text errors found: " + errors);
|
||||
}
|
||||
}
|
||||
|
||||
private static double getColorValue(int r0, int g0, int b0) {
|
||||
// Use simple addition for normalized color components
|
||||
return r0 / 255.0 + g0 / 255.0 + b0 / 255.0;
|
||||
}
|
||||
}
|
||||
@@ -853,8 +853,6 @@ sun/security/tools/keytool/ListKeychainStore.sh
|
||||
security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java 8224768 generic-all
|
||||
security/infra/java/security/cert/CertPathValidator/certification/BuypassCA.java 8243543 generic-all
|
||||
security/infra/java/security/cert/CertPathValidator/certification/ComodoCA.java 8263059 generic-all
|
||||
security/infra/java/security/cert/CertPathValidator/certification/LetsEncryptCA.java 8268678 generic-all
|
||||
security/infra/java/security/cert/CertPathValidator/certification/QuoVadisCA.java 8248899 generic-all
|
||||
|
||||
############################################################################
|
||||
|
||||
|
||||
@@ -116,38 +116,38 @@ public class LetsEncryptCA {
|
||||
|
||||
// Owner: CN=revoked-isrgrootx1.letsencrypt.org
|
||||
// Issuer: CN=R3, O=Let's Encrypt, C=US
|
||||
// Serial number: 3626488cf28e94f1719074128bbb58a7829
|
||||
// Valid from: Thu Apr 08 15:58:32 PDT 2021 until: Wed Jul 07 15:58:32 PDT 2021
|
||||
// Serial number: 4f1333011635d76d6356c5f1fb8a7273617
|
||||
// Valid from: Fri Jun 25 08:18:10 PDT 2021 until: Thu Sep 23 08:18:09 PDT 2021
|
||||
private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIFSjCCBDKgAwIBAgISA2JkiM8o6U8XGQdBKLu1ingpMA0GCSqGSIb3DQEBCwUA\n" +
|
||||
"MIIFSTCCBDGgAwIBAgISBPEzMBFjXXbWNWxfH7inJzYXMA0GCSqGSIb3DQEBCwUA\n" +
|
||||
"MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD\n" +
|
||||
"EwJSMzAeFw0yMTA0MDgyMjU4MzJaFw0yMTA3MDcyMjU4MzJaMC0xKzApBgNVBAMT\n" +
|
||||
"EwJSMzAeFw0yMTA2MjUxNTE4MTBaFw0yMTA5MjMxNTE4MDlaMC0xKzApBgNVBAMT\n" +
|
||||
"InJldm9rZWQtaXNyZ3Jvb3R4MS5sZXRzZW5jcnlwdC5vcmcwggEiMA0GCSqGSIb3\n" +
|
||||
"DQEBAQUAA4IBDwAwggEKAoIBAQC1NecSgcQLX4K94pR0HBaUun8wi++lyNTGkpoY\n" +
|
||||
"4xGB7M/WMnJpR8Y+49sO6QSe7fyU18zMjunT3Z5ahQtQi27dGU+xS7KUJUZl2NSJ\n" +
|
||||
"4MLf717cSbBmDBvZiqmuXmUuy5Ehhabk1jBx1NgsR9uqsJFyILPc9sEAKq6MwT7N\n" +
|
||||
"CnaVW1QhpUB9F5Zlc8cmHuhMsyrxGTM3h6P7QeVpqBT91mBEukvWUb01eifk134v\n" +
|
||||
"Sv1gXblr2bksHd9fiIoQvEUnSK9hXcRilDpOjaF5qkiNsQPpuEZqM56XyfOSeaCr\n" +
|
||||
"1HtEYa5Y+SXZ4G4Jt4AZt44WKoDwika9Iex826rETvAFaiTFAgMBAAGjggJdMIIC\n" +
|
||||
"WTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC\n" +
|
||||
"MAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFEwvrwbqSUpGjtFPPpoXpNO77gJuMB8G\n" +
|
||||
"DQEBAQUAA4IBDwAwggEKAoIBAQCkCp4fq7FnN5lfAWX0vhCcyC5WO9TuU6ckuYYj\n" +
|
||||
"8/wQ8GQ/FIl+vXCAmHIfIX14irQN8TISeVdMOP0C7sa73d3GSawX7qMaRhddXn7V\n" +
|
||||
"EL+4CbHQ6qit5YkakwhHz9tKbYX16wPj+inn22kJVwi8iLbhYB9WWSvv7OyiNSHv\n" +
|
||||
"nmlYUkMv8+9UhgPT4yCKF1OEI5ajUOuecjOKc+EzsT/JqPRErvBOIKn3PRn4h8UM\n" +
|
||||
"0BJDrDtZMpkvD4/lyRs3g/BLsf3DQjlEgKit0hvc72yyhiDbKd41EmBoQC5rNF7o\n" +
|
||||
"B0CnBXhDLHbC/YRunVrYGsF0h2J9hw4055BdaXbS2BJnPEFnAgMBAAGjggJcMIIC\n" +
|
||||
"WDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC\n" +
|
||||
"MAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFJBkf3Z/ICoCTUx3JCgrBeoMyedQMB8G\n" +
|
||||
"A1UdIwQYMBaAFBQusxe3WFbLrlAJQOYfr52LFMLGMFUGCCsGAQUFBwEBBEkwRzAh\n" +
|
||||
"BggrBgEFBQcwAYYVaHR0cDovL3IzLm8ubGVuY3Iub3JnMCIGCCsGAQUFBzAChhZo\n" +
|
||||
"dHRwOi8vcjMuaS5sZW5jci5vcmcvMC0GA1UdEQQmMCSCInJldm9rZWQtaXNyZ3Jv\n" +
|
||||
"b3R4MS5sZXRzZW5jcnlwdC5vcmcwTAYDVR0gBEUwQzAIBgZngQwBAgEwNwYLKwYB\n" +
|
||||
"BAGC3xMBAQEwKDAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlwdC5v\n" +
|
||||
"cmcwggEEBgorBgEEAdZ5AgQCBIH1BIHyAPAAdgBElGUusO7Or8RAB9io/ijA2uaC\n" +
|
||||
"vtjLMbU/0zOWtbaBqAAAAXiz7FLbAAAEAwBHMEUCIA8aoTszzeBJMP0aOhnMVizJ\n" +
|
||||
"mQe6c+OHAjG+dP1y9bD2AiEA0oJOb9ZKys+OE0JP5JT0kjdYH8U3ibJ+k6nHKMOI\n" +
|
||||
"CdgAdgD2XJQv0XcwIhRUGAgwlFaO400TGTO/3wwvIAvMTvFk4wAAAXiz7FLQAAAE\n" +
|
||||
"AwBHMEUCIGTdYSTO0IXQ6HSLwwGw1rlkH+lmg7EFpC+A25lhgtWCAiEAgi/7FtTG\n" +
|
||||
"KWKkWLU7ZP1AqIaaWlyXzRK2myrYKcBE804wDQYJKoZIhvcNAQELBQADggEBAByr\n" +
|
||||
"Q4mfzlT+4OBDI4hFjdrPHeHgePUK0HsmQ7GPNwe3pIxTQYs6fKIv+jb4mzKiggLy\n" +
|
||||
"882L+cYLfafggIpRjcoV9bAR2ceea+7uiyat54w5UZYLAmHgAdd4Y7OAUcrTL8rg\n" +
|
||||
"SAXNECrCGIfh0PwxyoJEgxcJnOoGgD5lVAycspUl3u3itmu9tcjcZA7CD5t2xPTQ\n" +
|
||||
"j/eoqH+5fHGXIvZuZxRVllWRwtLHRNafYiotLAW0P1i0i3wevTqmQ8ABVUuzYmJE\n" +
|
||||
"hjTktcZqbYIZqkDalLcGXJm8FFILQHv/vhXd/G2IbPODYgjTS7e4jCTXg2eIf17Z\n" +
|
||||
"yzs5yR8FPDdK48UWPgU=\n" +
|
||||
"cmcwggEDBgorBgEEAdZ5AgQCBIH0BIHxAO8AdQCUILwejtWNbIhzH4KLIiwN0dpN\n" +
|
||||
"XmxPlD1h204vWE2iwgAAAXpD9t6nAAAEAwBGMEQCIHwF9NcPqsovYp56lhqFkWYj\n" +
|
||||
"QCATATrLzzxgUoLDYRwgAiBBecqe5Ub32I+q9oqH1nbK/s8QadcafIL3bkrRVbFB\n" +
|
||||
"TAB2AH0+8viP/4hVaCTCwMqeUol5K8UOeAl/LmqXaJl+IvDXAAABekP23sYAAAQD\n" +
|
||||
"AEcwRQIgGli/1mmKKnZ0uxDIX7ySqAyD2C7FTf+y3py2S0Xcv4YCIQCZve3cqKZ2\n" +
|
||||
"lrEyyaMeLZA+PIxUMniHx3gDkro0sKLzOzANBgkqhkiG9w0BAQsFAAOCAQEAle42\n" +
|
||||
"p58OTusm7DAOcdK4ld+pJu2bz9F940Wrnql08rciRjGIVpp5PhMNFm9AOaptKPNY\n" +
|
||||
"h62V2GEOVaLxmvr9/8EDFcCCPAGV1DNYrG9aTKaiXk7IzO4UxKbzox4iUcuop/zB\n" +
|
||||
"uofxT8uBLmT4XYZrQXXKj1KdfJGzgeoXqBv5PPCiP3hmBQixoJnSKImnUIXWh4O8\n" +
|
||||
"kBtmgII5ug0q+jI3LvpJuv7xQsaNYFBcmFiQQ7YRt4W99GMdbYGjhzT8iBDEH7nG\n" +
|
||||
"MsqWuwB5TN5vIuw2aWxcfaqKayq7UPA4rJePWdD/5RzKlQKLQx0BA3AL+3Nnj1fT\n" +
|
||||
"NEKwCWWylIND6z/9Xw==\n" +
|
||||
"-----END CERTIFICATE-----";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
@@ -168,9 +168,6 @@ public class LetsEncryptCA {
|
||||
ValidatePathWithParams pathValidator = new ValidatePathWithParams(new String[]{INT});
|
||||
pathValidator.enableOCSPCheck();
|
||||
|
||||
// Perform backdate check as test artifacts expire in July 2021
|
||||
pathValidator.setValidationDate("June 15, 2021");
|
||||
|
||||
// Validate valid
|
||||
pathValidator.validate(new String[]{VALID},
|
||||
ValidatePathWithParams.Status.GOOD, null, System.out);
|
||||
@@ -178,6 +175,6 @@ public class LetsEncryptCA {
|
||||
// Validate Revoked
|
||||
pathValidator.validate(new String[]{REVOKED},
|
||||
ValidatePathWithParams.Status.REVOKED,
|
||||
"Thu Apr 08 17:05:26 PDT 2021", System.out);
|
||||
"Fri Jun 25 09:18:12 PDT 2021", System.out);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user