8256372: [macos] Unexpected symbol was displayed on JTextField with Monospaced font

Reviewed-by: erikj, serb
This commit is contained in:
Phil Race 2021-05-20 19:49:03 +00:00
parent 81f39ed3e0
commit 005d8a7fca
9 changed files with 73 additions and 1360 deletions

View file

@ -447,9 +447,6 @@ else
ifeq ($(call isTargetOs, linux macosx), true) ifeq ($(call isTargetOs, linux macosx), true)
HARFBUZZ_CFLAGS += -DHAVE_INTEL_ATOMIC_PRIMITIVES HARFBUZZ_CFLAGS += -DHAVE_INTEL_ATOMIC_PRIMITIVES
endif endif
ifeq ($(call isTargetOs, macosx), true)
HARFBUZZ_CFLAGS += -DHAVE_CORETEXT
endif
# Early re-canonizing has to be disabled to workaround an internal XlC compiler error # Early re-canonizing has to be disabled to workaround an internal XlC compiler error
# when building libharfbuzz # when building libharfbuzz
@ -457,9 +454,6 @@ else
HARFBUZZ_CFLAGS += -qdebug=necan HARFBUZZ_CFLAGS += -qdebug=necan
endif endif
ifeq ($(call isTargetOs, macosx), false)
LIBFONTMANAGER_EXCLUDE_FILES += libharfbuzz/hb-coretext.cc
endif
# hb-ft.cc is not presently needed, and requires freetype 2.4.2 or later. # hb-ft.cc is not presently needed, and requires freetype 2.4.2 or later.
LIBFONTMANAGER_EXCLUDE_FILES += libharfbuzz/hb-ft.cc LIBFONTMANAGER_EXCLUDE_FILES += libharfbuzz/hb-ft.cc

View file

@ -211,7 +211,13 @@ public final class CFont extends PhysicalFont implements FontSubstitution {
PhysicalFont[] fonts = new PhysicalFont[numFonts]; PhysicalFont[] fonts = new PhysicalFont[numFonts];
fonts[0] = this; fonts[0] = this;
int idx = 1; int idx = 1;
if (FontUtilities.isLogging()) {
FontUtilities.logInfo("Cascading list for " + this + " :");
}
for (String s : listOfString) { for (String s : listOfString) {
if (FontUtilities.isLogging()) {
FontUtilities.logInfo("Fallback:" + s);
}
if (s.equals(".AppleSymbolsFB")) { if (s.equals(".AppleSymbolsFB")) {
// Don't know why we get the weird name above .. replace. // Don't know why we get the weird name above .. replace.
s = "AppleSymbols"; s = "AppleSymbols";

View file

@ -151,34 +151,9 @@ public final class SunLayoutEngine implements LayoutEngine, LayoutEngineFactory
this.key = key; this.key = key;
} }
static WeakHashMap<Font2D, Boolean> aatInfo = new WeakHashMap<>();
private static final WeakHashMap<Font2D, FaceRef> facePtr = private static final WeakHashMap<Font2D, FaceRef> facePtr =
new WeakHashMap<>(); new WeakHashMap<>();
private static boolean isAAT(Font2D font) {
Boolean aatObj;
synchronized (aatInfo) {
aatObj = aatInfo.get(font);
}
if (aatObj != null) {
return aatObj.booleanValue();
}
boolean aat = false;
if (font instanceof TrueTypeFont) {
TrueTypeFont ttf = (TrueTypeFont)font;
aat = ttf.getDirectoryEntry(TrueTypeFont.morxTag) != null ||
ttf.getDirectoryEntry(TrueTypeFont.mortTag) != null;
} else if (font instanceof PhysicalFont) {
PhysicalFont pf = (PhysicalFont)font;
aat = pf.getTableBytes(TrueTypeFont.morxTag) != null ||
pf.getTableBytes(TrueTypeFont.mortTag) != null;
}
synchronized (aatInfo) {
aatInfo.put(font, Boolean.valueOf(aat));
}
return aat;
}
private long getFacePtr(Font2D font2D) { private long getFacePtr(Font2D font2D) {
FaceRef ref; FaceRef ref;
synchronized (facePtr) { synchronized (facePtr) {
@ -192,11 +167,9 @@ public final class SunLayoutEngine implements LayoutEngine, LayoutEngineFactory
Point2D.Float pt, GVData data) { Point2D.Float pt, GVData data) {
Font2D font = key.font(); Font2D font = key.font();
FontStrike strike = font.getStrike(desc); FontStrike strike = font.getStrike(desc);
long pNativeFont = font.getPlatformNativeFontPtr(); // used on OSX
long pFace = getFacePtr(font); long pFace = getFacePtr(font);
if (pFace != 0) { if (pFace != 0) {
shape(font, strike, ptSize, mat, pNativeFont, shape(font, strike, ptSize, mat, pFace,
pFace, isAAT(font),
tr.text, data, key.script(), tr.text, data, key.script(),
tr.start, tr.limit, baseIndex, pt, tr.start, tr.limit, baseIndex, pt,
typo_flags, gmask); typo_flags, gmask);
@ -206,13 +179,12 @@ public final class SunLayoutEngine implements LayoutEngine, LayoutEngineFactory
/* Native method to invoke harfbuzz layout engine */ /* Native method to invoke harfbuzz layout engine */
private static native boolean private static native boolean
shape(Font2D font, FontStrike strike, float ptSize, float[] mat, shape(Font2D font, FontStrike strike, float ptSize, float[] mat,
long pNativeFont, long pFace, boolean aat, long pFace,
char[] chars, GVData data, char[] chars, GVData data,
int script, int offset, int limit, int script, int offset, int limit,
int baseIndex, Point2D.Float pt, int typo_flags, int slot); int baseIndex, Point2D.Float pt, int typo_flags, int slot);
private static native long createFace(Font2D font, private static native long createFace(Font2D font,
boolean aat,
long platformNativeFontPtr); long platformNativeFontPtr);
private static native void disposeFace(long facePtr); private static native void disposeFace(long facePtr);
@ -227,7 +199,7 @@ public final class SunLayoutEngine implements LayoutEngine, LayoutEngineFactory
private synchronized long getNativePtr() { private synchronized long getNativePtr() {
if (facePtr == null) { if (facePtr == null) {
facePtr = createFace(font, isAAT(font), facePtr = createFace(font,
font.getPlatformNativeFontPtr()); font.getPlatformNativeFontPtr());
if (facePtr != 0) { if (facePtr != 0) {
Disposer.addObjectRecord(font, this); Disposer.addObjectRecord(font, this);

View file

@ -28,9 +28,6 @@
#include "hb.h" #include "hb.h"
#include "hb-jdk.h" #include "hb-jdk.h"
#include "hb-ot.h" #include "hb-ot.h"
#ifdef MACOSX
#include "hb-coretext.h"
#endif
#include "scriptMapping.h" #include "scriptMapping.h"
static jclass gvdClass = 0; static jclass gvdClass = 0;
@ -201,9 +198,7 @@ JDKFontInfo*
jobject font2D, jobject font2D,
jobject fontStrike, jobject fontStrike,
jfloat ptSize, jfloat ptSize,
jlong pNativeFont, jfloatArray matrix) {
jfloatArray matrix,
jboolean aat) {
JDKFontInfo *fi = (JDKFontInfo*)malloc(sizeof(JDKFontInfo)); JDKFontInfo *fi = (JDKFontInfo*)malloc(sizeof(JDKFontInfo));
@ -213,13 +208,11 @@ JDKFontInfo*
fi->env = env; // this is valid only for the life of this JNI call. fi->env = env; // this is valid only for the life of this JNI call.
fi->font2D = font2D; fi->font2D = font2D;
fi->fontStrike = fontStrike; fi->fontStrike = fontStrike;
fi->nativeFont = pNativeFont;
fi->aat = aat;
(*env)->GetFloatArrayRegion(env, matrix, 0, 4, fi->matrix); (*env)->GetFloatArrayRegion(env, matrix, 0, 4, fi->matrix);
fi->ptSize = ptSize; fi->ptSize = ptSize;
fi->xPtSize = euclidianDistance(fi->matrix[0], fi->matrix[1]); fi->xPtSize = euclidianDistance(fi->matrix[0], fi->matrix[1]);
fi->yPtSize = euclidianDistance(fi->matrix[2], fi->matrix[3]); fi->yPtSize = euclidianDistance(fi->matrix[2], fi->matrix[3]);
if (!aat && (getenv("HB_NODEVTX") != NULL)) { if (getenv("HB_NODEVTX") != NULL) {
fi->devScale = fi->xPtSize / fi->ptSize; fi->devScale = fi->xPtSize / fi->ptSize;
} else { } else {
fi->devScale = 1.0f; fi->devScale = 1.0f;
@ -238,9 +231,7 @@ JNIEXPORT jboolean JNICALL Java_sun_font_SunLayoutEngine_shape
jobject fontStrike, jobject fontStrike,
jfloat ptSize, jfloat ptSize,
jfloatArray matrix, jfloatArray matrix,
jlong pNativeFont,
jlong pFace, jlong pFace,
jboolean aat,
jcharArray text, jcharArray text,
jobject gvdata, jobject gvdata,
jint script, jint script,
@ -268,8 +259,7 @@ JNIEXPORT jboolean JNICALL Java_sun_font_SunLayoutEngine_shape
unsigned int buflen; unsigned int buflen;
JDKFontInfo *jdkFontInfo = JDKFontInfo *jdkFontInfo =
createJDKFontInfo(env, font2D, fontStrike, ptSize, createJDKFontInfo(env, font2D, fontStrike, ptSize, matrix);
pNativeFont, matrix, aat);
if (!jdkFontInfo) { if (!jdkFontInfo) {
return JNI_FALSE; return JNI_FALSE;
} }

View file

@ -28,9 +28,6 @@
#include "hb.h" #include "hb.h"
#include "hb-jdk.h" #include "hb-jdk.h"
#ifdef MACOSX
#include "hb-coretext.h"
#endif
#include <stdlib.h> #include <stdlib.h>
#if defined(__GNUC__) && __GNUC__ >= 4 #if defined(__GNUC__) && __GNUC__ >= 4
@ -363,19 +360,12 @@ extern "C" {
/* /*
* Class: sun_font_SunLayoutEngine * Class: sun_font_SunLayoutEngine
* Method: createFace * Method: createFace
* Signature: (Lsun/font/Font2D;ZJJ)J * Signature: (Lsun/font/Font2D;JJ)J
*/ */
JNIEXPORT jlong JNICALL Java_sun_font_SunLayoutEngine_createFace(JNIEnv *env, JNIEXPORT jlong JNICALL Java_sun_font_SunLayoutEngine_createFace(JNIEnv *env,
jclass cls, jclass cls,
jobject font2D, jobject font2D,
jboolean aat,
jlong platformFontPtr) { jlong platformFontPtr) {
#ifdef MACOSX
if (aat && platformFontPtr) {
hb_face_t *face = hb_coretext_face_create((CGFontRef)platformFontPtr);
return ptr_to_jlong(face);
}
#endif
Font2DPtr *fi = (Font2DPtr*)malloc(sizeof(Font2DPtr)); Font2DPtr *fi = (Font2DPtr*)malloc(sizeof(Font2DPtr));
if (!fi) { if (!fi) {
return 0; return 0;
@ -439,10 +429,6 @@ static hb_font_t* _hb_jdk_ct_font_create(hb_face_t* face,
hb_font_t* hb_jdk_font_create(hb_face_t* hbFace, hb_font_t* hb_jdk_font_create(hb_face_t* hbFace,
JDKFontInfo *jdkFontInfo, JDKFontInfo *jdkFontInfo,
hb_destroy_func_t destroy) { hb_destroy_func_t destroy) {
#ifdef MACOSX
if (jdkFontInfo->aat && jdkFontInfo->nativeFont) {
return _hb_jdk_ct_font_create(hbFace, jdkFontInfo);
}
#endif
return _hb_jdk_font_create(hbFace, jdkFontInfo, destroy); return _hb_jdk_font_create(hbFace, jdkFontInfo, destroy);
} }

View file

@ -38,13 +38,11 @@ typedef struct JDKFontInfo_Struct {
JNIEnv* env; JNIEnv* env;
jobject font2D; jobject font2D;
jobject fontStrike; jobject fontStrike;
jlong nativeFont;
float matrix[4]; float matrix[4];
float ptSize; float ptSize;
float xPtSize; float xPtSize;
float yPtSize; float yPtSize;
float devScale; // How much applying the full glyph tx scales x distance. float devScale; // How much applying the full glyph tx scales x distance.
jboolean aat;
} JDKFontInfo; } JDKFontInfo;

File diff suppressed because it is too large Load diff

View file

@ -1,96 +0,0 @@
/*
* Copyright © 2012 Mozilla Foundation.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Mozilla Author(s): Jonathan Kew
*/
#ifndef HB_CORETEXT_H
#define HB_CORETEXT_H
#include "hb.h"
#include <TargetConditionals.h>
#if TARGET_OS_IPHONE
# include <CoreText/CoreText.h>
# include <CoreGraphics/CoreGraphics.h>
#else
# include <ApplicationServices/ApplicationServices.h>
#endif
HB_BEGIN_DECLS
/**
* HB_CORETEXT_TAG_MORT:
*
* The #hb_tag_t tag for the `mort` (glyph metamorphosis) table,
* which holds AAT features.
*
* For more information, see
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6mort.html
*
**/
#define HB_CORETEXT_TAG_MORT HB_TAG('m','o','r','t')
/**
* HB_CORETEXT_TAG_MORX:
*
* The #hb_tag_t tag for the `morx` (extended glyph metamorphosis)
* table, which holds AAT features.
*
* For more information, see
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html
*
**/
#define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x')
/**
* HB_CORETEXT_TAG_KERX:
*
* The #hb_tag_t tag for the `kerx` (extended kerning) table, which
* holds AAT kerning information.
*
* For more information, see
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kerx.html
*
**/
#define HB_CORETEXT_TAG_KERX HB_TAG('k','e','r','x')
HB_EXTERN hb_face_t *
hb_coretext_face_create (CGFontRef cg_font);
HB_EXTERN hb_font_t *
hb_coretext_font_create (CTFontRef ct_font);
HB_EXTERN CGFontRef
hb_coretext_face_get_cg_font (hb_face_t *face);
HB_EXTERN CTFontRef
hb_coretext_font_get_ct_font (hb_font_t *font);
HB_END_DECLS
#endif /* HB_CORETEXT_H */

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8256372
*/
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
public class NLGlyphTest {
public static void main(String[] args) {
char[] chs = { '\n' };
FontRenderContext frc = new FontRenderContext(null, true, true);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
Font[] fonts = ge.getAllFonts();
for (Font font : fonts) {
GlyphVector cgv = font.createGlyphVector(frc, "\n");
GlyphVector lgv = font.layoutGlyphVector(frc, chs, 0, 1, 0);
int c_code = cgv.getGlyphCode(0);
int l_code = lgv.getGlyphCode(0);
if ((c_code != l_code) || (l_code == 0)) {
System.out.println(font);
System.out.println("create code="+c_code + " layout code="+l_code);
Rectangle r_l = lgv.getPixelBounds(frc, 0f, 0f);
Rectangle r_c = cgv.getPixelBounds(frc, 0f, 0f);
System.out.println(r_l.isEmpty()+" "+ r_c.isEmpty());
if (r_l.isEmpty() != r_c.isEmpty()) {
throw new RuntimeException("One glyph renders");
}
}
}
}
}