diff options
author | Dmitry Batrak <Dmitry.Batrak@jetbrains.com> | 2021-12-03 16:02:54 +0300 |
---|---|---|
committer | Dmitry Batrak <Dmitry.Batrak@jetbrains.com> | 2021-12-06 17:59:44 +0300 |
commit | d0d8a63e0bc7a7e7f9f539b68c71d6b040ee9711 (patch) | |
tree | f2fb1c5db451db1223e6a68fa9d274737b5740f0 | |
parent | 09c200ccfd04cc2611bc141d9b71ae02a2b395f0 (diff) | |
download | JetBrainsRuntime-d0d8a63e0bc7a7e7f9f539b68c71d6b040ee9711.tar.gz |
JBR-4072 Migrate font fallback implementation on macOS to cascade listsjb17_0_1-b222
(cherry picked from commit a155760e94d989ce2584233fa955072e6ef72287)
26 files changed, 254 insertions, 849 deletions
diff --git a/src/java.desktop/macosx/classes/sun/font/CCharToGlyphMapper.java b/src/java.desktop/macosx/classes/sun/font/CCharToGlyphMapper.java index c48c382256d..0914a9aa9b2 100644 --- a/src/java.desktop/macosx/classes/sun/font/CCharToGlyphMapper.java +++ b/src/java.desktop/macosx/classes/sun/font/CCharToGlyphMapper.java @@ -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); diff --git a/src/java.desktop/macosx/classes/sun/font/CCompositeFont.java b/src/java.desktop/macosx/classes/sun/font/CCompositeFont.java deleted file mode 100644 index eae2d36f5bb..00000000000 --- a/src/java.desktop/macosx/classes/sun/font/CCompositeFont.java +++ /dev/null @@ -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++; - } -} diff --git a/src/java.desktop/macosx/classes/sun/font/CCompositeGlyphMapper.java b/src/java.desktop/macosx/classes/sun/font/CCompositeGlyphMapper.java deleted file mode 100644 index b55c8cd8da8..00000000000 --- a/src/java.desktop/macosx/classes/sun/font/CCompositeGlyphMapper.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.font; - -import java.awt.*; - -public final class CCompositeGlyphMapper extends CompositeGlyphMapper { - public CCompositeGlyphMapper(CCompositeFont compFont) { - super(compFont); - } - - @Override - protected int convertToGlyph(int unicode) { - CCompositeFont compositeFont = (CCompositeFont) font; - CFont mainFont = (CFont) font.getSlotFont(0); - String[] fallbackFontInfo = new String[2]; - int glyphCode = nativeCodePointToGlyph(mainFont.getNativeFontPtr(), unicode, fallbackFontInfo); - if (glyphCode == missingGlyph) { - setCachedGlyphCode(unicode, missingGlyph); - return missingGlyph; - } - String fallbackFontName = fallbackFontInfo[0]; - String fallbackFontFamilyName = fallbackFontInfo[1]; - if (fallbackFontName == null || fallbackFontFamilyName == null) { - int result = compositeGlyphCode(0, glyphCode); - setCachedGlyphCode(unicode, result); - return result; - } - - int slot = compositeFont.findSlot(fallbackFontName); - - if (slot < 0) { - Font2D fallbackFont = FontManagerFactory.getInstance().findFont2D(fallbackFontName, - Font.PLAIN, FontManager.NO_FALLBACK); - if (!(fallbackFont instanceof CFont) || - !fallbackFontName.equals(((CFont) fallbackFont).getNativeFontName())) { - // Native font fallback mechanism can return "hidden" fonts - their names start with dot, - // and they are not returned in a list of fonts available in system, but they can still be used - // if requested explicitly. - fallbackFont = new CFont(fallbackFontName, fallbackFontFamilyName, null); - } - - if (mainFont.isFakeItalic()) fallbackFont = ((CFont)fallbackFont).createItalicVariant(false); - - slot = compositeFont.addSlot((CFont) fallbackFont); - } - - int result = compositeGlyphCode(slot, glyphCode); - setCachedGlyphCode(unicode, result); - return result; - } - - // This invokes native font fallback mechanism, returning information about font (its Postscript and family names) - // able to display a given character, and corresponding glyph code - private static native int nativeCodePointToGlyph(long nativeFontPtr, int codePoint, String[] result); -}
\ No newline at end of file diff --git a/src/java.desktop/macosx/classes/sun/font/CFont.java b/src/java.desktop/macosx/classes/sun/font/CFont.java index 4323567f87f..09892c3a609 100644 --- a/src/java.desktop/macosx/classes/sun/font/CFont.java +++ b/src/java.desktop/macosx/classes/sun/font/CFont.java @@ -31,6 +31,9 @@ import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.Set; // Right now this class is final to avoid a problem with native code. // For some reason the JNI IsInstanceOf was not working correctly @@ -175,14 +178,12 @@ public final class CFont extends PhysicalFont implements FontSubstitution, FontW isFakeItalic = other.isFakeItalic; } - public CFont createItalicVariant(boolean updateStyle) { + public CFont createItalicVariant() { CFont font = new CFont(this, familyName); font.nativeFontName = fullName; font.fullName = fullName + (style == Font.BOLD ? "" : "-") + "Italic-Derived"; - if (updateStyle) { - font.style |= Font.ITALIC; - } + font.style |= Font.ITALIC; font.isFakeItalic = true; return font; } @@ -204,11 +205,51 @@ public final class CFont extends PhysicalFont implements FontSubstitution, FontW return getCGFontPtrNative(getNativeFontPtr()); } + static native void getCascadeList(long nativeFontPtr, ArrayList<String> listOfString); + + private CompositeFont createCompositeFont() { + ArrayList<String> listOfString = new ArrayList<String>(); + getCascadeList(getNativeFontPtr(), listOfString); + + Set<String> components = new LinkedHashSet<>(listOfString); + // In some italic cases the standard Mac cascade list is missing Arabic. + components.add("GeezaPro"); + CFontManager fm = (CFontManager) FontManagerFactory.getInstance(); + components.addAll(fm.getAdditionalFallbackVariants()); + int numFonts = 1 + components.size(); + PhysicalFont[] fonts = new PhysicalFont[numFonts]; + fonts[0] = this; + int idx = 1; + if (FontUtilities.isLogging()) { + FontUtilities.logInfo("Cascading list for " + this + " :"); + } + for (String s : components) { + if (FontUtilities.isLogging()) { + FontUtilities.logInfo("Fallback:" + s); + } + if (s.equals(".AppleSymbolsFB")) { + // Don't know why we get the weird name above .. replace. + s = "AppleSymbols"; + } + Font2D f2d = fm.getOrCreateFallbackFont(s); + if (f2d == null || f2d == this) { + continue; + } + fonts[idx++] = (PhysicalFont)f2d; + } + if (idx < fonts.length) { + PhysicalFont[] orig = fonts; + fonts = new PhysicalFont[idx]; + System.arraycopy(orig, 0, fonts, 0, idx); + } + return new CompositeFont(fonts); + } + private CompositeFont compFont; public CompositeFont getCompositeFont2D() { if (compFont == null) { - compFont = new CCompositeFont(this); + compFont = createCompositeFont(); } return compFont; } @@ -236,14 +277,6 @@ public final class CFont extends PhysicalFont implements FontSubstitution, FontW return new CStrike(this, desc); } - boolean isFakeItalic() { - return isFakeItalic; - } - - String getNativeFontName() { - return nativeFontName; - } - @Override public String getTypographicSubfamilyName() { return faceName == null ? super.getTypographicSubfamilyName() : faceName; @@ -276,8 +309,4 @@ public final class CFont extends PhysicalFont implements FontSubstitution, FontW ", familyName: " + familyName + ", style: " + style + " } aka: " + super.toString(); } - - public Font2D createItalic() { - return this.createItalicVariant(true); - } } diff --git a/src/java.desktop/macosx/classes/sun/font/CFontManager.java b/src/java.desktop/macosx/classes/sun/font/CFontManager.java index 42967b84804..fe92f5a228e 100644 --- a/src/java.desktop/macosx/classes/sun/font/CFontManager.java +++ b/src/java.desktop/macosx/classes/sun/font/CFontManager.java @@ -30,20 +30,27 @@ import java.io.File; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.Hashtable; +import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; import javax.swing.plaf.FontUIResource; import sun.awt.FontConfiguration; import sun.awt.HeadlessToolkit; import sun.lwawt.macosx.*; +import sun.security.action.GetBooleanAction; import sun.util.logging.PlatformLogger; public final class CFontManager extends SunFontManager { private static Hashtable<String, Font2D> genericFonts = new Hashtable<String, Font2D>(); + private final Map<String, Font2D> fallbackFonts = new ConcurrentHashMap<>(); + private final List<String> extFallbackVariants = new ArrayList<>(); @Override protected FontConfiguration createFontConfiguration() { @@ -230,6 +237,7 @@ public final class CFontManager extends SunFontManager { public Object run() { if (!loadedAllFonts) { loadNativeFonts(); + collectAdditionalFallbackVariants(); loadedAllFonts = true; } return null; @@ -337,4 +345,40 @@ public final class CFontManager extends SunFontManager { @Override protected void populateFontFileNameMap(HashMap<String, String> fontToFileMap, HashMap<String, String> fontToFamilyNameMap, HashMap<String, ArrayList<String>> familyToFontListMap, Locale locale) {} + + @SuppressWarnings("removal") + private void collectAdditionalFallbackVariants() { + if (AccessController.doPrivileged(new GetBooleanAction("mac.ext.font.fallback"))) { + for (String fontName : genericFonts.keySet()) { + boolean accept = false; + if (fontName.equals("ArialUnicodeMS")) { + accept = true; + } else if (fontName.startsWith("NotoSans")) { + int pos = fontName.indexOf('-'); + accept = pos == -1 || fontName.substring(pos + 1).equals("Regular"); + } + if (accept) { + extFallbackVariants.add(fontName); + } + } + Collections.sort(extFallbackVariants); // ensure predictable order + } + } + + List<String> getAdditionalFallbackVariants() { + return extFallbackVariants; + } + + Font2D getOrCreateFallbackFont(String fontName) { + Font2D font2D = findFont2D(fontName, Font.PLAIN, FontManager.NO_FALLBACK); + if (font2D != null || fontName.startsWith(".")) { + return font2D; + } else { + // macOS doesn't list some system fonts in [NSFontManager availableFontFamilies] output, + // so they are not registered in font manager as part of 'loadNativeFonts'. + // These fonts are present in [NSFontManager availableFonts] output though, + // and can be accessed in the same way as other system fonts. + return fallbackFonts.computeIfAbsent(fontName, name -> new CFont(name, null, null)); + } + } } diff --git a/src/java.desktop/macosx/classes/sun/font/CStrike.java b/src/java.desktop/macosx/classes/sun/font/CStrike.java index 418ffae4b98..b126479928b 100644 --- a/src/java.desktop/macosx/classes/sun/font/CStrike.java +++ b/src/java.desktop/macosx/classes/sun/font/CStrike.java @@ -358,18 +358,14 @@ public final class CStrike extends PhysicalStrike { } } - // This class stores glyph pointers, and is indexed based on glyph codes, - // and negative unicode values. See the comments in - // CCharToGlyphMapper for more details on our glyph code strategy. + // This class stores glyph pointers, and is indexed based on glyph codes. private static class GlyphInfoCache extends CStrikeDisposer { private static final int FIRST_LAYER_SIZE = 256; - private static final int SECOND_LAYER_SIZE = 16384; // 16384 = 128x128 // rdar://problem/5204197 private final AtomicBoolean disposed = new AtomicBoolean(false); private final long[] firstLayerCache; - private SparseBitShiftingTwoLayerArray secondLayerCache; private HashMap<Integer, Long> generalCache; GlyphInfoCache(final Font2D nativeFont, final FontStrikeDesc desc) { @@ -378,19 +374,9 @@ public final class CStrike extends PhysicalStrike { } public synchronized long get(final int index) { - if (index < 0) { - if (-index < SECOND_LAYER_SIZE) { - // catch common unicodes - if (secondLayerCache == null) { - return 0L; - } - return secondLayerCache.get(-index); - } - } else { - if (index < FIRST_LAYER_SIZE) { - // catch common glyphcodes - return firstLayerCache[index]; - } + if (index < FIRST_LAYER_SIZE) { + // catch common glyphcodes + return firstLayerCache[index]; } if (generalCache == null) { @@ -404,21 +390,10 @@ public final class CStrike extends PhysicalStrike { } public synchronized void put(final int index, final long value) { - if (index < 0) { - if (-index < SECOND_LAYER_SIZE) { - // catch common unicodes - if (secondLayerCache == null) { - secondLayerCache = new SparseBitShiftingTwoLayerArray(SECOND_LAYER_SIZE, 7); // 128x128 - } - secondLayerCache.put(-index, value); - return; - } - } else { - if (index < FIRST_LAYER_SIZE) { - // catch common glyphcodes - firstLayerCache[index] = value; - return; - } + if (index < FIRST_LAYER_SIZE) { + // catch common glyphcodes + firstLayerCache[index] = value; + return; } if (generalCache == null) { @@ -441,14 +416,6 @@ public final class CStrike extends PhysicalStrike { // clean out the first array disposeLongArray(firstLayerCache); - // clean out the two layer arrays - if (secondLayerCache != null) { - final long[][] secondLayerLongArrayArray = secondLayerCache.cache; - for (final long[] longArray : secondLayerLongArrayArray) { - if (longArray != null) disposeLongArray(longArray); - } - } - // clean up everyone else if (generalCache != null) { for (Long aLong : generalCache.values()) { @@ -485,56 +452,18 @@ public final class CStrike extends PhysicalStrike { } } } - - private static class SparseBitShiftingTwoLayerArray { - final long[][] cache; - final int shift; - final int secondLayerLength; - - SparseBitShiftingTwoLayerArray(final int size, final int shift) { - this.shift = shift; - this.cache = new long[1 << shift][]; - this.secondLayerLength = size >> shift; - } - - public long get(final int index) { - final int firstIndex = index >> shift; - final long[] firstLayerRow = cache[firstIndex]; - if (firstLayerRow == null) return 0L; - return firstLayerRow[index - (firstIndex * (1 << shift))]; - } - - public void put(final int index, final long value) { - final int firstIndex = index >> shift; - long[] firstLayerRow = cache[firstIndex]; - if (firstLayerRow == null) { - cache[firstIndex] = firstLayerRow = new long[secondLayerLength]; - } - firstLayerRow[index - (firstIndex * (1 << shift))] = value; - } - } } private static class GlyphAdvanceCache { private static final int FIRST_LAYER_SIZE = 256; - private static final int SECOND_LAYER_SIZE = 16384; // 16384 = 128x128 private final float[] firstLayerCache = new float[FIRST_LAYER_SIZE]; - private SparseBitShiftingTwoLayerArray secondLayerCache; private HashMap<Integer, Float> generalCache; public synchronized float get(final int index) { - if (index < 0) { - if (-index < SECOND_LAYER_SIZE) { - // catch common unicodes - if (secondLayerCache == null) return 0; - return secondLayerCache.get(-index); - } - } else { - if (index < FIRST_LAYER_SIZE) { - // catch common glyphcodes - return firstLayerCache[index]; - } + if (index < FIRST_LAYER_SIZE) { + // catch common glyphcodes + return firstLayerCache[index]; } if (generalCache == null) return 0; @@ -544,21 +473,10 @@ public final class CStrike extends PhysicalStrike { } public synchronized void put(final int index, final float value) { - if (index < 0) { - if (-index < SECOND_LAYER_SIZE) { - // catch common unicodes - if (secondLayerCache == null) { - secondLayerCache = new SparseBitShiftingTwoLayerArray(SECOND_LAYER_SIZE, 7); // 128x128 - } - secondLayerCache.put(-index, value); - return; - } - } else { - if (index < FIRST_LAYER_SIZE) { - // catch common glyphcodes - firstLayerCache[index] = value; - return; - } + if (index < FIRST_LAYER_SIZE) { + // catch common glyphcodes + firstLayerCache[index] = value; + return; } if (generalCache == null) { @@ -567,34 +485,5 @@ public final class CStrike extends PhysicalStrike { generalCache.put(Integer.valueOf(index), Float.valueOf(value)); } - - private static class SparseBitShiftingTwoLayerArray { - final float[][] cache; - final int shift; - final int secondLayerLength; - - SparseBitShiftingTwoLayerArray(final int size, final int shift) { - this.shift = shift; - this.cache = new float[1 << shift][]; - this.secondLayerLength = size >> shift; - } - - public float get(final int index) { - final int firstIndex = index >> shift; - final float[] firstLayerRow = cache[firstIndex]; - if (firstLayerRow == null) return 0L; - return firstLayerRow[index - (firstIndex * (1 << shift))]; - } - - public void put(final int index, final float value) { - final int firstIndex = index >> shift; - float[] firstLayerRow = cache[firstIndex]; - if (firstLayerRow == null) { - cache[firstIndex] = firstLayerRow = - new float[secondLayerLength]; - } - firstLayerRow[index - (firstIndex * (1 << shift))] = value; - } - } } } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CTextPipe.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CTextPipe.m index c95ea3822d2..12608a719ca 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CTextPipe.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CTextPipe.m @@ -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); } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m index 420b05c419b..68d537f6d8e 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m @@ -3341,6 +3341,64 @@ Java_sun_awt_FontDescriptor_initIDs } #endif +/* + * Class: sun_font_CFont + * Method: getCascadeList + * Signature: (JLjava/util/ArrayList;)V + */ +JNIEXPORT void JNICALL +Java_sun_font_CFont_getCascadeList + (JNIEnv *env, jclass cls, jlong awtFontPtr, jobject arrayListOfString) +{ +JNI_COCOA_ENTER(env); + jclass alc = (*env)->FindClass(env, "java/util/ArrayList"); + if (alc == NULL) return; + jmethodID addMID = (*env)->GetMethodID(env, alc, "add", "(Ljava/lang/Object;)Z"); + if (addMID == NULL) return; + + CFIndex i; + AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr); + NSFont* nsFont = awtFont->fFont; +#ifdef DEBUG + CFStringRef base = CTFontCopyFullName((CTFontRef)nsFont); + NSLog(@"BaseFont is : %@", (NSString*)base); + CFRelease(base); +#endif + bool anotherBaseFont = false; + if (awtFont->fFallbackBase != nil) { + nsFont = awtFont->fFallbackBase; + anotherBaseFont = true; + } + CTFontRef font = (CTFontRef)nsFont; + CFArrayRef codes = CFLocaleCopyISOLanguageCodes(); + + CFArrayRef fds = CTFontCopyDefaultCascadeListForLanguages(font, codes); + CFRelease(codes); + CFIndex cnt = CFArrayGetCount(fds); + for (i= anotherBaseFont ? -1 : 0; i<cnt; i++) { + CFStringRef fontname; + if (i < 0) { + fontname = CTFontCopyPostScriptName(font); + } else { + CTFontDescriptorRef ref = CFArrayGetValueAtIndex(fds, i); + fontname = CTFontDescriptorCopyAttribute(ref, kCTFontNameAttribute); + } +#ifdef DEBUG + NSLog(@"Font is : %@", (NSString*)fontname); +#endif + jstring jFontName = (jstring)NSStringToJavaString(env, fontname); + CFRelease(fontname); + (*env)->CallBooleanMethod(env, arrayListOfString, addMID, jFontName); + if ((*env)->ExceptionOccurred(env)) { + CFRelease(fds); + return; + } + (*env)->DeleteLocalRef(env, jFontName); + } + CFRelease(fds); +JNI_COCOA_EXIT(env); +} + static CFStringRef EMOJI_FONT_NAME = CFSTR("Apple Color Emoji"); bool IsEmojiFont(CTFontRef font) diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m index 89d779deb5d..dcd6bb275be 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m @@ -28,7 +28,6 @@ #import "sun_font_CStrikeDisposer.h" #import "CGGlyphImages.h" #import "CGGlyphOutlines.h" -#import "CoreTextSupport.h" #import "JNIUtilities.h" #include "fontscalerdefs.h" #import "LWCToolkit.h" @@ -160,12 +159,8 @@ JNI_COCOA_ENTER(env); AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr); AWTFont *awtFont = awtStrike->fAWTFont; - // negative glyph codes are really unicodes, which were placed there by the mapper - // to indicate we should use CoreText to substitute the character - CGGlyph glyph; - const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph); - CGGlyphImages_GetGlyphMetrics(fallback, &awtStrike->fAltTx, awtStrike->fSize, awtStrike->fStyle, &glyph, 1, NULL, &advance, IS_OSX_GT10_14); - CFRelease(fallback); + CGGlyph glyph = glyphCode; + CGGlyphImages_GetGlyphMetrics((CTFontRef)awtFont->fFont, &awtStrike->fAltTx, awtStrike->fSize, awtStrike->fStyle, &glyph, 1, NULL, &advance, IS_OSX_GT10_14); advance = CGSizeApplyAffineTransform(advance, awtStrike->fFontTx); if (!JRSFontStyleUsesFractionalMetrics(awtStrike->fStyle)) { advance.width = round(advance.width); @@ -195,14 +190,9 @@ JNI_COCOA_ENTER(env); tx.tx += x; tx.ty += y; - // negative glyph codes are really unicodes, which were placed there by the mapper - // to indicate we should use CoreText to substitute the character - CGGlyph glyph; - const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph); - + CGGlyph glyph = glyphCode; CGRect bbox; - CGGlyphImages_GetGlyphMetrics(fallback, &tx, awtStrike->fSize, awtStrike->fStyle, &glyph, 1, &bbox, NULL, IS_OSX_GT10_14); - CFRelease(fallback); + CGGlyphImages_GetGlyphMetrics((CTFontRef)awtFont->fFont, &tx, awtStrike->fSize, awtStrike->fStyle, &glyph, 1, &bbox, NULL, IS_OSX_GT10_14); // the origin of this bounding box is relative to the bottom-left corner baseline CGFloat decender = -bbox.origin.y; @@ -251,14 +241,12 @@ AWT_FONT_CLEANUP_CHECK(awtfont); tx.tx += xPos; tx.ty += yPos; - // get the right font and glyph for this "Java GlyphCode" - - CGGlyph glyph; - const CTFontRef font = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtfont, glyphCode, &glyph); + CGGlyph glyph = glyphCode; + NSFont *font = awtfont->fFont; // get the advance of this glyph CGSize advance; - CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, &glyph, &advance, 1); + CTFontGetAdvancesForGlyphs((CTFontRef)font, kCTFontDefaultOrientation, &glyph, &advance, 1); // Create AWTPath path = AWTPathCreate(CGSizeMake(xPos, yPos)); @@ -267,8 +255,7 @@ AWT_FONT_CLEANUP_CHECK(path); // Get the paths tx = awtStrike->fTx; tx = CGAffineTransformConcat(tx, sInverseTX); - AWTGetGlyphOutline(&glyph, (NSFont *)font, &advance, &tx, 0, 1, &path); - CFRelease(font); + AWTGetGlyphOutline(&glyph, font, &advance, &tx, 0, 1, &path); pointCoords = (*env)->NewFloatArray(env, path->fNumberOfDataElements); AWT_FONT_CLEANUP_CHECK(pointCoords); @@ -322,19 +309,14 @@ JNIEXPORT void JNICALL Java_sun_font_CStrike_getNativeGlyphOutlineBounds AWT_FONT_CLEANUP_SETUP; AWT_FONT_CLEANUP_CHECK(awtfont); - // get the right font and glyph for this "Java GlyphCode" - CGGlyph glyph; - const CTFontRef font = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode( - awtfont, glyphCode, &glyph); - + CGGlyph glyph = glyphCode; CGRect bbox = CTFontGetBoundingRectsForGlyphs( - font, kCTFontOrientationDefault, &glyph, NULL, 1); + (CTFontRef)awtfont->fFont, kCTFontOrientationDefault, &glyph, NULL, 1); CGAffineTransform tx = CGAffineTransformConcat(awtStrike->fTx, sInverseTX); bbox = CGRectApplyAffineTransform (bbox, tx); - CFRelease(font); jfloat *rawRectData = (*env)->GetPrimitiveArrayCritical(env, rectData, NULL); diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/CCharToGlyphMapper.m b/src/java.desktop/macosx/native/libawt_lwawt/font/CCharToGlyphMapper.m index 2178d888198..393d33bdbe6 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/CCharToGlyphMapper.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/CCharToGlyphMapper.m @@ -29,7 +29,6 @@ #import "CoreTextSupport.h" #import "sun_font_CCharToGlyphMapper.h" -#import "sun_font_CCompositeGlyphMapper.h" /* * Class: sun_font_CCharToGlyphMapper @@ -114,28 +113,3 @@ JNI_COCOA_ENTER(env); JNI_COCOA_EXIT(env); } - -/* - * Class: sun_font_CCompositeGlyphMapper - * Method: nativeCodePointToGlyph - * Signature: (JI[Ljava/lang/String;)I - */ -JNIEXPORT jint JNICALL -Java_sun_font_CCompositeGlyphMapper_nativeCodePointToGlyph -(JNIEnv *env, jclass clazz, jlong awtFontPtr, jint codePoint, jobjectArray resultArray) -{ -JNI_COCOA_ENTER(env); - AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr); - CFStringRef fontNames[] = {NULL, NULL}; - CGGlyph glyph = CTS_CopyGlyphAndFontNamesForCodePoint(awtFont, (UnicodeScalarValue)codePoint, fontNames); - if (glyph > 0) { - jstring fontName = NSStringToJavaString(env, (NSString *)fontNames[0]); - (*env)->SetObjectArrayElement(env, resultArray, 0, fontName); - jstring fontFamilyName = NSStringToJavaString(env, (NSString *)fontNames[1]); - (*env)->SetObjectArrayElement(env, resultArray, 1, fontFamilyName); - } - if (fontNames[0]) CFRelease(fontNames[0]); - if (fontNames[1]) CFRelease(fontNames[1]); - return glyph; -JNI_COCOA_EXIT(env); -} diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m b/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m index 8cfa979a79e..4b591f5f5c8 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m @@ -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" @@ -739,78 +738,6 @@ CGGI_CreateImageForGlyph /* * CoreText path... */ -static inline GlyphInfo * -CGGI_CreateImageForUnicode - (CGGI_GlyphCanvas *canvas, const AWTStrike *strike, - const CGGI_RenderingMode *mode, const UnicodeScalarValue uniChar, - const bool isCatalinaOrAbove) -{ - // save the graphics state - CGContextSaveGState(canvas->context); - // text matrix is not considered part of graphics state - CGAffineTransform originalTx = CGContextGetTextMatrix(canvas->context); - - // get the glyph, measure it using CG - CGGlyph glyph; - CTFontRef fallback; - if (uniChar > 0xFFFF) { - UTF16Char charRef[2]; - CTS_BreakupUnicodeIntoSurrogatePairs(uniChar, charRef); - CGGlyph glyphTmp[2]; - fallback = CTS_CopyCTFallbackFontAndGlyphForUnicode(strike->fAWTFont, (const UTF16Char *)&charRef, (CGGlyph *)&glyphTmp, 2); - glyph = glyphTmp[0]; - } else { - UTF16Char charRef; - charRef = (UTF16Char) uniChar; // truncate. - fallback = CTS_CopyCTFallbackFontAndGlyphForUnicode(strike->fAWTFont, (const UTF16Char *)&charRef, &glyph, 1); - } - - JRSFontRenderingStyle style = JRSFontAlignStyleForFractionalMeasurement(strike->fStyle); - - CGGI_GlyphInfoDescriptor *glyphDescriptor = CGGI_GetGlyphInfoDescriptor(mode, fallback); - - bool subpixelResolution = mode->subpixelResolution && glyphDescriptor == &grey; - - CGRect bbox; - CGSize advance; - CGGlyphImages_GetGlyphMetrics(fallback, &strike->fTx, strike->fSize, style, &glyph, 1, &bbox, &advance, isCatalinaOrAbove); - - - // create the Sun2D GlyphInfo we are going to strike into - GlyphInfo *info = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, glyphDescriptor, subpixelResolution); - - // fix the context size, just in case the substituted character is unexpectedly large - CGGI_SizeCanvas(canvas, info->width * info->subpixelResolutionX, info->height * info->subpixelResolutionY, mode); - - // align the transform for the real CoreText strike - CGContextSetTextMatrix(canvas->context, strike->fAltTx); - - const CGFontRef cgFallback = CTFontCopyGraphicsFont(fallback, NULL); - CGContextSetFont(canvas->context, cgFallback); - CFRelease(cgFallback); - - // clean the canvas - align, strike, and copy the glyph from the canvas into the info - CGGI_CreateImageForGlyph(canvas, glyph, info, glyphDescriptor, strike, fallback, isCatalinaOrAbove); - - // restore graphics state - CGContextRestoreGState(canvas->context); - CGContextSetTextMatrix(canvas->context, originalTx); - - CFRelease(fallback); -#ifdef CGGI_DEBUG - DUMP_GLYPHINFO(info); -#endif - -#ifdef CGGI_DEBUG_DUMP - DUMP_IMG_PIXELS("CGGI Canvas", canvas->image); -#if 0 - PRINT_CGSTATES_INFO(NULL); -#endif -#endif - - return info; -} - #pragma mark --- GlyphInfo Filling and Canvas Managment --- @@ -825,7 +752,6 @@ CGGI_FillImagesForGlyphsWithSizedCanvas(CGGI_GlyphCanvas *canvas, const AWTStrike *strike, const CGGI_RenderingMode *mode, jlong glyphInfos[], - const UnicodeScalarValue uniChars[], const CGGlyph glyphs[], const CFIndex len) { @@ -838,13 +764,8 @@ CGGI_FillImagesForGlyphsWithSizedCanvas(CGGI_GlyphCanvas *canvas, CFIndex i; for (i = 0; i < len; i++) { GlyphInfo *info = (GlyphInfo *)jlong_to_ptr(glyphInfos[i]); - if (info != NULL) { - CGGI_CreateImageForGlyph(canvas, glyphs[i], info, mode->mainFontDescriptor, - strike, (CTFontRef)strike->fAWTFont->fFont, isMojaveOrAbove); - } else { - info = CGGI_CreateImageForUnicode(canvas, strike, mode, uniChars[i], isMojaveOrAbove); - glyphInfos[i] = ptr_to_jlong(info); - } + CGGI_CreateImageForGlyph(canvas, glyphs[i], info, mode->mainFontDescriptor, + strike, (CTFontRef)strike->fAWTFont->fFont, isMojaveOrAbove); #ifdef CGGI_DEBUG DUMP_GLYPHINFO(info); #endif @@ -879,7 +800,7 @@ static NSString *threadLocalLCDCanvasKey = static inline void CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike, const CGGI_RenderingMode *mode, - const UnicodeScalarValue uniChars[], const CGGlyph glyphs[], + const CGGlyph glyphs[], const size_t maxWidth, const size_t maxHeight, const CFIndex len) { @@ -889,8 +810,7 @@ CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike, CGGI_GlyphCanvas *tmpCanvas = [[CGGI_GlyphCanvas alloc] init]; CGGI_InitCanvas(tmpCanvas, maxWidth, maxHeight, mode); CGGI_FillImagesForGlyphsWithSizedCanvas(tmpCanvas, strike, - mode, glyphInfos, uniChars, - glyphs, len); + mode, glyphInfos, glyphs, len); CGGI_FreeCanvas(tmpCanvas); [tmpCanvas release]; @@ -910,7 +830,7 @@ CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike, CGGI_SizeCanvas(canvas, maxWidth, maxHeight, mode); CGGI_FillImagesForGlyphsWithSizedCanvas(canvas, strike, mode, - glyphInfos, uniChars, glyphs, len); + glyphInfos, glyphs, len); } /* @@ -926,7 +846,7 @@ CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike, static inline void CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike, const CGGI_RenderingMode *mode, - const UnicodeScalarValue uniChars[], const CGGlyph glyphs[], + const CGGlyph glyphs[], CGSize advances[], CGRect bboxes[], const CFIndex len) { AWTFont *font = strike->fAWTFont; @@ -941,12 +861,6 @@ CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike, CFIndex i; for (i = 0; i < len; i++) { - if (uniChars[i] != 0) - { - glyphInfos[i] = 0L; - continue; // will be handled later - } - CGSize advance = advances[i]; CGRect bbox = bboxes[i]; @@ -963,41 +877,29 @@ CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike, glyphInfos[i] = ptr_to_jlong(glyphInfo); } - CGGI_FillImagesForGlyphs(glyphInfos, strike, mode, uniChars, + CGGI_FillImagesForGlyphs(glyphInfos, strike, mode, glyphs, maxWidth, maxHeight, len); } #pragma mark --- Temporary Buffer Allocations and Initialization --- -/* - * This stage separates the already valid glyph codes from the unicode values - * that need special handling - the rawGlyphCodes array is no longer used - * after this stage. - */ static void -CGGI_CreateGlyphsAndScanForComplexities(jlong *glyphInfos, - const AWTStrike *strike, - const CGGI_RenderingMode *mode, - jint rawGlyphCodes[], - UnicodeScalarValue uniChars[], CGGlyph glyphs[], - CGSize advances[], CGRect bboxes[], - const CFIndex len) +CGGI_CreateGlyphs(jlong *glyphInfos, + const AWTStrike *strike, + const CGGI_RenderingMode *mode, + jint rawGlyphCodes[], + CGGlyph glyphs[], + CGSize advances[], CGRect bboxes[], + const CFIndex len) { CFIndex i; for (i = 0; i < len; i++) { - jint code = rawGlyphCodes[i]; - if (code < 0) { - glyphs[i] = 0; - uniChars[i] = -code; - } else { - glyphs[i] = code; - uniChars[i] = 0; - } + glyphs[i] = rawGlyphCodes[i]; } CGGI_CreateGlyphInfos(glyphInfos, strike, mode, - uniChars, glyphs, advances, bboxes, len); + glyphs, advances, bboxes, len); #ifdef CGGI_DEBUG_HIT_COUNT static size_t hitCount = 0; @@ -1023,31 +925,29 @@ CGGlyphImages_GetGlyphImagePtrs(jlong glyphInfos[], CGRect bboxes[len]; CGSize advances[len]; CGGlyph glyphs[len]; - UnicodeScalarValue uniChars[len]; - CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode, - rawGlyphCodes, uniChars, glyphs, - advances, bboxes, len); + CGGI_CreateGlyphs(glyphInfos, strike, &mode, + rawGlyphCodes, glyphs, + advances, bboxes, len); return; } // just do one malloc, and carve it up for all the buffers - void *buffer = malloc(sizeof(CGRect) * sizeof(CGSize) * - sizeof(CGGlyph) * sizeof(UnicodeScalarValue) * len); + void *buffer = malloc((sizeof(CGRect) + sizeof(CGSize) + sizeof(CGGlyph)) * + len); if (buffer == NULL) { [[NSException exceptionWithName:NSMallocException reason:@"Failed to allocate memory for the temporary glyph strike and measurement buffers." userInfo:nil] raise]; } CGRect *bboxes = (CGRect *)(buffer); - CGSize *advances = (CGSize *)(bboxes + sizeof(CGRect) * len); - CGGlyph *glyphs = (CGGlyph *)(advances + sizeof(CGGlyph) * len); - UnicodeScalarValue *uniChars = (UnicodeScalarValue *)(glyphs + sizeof(UnicodeScalarValue) * len); + CGSize *advances = (CGSize *)(bboxes + len); + CGGlyph *glyphs = (CGGlyph *)(advances + len); - CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode, - rawGlyphCodes, uniChars, glyphs, - advances, bboxes, len); + CGGI_CreateGlyphs(glyphInfos, strike, &mode, + rawGlyphCodes, glyphs, + advances, bboxes, len); free(buffer); } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/CoreTextSupport.h b/src/java.desktop/macosx/native/libawt_lwawt/font/CoreTextSupport.h index 27a09fccba3..d3fe1268620 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/CoreTextSupport.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/CoreTextSupport.h @@ -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 { diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/CoreTextSupport.m b/src/java.desktop/macosx/native/libawt_lwawt/font/CoreTextSupport.m index 7583fabd9f2..567ea866d5b 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/CoreTextSupport.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/CoreTextSupport.m @@ -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); -} - -/* - * 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; - } + CTFontGetGlyphsForCharacters((CTFontRef)font->fFont, unicodes, glyphs, count); - 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; -} diff --git a/src/java.desktop/share/classes/java/awt/Font.java b/src/java.desktop/share/classes/java/awt/Font.java index 98b83edd97a..7259613bf54 100644 --- a/src/java.desktop/share/classes/java/awt/Font.java +++ b/src/java.desktop/share/classes/java/awt/Font.java @@ -67,6 +67,7 @@ import sun.font.FontDesignMetrics; import sun.font.FontLineMetrics; import sun.font.FontManager; import sun.font.FontManagerFactory; +import sun.font.FontSubstitution; import sun.font.FontUtilities; import sun.font.GlyphLayout; import sun.font.StandardGlyphVector; @@ -266,6 +267,11 @@ public class Font implements java.io.Serializable return font.getFont2D(); } + @Override + public Font2D getFont2DWithSubstitution(Font font) { + return font.getFont2DWithSubstitution(); + } + public void setFont2D(Font font, Font2DHandle handle) { font.font2DHandle = handle; } @@ -537,6 +543,11 @@ public class Font implements java.io.Serializable return font2DHandle.font2D; } + private Font2D getFont2DWithSubstitution() { + Font2D font2D = getFont2D(); + return font2D instanceof FontSubstitution ? ((FontSubstitution) font2D).getCompositeFont2D() : font2D; + } + /** * Creates a new {@code Font} from the specified name, style and * point size. @@ -2223,7 +2234,7 @@ public class Font implements java.io.Serializable * @since 1.2 */ public boolean canDisplay(char c){ - return getFont2D().canDisplay(c); + return getFont2DWithSubstitution().canDisplay(c); } /** @@ -2244,7 +2255,7 @@ public class Font implements java.io.Serializable throw new IllegalArgumentException("invalid code point: " + Integer.toHexString(codePoint)); } - return getFont2D().canDisplay(codePoint); + return getFont2DWithSubstitution().canDisplay(codePoint); } /** @@ -2265,7 +2276,7 @@ public class Font implements java.io.Serializable * @since 1.2 */ public int canDisplayUpTo(String str) { - Font2D font2d = getFont2D(); + Font2D font2d = getFont2DWithSubstitution(); int len = str.length(); for (int i = 0; i < len; i++) { char c = str.charAt(i); @@ -2303,7 +2314,7 @@ public class Font implements java.io.Serializable * @since 1.2 */ public int canDisplayUpTo(char[] text, int start, int limit) { - Font2D font2d = getFont2D(); + Font2D font2d = getFont2DWithSubstitution(); for (int i = start; i < limit; i++) { char c = text[i]; if (font2d.canDisplay(c)) { @@ -2338,7 +2349,7 @@ public class Font implements java.io.Serializable * @since 1.2 */ public int canDisplayUpTo(CharacterIterator iter, int start, int limit) { - Font2D font2d = getFont2D(); + Font2D font2d = getFont2DWithSubstitution(); char c = iter.setIndex(start); for (int i = start; i < limit; i++, c = iter.next()) { if (font2d.canDisplay(c)) { diff --git a/src/java.desktop/share/classes/sun/font/CompositeFont.java b/src/java.desktop/share/classes/sun/font/CompositeFont.java index 5473ea98f22..bc136d75cfa 100644 --- a/src/java.desktop/share/classes/sun/font/CompositeFont.java +++ b/src/java.desktop/share/classes/sun/font/CompositeFont.java @@ -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; diff --git a/src/java.desktop/share/classes/sun/font/CompositeGlyphMapper.java b/src/java.desktop/share/classes/sun/font/CompositeGlyphMapper.java index 9db3ddfcee8..6be4b353603 100644 --- a/src/java.desktop/share/classes/sun/font/CompositeGlyphMapper.java +++ b/src/java.desktop/share/classes/sun/font/CompositeGlyphMapper.java @@ -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)) { diff --git a/src/java.desktop/share/classes/sun/font/Font2D.java b/src/java.desktop/share/classes/sun/font/Font2D.java index 4de9ad268d3..5a066811cb0 100644 --- a/src/java.desktop/share/classes/sun/font/Font2D.java +++ b/src/java.desktop/share/classes/sun/font/Font2D.java @@ -335,7 +335,7 @@ public abstract class Font2D { return getStrike(desc, true); } - FontStrike getStrike(FontStrikeDesc desc, boolean copy) { + private FontStrike getStrike(FontStrikeDesc desc, boolean copy) { /* Before looking in the map, see if the descriptor matches the * last strike returned from this Font2D. This should often be a win * since its common for the same font, in the same size to be diff --git a/src/java.desktop/share/classes/sun/font/FontAccess.java b/src/java.desktop/share/classes/sun/font/FontAccess.java index c51077e0533..895cbb53a95 100644 --- a/src/java.desktop/share/classes/sun/font/FontAccess.java +++ b/src/java.desktop/share/classes/sun/font/FontAccess.java @@ -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); diff --git a/src/java.desktop/share/classes/sun/font/FontDesignMetrics.java b/src/java.desktop/share/classes/sun/font/FontDesignMetrics.java index b024514ab47..c6c4d2a7678 100644 --- a/src/java.desktop/share/classes/sun/font/FontDesignMetrics.java +++ b/src/java.desktop/share/classes/sun/font/FontDesignMetrics.java @@ -356,7 +356,7 @@ public final class FontDesignMetrics extends FontMetrics { private void initMatrixAndMetrics() { - Font2D font2D = FontUtilities.getFont2D(font); + Font2D font2D = FontUtilities.getFont2DWithSubstitution(font); fontStrike = font2D.getStrike(font, frc); StrikeMetrics metrics = fontStrike.getFontMetrics(); this.ascent = metrics.getAscent(); diff --git a/src/java.desktop/share/classes/sun/font/FontFamily.java b/src/java.desktop/share/classes/sun/font/FontFamily.java index bbe6a997a51..d3ce74b104f 100644 --- a/src/java.desktop/share/classes/sun/font/FontFamily.java +++ b/src/java.desktop/share/classes/sun/font/FontFamily.java @@ -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(); diff --git a/src/java.desktop/share/classes/sun/font/FontUtilities.java b/src/java.desktop/share/classes/sun/font/FontUtilities.java index f10084d6078..de21a227a3d 100644 --- a/src/java.desktop/share/classes/sun/font/FontUtilities.java +++ b/src/java.desktop/share/classes/sun/font/FontUtilities.java @@ -168,6 +168,10 @@ public final class FontUtilities { return FontAccess.getFontAccess().getFont2D(font); } + public static Font2D getFont2DWithSubstitution(Font font) { + return FontAccess.getFontAccess().getFont2DWithSubstitution(font); + } + /** * Return true if there any characters which would trigger layout. * This method considers supplementary characters to be simple, diff --git a/src/java.desktop/share/classes/sun/font/FontWithDerivedItalic.java b/src/java.desktop/share/classes/sun/font/FontWithDerivedItalic.java index 7d506a66920..9cc8a60b94a 100644 --- a/src/java.desktop/share/classes/sun/font/FontWithDerivedItalic.java +++ b/src/java.desktop/share/classes/sun/font/FontWithDerivedItalic.java @@ -1,5 +1,5 @@ package sun.font; interface FontWithDerivedItalic { - Font2D createItalic(); + Font2D createItalicVariant(); }
\ No newline at end of file diff --git a/src/java.desktop/share/classes/sun/font/GlyphLayout.java b/src/java.desktop/share/classes/sun/font/GlyphLayout.java index 966910db529..018d67dd92b 100644 --- a/src/java.desktop/share/classes/sun/font/GlyphLayout.java +++ b/src/java.desktop/share/classes/sun/font/GlyphLayout.java @@ -410,10 +410,7 @@ public final class GlyphLayout { int lang = -1; // default for now - Font2D font2D = FontUtilities.getFont2D(font); - if (font2D instanceof FontSubstitution) { - font2D = ((FontSubstitution)font2D).getCompositeFont2D(); - } + Font2D font2D = FontUtilities.getFont2DWithSubstitution(font); _textRecord.init(text, offset, lim, min, max); int start = offset; diff --git a/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java b/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java index 41097272896..d2843c1c2ea 100644 --- a/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java +++ b/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java @@ -197,8 +197,7 @@ public class StandardGlyphVector extends GlyphVector { // how do we know its a base glyph // for now, it is if the natural advance of the glyph is non-zero - Font2D f2d = FontUtilities.getFont2D(font); - FontStrike strike = f2d.getStrike(font, frc); + FontStrike strike = font2D.getStrike(font, frc); float[] deltas = { trackPt.x, trackPt.y }; for (int j = 0; j < deltas.length; ++j) { @@ -1106,10 +1105,7 @@ public class StandardGlyphVector extends GlyphVector { } private void initFontData() { - font2D = FontUtilities.getFont2D(font); - if (font2D instanceof FontSubstitution) { - font2D = ((FontSubstitution)font2D).getCompositeFont2D(); - } + font2D = FontUtilities.getFont2DWithSubstitution(font); float s = font.getSize2D(); if (font.isTransformed()) { ftx = font.getTransform(); @@ -1728,12 +1724,7 @@ public class StandardGlyphVector extends GlyphVector { aa, fm); // Get the strike via the handle. Shouldn't matter // if we've invalidated the font but its an extra precaution. - // do we want the CompFont from CFont here ? - Font2D f2d = sgv.font2D; - if (f2d instanceof FontSubstitution) { - f2d = ((FontSubstitution)f2d).getCompositeFont2D(); - } - FontStrike strike = f2d.handle.font2D.getStrike(desc); // !!! getStrike(desc, false) + FontStrike strike = sgv.font2D.handle.font2D.getStrike(desc); // !!! getStrike(desc, false) return new GlyphStrike(sgv, strike, dx, dy); } diff --git a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java index 49905d33cab..158aff53a34 100644 --- a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java +++ b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java @@ -670,7 +670,7 @@ public final class SunGraphics2D info.nonInvertibleTx = (Math.abs(textAt.getDeterminant()) <= Double.MIN_VALUE); - info.font2D = FontUtilities.getFont2D(font); + info.font2D = FontUtilities.getFont2DWithSubstitution(font); int fmhint = fractionalMetricsHint; if (fmhint == SunHints.INTVAL_FRACTIONALMETRICS_DEFAULT) { diff --git a/src/java.desktop/share/classes/sun/print/PathGraphics.java b/src/java.desktop/share/classes/sun/print/PathGraphics.java index 1fbd7fa68d6..f50aeaf3807 100644 --- a/src/java.desktop/share/classes/sun/print/PathGraphics.java +++ b/src/java.desktop/share/classes/sun/print/PathGraphics.java @@ -698,7 +698,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { } Font font = g.getFont(); - Font2D font2D = FontUtilities.getFont2D(font); + Font2D font2D = FontUtilities.getFont2DWithSubstitution(font); if (font2D.handle.font2D != font2D) { /* suspicious, may be a bad font. lets bail */ return false; |