Skip to content

Commit

Permalink
Merge branch 'jfx23-cpu-2404' into merge-jfx23-cpu-2404
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinrushforth committed Apr 16, 2024
2 parents 44d53ba + c721a4b commit b3b0e5e
Show file tree
Hide file tree
Showing 20 changed files with 543 additions and 166 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -954,15 +954,14 @@ private String findFile(String name) {
private static String sysFontDir = null;
private static String userFontDir = null;

private static native byte[] getFontPath();
private static native String getFontPath();

private static void getPlatformFontDirs() {

if (userFontDir != null || sysFontDir != null) {
return;
}
byte [] pathBytes = getFontPath();
String path = new String(pathBytes);
String path = getFontPath();

int scIdx = path.indexOf(';');
if (scIdx < 0) {
Expand Down
116 changes: 95 additions & 21 deletions modules/javafx.graphics/src/main/native-font/coretext.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#if TARGET_OS_MAC

#include <stdint.h>
#include <jni.h>
#include <com_sun_javafx_font_coretext_OS.h>

Expand All @@ -43,6 +44,12 @@

#define OS_NATIVE(func) Java_com_sun_javafx_font_coretext_OS_##func

#define SAFE_FREE(PTR) \
if ((PTR) != NULL) { \
free(PTR); \
(PTR) = NULL; \
}

extern jboolean checkAndClearException(JNIEnv *env);

jboolean checkAndClearException(JNIEnv *env)
Expand Down Expand Up @@ -665,7 +672,13 @@ JNIEXPORT jlong JNICALL OS_NATIVE(CFStringCreateWithCharacters__J_3CJJ)
{
jchar *lparg1=NULL;
jlong rc = 0;
if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
if (!arg1) goto fail;
if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail;
if (arg2 < 0) goto fail;
if (arg3 < 0) goto fail;
if (arg2 > LONG_MAX - arg3) goto fail;
if (arg2 + arg3 > (*env)->GetArrayLength(env, arg1)) goto fail;

UniChar* str = lparg1 + arg2;
rc = (jlong)CFStringCreateWithCharacters((CFAllocatorRef)arg0, str, (CFIndex)arg3);
fail:
Expand All @@ -679,7 +692,7 @@ JNIEXPORT jint JNICALL OS_NATIVE(CTRunGetGlyphs)
CTRunRef run = (CTRunRef)runRef;
const CGGlyph * glyphs = CTRunGetGlyphsPtr(run);
CFIndex count = CTRunGetGlyphCount(run);
if (count == 0) {
if (count == 0 || count > SIZE_MAX / sizeof(CGGlyph)) {
return 0;
}

Expand Down Expand Up @@ -823,10 +836,17 @@ JNIEXPORT jbyteArray JNICALL OS_NATIVE(CGImageContextGetData)
(JNIEnv *env, jclass that, jlong arg0, jint dstWidth, jint dstHeight, jint bpp)
{
jbyteArray result = NULL;
if (dstWidth < 0) return NULL;
if (dstHeight < 0) return NULL;
if (dstWidth <= 0) return NULL;
if (dstHeight <= 0) return NULL;
if (bpp != 32) return NULL;

size_t dstStep = bpp / 8;
// for these checks we tested above that dstWidth/dstHeight/bpp cannot be 0
// checks are against INT_MAX - dst* variables are used later in
// (*env)->NewByteArray() which expects jint
if (dstWidth > (INT_MAX / dstStep)) return NULL;
if (dstHeight > (INT_MAX / (dstWidth * dstStep))) return NULL;

CGContextRef context = (CGContextRef)arg0;
if (context == NULL) return NULL;
jbyte *srcData = (jbyte*)CGBitmapContextGetData(context);
Expand All @@ -838,15 +858,15 @@ JNIEXPORT jbyteArray JNICALL OS_NATIVE(CGImageContextGetData)
if (srcHeight < dstHeight) return NULL;
size_t srcBytesPerRow = CGBitmapContextGetBytesPerRow(context);
size_t srcStep = CGBitmapContextGetBitsPerPixel(context) / 8;
int srcOffset = (srcHeight - dstHeight) * srcBytesPerRow;
if (srcBytesPerRow == 0) return NULL;
if ((srcHeight - dstHeight) > SIZE_MAX / srcBytesPerRow) return NULL;
size_t srcOffset = (srcHeight - dstHeight) * srcBytesPerRow;

int dstStep = bpp / 8;
size_t size = dstWidth * dstHeight * dstStep;
jbyte* data = (jbyte*)calloc(size, sizeof(jbyte));
if (data == NULL) return NULL;

int x, y, sx;

int dstOffset = 0;
for (y = 0; y < dstHeight; y++) {
for (x = 0, sx = 0; x < dstWidth; x++, dstOffset += dstStep, sx += srcStep) {
Expand All @@ -872,11 +892,20 @@ JNIEXPORT jbyteArray JNICALL OS_NATIVE(CGBitmapContextGetData)
(JNIEnv *env, jclass that, jlong arg0, jint dstWidth, jint dstHeight, jint bpp)
{
jbyteArray result = NULL;
if (dstWidth < 0) return NULL;
if (dstHeight < 0) return NULL;
if (dstWidth <= 0) return NULL;
if (dstHeight <= 0) return NULL;
if (bpp != 8 && bpp != 24) return NULL;
CGContextRef context = (CGContextRef)arg0;
if (context == NULL) return NULL;

//bits per pixel, either 8 for gray or 24 for LCD.
size_t dstStep = bpp / 8;
// for these checks we tested above that dstWidth/dstHeight/bpp cannot be 0
// checks are against INT_MAX - dst* variables are used later in
// (*env)->NewByteArray() which expects jint
if (dstWidth > (INT_MAX / dstStep)) return NULL;
if (dstHeight > (INT_MAX / (dstWidth * dstStep))) return NULL;

jbyte *srcData = (jbyte*)CGBitmapContextGetData(context);

if (srcData) {
Expand All @@ -886,12 +915,11 @@ JNIEXPORT jbyteArray JNICALL OS_NATIVE(CGBitmapContextGetData)
size_t srcHeight = CGBitmapContextGetHeight(context);
if (srcHeight < dstHeight) return NULL;
size_t srcBytesPerRow = CGBitmapContextGetBytesPerRow(context);
if (srcBytesPerRow == 0) return NULL;
if ((srcHeight - dstHeight) > SIZE_MAX / srcBytesPerRow) return NULL;
size_t srcStep = CGBitmapContextGetBitsPerPixel(context) / 8;
int srcOffset = (srcHeight - dstHeight) * srcBytesPerRow;

size_t srcOffset = (srcHeight - dstHeight) * srcBytesPerRow;

//bits per pixel, either 8 for gray or 24 for LCD.
int dstStep = bpp / 8;
size_t size = dstWidth * dstHeight * dstStep;
jbyte* data = (jbyte*)calloc(size, sizeof(jbyte));
if (data == NULL) return NULL;
Expand Down Expand Up @@ -1055,18 +1083,37 @@ static const int DEFAULT_LEN_TYPES = 10;
static const int DEFAULT_LEN_COORDS = 50;
typedef struct _PathData {
jbyte* pointTypes;
int numTypes;
int lenTypes;
size_t numTypes;
size_t lenTypes;
jfloat* pointCoords;
int numCoords;
int lenCoords;
size_t numCoords;
size_t lenCoords;
} PathData;

void pathApplierFunctionFast(void *i, const CGPathElement *e) {
PathData *info = (PathData *)i;

// point data buffers should always be valid, skip consecutive path
// applications if realloc() calls failed earlier on
if (info->pointTypes == NULL || info->pointCoords == NULL) {
return;
}

if (info->numTypes == info->lenTypes) {
if (info->lenTypes > SIZE_MAX - DEFAULT_LEN_TYPES) {
goto fail;
}
info->lenTypes += DEFAULT_LEN_TYPES;
info->pointTypes = (jbyte*)realloc(info->pointTypes, info->lenTypes * sizeof(jbyte));

if (info->lenTypes > (SIZE_MAX / sizeof(jbyte))) {
goto fail;
}
jbyte* newPointTypes = (jbyte*)realloc(info->pointTypes, info->lenTypes * sizeof(jbyte));
if (newPointTypes == NULL) {
goto fail;
}

info->pointTypes = newPointTypes;
}
jint type;
int coordCount = 0;
Expand Down Expand Up @@ -1095,15 +1142,34 @@ void pathApplierFunctionFast(void *i, const CGPathElement *e) {
info->pointTypes[info->numTypes++] = type;

if (info->numCoords + (coordCount * 2) > info->lenCoords) {
if (info->lenCoords > SIZE_MAX - DEFAULT_LEN_COORDS) {
goto fail;
}
info->lenCoords += DEFAULT_LEN_COORDS;
info->pointCoords = (jfloat*)realloc(info->pointCoords, info->lenCoords * sizeof(jfloat));

if (info->lenCoords > (SIZE_MAX / sizeof(jfloat))) {
goto fail;
}
jfloat* newPointCoords = (jfloat*)realloc(info->pointCoords, info->lenCoords * sizeof(jfloat));
if (newPointCoords == NULL) {
goto fail;
}

info->pointCoords = newPointCoords;
}
int j;
for (j = 0; j < coordCount; j++) {
CGPoint pt = e->points[j];
info->pointCoords[info->numCoords++] = pt.x;
info->pointCoords[info->numCoords++] = pt.y;
}

return;

fail:
fprintf(stderr, "OS_NATIVE error: pathApplierFunctionFast allocations failed");
SAFE_FREE(info->pointCoords);
SAFE_FREE(info->pointTypes);
}

JNIEXPORT jobject JNICALL OS_NATIVE(CGPathApply)
Expand All @@ -1118,8 +1184,16 @@ JNIEXPORT jobject JNICALL OS_NATIVE(CGPathApply)
data.numCoords = 0;
data.lenCoords = DEFAULT_LEN_COORDS;

if (data.pointTypes == NULL || data.pointCoords == NULL) {
goto fail;
}

CGPathApply((CGPathRef)arg0, &data, pathApplierFunctionFast);

if (data.pointTypes == NULL || data.pointCoords == NULL) {
goto fail;
}

static jclass path2DClass = NULL;
static jmethodID path2DCtr = NULL;
if (path2DClass == NULL) {
Expand Down Expand Up @@ -1158,8 +1232,8 @@ JNIEXPORT jobject JNICALL OS_NATIVE(CGPathApply)
}
}
fail:
free(data.pointTypes);
free(data.pointCoords);
SAFE_FREE(data.pointTypes);
SAFE_FREE(data.pointCoords);
return path2D;
}

Expand Down
9 changes: 9 additions & 0 deletions modules/javafx.graphics/src/main/native-font/directwrite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1517,6 +1517,8 @@ JNIEXPORT jint JNICALL OS_NATIVE(JFXTextRendererGetGlyphIndices)
if (!arg1) return 0;
jint* data = env->GetIntArrayElements(arg1, NULL);
if (!data) return 0;
if (start < 0) return 0;
if (slot < 0) return 0;

JFXTextRenderer* renderer = (JFXTextRenderer*)arg0;
// Type cast unsigned int to int. It is safe to assume that GetGlyphCount will never exceed max of jint
Expand All @@ -1538,6 +1540,7 @@ JNIEXPORT jint JNICALL OS_NATIVE(JFXTextRendererGetGlyphAdvances)
if (!arg1) return 0;
jfloat* data = env->GetFloatArrayElements(arg1, NULL);
if (!data) return 0;
if (start < 0) return 0;

JFXTextRenderer* renderer = (JFXTextRenderer*)arg0;
// Type cast unsigned int to int. It is safe to assume that GetGlyphCount will never exceed max of jint
Expand All @@ -1559,12 +1562,14 @@ JNIEXPORT jint JNICALL OS_NATIVE(JFXTextRendererGetGlyphOffsets)
if (!arg1) return 0;
jfloat* data = env->GetFloatArrayElements(arg1, NULL);
if (!data) return 0;
if (start < 0) return 0;

JFXTextRenderer* renderer = (JFXTextRenderer*)arg0;
// Type cast unsigned int to int. It is safe to assume the result will never exceed max of jint
jint offsetCount = (jint) renderer->GetGlyphCount() * 2;
jint length = env->GetArrayLength(arg1);
jint copiedCount = length - start > offsetCount ? offsetCount : length - start;
if (copiedCount % 2 != 0) return 0;

const DWRITE_GLYPH_OFFSET* offsets = renderer->GetGlyphOffsets();
UINT32 i = 0, j = 0;
Expand All @@ -1582,6 +1587,8 @@ JNIEXPORT jint JNICALL OS_NATIVE(JFXTextRendererGetClusterMap)
if (!arg1) return 0;
jshort* data = env->GetShortArrayElements(arg1, NULL);
if (!data) return 0;
if (start < 0) return 0;
if (glyphStart < 0) return 0;

JFXTextRenderer* renderer = (JFXTextRenderer*)arg0;
// Type cast unsigned int to int. It is safe to assume that GetLength will never exceed max of jint
Expand Down Expand Up @@ -1890,6 +1897,8 @@ JNIEXPORT jlong JNICALL OS_NATIVE(CreateTextLayout)
IDWriteTextLayout* result = NULL;
jchar *lparg1 = NULL;
if (arg1) if ((lparg1 = env->GetCharArrayElements(arg1, NULL)) == NULL) goto fail;
if (start < 0 || count < 0) goto fail;
if (count > INT_MAX - start) goto fail;
if (start + count > env->GetArrayLength(arg1)) goto fail;

const WCHAR * text = (const WCHAR *)(lparg1 + start);
Expand Down
Loading

0 comments on commit b3b0e5e

Please sign in to comment.