IDEA-57233, IDEA-152816, IDEA-152454 Editor font antialising/appearance problems on Linux

Used desktop DPI instead of hard-coded 72
Compensated increased glyph bitmap size by adjusting font size
Added LCD filter for sub-pixel rendering
Use fontconfig library to provide right rendering options for fonts
Corrected sizes passed to fontconfig library and hinting disabling policy
Added logging and versioned fontconfig lib loading
Resolved font rendering problem in lenses
fix text rendering issues (text cutoff and incorrect rendering in editor fragment components)
FcMatchFont-type pattern substitutions shouldn't be invoked before specific font is selected - it can apply unrelated rules
port commit e21cd635 from JBR 9
partially rollback JBR-363 fix, to apply corresponding change from OpenJDK 12

(cherry picked from commit 5d704a963b)
(cherry picked from commit 3d7ac30072)
(cherry picked from commit 0456745afb)
(cherry picked from commit 3d7ac30072)
(cherry picked from commit 4c8351fecf)
(cherry picked from commit 5faebc73d5)
(cherry picked from commit d1ed8ab118)
(cherry picked from commit 20487c7515)
This commit is contained in:
Alexey Ushakov
2015-09-21 16:19:19 +03:00
committed by jbrbot
parent 2afd4d6d21
commit f0291d05c4
4 changed files with 1391 additions and 23 deletions

View File

@@ -348,6 +348,7 @@ else
endif
LIBFONTMANAGER_EXTRA_HEADER_DIRS := \
java.base:libjvm \
common/awt \
common/awt/utility \
common/font \

View File

@@ -25,6 +25,7 @@
package sun.font;
import java.awt.*;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
@@ -47,10 +48,10 @@ class FreetypeFontScaler extends FontScaler {
/* At the moment fontmanager library depends on freetype library
and therefore no need to load it explicitly here */
FontManagerNativeLibrary.load();
initIDs(FreetypeFontScaler.class);
initIDs(FreetypeFontScaler.class, Toolkit.class, PhysicalFont.class);
}
private static native void initIDs(Class<?> FFS);
private static native void initIDs(Class<?> FFS, Class<?> toolkitClass, Class<?> pfClass);
private void invalidateScaler() throws FontScalerException {
nativeScaler = 0;

File diff suppressed because it is too large Load Diff

View File

@@ -25,7 +25,7 @@
#include "jni.h"
#include "jni_util.h"
#include "jlong.h"
#include "jvm_md.h"
#include "sunfontids.h"
#include "sun_font_FreetypeFontScaler.h"
@@ -34,8 +34,10 @@
#include <dlfcn.h>
#include "jvm.h"
#endif
#include <stdlib.h>
#include <math.h>
#include "ft2build.h"
#include FT_LCD_FILTER_H
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_BBOX_H
@@ -44,6 +46,12 @@
#include FT_SYNTHESIS_H
#include FT_LCD_FILTER_H
#include FT_MODULE_H
#include FT_LCD_FILTER_H
#ifndef _WIN32
/* Use bundled fontconfig.h for now */
#include "fontconfig.h"
#endif
#include "fontscaler.h"
@@ -57,6 +65,23 @@
#define FloatToFTFixed(f) (FT_Fixed)((f) * (float)(ftFixed1))
#define FTFixedToFloat(x) ((x) / (float)(ftFixed1))
#define FT26Dot6ToFloat(x) ((x) / ((float) (1<<6)))
#define ROUND(x) ((int) ((x<0) ? (x-0.5) : (x+0.5)))
#define FT26Dot6ToDouble(x) ((x) / ((double) (1<<6)))
#define FT26Dot6ToInt(x) (((int)(x)) >> 6)
#define DEFAULT_DPI 72
#define ADJUST_FONT_SIZE(X, DPI) (((X)*DEFAULT_DPI + ((DPI)>>1))/(DPI))
#ifndef _WIN32
#define FONTCONFIG_DLL JNI_LIB_NAME("fontconfig")
#define FONTCONFIG_DLL_VERSIONED VERSIONED_JNI_LIB_NAME("fontconfig", "1")
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
typedef struct {
/* Important note:
@@ -88,7 +113,12 @@ typedef struct FTScalerContext {
jint fmType; /* fractional metrics - on/off */
jboolean doBold; /* perform algorithmic bolding? */
jboolean doItalize; /* perform algorithmic italicizing? */
int renderFlags; /* configuration specific to particular engine */
/* Fontconfig info */
FT_Render_Mode renderFlags;
FT_Int32 loadFlags;
FT_LcdFilter lcdFilter;
int pathType;
int ptsz; /* size in points */
} FTScalerContext;
@@ -105,10 +135,70 @@ void z_error(char *s) {}
static jmethodID invalidateScalerMID;
static jboolean debugFonts; // Stores the value of FontUtilities.debugFonts()
static jmethodID getDefaultToolkitMID;
static jclass tkClass;
static jmethodID getScreenResolutionMID;
static jfieldID platNameFID;
#ifndef _WIN32
typedef FcBool (*FcPatternAddPtrType) (FcPattern *p, const char *object, FcValue value, FcBool append);
typedef FcBool (*FcPatternAddBoolPtrType) (FcPattern *p, const char *object, FcBool b);
typedef FcBool (*FcPatternAddDoublePtrType) (FcPattern *p, const char *object, double d);
typedef FcBool (*FcConfigSubstitutePtrType) (FcConfig *config, FcPattern *p, FcMatchKind kind);
typedef void (*FcDefaultSubstitutePtrType) (FcPattern *pattern);
typedef FcPattern* (*FcPatternCreatePtrType) ();
typedef FcPattern* (*FcFontMatchPtrType) (FcConfig *config, FcPattern *p, FcResult *result);
typedef void (*FcPatternDestroyPtrType) (FcPattern *p);
typedef FcResult (*FcPatternGetBoolPtrType) (const FcPattern *p, const char *object, int n, FcBool *b);
typedef FcResult (*FcPatternGetIntegerPtrType) (const FcPattern *p, const char *object, int n, int *i);
#endif
static void *libFontConfig = NULL;
static jboolean logFC = JNI_FALSE;
#ifndef _WIN32
static FcPatternAddPtrType FcPatternAddPtr;
static FcPatternAddBoolPtrType FcPatternAddBoolPtr;
static FcPatternAddDoublePtrType FcPatternAddDoublePtr;
static FcConfigSubstitutePtrType FcConfigSubstitutePtr;
static FcDefaultSubstitutePtrType FcDefaultSubstitutePtr;
static FcPatternCreatePtrType FcPatternCreatePtr;
static FcFontMatchPtrType FcFontMatchPtr;
static FcPatternDestroyPtrType FcPatternDestroyPtr;
static FcPatternGetBoolPtrType FcPatternGetBoolPtr;
static FcPatternGetIntegerPtrType FcPatternGetIntegerPtr;
#endif
static void* openFontConfig() {
void* libfontconfig = NULL;
#ifndef _WIN32
char *fcLogEnabled = getenv("OPENJDK_FFS_LOG_FC");
if (fcLogEnabled != NULL && !strcmp(fcLogEnabled, "yes")) {
logFC = JNI_TRUE;
}
char *useFC = getenv("OPENJDK_FFS_USE_FC");
if (useFC != NULL && !strcmp(useFC, "no")) {
if (logFC) fprintf(stderr, "FC_LOG: fontconfig disabled in freetypescaler\n");
return NULL;
}
libfontconfig = dlopen(FONTCONFIG_DLL_VERSIONED, RTLD_LOCAL | RTLD_LAZY);
if (libfontconfig == NULL) {
libfontconfig = dlopen(FONTCONFIG_DLL, RTLD_LOCAL | RTLD_LAZY);
if (libfontconfig == NULL) {
if (logFC) fprintf(stderr, "FC_LOG: cannot open %s\n", FONTCONFIG_DLL);
return NULL;
}
}
#endif
return libfontconfig;
}
JNIEXPORT void JNICALL
Java_sun_font_FreetypeFontScaler_initIDs(
JNIEnv *env, jobject scaler, jclass FFSClass) {
JNIEnv *env, jobject scaler, jclass FFSClass, jclass TKClass, jclass PFClass) {
invalidateScalerMID =
(*env)->GetMethodID(env, FFSClass, "invalidateScaler", "()V");
@@ -116,6 +206,51 @@ Java_sun_font_FreetypeFontScaler_initIDs(
debugFonts = JNU_CallStaticMethodByName(env, &ignoreException,
"sun/font/FontUtilities",
"debugFonts", "()Z").z;
getDefaultToolkitMID =
(*env)->GetStaticMethodID(env, TKClass, "getDefaultToolkit",
"()Ljava/awt/Toolkit;");
getScreenResolutionMID =
(*env)->GetMethodID(env, TKClass, "getScreenResolution", "()I");
tkClass = (*env)->NewGlobalRef(env, TKClass);
platNameFID = (*env)->GetFieldID(env, PFClass, "platName", "Ljava/lang/String;");
libFontConfig = openFontConfig();
#ifndef _WIN32
if (libFontConfig) {
FcPatternAddPtr = (FcPatternAddPtrType) dlsym(libFontConfig, "FcPatternAdd");
FcPatternAddBoolPtr = (FcPatternAddBoolPtrType) dlsym(libFontConfig, "FcPatternAddBool");
FcPatternAddDoublePtr = (FcPatternAddDoublePtrType) dlsym(libFontConfig, "FcPatternAddDouble");
FcConfigSubstitutePtr = (FcConfigSubstitutePtrType) dlsym(libFontConfig, "FcConfigSubstitute");
FcDefaultSubstitutePtr = (FcDefaultSubstitutePtrType) dlsym(libFontConfig, "FcDefaultSubstitute");
FcPatternCreatePtr = (FcPatternCreatePtrType) dlsym(libFontConfig, "FcPatternCreate");
FcFontMatchPtr = (FcFontMatchPtrType) dlsym(libFontConfig, "FcFontMatch");
FcPatternDestroyPtr = (FcPatternDestroyPtrType) dlsym(libFontConfig, "FcPatternDestroy");
FcPatternGetBoolPtr = (FcPatternGetBoolPtrType) dlsym(libFontConfig, "FcPatternGetBool");
FcPatternGetIntegerPtr = (FcPatternGetIntegerPtrType) dlsym(libFontConfig, "FcPatternGetInteger");
}
#endif
}
static char* getPhysFontName(JNIEnv *env, jobject font2d) {
jstring jstr;
jstr = (*env)->GetObjectField(env, font2d, platNameFID);
return (char*)(*env)->GetStringUTFChars(env, jstr, NULL);
}
static int getScreenResolution(JNIEnv *env) {
jthrowable exc;
jclass tk = (*env)->CallStaticObjectMethod(
env, tkClass, getDefaultToolkitMID);
int dpi = (*env)->CallIntMethod(env, tk, getScreenResolutionMID);
/* Test if there is no exception here (can get java.awt.HeadlessException)
* Fallback to default DPI otherwise
*/
exc = (*env)->ExceptionOccurred(env);
if (exc) {
(*env)->ExceptionClear(env);
return DEFAULT_DPI;
}
return dpi;
}
static void freeNativeResources(JNIEnv *env, FTScalerInfo* scalerInfo) {
@@ -609,27 +744,236 @@ static void setupTransform(FT_Matrix* target, FTScalerContext *context) {
static int setupFTContext(JNIEnv *env,
jobject font2D,
FTScalerInfo *scalerInfo,
FTScalerContext *context) {
FTScalerContext *context,
FT_Bool configureFont) {
FT_Matrix matrix;
int errCode = 0;
scalerInfo->env = env;
scalerInfo->font2D = font2D;
if (context != NULL) {
setupTransform(&matrix, context);
FT_Set_Transform(scalerInfo->face, &matrix, NULL);
FT_UInt dpi = (FT_UInt) getScreenResolution(env);
errCode = FT_Set_Char_Size(scalerInfo->face, 0, context->ptsz, 72, 72);
errCode = FT_Set_Char_Size(scalerInfo->face, 0, ADJUST_FONT_SIZE(context->ptsz, dpi), dpi, dpi);
if (errCode) return errCode;
if (errCode == 0) {
errCode = FT_Activate_Size(scalerInfo->face->size);
errCode = FT_Activate_Size(scalerInfo->face->size);
if (errCode) return errCode;
if (configureFont) {
context->renderFlags = FT_RENDER_MODE_NORMAL;
context->lcdFilter = FT_LCD_FILTER_NONE;
context->loadFlags = FT_LOAD_DEFAULT;
if (libFontConfig == NULL) {
if (context->aaType == TEXT_AA_OFF) {
context->loadFlags = FT_LOAD_TARGET_MONO;
} else if (context->aaType == TEXT_AA_ON) {
context->loadFlags = FT_LOAD_TARGET_LIGHT;
} else {
context->lcdFilter = FT_LCD_FILTER_LIGHT;
if (context->aaType == TEXT_AA_LCD_HRGB ||
context->aaType == TEXT_AA_LCD_HBGR) {
context->loadFlags = FT_LOAD_TARGET_LCD;
} else {
context->loadFlags = FT_LOAD_TARGET_LCD_V;
}
}
context->renderFlags = FT_LOAD_TARGET_MODE(context->loadFlags);
return 0;
}
#ifndef _WIN32
FcPattern *fcPattern = 0;
fcPattern = (*FcPatternCreatePtr)();
FcValue fcValue;
fcValue.type = FcTypeString;
char *fontName = getPhysFontName(env, font2D);
if (logFC) fprintf(stderr, "FC_LOG: %s ", fontName);
fcValue.u.s = (const FcChar8*)fontName;
(*FcPatternAddPtr)(fcPattern, FC_FILE, fcValue, FcTrue);
(*FcPatternAddBoolPtr)(fcPattern, FC_SCALABLE, FcTrue);
double fcSize = FT26Dot6ToDouble(ADJUST_FONT_SIZE(context->ptsz, dpi));
(*FcPatternAddDoublePtr)(fcPattern, FC_SIZE, fcSize);
if (logFC) fprintf(stderr, " size=%f", fcSize);
(*FcConfigSubstitutePtr)(0, fcPattern, FcMatchPattern);
(*FcDefaultSubstitutePtr)(fcPattern);
FcResult matchResult = FcResultNoMatch;
FcPattern *resultPattern = 0;
resultPattern = (*FcFontMatchPtr)(0, fcPattern, &matchResult);
if (matchResult != FcResultMatch) {
(*FcPatternDestroyPtr)(fcPattern);
if (logFC) fprintf(stderr, " - NOT FOUND\n");
return 1;
}
if (logFC) fprintf(stderr, "\nFC_LOG: ");
(*FcPatternDestroyPtr)(fcPattern);
FcPattern *pattern = resultPattern;
FcBool fcHinting = FcFalse;
FcBool fcHintingSet = (*FcPatternGetBoolPtr)(pattern, FC_HINTING, 0, &fcHinting) == FcResultMatch;
if (logFC && fcHintingSet) fprintf(stderr, "FC_HINTING(%d) ", fcHinting);
int fcHintStyle = FC_HINT_NONE;
FcBool fcHintStyleSet = (*FcPatternGetIntegerPtr)(pattern, FC_HINT_STYLE, 0, &fcHintStyle) == FcResultMatch;
if (logFC && fcHintStyleSet) {
switch (fcHintStyle) {
case FC_HINT_NONE:
fprintf(stderr, "FC_HINT_NONE ");
break;
case FC_HINT_SLIGHT:
fprintf(stderr, "FC_HINT_SLIGHT ");
break;
case FC_HINT_MEDIUM:
fprintf(stderr, "FC_HINT_MEDIUM ");
break;
case FC_HINT_FULL:
fprintf(stderr, "FC_HINT_FULL ");
break;
default:
fprintf(stderr, "FC_HINT_UNKNOWN ");
break;
}
}
if (fcHintingSet && !fcHinting) {
fcHintStyleSet = FcTrue;
fcHintStyle = FC_HINT_NONE;
}
if (fcHintStyleSet && fcHintStyle == FC_HINT_NONE) {
fcHintingSet = FcTrue;
fcHinting = FcFalse;
}
FcBool fcAntialias = FcFalse;
FcBool fcAntialiasSet = (*FcPatternGetBoolPtr)(pattern, FC_ANTIALIAS, 0, &fcAntialias) == FcResultMatch;
if (logFC) {
switch(context->aaType) {
case TEXT_AA_ON:
fprintf(stderr, "JDK_AA_ON ");
break;
case TEXT_AA_OFF:
fprintf(stderr, "JDK_AA_OFF ");
break;
case TEXT_AA_LCD_HRGB:
fprintf(stderr, "JDK_AA_LCD_HRGB ");
break;
case TEXT_AA_LCD_HBGR:
fprintf(stderr, "JDK_AA_LCD_HBGR ");
break;
default:
fprintf(stderr, "JDK_AA_UNKNOWN ");
break;
}
if (fcAntialiasSet) fprintf(stderr, "FC_ANTIALIAS(%d) ", fcAntialias);
}
if (context->aaType == TEXT_AA_ON) { // Greyscale AA
context->renderFlags = FT_RENDER_MODE_NORMAL;
if (fcHintingSet) {
switch (fcHintStyle) {
case FC_HINT_NONE:
context->loadFlags = FT_LOAD_NO_HINTING;
break;
case FC_HINT_SLIGHT:
context->loadFlags = FT_LOAD_TARGET_LIGHT;
break;
case FC_HINT_MEDIUM:
case FC_HINT_FULL:
default:
break;
}
}
}
else if (context->aaType == TEXT_AA_OFF) { // No AA
context->renderFlags = FT_RENDER_MODE_MONO;
context->loadFlags = (!fcHintingSet || fcHinting) ? FT_LOAD_TARGET_MONO : FT_LOAD_NO_HINTING;
} else {
int fcRGBA = FC_RGBA_UNKNOWN;
if (fcAntialiasSet && fcAntialias) {
if ((*FcPatternGetIntegerPtr)(pattern, FC_RGBA, 0, &fcRGBA) == FcResultMatch) {
switch (fcRGBA) {
case FC_RGBA_RGB:
case FC_RGBA_BGR:
if (logFC) fprintf(stderr, fcRGBA == FC_RGBA_RGB ? "FC_RGBA_RGB " : "FC_RGBA_BGR ");
context->loadFlags = FT_LOAD_TARGET_LCD;
context->renderFlags = FT_RENDER_MODE_LCD;
break;
case FC_RGBA_VRGB:
case FC_RGBA_VBGR:
if (logFC) fprintf(stderr, fcRGBA == FC_RGBA_VRGB ? "FC_RGBA_VRGB " : "FC_RGBA_VBGR ");
context->loadFlags = FT_LOAD_TARGET_LCD_V;
context->renderFlags = FT_RENDER_MODE_LCD_V;
break;
default:
if (logFC) fprintf(stderr, "FC_RGBA_UNKNOWN ");
break;
}
}
}
if (fcRGBA == FC_RGBA_UNKNOWN) {
if (context->aaType == TEXT_AA_LCD_HRGB ||
context->aaType == TEXT_AA_LCD_HBGR) {
context->loadFlags = FT_LOAD_TARGET_LCD;
context->renderFlags = FT_RENDER_MODE_LCD;
} else {
context->loadFlags = FT_LOAD_TARGET_LCD_V;
context->renderFlags = FT_RENDER_MODE_LCD_V;
}
}
}
FcBool fcAutohint = FcFalse;
FcBool fcAutohintSet = (*FcPatternGetBoolPtr)(pattern, FC_AUTOHINT, 0, &fcAutohint) == FcResultMatch;
if (logFC && fcAutohintSet) fprintf(stderr, "FC_AUTOHINT(%d) ", fcAutohint);
if (fcAutohintSet && fcAutohint) {
context->loadFlags |= FT_LOAD_FORCE_AUTOHINT;
}
FT_LcdFilter fcLCDFilter;
FcBool fcLCDFilterSet = (*FcPatternGetIntegerPtr)(pattern, FC_LCD_FILTER, 0, (int*) &fcLCDFilter) == FcResultMatch;
context->lcdFilter = FT_LCD_FILTER_DEFAULT;
if (fcLCDFilterSet) {
switch (fcLCDFilter) {
case FC_LCD_NONE:
if (logFC) fprintf(stderr, "FC_LCD_NONE");
context->lcdFilter = FT_LCD_FILTER_NONE;
break;
case FC_LCD_LIGHT:
if (logFC) fprintf(stderr, "FC_LCD_LIGHT");
context->lcdFilter = FT_LCD_FILTER_LIGHT;
break;
case FC_LCD_LEGACY:
if (logFC) fprintf(stderr, "FC_LCD_LEGACY");
context->lcdFilter = FT_LCD_FILTER_LEGACY;
break;
case FC_LCD_DEFAULT:
if (logFC) fprintf(stderr, "FC_LCD_DEFAULT");
break;
default:
if (logFC) fprintf(stderr, "FC_LCD_UNKNOWN");
;
}
}
(*FcPatternDestroyPtr)(pattern);
if (logFC) fprintf(stderr, "\n");
#endif
}
FT_Library_SetLcdFilter(scalerInfo->library, FT_LCD_FILTER_DEFAULT);
}
return errCode;
return 0;
}
// using same values as for the transformation matrix
@@ -662,7 +1006,7 @@ Java_sun_font_FreetypeFontScaler_getFontMetricsNative(
f0, f0, f0, f0, f0, f0, f0, f0, f0, f0);
}
errCode = setupFTContext(env, font2D, scalerInfo, context);
errCode = setupFTContext(env, font2D, scalerInfo, context, FALSE);
if (errCode) {
metrics = (*env)->NewObject(env,
@@ -945,8 +1289,10 @@ static jlong
int error, imageSize;
UInt16 width, height, rowBytes;
GlyphInfo *glyphInfo;
int renderFlags = FT_LOAD_DEFAULT, target;
int target;
FT_GlyphSlot ftglyph;
FT_LcdFilter lcdFilter = FT_LCD_FILTER_NONE;
FT_Library library;
FTScalerContext* context =
(FTScalerContext*) jlong_to_ptr(pScalerContext);
@@ -957,7 +1303,7 @@ static jlong
return ptr_to_jlong(getNullGlyphImage());
}
error = setupFTContext(env, font2D, scalerInfo, context);
error = setupFTContext(env, font2D, scalerInfo, context, TRUE);
if (error) {
invalidateJavaScaler(env, scaler, scalerInfo);
return ptr_to_jlong(getNullGlyphImage());
@@ -971,11 +1317,11 @@ static jlong
* which did not use freetype.
*/
if (context->aaType == TEXT_AA_ON && context->fmType == TEXT_FM_ON) {
renderFlags |= FT_LOAD_NO_HINTING;
}
context->loadFlags |= FT_LOAD_NO_HINTING;
}
if (!context->useSbits) {
renderFlags |= FT_LOAD_NO_BITMAP;
context->loadFlags |= FT_LOAD_NO_BITMAP;
}
/* NB: in case of non identity transform
@@ -994,9 +1340,9 @@ static jlong
} else {
target = FT_LOAD_TARGET_LCD_V;
}
renderFlags |= target;
context->loadFlags |= target;
error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags);
error = FT_Load_Glyph(scalerInfo->face, glyphCode, context->loadFlags);
if (error) {
//do not destroy scaler yet.
//this can be problem of particular context (e.g. with bad transform)
@@ -1004,6 +1350,8 @@ static jlong
}
ftglyph = scalerInfo->face->glyph;
library = ftglyph->library;
FT_Library_SetLcdFilter (library, context->lcdFilter);
/* apply styles */
if (context->doBold) { /* if bold style */
@@ -1021,7 +1369,7 @@ static jlong
glyphInfo = getNullGlyphImage();
return ptr_to_jlong(glyphInfo);
}
error = FT_Render_Glyph(ftglyph, FT_LOAD_TARGET_MODE(target));
error = FT_Render_Glyph(ftglyph, context->renderFlags);
if (error != 0) {
return ptr_to_jlong(getNullGlyphImage());
}
@@ -1154,7 +1502,7 @@ Java_sun_font_FreetypeFontScaler_disposeNativeScaler(
/* Freetype functions *may* cause callback to java
that can use cached values. Make sure our cache is up to date.
NB: scaler context is not important at this point, can use NULL. */
int errCode = setupFTContext(env, font2D, scalerInfo, NULL);
int errCode = setupFTContext(env, font2D, scalerInfo, NULL, FALSE);
if (errCode) {
return;
}
@@ -1217,7 +1565,7 @@ Java_sun_font_FreetypeFontScaler_getGlyphCodeNative(
/* Freetype functions *may* cause callback to java
that can use cached values. Make sure our cache is up to date.
Scaler context is not important here, can use NULL. */
errCode = setupFTContext(env, font2D, scalerInfo, NULL);
errCode = setupFTContext(env, font2D, scalerInfo, NULL, FALSE);
if (errCode) {
return 0;
}
@@ -1240,7 +1588,7 @@ static FT_Outline* getFTOutline(JNIEnv* env, jobject font2D,
return NULL;
}
error = setupFTContext(env, font2D, scalerInfo, context);
error = setupFTContext(env, font2D, scalerInfo, context, TRUE);
if (error) {
return NULL;
}
@@ -1681,3 +2029,11 @@ Java_sun_font_FreetypeFontScaler_getGlyphPointNative(
return (*env)->NewObject(env, sunFontIDs.pt2DFloatClass,
sunFontIDs.pt2DFloatCtr, x, y);
}
void JNI_OnUnload(JavaVM *vm, void *reserved) {
if (libFontConfig != NULL) {
#ifndef _WIN32
dlclose(libFontConfig);
#endif
}
}