mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-17 14:59:41 +01:00
reimplement JDK-7162125 to fix JDK-8147002
port commit ba38e5c4 from JBR 9 port from JBR 11 to JBR 15(cherry picked from commita949f9d220) cherry-picked from commitf309844f75with fix for JBR-5300 Change source code and test files to use GPL license (cherry picked from commitf9942d50a8)
This commit is contained in:
90
src/java.desktop/macosx/classes/sun/font/CCompositeFont.java
Normal file
90
src/java.desktop/macosx/classes/sun/font/CCompositeFont.java
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2023 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. 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.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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,131 +25,50 @@
|
|||||||
|
|
||||||
package sun.font;
|
package sun.font;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
public final class CCompositeGlyphMapper extends CompositeGlyphMapper {
|
public final class CCompositeGlyphMapper extends CompositeGlyphMapper {
|
||||||
|
public CCompositeGlyphMapper(CCompositeFont compFont) {
|
||||||
private CompositeFont font;
|
|
||||||
private CharToGlyphMapper[] slotMappers;
|
|
||||||
|
|
||||||
public CCompositeGlyphMapper(CompositeFont compFont) {
|
|
||||||
super(compFont);
|
super(compFont);
|
||||||
font = compFont;
|
|
||||||
slotMappers = new CharToGlyphMapper[font.numSlots];
|
|
||||||
missingGlyph = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CharToGlyphMapper getSlotMapper(int slot) {
|
@Override
|
||||||
CharToGlyphMapper mapper = slotMappers[slot];
|
protected int convertToGlyph(int unicode) {
|
||||||
if (mapper == null) {
|
CCompositeFont compositeFont = (CCompositeFont) font;
|
||||||
mapper = font.getSlotFont(slot).getMapper();
|
CFont mainFont = (CFont) font.getSlotFont(0);
|
||||||
slotMappers[slot] = mapper;
|
String[] fallbackFontInfo = new String[2];
|
||||||
|
int glyphCode = nativeCodePointToGlyph(mainFont.getNativeFontPtr(), unicode, fallbackFontInfo);
|
||||||
|
if (glyphCode == missingGlyph) {
|
||||||
|
return missingGlyph;
|
||||||
}
|
}
|
||||||
return mapper;
|
String fallbackFontName = fallbackFontInfo[0];
|
||||||
}
|
String fallbackFontFamilyName = fallbackFontInfo[1];
|
||||||
|
if (fallbackFontName == null || fallbackFontFamilyName == null) {
|
||||||
public boolean canDisplay(char ch) {
|
return compositeGlyphCode(0, glyphCode);
|
||||||
int glyph = charToGlyph(ch);
|
|
||||||
return glyph != missingGlyph;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int convertToGlyph(int unicode) {
|
|
||||||
for (int slot = 0; slot < font.numSlots; slot++) {
|
|
||||||
CharToGlyphMapper mapper = getSlotMapper(slot);
|
|
||||||
int glyphCode = mapper.charToGlyph(unicode);
|
|
||||||
// The CFont Mappers will return a negative code
|
|
||||||
// for fonts that will fill the glyph from fallbacks
|
|
||||||
// - cascading font in OSX-speak. But we need to be
|
|
||||||
// know here that only the codes > 0 are really present.
|
|
||||||
if (glyphCode > 0) {
|
|
||||||
glyphCode = compositeGlyphCode(slot, glyphCode);
|
|
||||||
return glyphCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return missingGlyph;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumGlyphs() {
|
|
||||||
int numGlyphs = 0;
|
|
||||||
for (int slot=0; slot<1 /*font.numSlots*/; slot++) {
|
|
||||||
CharToGlyphMapper mapper = slotMappers[slot];
|
|
||||||
if (mapper == null) {
|
|
||||||
mapper = font.getSlotFont(slot).getMapper();
|
|
||||||
slotMappers[slot] = mapper;
|
|
||||||
}
|
|
||||||
numGlyphs += mapper.getNumGlyphs();
|
|
||||||
}
|
|
||||||
return numGlyphs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int charToGlyph(int unicode) {
|
|
||||||
return convertToGlyph(unicode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int charToGlyph(char unicode) {
|
|
||||||
return convertToGlyph(unicode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) {
|
|
||||||
|
|
||||||
for (int i=0; i<count; i++) {
|
|
||||||
int code = unicodes[i]; // char is unsigned.
|
|
||||||
|
|
||||||
if (code >= HI_SURROGATE_START &&
|
|
||||||
code <= HI_SURROGATE_END && i < count - 1) {
|
|
||||||
char low = unicodes[i + 1];
|
|
||||||
|
|
||||||
if (low >= LO_SURROGATE_START &&
|
|
||||||
low <= LO_SURROGATE_END) {
|
|
||||||
code = (code - HI_SURROGATE_START) *
|
|
||||||
0x400 + low - LO_SURROGATE_START + 0x10000;
|
|
||||||
glyphs[i + 1] = INVISIBLE_GLYPH_ID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glyphs[i] = convertToGlyph(code);
|
|
||||||
|
|
||||||
if (code < FontUtilities.MIN_LAYOUT_CHARCODE) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (FontUtilities.isComplexCharCode(code)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (code >= 0x10000) {
|
|
||||||
i += 1; // Empty glyph slot after surrogate
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
int slot = compositeFont.findSlot(fallbackFontName);
|
||||||
}
|
|
||||||
|
|
||||||
public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) {
|
if (slot < 0) {
|
||||||
for (int i=0; i<count; i++) {
|
Font2D fallbackFont = FontManagerFactory.getInstance().findFont2D(fallbackFontName,
|
||||||
int code = unicodes[i]; // char is unsigned.
|
Font.PLAIN, FontManager.NO_FALLBACK);
|
||||||
|
if (!(fallbackFont instanceof CFont) ||
|
||||||
if (code >= HI_SURROGATE_START &&
|
!fallbackFontName.equals(((CFont) fallbackFont).getNativeFontName())) {
|
||||||
code <= HI_SURROGATE_END && i < count - 1) {
|
// Native font fallback mechanism can return "hidden" fonts - their names start with dot,
|
||||||
char low = unicodes[i + 1];
|
// and they are not returned in a list of fonts available in system, but they can still be used
|
||||||
|
// if requested explicitly.
|
||||||
if (low >= LO_SURROGATE_START &&
|
fallbackFont = new CFont(fallbackFontName, fallbackFontFamilyName);
|
||||||
low <= LO_SURROGATE_END) {
|
|
||||||
code = (code - HI_SURROGATE_START) *
|
|
||||||
0x400 + low - LO_SURROGATE_START + 0x10000;
|
|
||||||
|
|
||||||
glyphs[i] = convertToGlyph(code);
|
|
||||||
i += 1; // Empty glyph slot after surrogate
|
|
||||||
glyphs[i] = INVISIBLE_GLYPH_ID;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glyphs[i] = convertToGlyph(code);
|
if (mainFont.isFakeItalic()) fallbackFont = ((CFont)fallbackFont).createItalicVariant(false);
|
||||||
|
|
||||||
|
slot = compositeFont.addSlot((CFont) fallbackFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return compositeGlyphCode(slot, glyphCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) {
|
// This invokes native font fallback mechanism, returning information about font (its Postscript and family names)
|
||||||
for (int i=0; i<count; i++) {
|
// able to display a given character, and corresponding glyph code
|
||||||
glyphs[i] = convertToGlyph(unicodes[i]);
|
private static native int nativeCodePointToGlyph(long nativeFontPtr, int codePoint, String[] result);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -31,7 +31,6 @@ import java.awt.geom.AffineTransform;
|
|||||||
import java.awt.geom.GeneralPath;
|
import java.awt.geom.GeneralPath;
|
||||||
import java.awt.geom.Point2D;
|
import java.awt.geom.Point2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
// Right now this class is final to avoid a problem with native code.
|
// Right now this class is final to avoid a problem with native code.
|
||||||
// For some reason the JNI IsInstanceOf was not working correctly
|
// For some reason the JNI IsInstanceOf was not working correctly
|
||||||
@@ -174,12 +173,14 @@ public final class CFont extends PhysicalFont implements FontSubstitution {
|
|||||||
isFakeItalic = other.isFakeItalic;
|
isFakeItalic = other.isFakeItalic;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CFont createItalicVariant() {
|
public CFont createItalicVariant(boolean updateStyle) {
|
||||||
CFont font = new CFont(this, familyName);
|
CFont font = new CFont(this, familyName);
|
||||||
font.nativeFontName = fullName;
|
font.nativeFontName = fullName;
|
||||||
font.fullName =
|
font.fullName =
|
||||||
fullName + (style == Font.BOLD ? "" : "-") + "Italic-Derived";
|
fullName + (style == Font.BOLD ? "" : "-") + "Italic-Derived";
|
||||||
font.style |= Font.ITALIC;
|
if (updateStyle) {
|
||||||
|
font.style |= Font.ITALIC;
|
||||||
|
}
|
||||||
font.isFakeItalic = true;
|
font.isFakeItalic = true;
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
@@ -198,51 +199,11 @@ public final class CFont extends PhysicalFont implements FontSubstitution {
|
|||||||
return getCGFontPtrNative(getNativeFontPtr());
|
return getCGFontPtrNative(getNativeFontPtr());
|
||||||
}
|
}
|
||||||
|
|
||||||
static native void getCascadeList(long nativeFontPtr, ArrayList<String> listOfString);
|
|
||||||
|
|
||||||
private CompositeFont createCompositeFont() {
|
|
||||||
ArrayList<String> listOfString = new ArrayList<String>();
|
|
||||||
getCascadeList(nativeFontPtr, listOfString);
|
|
||||||
|
|
||||||
// In some italic cases the standard Mac cascade list is missing Arabic.
|
|
||||||
listOfString.add("GeezaPro");
|
|
||||||
CFontManager fm = (CFontManager) FontManagerFactory.getInstance();
|
|
||||||
int numFonts = 1 + listOfString.size();
|
|
||||||
PhysicalFont[] fonts = new PhysicalFont[numFonts];
|
|
||||||
fonts[0] = this;
|
|
||||||
int idx = 1;
|
|
||||||
if (FontUtilities.isLogging()) {
|
|
||||||
FontUtilities.logInfo("Cascading list for " + this + " :");
|
|
||||||
}
|
|
||||||
for (String s : listOfString) {
|
|
||||||
if (FontUtilities.isLogging()) {
|
|
||||||
FontUtilities.logInfo("Fallback:" + s);
|
|
||||||
}
|
|
||||||
if (s.equals(".AppleSymbolsFB")) {
|
|
||||||
// Don't know why we get the weird name above .. replace.
|
|
||||||
s = "AppleSymbols";
|
|
||||||
}
|
|
||||||
Font2D f2d = fm.getOrCreateFallbackFont(s);
|
|
||||||
if (f2d == null || f2d == this) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
fonts[idx++] = (PhysicalFont)f2d;
|
|
||||||
}
|
|
||||||
if (idx < fonts.length) {
|
|
||||||
PhysicalFont[] orig = fonts;
|
|
||||||
fonts = new PhysicalFont[idx];
|
|
||||||
System.arraycopy(orig, 0, fonts, 0, idx);
|
|
||||||
}
|
|
||||||
CompositeFont compFont = new CompositeFont(fonts);
|
|
||||||
compFont.mapper = new CCompositeGlyphMapper(compFont);
|
|
||||||
return compFont;
|
|
||||||
}
|
|
||||||
|
|
||||||
private CompositeFont compFont;
|
private CompositeFont compFont;
|
||||||
|
|
||||||
public CompositeFont getCompositeFont2D() {
|
public CompositeFont getCompositeFont2D() {
|
||||||
if (compFont == null) {
|
if (compFont == null) {
|
||||||
compFont = createCompositeFont();
|
compFont = new CCompositeFont(this);
|
||||||
}
|
}
|
||||||
return compFont;
|
return compFont;
|
||||||
}
|
}
|
||||||
@@ -270,6 +231,14 @@ public final class CFont extends PhysicalFont implements FontSubstitution {
|
|||||||
return new CStrike(this, desc);
|
return new CStrike(this, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isFakeItalic() {
|
||||||
|
return isFakeItalic;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getNativeFontName() {
|
||||||
|
return nativeFontName;
|
||||||
|
}
|
||||||
|
|
||||||
// <rdar://problem/5321707> sun.font.Font2D caches the last used strike,
|
// <rdar://problem/5321707> sun.font.Font2D caches the last used strike,
|
||||||
// but does not check if the properties of the strike match the properties
|
// but does not check if the properties of the strike match the properties
|
||||||
// of the incoming java.awt.Font object (size, style, etc).
|
// of the incoming java.awt.Font object (size, style, etc).
|
||||||
|
|||||||
@@ -32,9 +32,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
import javax.swing.plaf.FontUIResource;
|
import javax.swing.plaf.FontUIResource;
|
||||||
|
|
||||||
@@ -44,7 +42,6 @@ import sun.lwawt.macosx.*;
|
|||||||
|
|
||||||
public final class CFontManager extends SunFontManager {
|
public final class CFontManager extends SunFontManager {
|
||||||
private static Hashtable<String, Font2D> genericFonts = new Hashtable<String, Font2D>();
|
private static Hashtable<String, Font2D> genericFonts = new Hashtable<String, Font2D>();
|
||||||
private final Map<String, Font2D> fallbackFonts = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FontConfiguration createFontConfiguration() {
|
protected FontConfiguration createFontConfiguration() {
|
||||||
@@ -205,10 +202,10 @@ public final class CFontManager extends SunFontManager {
|
|||||||
if (plain == null && bold == null) continue;
|
if (plain == null && bold == null) continue;
|
||||||
if (italic != null && boldItalic != null) continue;
|
if (italic != null && boldItalic != null) continue;
|
||||||
if (plain != null && italic == null) {
|
if (plain != null && italic == null) {
|
||||||
registerGenericFont(plain.createItalicVariant(), true);
|
registerGenericFont(plain.createItalicVariant(true), true);
|
||||||
}
|
}
|
||||||
if (bold != null && boldItalic == null) {
|
if (bold != null && boldItalic == null) {
|
||||||
registerGenericFont(bold.createItalicVariant(), true);
|
registerGenericFont(bold.createItalicVariant(true), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,17 +325,4 @@ public final class CFontManager extends SunFontManager {
|
|||||||
@Override
|
@Override
|
||||||
protected void populateFontFileNameMap(HashMap<String, String> fontToFileMap, HashMap<String, String> fontToFamilyNameMap,
|
protected void populateFontFileNameMap(HashMap<String, String> fontToFileMap, HashMap<String, String> fontToFamilyNameMap,
|
||||||
HashMap<String, ArrayList<String>> familyToFontListMap, Locale locale) {}
|
HashMap<String, ArrayList<String>> familyToFontListMap, Locale locale) {}
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1232,7 +1232,7 @@ static NSDictionary* prebuiltFamilyNames() {
|
|||||||
@"Wingdings3" : @"Wingdings 3",
|
@"Wingdings3" : @"Wingdings 3",
|
||||||
@"ZapfDingbatsITC" : @"Zapf Dingbats",
|
@"ZapfDingbatsITC" : @"Zapf Dingbats",
|
||||||
@"Zapfino" : @"Zapfino",
|
@"Zapfino" : @"Zapfino",
|
||||||
|
|
||||||
// JetBrains fonts
|
// JetBrains fonts
|
||||||
@"DroidSans" : @"Droid Sans",
|
@"DroidSans" : @"Droid Sans",
|
||||||
@"DroidSans-Bold" : @"Droid Sans",
|
@"DroidSans-Bold" : @"Droid Sans",
|
||||||
@@ -1583,55 +1583,6 @@ Java_sun_awt_FontDescriptor_initIDs
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: sun_awt_FontDescriptor
|
|
||||||
* Method: initIDs
|
|
||||||
* Signature: ()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;
|
|
||||||
CTFontRef font = (CTFontRef)nsFont;
|
|
||||||
CFArrayRef codes = CFLocaleCopyISOLanguageCodes();
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
CFStringRef base = CTFontCopyFullName(font);
|
|
||||||
NSLog(@"BaseFont is : %@", (NSString*)base);
|
|
||||||
CFRelease(base);
|
|
||||||
#endif
|
|
||||||
CFArrayRef fds = CTFontCopyDefaultCascadeListForLanguages(font, codes);
|
|
||||||
CFRelease(codes);
|
|
||||||
CFIndex cnt = CFArrayGetCount(fds);
|
|
||||||
for (i=0; i<cnt; i++) {
|
|
||||||
CTFontDescriptorRef ref = CFArrayGetValueAtIndex(fds, i);
|
|
||||||
CFStringRef 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)->ExceptionCheck(env)) {
|
|
||||||
CFRelease(fds);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
(*env)->DeleteLocalRef(env, jFontName);
|
|
||||||
}
|
|
||||||
CFRelease(fds);
|
|
||||||
JNI_COCOA_EXIT(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
static CFStringRef EMOJI_FONT_NAME = CFSTR("Apple Color Emoji");
|
static CFStringRef EMOJI_FONT_NAME = CFSTR("Apple Color Emoji");
|
||||||
|
|
||||||
bool IsEmojiFont(CTFontRef font)
|
bool IsEmojiFont(CTFontRef font)
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#import "CoreTextSupport.h"
|
#import "CoreTextSupport.h"
|
||||||
|
|
||||||
#import "sun_font_CCharToGlyphMapper.h"
|
#import "sun_font_CCharToGlyphMapper.h"
|
||||||
|
#import "sun_font_CCompositeGlyphMapper.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: sun_font_CCharToGlyphMapper
|
* Class: sun_font_CCharToGlyphMapper
|
||||||
@@ -115,3 +116,28 @@ JNI_COCOA_ENTER(env);
|
|||||||
|
|
||||||
JNI_COCOA_EXIT(env);
|
JNI_COCOA_EXIT(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: sun_font_CCompositeGlyphMapper
|
||||||
|
* Method: nativeCodePointToGlyph
|
||||||
|
* Signature: (JI[Ljava/lang/String;)I
|
||||||
|
*/
|
||||||
|
JNIEXPORT jint JNICALL
|
||||||
|
Java_sun_font_CCompositeGlyphMapper_nativeCodePointToGlyph
|
||||||
|
(JNIEnv *env, jclass clazz, jlong awtFontPtr, jint codePoint, jobjectArray resultArray)
|
||||||
|
{
|
||||||
|
JNI_COCOA_ENTER(env);
|
||||||
|
AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
|
||||||
|
CFStringRef fontNames[] = {NULL, NULL};
|
||||||
|
CGGlyph glyph = CTS_CopyGlyphAndFontNamesForCodePoint(awtFont, (UnicodeScalarValue)codePoint, fontNames);
|
||||||
|
if (glyph > 0) {
|
||||||
|
jstring fontName = NSStringToJavaString(env, (NSString *)fontNames[0]);
|
||||||
|
(*env)->SetObjectArrayElement(env, resultArray, 0, fontName);
|
||||||
|
jstring fontFamilyName = NSStringToJavaString(env, (NSString *)fontNames[1]);
|
||||||
|
(*env)->SetObjectArrayElement(env, resultArray, 1, fontFamilyName);
|
||||||
|
}
|
||||||
|
if (fontNames[0]) CFRelease(fontNames[0]);
|
||||||
|
if (fontNames[1]) CFRelease(fontNames[1]);
|
||||||
|
return glyph;
|
||||||
|
JNI_COCOA_EXIT(env);
|
||||||
|
}
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ CTFontRef CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(const AWTFont *font, co
|
|||||||
// Returns the substituted font, and places the appropriate glyph into "glyphRef"
|
// 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 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
|
// Breakup a 32 bit unicode value into the component surrogate pairs
|
||||||
void CTS_BreakupUnicodeIntoSurrogatePairs(int uniChar, UTF16Char charRef[]);
|
void CTS_BreakupUnicodeIntoSurrogatePairs(int uniChar, UTF16Char charRef[]);
|
||||||
|
|
||||||
|
|||||||
@@ -88,18 +88,10 @@ ReleaseCTStateDictionary(CFDictionaryRef ctStateDict)
|
|||||||
CFRelease(ctStateDict); // GC
|
CFRelease(ctStateDict); // GC
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void GetFontsAndGlyphsForCharacters(CTFontRef font, const UniChar unicodes[], CGGlyph glyphs[], jint glyphsAsInts[],
|
||||||
* Transform Unicode characters into glyphs.
|
CTFontRef actualFonts[], const size_t count)
|
||||||
*
|
|
||||||
* Fills the "glyphsAsInts" array with the glyph codes for the current font,
|
|
||||||
* or the negative unicode value if we know the character can be hot-substituted.
|
|
||||||
*
|
|
||||||
* This is the heart of "Universal Font Substitution" in Java.
|
|
||||||
*/
|
|
||||||
void CTS_GetGlyphsAsIntsForCharacters
|
|
||||||
(const AWTFont *font, const UniChar unicodes[], CGGlyph glyphs[], jint glyphsAsInts[], const size_t count)
|
|
||||||
{
|
{
|
||||||
CTFontGetGlyphsForCharacters((CTFontRef)font->fFont, unicodes, glyphs, count);
|
CTFontGetGlyphsForCharacters(font, unicodes, glyphs, count);
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
@@ -115,12 +107,15 @@ void CTS_GetGlyphsAsIntsForCharacters
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CTFontRef fallback = JRSFontCreateFallbackFontForCharacters((CTFontRef)font->fFont, &unicodes[i],
|
const CTFontRef fallback = JRSFontCreateFallbackFontForCharacters(font, &unicodes[i], surrogatePair ? 2 : 1);
|
||||||
surrogatePair ? 2 : 1);
|
|
||||||
if (fallback) {
|
if (fallback) {
|
||||||
CTFontGetGlyphsForCharacters(fallback, &unicodes[i], &glyphs[i], surrogatePair ? 2 : 1);
|
CTFontGetGlyphsForCharacters(fallback, &unicodes[i], &glyphs[i], surrogatePair ? 2 : 1);
|
||||||
glyph = glyphs[i];
|
glyph = glyphs[i];
|
||||||
CFRelease(fallback);
|
if (actualFonts && glyph > 0) {
|
||||||
|
actualFonts[i] = fallback;
|
||||||
|
} else {
|
||||||
|
CFRelease(fallback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glyph > 0) {
|
if (glyph > 0) {
|
||||||
@@ -134,6 +129,53 @@ void CTS_GetGlyphsAsIntsForCharacters
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
void CTS_GetGlyphsAsIntsForCharacters
|
||||||
|
(const AWTFont *font, const UniChar unicodes[], CGGlyph glyphs[], jint glyphsAsInts[], const size_t count)
|
||||||
|
{
|
||||||
|
GetFontsAndGlyphsForCharacters((CTFontRef)font->fFont, unicodes, glyphs, glyphsAsInts, NULL, 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;
|
||||||
|
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, 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
|
* Translates a Unicode into a CGGlyph/CTFontRef pair
|
||||||
* Returns the substituted font, and places the appropriate glyph into "glyphRef"
|
* Returns the substituted font, and places the appropriate glyph into "glyphRef"
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import java.awt.Font;
|
|||||||
* But its probably OK to include it so long as only composites include
|
* But its probably OK to include it so long as only composites include
|
||||||
* fallbacks. If physicals do then it would be really confusing ..
|
* fallbacks. If physicals do then it would be really confusing ..
|
||||||
*/
|
*/
|
||||||
public final class CompositeFont extends Font2D {
|
public class CompositeFont extends Font2D {
|
||||||
|
|
||||||
private boolean[] deferredInitialisation;
|
private boolean[] deferredInitialisation;
|
||||||
String[] componentFileNames;
|
String[] componentFileNames;
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ public class CompositeGlyphMapper extends CharToGlyphMapper {
|
|||||||
return mapper;
|
return mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int convertToGlyph(int unicode) {
|
protected int convertToGlyph(int unicode) {
|
||||||
|
|
||||||
for (int slot = 0; slot < font.numSlots; slot++) {
|
for (int slot = 0; slot < font.numSlots; slot++) {
|
||||||
if (!hasExcludes || !font.isExcludedChar(slot, unicode)) {
|
if (!hasExcludes || !font.isExcludedChar(slot, unicode)) {
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ public abstract class Font2D {
|
|||||||
return getStrike(desc, true);
|
return getStrike(desc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FontStrike getStrike(FontStrikeDesc desc, boolean copy) {
|
FontStrike getStrike(FontStrikeDesc desc, boolean copy) {
|
||||||
/* Before looking in the map, see if the descriptor matches the
|
/* Before looking in the map, see if the descriptor matches the
|
||||||
* last strike returned from this Font2D. This should often be a win
|
* 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
|
* since its common for the same font, in the same size to be
|
||||||
|
|||||||
Reference in New Issue
Block a user