--- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c Thu Oct 17 20:27:44 2019 +0100
+++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c Thu Oct 17 20:53:35 2019 +0100
@@ -29,7 +29,10 @@
#include "sunfontids.h"
#include "sun_font_FreetypeFontScaler.h"
-#include<stdlib.h>
+#include <stdlib.h>
+#if !defined(_WIN32) && !defined(__APPLE_)
+#include <dlfcn.h>
+#endif
#include <math.h>
#include "ft2build.h"
#include FT_FREETYPE_H
@@ -39,6 +42,7 @@
#include FT_OUTLINE_H
#include FT_SYNTHESIS_H
#include FT_LCD_FILTER_H
+#include FT_MODULE_H
#include "fontscaler.h"
@@ -150,7 +154,31 @@
jobject bBuffer;
int bread = 0;
- if (numBytes == 0) return 0;
+ /* A call with numBytes == 0 is a seek. It should return 0 if the
+ * seek position is within the file and non-zero otherwise.
+ * For all other cases, ie numBytes !=0, return the number of bytes
+ * actually read. This applies to truncated reads and also failed reads.
+ */
+
+ if (numBytes == 0) {
+ if (offset > scalerInfo->fileSize) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+
+ if (offset + numBytes < offset) {
+ return 0; // ft should not do this, but just in case.
+ }
+
+ if (offset >= scalerInfo->fileSize) {
+ return 0;
+ }
+
+ if (offset + numBytes > scalerInfo->fileSize) {
+ numBytes = scalerInfo->fileSize - offset;
+ }
/* Large reads will bypass the cache and data copying */
if (numBytes > FILEDATACACHESIZE) {
@@ -160,7 +188,11 @@
scalerInfo->font2D,
sunFontIDs.ttReadBlockMID,
bBuffer, offset, numBytes);
- return bread;
+ if (bread < 0) {
+ return 0;
+ } else {
+ return bread;
+ }
} else {
/* We probably hit bug 4845371. For reasons that
* are currently unclear, the call stacks after the initial
@@ -175,9 +207,18 @@
(*env)->CallObjectMethod(env, scalerInfo->font2D,
sunFontIDs.ttReadBytesMID,
offset, numBytes);
- (*env)->GetByteArrayRegion(env, byteArray,
- 0, numBytes, (jbyte*)destBuffer);
- return numBytes;
+ /* If there's an OutofMemoryError then byteArray will be null */
+ if (byteArray == NULL) {
+ return 0;
+ } else {
+ jsize len = (*env)->GetArrayLength(env, byteArray);
+ if (len < numBytes) {
+ numBytes = len; // don't get more bytes than there are ..
+ }
+ (*env)->GetByteArrayRegion(env, byteArray,
+ 0, numBytes, (jbyte*)destBuffer);
+ return numBytes;
+ }
}
} /* Do we have a cache hit? */
else if (scalerInfo->fontDataOffset <= offset &&
@@ -199,11 +240,62 @@
sunFontIDs.ttReadBlockMID,
bBuffer, offset,
scalerInfo->fontDataLength);
+ if (bread <= 0) {
+ return 0;
+ } else if (bread < numBytes) {
+ numBytes = bread;
+ }
memcpy(destBuffer, scalerInfo->fontData, numBytes);
return numBytes;
}
}
+typedef FT_Error (*FT_Prop_Set_Func)(FT_Library library,
+ const FT_String* module_name,
+ const FT_String* property_name,
+ const void* value );
+
+/**
+ * Prefer the older v35 freetype byte code interpreter.
+ */
+static void setInterpreterVersion(FT_Library library) {
+
+ char* props = getenv("FREETYPE_PROPERTIES");
+ int version = 35;
+ const char* module = "truetype";
+ const char* property = "interpreter-version";
+
+ /* If some one is setting this, don't override it */
+ if (props != NULL && strstr(property, props)) {
+ return;
+ }
+ /*
+ * FT_Property_Set was introduced in 2.4.11.
+ * Some older supported Linux OSes may not include it so look
+ * this up dynamically.
+ * And if its not available it doesn't matter, since the reason
+ * we need it dates from 2.7.
+ * On Windows & Mac the library is always bundled so it is safe
+ * to use directly in those cases.
+ */
+#if defined(_WIN32) || defined(__APPLE__)
+ FT_Property_Set(library, module, property, (void*)(&version));
+#else
+ void *lib = dlopen("libfreetype.so", RTLD_LOCAL|RTLD_LAZY);
+ if (lib == NULL) {
+ lib = dlopen("libfreetype.so.6", RTLD_LOCAL|RTLD_LAZY);
+ if (lib == NULL) {
+ return;
+ }
+ }
+ FT_Prop_Set_Func func = (FT_Prop_Set_Func)dlsym(lib, "FT_Property_Set");
+ if (func != NULL) {
+ func(library, module, property, (void*)(&version));
+ }
+ dlclose(lib);
+#endif
+}
+
/*
* Class: sun_font_FreetypeFontScaler
* Method: initNativeScaler
@@ -243,6 +335,7 @@
free(scalerInfo);
return 0;
}
+ setInterpreterVersion(scalerInfo->library);
#define TYPE1_FROM_JAVA 2
@@ -542,16 +635,17 @@
to avoid unnecesary work with bitmaps. */
GlyphInfo *info;
- jfloat advance;
+ jfloat advance = 0.0f;
jlong image;
image = Java_sun_font_FreetypeFontScaler_getGlyphImageNative(
env, scaler, font2D, pScalerContext, pScaler, glyphCode);
info = (GlyphInfo*) jlong_to_ptr(image);
- advance = info->advanceX;
-
- free(info);
+ if (info != NULL) {
+ advance = info->advanceX;
+ free(info);
+ }
return advance;
}
@@ -689,6 +783,13 @@
}
+/* JDK does not use glyph images for fonts with a
+ * pixel size > 100 (see THRESHOLD in OutlineTextRenderer.java)
+ * so if the glyph bitmap image dimension is > 1024 pixels,
+ * something is up.
+ */
+#define MAX_GLYPH_DIM 1024
+
/*
* Class: sun_font_FreetypeFontScaler
* Method: getGlyphImageNative
@@ -762,6 +863,14 @@
/* generate bitmap if it is not done yet
e.g. if algorithmic styling is performed and style was added to outline */
if (ftglyph->format == FT_GLYPH_FORMAT_OUTLINE) {
+ FT_BBox bbox;
+ FT_Outline_Get_CBox(&(ftglyph->outline), &bbox);
+ int w = (int)((bbox.xMax>>6)-(bbox.xMin>>6));
+ int h = (int)((bbox.yMax>>6)-(bbox.yMin>>6));
+ if (w > MAX_GLYPH_DIM || h > MAX_GLYPH_DIM) {
+ glyphInfo = getNullGlyphImage();
+ return ptr_to_jlong(glyphInfo);
+ }
error = FT_Render_Glyph(ftglyph, FT_LOAD_TARGET_MODE(target));
if (error != 0) {
return ptr_to_jlong(getNullGlyphImage());
@@ -770,6 +879,11 @@
width = (UInt16) ftglyph->bitmap.width;
height = (UInt16) ftglyph->bitmap.rows;
+ if (width > MAX_GLYPH_DIM || height > MAX_GLYPH_DIM) {
+ glyphInfo = getNullGlyphImage();
+ return ptr_to_jlong(glyphInfo);
+ }
+
imageSize = width*height;
glyphInfo = (GlyphInfo*) malloc(sizeof(GlyphInfo) + imageSize);