7162125: [macosx] A font has different behaviour for ligatures depending on its creation mod
Reviewed-by: srl, jgodinez
This commit is contained in:
parent
7d7c956397
commit
8b00726f06
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.font;
|
||||
|
||||
public final class CCompositeGlyphMapper extends CompositeGlyphMapper {
|
||||
|
||||
private CompositeFont font;
|
||||
private CharToGlyphMapper slotMappers[];
|
||||
|
||||
public CCompositeGlyphMapper(CompositeFont compFont) {
|
||||
super(compFont);
|
||||
font = compFont;
|
||||
slotMappers = new CharToGlyphMapper[font.numSlots];
|
||||
missingGlyph = 0;
|
||||
}
|
||||
|
||||
private CharToGlyphMapper getSlotMapper(int slot) {
|
||||
CharToGlyphMapper mapper = slotMappers[slot];
|
||||
if (mapper == null) {
|
||||
mapper = font.getSlotFont(slot).getMapper();
|
||||
slotMappers[slot] = mapper;
|
||||
}
|
||||
return mapper;
|
||||
}
|
||||
|
||||
public boolean canDisplay(char ch) {
|
||||
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;
|
||||
}
|
||||
|
||||
public void charsToGlyphs(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] = convertToGlyph(code);
|
||||
i += 1; // Empty glyph slot after surrogate
|
||||
glyphs[i] = INVISIBLE_GLYPH_ID;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
glyphs[i] = convertToGlyph(code);
|
||||
}
|
||||
}
|
||||
|
||||
public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) {
|
||||
for (int i=0; i<count; i++) {
|
||||
glyphs[i] = convertToGlyph(unicodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -31,12 +31,13 @@ import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.ArrayList;
|
||||
|
||||
// Right now this class is final to avoid a problem with native code.
|
||||
// For some reason the JNI IsInstanceOf was not working correctly
|
||||
// so we are checking the class specifically. If we subclass this
|
||||
// we need to modify the native code in CFontWrapper.m
|
||||
public final class CFont extends PhysicalFont {
|
||||
public final class CFont extends PhysicalFont implements FontSubstitution {
|
||||
|
||||
/* CFontStrike doesn't call these methods so they are unimplemented.
|
||||
* They are here to meet the requirements of PhysicalFont, needed
|
||||
@ -76,6 +77,20 @@ public final class CFont extends PhysicalFont {
|
||||
throw new InternalError("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getLayoutTableCache() {
|
||||
return getLayoutTableCacheNative(getNativeFontPtr());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getTableBytes(int tag) {
|
||||
return getTableBytesNative(getNativeFontPtr(), tag);
|
||||
}
|
||||
|
||||
private native synchronized long getLayoutTableCacheNative(long nativeFontPtr);
|
||||
|
||||
private native byte[] getTableBytesNative(long nativeFontPtr, int tag);
|
||||
|
||||
private static native long createNativeFont(final String nativeFontName,
|
||||
final int style);
|
||||
private static native void disposeNativeFont(final long nativeFontPtr);
|
||||
@ -179,10 +194,51 @@ public final class CFont extends PhysicalFont {
|
||||
protected synchronized long getNativeFontPtr() {
|
||||
if (nativeFontPtr == 0L) {
|
||||
nativeFontPtr = createNativeFont(nativeFontName, style);
|
||||
}
|
||||
}
|
||||
return nativeFontPtr;
|
||||
}
|
||||
|
||||
static native void getCascadeList(long nativeFontPtr, ArrayList<String> listOfString);
|
||||
|
||||
private CompositeFont createCompositeFont() {
|
||||
ArrayList<String> listOfString = new ArrayList<String>();
|
||||
getCascadeList(nativeFontPtr, listOfString);
|
||||
|
||||
FontManager fm = FontManagerFactory.getInstance();
|
||||
int numFonts = 1 + listOfString.size();
|
||||
PhysicalFont[] fonts = new PhysicalFont[numFonts];
|
||||
fonts[0] = this;
|
||||
int idx = 1;
|
||||
for (String s : listOfString) {
|
||||
if (s.equals(".AppleSymbolsFB")) {
|
||||
// Don't know why we get the weird name above .. replace.
|
||||
s = "AppleSymbols";
|
||||
}
|
||||
Font2D f2d = fm.findFont2D(s, Font.PLAIN, FontManager.NO_FALLBACK);
|
||||
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;
|
||||
|
||||
public CompositeFont getCompositeFont2D() {
|
||||
if (compFont == null) {
|
||||
compFont = createCompositeFont();
|
||||
}
|
||||
return compFont;
|
||||
}
|
||||
|
||||
protected synchronized void finalize() {
|
||||
if (nativeFontPtr != 0) {
|
||||
disposeNativeFont(nativeFontPtr);
|
||||
|
@ -31,7 +31,7 @@ import java.util.*;
|
||||
|
||||
import sun.awt.SunHints;
|
||||
|
||||
public final class CStrike extends FontStrike {
|
||||
public final class CStrike extends PhysicalStrike {
|
||||
|
||||
// Creates the native strike
|
||||
private static native long createNativeStrikePtr(long nativeFontPtr,
|
||||
|
@ -26,6 +26,8 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <JavaRuntimeSupport/JavaRuntimeSupport.h>
|
||||
|
||||
#import "fontscalerdefs.h"
|
||||
|
||||
#define MAX_STACK_ALLOC_GLYPH_BUFFER_SIZE 256
|
||||
|
||||
@interface AWTFont : NSObject {
|
||||
@ -33,6 +35,7 @@
|
||||
NSFont *fFont;
|
||||
CGFontRef fNativeCGFont;
|
||||
BOOL fIsFakeItalic;
|
||||
TTLayoutTableCache* layoutTableCache;
|
||||
}
|
||||
|
||||
+ (AWTFont *) awtFontForName:(NSString *)name
|
||||
|
@ -42,10 +42,33 @@
|
||||
if (self) {
|
||||
fFont = [font retain];
|
||||
fNativeCGFont = CTFontCopyGraphicsFont((CTFontRef)font, NULL);
|
||||
layoutTableCache = NULL;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static TTLayoutTableCache* newCFontLayoutTableCache() {
|
||||
TTLayoutTableCache* ltc = calloc(1, sizeof(TTLayoutTableCache));
|
||||
if (ltc) {
|
||||
int i;
|
||||
for(i=0;i<LAYOUTCACHE_ENTRIES;i++) {
|
||||
ltc->entries[i].len = -1;
|
||||
}
|
||||
}
|
||||
return ltc;
|
||||
}
|
||||
|
||||
static void freeCFontLayoutTableCache(TTLayoutTableCache* ltc) {
|
||||
if (ltc) {
|
||||
int i;
|
||||
for(i=0;i<LAYOUTCACHE_ENTRIES;i++) {
|
||||
if(ltc->entries[i].ptr) free (ltc->entries[i].ptr);
|
||||
}
|
||||
if (ltc->kernPairs) free(ltc->kernPairs);
|
||||
free(ltc);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) dealloc {
|
||||
[fFont release];
|
||||
fFont = nil;
|
||||
@ -53,6 +76,10 @@
|
||||
if (fNativeCGFont) {
|
||||
CGFontRelease(fNativeCGFont);
|
||||
fNativeCGFont = NULL;
|
||||
if (layoutTableCache != NULL) {
|
||||
freeCFontLayoutTableCache(layoutTableCache);
|
||||
layoutTableCache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
[super dealloc];
|
||||
@ -63,6 +90,10 @@
|
||||
CGFontRelease(fNativeCGFont);
|
||||
fNativeCGFont = NULL;
|
||||
}
|
||||
if (layoutTableCache != NULL) {
|
||||
freeCFontLayoutTableCache(layoutTableCache);
|
||||
layoutTableCache = NULL;
|
||||
}
|
||||
[super finalize];
|
||||
}
|
||||
|
||||
@ -343,6 +374,95 @@ JNF_COCOA_EXIT(env);
|
||||
|
||||
#pragma mark --- sun.font.CFont JNI ---
|
||||
|
||||
/*
|
||||
* Class: sun_font_CFont
|
||||
* Method: getPlatformFontPtrNative
|
||||
* Signature: (JI)[B
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_font_CFont_getCGFontPtrNative
|
||||
(JNIEnv *env, jclass clazz,
|
||||
jlong awtFontPtr)
|
||||
{
|
||||
AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
|
||||
return (jlong)(awtFont->fNativeCGFont);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_font_CFont
|
||||
* Method: getLayoutTableCacheNative
|
||||
* Signature: (J)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_font_CFont_getLayoutTableCacheNative
|
||||
(JNIEnv *env, jclass clazz,
|
||||
jlong awtFontPtr)
|
||||
{
|
||||
AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
|
||||
if (awtFont->layoutTableCache == NULL) {
|
||||
awtFont->layoutTableCache = newCFontLayoutTableCache();
|
||||
}
|
||||
return (jlong)(awtFont->layoutTableCache);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_font_CFont
|
||||
* Method: getTableBytesNative
|
||||
* Signature: (JI)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_sun_font_CFont_getTableBytesNative
|
||||
(JNIEnv *env, jclass clazz,
|
||||
jlong awtFontPtr, jint jtag)
|
||||
{
|
||||
jbyteArray jbytes = NULL;
|
||||
JNF_COCOA_ENTER(env);
|
||||
|
||||
CTFontTableTag tag = (CTFontTableTag)jtag;
|
||||
int i, found = 0;
|
||||
AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
|
||||
NSFont* nsFont = awtFont->fFont;
|
||||
CTFontRef ctfont = (CTFontRef)nsFont;
|
||||
CFArrayRef tagsArray =
|
||||
CTFontCopyAvailableTables(ctfont, kCTFontTableOptionNoOptions);
|
||||
CFIndex numTags = CFArrayGetCount(tagsArray);
|
||||
for (i=0; i<numTags; i++) {
|
||||
if (tag ==
|
||||
(CTFontTableTag)(uintptr_t)CFArrayGetValueAtIndex(tagsArray, i)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CFRelease(tagsArray);
|
||||
if (!found) {
|
||||
return NULL;
|
||||
}
|
||||
CFDataRef table = CTFontCopyTable(ctfont, tag, kCTFontTableOptionNoOptions);
|
||||
if (table == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *tableBytes = (char*)(CFDataGetBytePtr(table));
|
||||
size_t tableLength = CFDataGetLength(table);
|
||||
if (tableBytes == NULL || tableLength == 0) {
|
||||
CFRelease(table);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jbytes = (*env)->NewByteArray(env, (jsize)tableLength);
|
||||
if (jbytes == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
(*env)->SetByteArrayRegion(env, jbytes, 0,
|
||||
(jsize)tableLength,
|
||||
(jbyte*)tableBytes);
|
||||
CFRelease(table);
|
||||
|
||||
JNF_COCOA_EXIT(env);
|
||||
|
||||
return jbytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_font_CFont
|
||||
* Method: initNativeFont
|
||||
@ -460,3 +580,42 @@ Java_sun_awt_FontDescriptor_initIDs
|
||||
{
|
||||
}
|
||||
#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)
|
||||
{
|
||||
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;
|
||||
CFStringRef base = CTFontCopyFullName(font);
|
||||
CFArrayRef codes = CFLocaleCopyISOLanguageCodes();
|
||||
|
||||
#ifdef DEBUG
|
||||
NSLog(@"BaseFont is : %@", (NSString*)base);
|
||||
#endif
|
||||
CFArrayRef fds = CTFontCopyDefaultCascadeListForLanguages(font, 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)JNFNSToJavaString(env, fontname);
|
||||
(*env)->CallBooleanMethod(env, arrayListOfString, addMID, jFontName);
|
||||
(*env)->DeleteLocalRef(env, jFontName);
|
||||
}
|
||||
}
|
||||
|
@ -149,6 +149,25 @@ public final class CompositeFont extends Font2D {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Build a composite from a set of individual slot fonts.
|
||||
*/
|
||||
CompositeFont(PhysicalFont[] slotFonts) {
|
||||
|
||||
isStdComposite = false;
|
||||
handle = new Font2DHandle(this);
|
||||
fullName = slotFonts[0].fullName;
|
||||
familyName = slotFonts[0].familyName;
|
||||
style = slotFonts[0].style;
|
||||
|
||||
numMetricsSlots = 1; /* Only the physical Font */
|
||||
numSlots = slotFonts.length;
|
||||
|
||||
components = new PhysicalFont[numSlots];
|
||||
System.arraycopy(slotFonts, 0, components, 0, numSlots);
|
||||
deferredInitialisation = new boolean[numSlots]; // all false.
|
||||
}
|
||||
|
||||
/* This method is currently intended to be called only from
|
||||
* FontManager.getCompositeFontUIResource(Font)
|
||||
* It creates a new CompositeFont with the contents of the Physical
|
||||
|
@ -42,7 +42,7 @@ package sun.font;
|
||||
* this appears to cause problems.
|
||||
*/
|
||||
|
||||
public final class CompositeGlyphMapper extends CharToGlyphMapper {
|
||||
public class CompositeGlyphMapper extends CharToGlyphMapper {
|
||||
|
||||
public static final int SLOTMASK = 0xff000000;
|
||||
public static final int GLYPHMASK = 0x00ffffff;
|
||||
|
@ -461,10 +461,17 @@ public abstract class Font2D {
|
||||
* to check the font class before attempting to run, rather than needing
|
||||
* to promote this method up from TrueTypeFont
|
||||
*/
|
||||
byte[] getTableBytes(int tag) {
|
||||
protected byte[] getTableBytes(int tag) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* implemented for fonts backed by an sfnt that has
|
||||
* OpenType or AAT layout tables.
|
||||
*/
|
||||
protected long getLayoutTableCache() {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
/* for layout code */
|
||||
protected long getUnitsPerEm() {
|
||||
return 2048;
|
||||
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.font;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface that indicates a Font2D that is not a Composite but has the
|
||||
* property that it internally behaves like one, substituting glyphs
|
||||
* from another font at render time.
|
||||
* In this case the Font must provide a way to behave like a regular
|
||||
* composite when that behaviour is not wanted.
|
||||
*/
|
||||
public interface FontSubstitution {
|
||||
public CompositeFont getCompositeFont2D();
|
||||
}
|
@ -408,6 +408,9 @@ public final class GlyphLayout {
|
||||
int lang = -1; // default for now
|
||||
|
||||
Font2D font2D = FontUtilities.getFont2D(font);
|
||||
if (font2D instanceof FontSubstitution) {
|
||||
font2D = ((FontSubstitution)font2D).getCompositeFont2D();
|
||||
}
|
||||
|
||||
_textRecord.init(text, offset, lim, min, max);
|
||||
int start = offset;
|
||||
|
@ -1124,6 +1124,9 @@ public class StandardGlyphVector extends GlyphVector {
|
||||
|
||||
private void initFontData() {
|
||||
font2D = FontUtilities.getFont2D(font);
|
||||
if (font2D instanceof FontSubstitution) {
|
||||
font2D = ((FontSubstitution)font2D).getCompositeFont2D();
|
||||
}
|
||||
float s = font.getSize2D();
|
||||
if (font.isTransformed()) {
|
||||
ftx = font.getTransform();
|
||||
@ -1742,7 +1745,12 @@ 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.
|
||||
FontStrike strike = sgv.font2D.handle.font2D.getStrike(desc); // !!! getStrike(desc, false)
|
||||
// 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)
|
||||
|
||||
return new GlyphStrike(sgv, strike, dx, dy);
|
||||
}
|
||||
|
@ -155,10 +155,7 @@ public final class SunLayoutEngine implements LayoutEngine, LayoutEngineFactory
|
||||
Point2D.Float pt, GVData data) {
|
||||
Font2D font = key.font();
|
||||
FontStrike strike = font.getStrike(desc);
|
||||
long layoutTables = 0;
|
||||
if (font instanceof TrueTypeFont) {
|
||||
layoutTables = ((TrueTypeFont) font).getLayoutTableCache();
|
||||
}
|
||||
long layoutTables = font.getLayoutTableCache();
|
||||
nativeLayout(font, strike, mat, gmask, baseIndex,
|
||||
tr.text, tr.start, tr.limit, tr.min, tr.max,
|
||||
key.script(), key.lang(), typo_flags, pt, data,
|
||||
|
@ -874,8 +874,8 @@ public class TrueTypeFont extends FileFont {
|
||||
}
|
||||
}
|
||||
|
||||
/* NB: is it better to move declaration to Font2D? */
|
||||
long getLayoutTableCache() {
|
||||
@Override
|
||||
protected long getLayoutTableCache() {
|
||||
try {
|
||||
return getScaler().getLayoutTableCache();
|
||||
} catch(FontScalerException fe) {
|
||||
@ -884,7 +884,7 @@ public class TrueTypeFont extends FileFont {
|
||||
}
|
||||
|
||||
@Override
|
||||
byte[] getTableBytes(int tag) {
|
||||
protected byte[] getTableBytes(int tag) {
|
||||
ByteBuffer buffer = getTableBuffer(tag);
|
||||
if (buffer == null) {
|
||||
return null;
|
||||
|
82
jdk/test/java/awt/font/TextLayout/OSXLigatureTest.java
Normal file
82
jdk/test/java/awt/font/TextLayout/OSXLigatureTest.java
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 7162125
|
||||
* @summary Test ligatures form on OS X.
|
||||
*/
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class OSXLigatureTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (!System.getProperty("os.name").startsWith("Mac")) {
|
||||
return;
|
||||
}
|
||||
String ligStr = "ffi";
|
||||
int w = 50, h = 50;
|
||||
|
||||
BufferedImage bi1 = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D bi1Graphics = bi1.createGraphics();
|
||||
bi1Graphics.setColor(Color.white);
|
||||
bi1Graphics.fillRect(0, 0, w, h);
|
||||
bi1Graphics.setColor(Color.black);
|
||||
Font noLigFont = new Font("Gill Sans", Font.PLAIN, 30);
|
||||
bi1Graphics.setFont(noLigFont);
|
||||
bi1Graphics.drawString(ligStr, 10, 40);
|
||||
|
||||
BufferedImage bi2 = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D bi2Graphics = bi2.createGraphics();
|
||||
bi2Graphics.setColor(Color.white);
|
||||
bi2Graphics.fillRect(0, 0, w, h);
|
||||
bi2Graphics.setColor(Color.black);
|
||||
Map<TextAttribute, Object> attributes = new HashMap<>();
|
||||
attributes.put(TextAttribute.LIGATURES, TextAttribute.LIGATURES_ON);
|
||||
Font ligFont = noLigFont.deriveFont(attributes);
|
||||
bi2Graphics.setFont(ligFont);
|
||||
bi2Graphics.drawString(ligStr, 10, 40);
|
||||
|
||||
boolean same = true;
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int c1 = bi1.getRGB(x, y);
|
||||
int c2 = bi2.getRGB(x, y);
|
||||
same &= (c1 == c2);
|
||||
}
|
||||
if (!same) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (same) {
|
||||
throw new RuntimeException("Images do not differ - no ligature");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user