1 /* 2 * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #ifdef __APPLE__ 27 #include <TargetConditionals.h> 28 29 #if TARGET_OS_MAC 30 31 #include <jni.h> 32 #include <com_sun_javafx_font_coretext_OS.h> 33 34 #import <CoreFoundation/CoreFoundation.h> 35 36 #if TARGET_OS_IPHONE 37 #import <CoreGraphics/CoreGraphics.h> 38 #import <CoreText/CoreText.h> 39 #else 40 #import <ApplicationServices/ApplicationServices.h> 41 #endif 42 43 44 #define OS_NATIVE(func) Java_com_sun_javafx_font_coretext_OS_##func 45 46 extern jboolean checkAndClearException(JNIEnv *env); 47 48 jboolean checkAndClearException(JNIEnv *env) 49 { 50 jthrowable t = (*env)->ExceptionOccurred(env); 51 if (!t) { 52 return JNI_FALSE; 53 } 54 (*env)->ExceptionClear(env); 55 return JNI_TRUE; 56 } 57 58 /**************************************************************************/ 59 /* */ 60 /* Structs */ 61 /* */ 62 /**************************************************************************/ 63 typedef struct CGAffineTransform_FID_CACHE { 64 int cached; 65 jclass clazz; 66 jfieldID a, b, c, d, tx, ty; 67 jmethodID init; 68 } CGAffineTransform_FID_CACHE; 69 70 CGAffineTransform_FID_CACHE CGAffineTransformFc; 71 72 void cacheCGAffineTransformFields(JNIEnv *env) 73 { 74 if (CGAffineTransformFc.cached) return; 75 jclass tmpClass = (*env)->FindClass(env, "com/sun/javafx/font/coretext/CGAffineTransform"); 76 if (checkAndClearException(env) || !tmpClass) { 77 fprintf(stderr, "cacheCGAffineTransformFields error: JNI exception or tmpClass == NULL"); 78 return; 79 } 80 CGAffineTransformFc.clazz = (jclass)(*env)->NewGlobalRef(env, tmpClass); 81 CGAffineTransformFc.a = (*env)->GetFieldID(env, CGAffineTransformFc.clazz, "a", "D"); 82 if (checkAndClearException(env) || !CGAffineTransformFc.a) { 83 fprintf(stderr, "cacheCGAffineTransformFields error: JNI exception or a == NULL"); 84 return; 85 } 86 CGAffineTransformFc.b = (*env)->GetFieldID(env, CGAffineTransformFc.clazz, "b", "D"); 87 if (checkAndClearException(env) || !CGAffineTransformFc.b) { 88 fprintf(stderr, "cacheCGAffineTransformFields error: JNI exception or b == NULL"); 89 return; 90 } 91 CGAffineTransformFc.c = (*env)->GetFieldID(env, CGAffineTransformFc.clazz, "c", "D"); 92 if (checkAndClearException(env) || !CGAffineTransformFc.c) { 93 fprintf(stderr, "cacheCGAffineTransformFields error: JNI exception or c == NULL"); 94 return; 95 } 96 CGAffineTransformFc.d = (*env)->GetFieldID(env, CGAffineTransformFc.clazz, "d", "D"); 97 if (checkAndClearException(env) || !CGAffineTransformFc.d) { 98 fprintf(stderr, "cacheCGAffineTransformFields error: JNI exception or d == NULL"); 99 return; 100 } 101 CGAffineTransformFc.tx = (*env)->GetFieldID(env, CGAffineTransformFc.clazz, "tx", "D"); 102 if (checkAndClearException(env) || !CGAffineTransformFc.tx) { 103 fprintf(stderr, "cacheCGAffineTransformFields error: JNI exception or tx == NULL"); 104 return; 105 } 106 CGAffineTransformFc.ty = (*env)->GetFieldID(env, CGAffineTransformFc.clazz, "ty", "D"); 107 if (checkAndClearException(env) || !CGAffineTransformFc.ty) { 108 fprintf(stderr, "cacheCGAffineTransformFields error: JNI exception or ty == NULL"); 109 return; 110 } 111 CGAffineTransformFc.init = (*env)->GetMethodID(env, CGAffineTransformFc.clazz, "<init>", "()V"); 112 if (checkAndClearException(env) || !CGAffineTransformFc.init) { 113 fprintf(stderr, "cacheCGAffineTransformFields error: JNI exception or init == NULL"); 114 return; 115 } 116 CGAffineTransformFc.cached = 1; 117 } 118 119 CGAffineTransform *getCGAffineTransformFields(JNIEnv *env, jobject lpObject, CGAffineTransform *lpStruct) 120 { 121 if (!CGAffineTransformFc.cached) cacheCGAffineTransformFields(env); 122 lpStruct->a = (*env)->GetDoubleField(env, lpObject, CGAffineTransformFc.a); 123 lpStruct->b = (*env)->GetDoubleField(env, lpObject, CGAffineTransformFc.b); 124 lpStruct->c = (*env)->GetDoubleField(env, lpObject, CGAffineTransformFc.c); 125 lpStruct->d = (*env)->GetDoubleField(env, lpObject, CGAffineTransformFc.d); 126 lpStruct->tx = (*env)->GetDoubleField(env, lpObject, CGAffineTransformFc.tx); 127 lpStruct->ty = (*env)->GetDoubleField(env, lpObject, CGAffineTransformFc.ty); 128 return lpStruct; 129 } 130 131 void setCGAffineTransformFields(JNIEnv *env, jobject lpObject, CGAffineTransform *lpStruct) 132 { 133 if (!CGAffineTransformFc.cached) cacheCGAffineTransformFields(env); 134 (*env)->SetDoubleField(env, lpObject, CGAffineTransformFc.a, (jdouble)lpStruct->a); 135 (*env)->SetDoubleField(env, lpObject, CGAffineTransformFc.b, (jdouble)lpStruct->b); 136 (*env)->SetDoubleField(env, lpObject, CGAffineTransformFc.c, (jdouble)lpStruct->c); 137 (*env)->SetDoubleField(env, lpObject, CGAffineTransformFc.d, (jdouble)lpStruct->d); 138 (*env)->SetDoubleField(env, lpObject, CGAffineTransformFc.tx, (jdouble)lpStruct->tx); 139 (*env)->SetDoubleField(env, lpObject, CGAffineTransformFc.ty, (jdouble)lpStruct->ty); 140 } 141 142 jobject newCGAffineTransform(JNIEnv *env, CGAffineTransform *lpStruct) 143 { 144 jobject lpObject = NULL; 145 if (!CGAffineTransformFc.cached) cacheCGAffineTransformFields(env); 146 lpObject = (*env)->NewObject(env, CGAffineTransformFc.clazz, CGAffineTransformFc.init); 147 if (lpObject && lpStruct) setCGAffineTransformFields(env, lpObject, lpStruct); 148 return lpObject; 149 } 150 151 typedef struct CGPoint_FID_CACHE { 152 int cached; 153 jclass clazz; 154 jfieldID x, y; 155 jmethodID init; 156 } CGPoint_FID_CACHE; 157 158 CGPoint_FID_CACHE CGPointFc; 159 160 void cacheCGPointFields(JNIEnv *env) 161 { 162 if (CGPointFc.cached) return; 163 jclass tmpClass = (*env)->FindClass(env, "com/sun/javafx/font/coretext/CGPoint"); 164 if (checkAndClearException(env) || !tmpClass) { 165 fprintf(stderr, "cacheCGPointFields error: JNI exception or tmpClass == NULL"); 166 return; 167 } 168 CGPointFc.clazz = (jclass)(*env)->NewGlobalRef(env, tmpClass); 169 CGPointFc.x = (*env)->GetFieldID(env, CGPointFc.clazz, "x", "D"); 170 if (checkAndClearException(env) || !CGPointFc.x) { 171 fprintf(stderr, "cacheCGPointFields error: JNI exception or x == NULL"); 172 return; 173 } 174 CGPointFc.y = (*env)->GetFieldID(env, CGPointFc.clazz, "y", "D"); 175 if (checkAndClearException(env) || !CGPointFc.y) { 176 fprintf(stderr, "cacheCGPointFields error: JNI exception or y == NULL"); 177 return; 178 } 179 CGPointFc.init = (*env)->GetMethodID(env, CGPointFc.clazz, "<init>", "()V"); 180 if (checkAndClearException(env) || !CGPointFc.init) { 181 fprintf(stderr, "cacheCGPointFields error: JNI exception or init == NULL"); 182 return; 183 } 184 CGPointFc.cached = 1; 185 } 186 187 CGPoint *getCGPointFields(JNIEnv *env, jobject lpObject, CGPoint *lpStruct) 188 { 189 if (!CGPointFc.cached) cacheCGPointFields(env); 190 lpStruct->x = (*env)->GetDoubleField(env, lpObject, CGPointFc.x); 191 lpStruct->y = (*env)->GetDoubleField(env, lpObject, CGPointFc.y); 192 return lpStruct; 193 } 194 195 void setCGPointFields(JNIEnv *env, jobject lpObject, CGPoint *lpStruct) 196 { 197 if (!CGPointFc.cached) cacheCGPointFields(env); 198 (*env)->SetDoubleField(env, lpObject, CGPointFc.x, (jdouble)lpStruct->x); 199 (*env)->SetDoubleField(env, lpObject, CGPointFc.y, (jdouble)lpStruct->y); 200 } 201 202 jobject newCGPoint(JNIEnv *env, CGPoint *lpStruct) 203 { 204 jobject lpObject = NULL; 205 if (!CGPointFc.cached) cacheCGPointFields(env); 206 lpObject = (*env)->NewObject(env, CGPointFc.clazz, CGPointFc.init); 207 if (lpObject && lpStruct) setCGPointFields(env, lpObject, lpStruct); 208 return lpObject; 209 } 210 211 typedef struct CGSize_FID_CACHE { 212 int cached; 213 jclass clazz; 214 jfieldID width, height; 215 jmethodID init; 216 } CGSize_FID_CACHE; 217 218 CGSize_FID_CACHE CGSizeFc; 219 220 void cacheCGSizeFields(JNIEnv *env) 221 { 222 if (CGSizeFc.cached) return; 223 jclass tmpClass = (*env)->FindClass(env, "com/sun/javafx/font/coretext/CGSize"); 224 if (checkAndClearException(env) || !tmpClass) { 225 fprintf(stderr, "cacheCGSizeFields error: JNI exception or tmpClass == NULL"); 226 return; 227 } 228 CGSizeFc.clazz = (jclass)(*env)->NewGlobalRef(env, tmpClass); 229 CGSizeFc.width = (*env)->GetFieldID(env, CGSizeFc.clazz, "width", "D"); 230 if (checkAndClearException(env) || !CGSizeFc.width) { 231 fprintf(stderr, "cacheCGSizeFields error: JNI exception or width == NULL"); 232 return; 233 } 234 CGSizeFc.height = (*env)->GetFieldID(env, CGSizeFc.clazz, "height", "D"); 235 if (checkAndClearException(env) || !CGSizeFc.height) { 236 fprintf(stderr, "cacheCGSizeFields error: JNI exception or height == NULL"); 237 return; 238 } 239 CGSizeFc.init = (*env)->GetMethodID(env, CGSizeFc.clazz, "<init>", "()V"); 240 if (checkAndClearException(env) || !CGSizeFc.init) { 241 fprintf(stderr, "cacheCGSizeFields error: JNI exception or init == NULL"); 242 return; 243 } 244 CGSizeFc.cached = 1; 245 } 246 247 CGSize *getCGSizeFields(JNIEnv *env, jobject lpObject, CGSize *lpStruct) 248 { 249 if (!CGSizeFc.cached) cacheCGSizeFields(env); 250 lpStruct->width = (*env)->GetDoubleField(env, lpObject, CGSizeFc.width); 251 lpStruct->height = (*env)->GetDoubleField(env, lpObject, CGSizeFc.height); 252 return lpStruct; 253 } 254 255 void setCGSizeFields(JNIEnv *env, jobject lpObject, CGSize *lpStruct) 256 { 257 if (!CGSizeFc.cached) cacheCGSizeFields(env); 258 (*env)->SetDoubleField(env, lpObject, CGSizeFc.width, (jdouble)lpStruct->width); 259 (*env)->SetDoubleField(env, lpObject, CGSizeFc.height, (jdouble)lpStruct->height); 260 } 261 262 jobject newCGSize(JNIEnv *env, CGSize *lpStruct) 263 { 264 jobject lpObject = NULL; 265 if (!CGSizeFc.cached) cacheCGSizeFields(env); 266 lpObject = (*env)->NewObject(env, CGSizeFc.clazz, CGSizeFc.init); 267 if (lpObject && lpStruct) setCGSizeFields(env, lpObject, lpStruct); 268 return lpObject; 269 } 270 271 typedef struct CGRect_FID_CACHE { 272 int cached; 273 jclass clazz; 274 jfieldID origin, size; 275 jmethodID init; 276 } CGRect_FID_CACHE; 277 278 CGRect_FID_CACHE CGRectFc; 279 280 void cacheCGRectFields(JNIEnv *env) 281 { 282 if (CGRectFc.cached) return; 283 jclass tmpClass = (*env)->FindClass(env, "com/sun/javafx/font/coretext/CGRect"); 284 if (checkAndClearException(env) || !tmpClass) { 285 fprintf(stderr, "cacheCGRectFields error: JNI exception or tmpClass == NULL"); 286 return; 287 } 288 CGRectFc.clazz = (jclass)(*env)->NewGlobalRef(env, tmpClass); 289 CGRectFc.origin = (*env)->GetFieldID(env, CGRectFc.clazz, "origin", "Lcom/sun/javafx/font/coretext/CGPoint;"); 290 if (checkAndClearException(env) || !CGRectFc.origin) { 291 fprintf(stderr, "cacheCGRectFields error: JNI exception or origin == NULL"); 292 return; 293 } 294 CGRectFc.size = (*env)->GetFieldID(env, CGRectFc.clazz, "size", "Lcom/sun/javafx/font/coretext/CGSize;"); 295 if (checkAndClearException(env) || !CGRectFc.size) { 296 fprintf(stderr, "cacheCGRectFields error: JNI exception or size == NULL"); 297 return; 298 } 299 CGRectFc.init = (*env)->GetMethodID(env, CGRectFc.clazz, "<init>", "()V"); 300 if (checkAndClearException(env) || !CGRectFc.init) { 301 fprintf(stderr, "cacheCGRectFields error: JNI exception or init == NULL"); 302 return; 303 } 304 CGRectFc.cached = 1; 305 } 306 307 CGRect *getCGRectFields(JNIEnv *env, jobject lpObject, CGRect *lpStruct) 308 { 309 if (!CGRectFc.cached) cacheCGRectFields(env); 310 { 311 jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CGRectFc.origin); 312 if (lpObject1 != NULL) getCGPointFields(env, lpObject1, &lpStruct->origin); 313 } 314 { 315 jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CGRectFc.size); 316 if (lpObject1 != NULL) getCGSizeFields(env, lpObject1, &lpStruct->size); 317 } 318 return lpStruct; 319 } 320 321 void setCGRectFields(JNIEnv *env, jobject lpObject, CGRect *lpStruct) 322 { 323 if (!CGRectFc.cached) cacheCGRectFields(env); 324 { 325 jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CGRectFc.origin); 326 if (lpObject1 != NULL) setCGPointFields(env, lpObject1, &lpStruct->origin); 327 } 328 { 329 jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CGRectFc.size); 330 if (lpObject1 != NULL) setCGSizeFields(env, lpObject1, &lpStruct->size); 331 } 332 } 333 334 jobject newCGRect(JNIEnv *env, CGRect *lpStruct) 335 { 336 jobject lpObject = NULL; 337 if (!CGRectFc.cached) cacheCGRectFields(env); 338 lpObject = (*env)->NewObject(env, CGRectFc.clazz, CGRectFc.init); 339 if (lpObject && lpStruct) setCGRectFields(env, lpObject, lpStruct); 340 return lpObject; 341 } 342 343 /**************************************************************************/ 344 /* */ 345 /* Functions */ 346 /* */ 347 /**************************************************************************/ 348 349 JNIEXPORT jlong JNICALL OS_NATIVE(kCFAllocatorDefault) 350 (JNIEnv *env, jclass that) 351 { 352 return (jlong)kCFAllocatorDefault; 353 } 354 355 JNIEXPORT jlong JNICALL OS_NATIVE(CFStringCreateWithCharacters__J_3CJ) 356 (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jlong arg2) 357 { 358 jchar *lparg1=NULL; 359 jlong rc = 0; 360 if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail; 361 rc = (jlong)CFStringCreateWithCharacters((CFAllocatorRef)arg0, (UniChar*)lparg1, (CFIndex)arg2); 362 fail: 363 if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, 0); 364 return rc; 365 } 366 367 JNIEXPORT void JNICALL OS_NATIVE(CFRelease) 368 (JNIEnv *env, jclass that, jlong arg0) 369 { 370 CFRelease((CFTypeRef)arg0); 371 } 372 373 JNIEXPORT jlong JNICALL OS_NATIVE(CTFontCreateWithGraphicsFont) 374 (JNIEnv *env, jclass that, jlong cgFont, jdouble size, jobject matrix, jlong attributes) 375 { 376 CGAffineTransform transform; 377 if (matrix) { 378 getCGAffineTransformFields(env, matrix, &transform); 379 } else { 380 transform = CGAffineTransformIdentity; 381 } 382 return (jlong)CTFontCreateWithGraphicsFont((CGFontRef)cgFont, (CGFloat)size, &transform, (CTFontDescriptorRef)attributes); 383 } 384 385 JNIEXPORT jlong JNICALL OS_NATIVE(CTFontCreateWithName) 386 (JNIEnv *env, jclass that, jlong arg0, jdouble arg1, jobject arg2) 387 { 388 CGAffineTransform _arg2, *lparg2=NULL; 389 jlong rc = 0; 390 if (arg2) if ((lparg2 = getCGAffineTransformFields(env, arg2, &_arg2)) == NULL) goto fail; 391 rc = (jlong)CTFontCreateWithName((CFStringRef)arg0, (CGFloat)arg1, (CGAffineTransform*)lparg2); 392 fail: 393 /* In only */ 394 // if (arg2 && lparg2) setCGAffineTransformFields(env, arg2, lparg2); 395 return rc; 396 } 397 398 399 JNIEXPORT jlong JNICALL OS_NATIVE(CFURLCreateWithFileSystemPath) 400 (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jboolean arg3) 401 { 402 return (jlong)CFURLCreateWithFileSystemPath((CFAllocatorRef)arg0, (CFStringRef)arg1, (CFURLPathStyle)arg2, (Boolean)arg3); 403 } 404 405 JNIEXPORT jboolean JNICALL OS_NATIVE(CTFontManagerRegisterFontsForURL) 406 (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2) 407 { 408 return (jboolean)CTFontManagerRegisterFontsForURL((CFURLRef)arg0, (CTFontManagerScope)arg1, (CFErrorRef*)arg2); 409 } 410 411 JNIEXPORT jlong JNICALL OS_NATIVE(CTFontCreatePathForGlyph) 412 (JNIEnv *env, jclass that, jlong arg0, jshort arg1, jobject arg2) 413 { 414 CGAffineTransform _arg2, *lparg2=NULL; 415 jlong rc = 0; 416 if (arg2) if ((lparg2 = getCGAffineTransformFields(env, arg2, &_arg2)) == NULL) goto fail; 417 rc = (jlong)CTFontCreatePathForGlyph((CTFontRef)arg0, (CGGlyph)arg1, (CGAffineTransform*)lparg2); 418 fail: 419 /* In Only */ 420 // if (arg2 && lparg2) setCGAffineTransformFields(env, arg2, lparg2); 421 return rc; 422 } 423 424 JNIEXPORT jlong JNICALL OS_NATIVE(CGFontCreateWithDataProvider) 425 (JNIEnv *env, jclass that, jlong dataProvider) 426 { 427 return (jlong)CGFontCreateWithDataProvider((CGDataProviderRef)dataProvider); 428 } 429 430 JNIEXPORT void JNICALL OS_NATIVE(CGPathRelease) 431 (JNIEnv *env, jclass that, jlong arg0) 432 { 433 CGPathRelease((CGPathRef)arg0); 434 } 435 436 JNIEXPORT jlong JNICALL OS_NATIVE(CGColorSpaceCreateDeviceRGB) 437 (JNIEnv *env, jclass that) 438 { 439 return (jlong)CGColorSpaceCreateDeviceRGB(); 440 } 441 442 JNIEXPORT jlong JNICALL OS_NATIVE(CGColorSpaceCreateDeviceGray) 443 (JNIEnv *env, jclass that) 444 { 445 return (jlong)CGColorSpaceCreateDeviceGray(); 446 } 447 448 JNIEXPORT jlong JNICALL OS_NATIVE(CGBitmapContextCreate) 449 (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlong arg3, jlong arg4, jlong arg5, jint arg6) 450 { 451 return (jlong)CGBitmapContextCreate((void*)arg0, (size_t)arg1, (size_t)arg2, (size_t)arg3, (size_t)arg4, (CGColorSpaceRef)arg5, (CGBitmapInfo)arg6); 452 } 453 454 JNIEXPORT void JNICALL OS_NATIVE(CGContextSetAllowsFontSmoothing) 455 (JNIEnv *env, jclass that, jlong arg0, jboolean arg1) 456 { 457 CGContextSetAllowsFontSmoothing((CGContextRef)arg0, (_Bool)arg1); 458 } 459 460 JNIEXPORT void JNICALL OS_NATIVE(CGContextSetAllowsAntialiasing) 461 (JNIEnv *env, jclass that, jlong arg0, jboolean arg1) 462 { 463 CGContextSetAllowsAntialiasing((CGContextRef)arg0, (_Bool)arg1); 464 } 465 466 JNIEXPORT void JNICALL OS_NATIVE(CGContextSetAllowsFontSubpixelPositioning) 467 (JNIEnv *env, jclass that, jlong arg0, jboolean arg1) 468 { 469 CGContextSetAllowsFontSubpixelPositioning((CGContextRef)arg0, (_Bool)arg1); 470 } 471 472 JNIEXPORT void JNICALL OS_NATIVE(CGContextSetAllowsFontSubpixelQuantization) 473 (JNIEnv *env, jclass that, jlong arg0, jboolean arg1) 474 { 475 CGContextSetAllowsFontSubpixelQuantization((CGContextRef)arg0, (_Bool)arg1); 476 } 477 478 JNIEXPORT void JNICALL OS_NATIVE(CGContextSetRGBFillColor) 479 (JNIEnv *env, jclass that, jlong arg0, jdouble arg1, jdouble arg2, jdouble arg3, jdouble arg4) 480 { 481 CGContextSetRGBFillColor((CGContextRef)arg0, (CGFloat)arg1, (CGFloat)arg2, (CGFloat)arg3, (CGFloat)arg4); 482 } 483 484 JNIEXPORT void JNICALL OS_NATIVE(CGContextFillRect) 485 (JNIEnv *env, jclass that, jlong arg0, jobject arg1) 486 { 487 CGRect _arg1, *lparg1=NULL; 488 /* In Only */ 489 if (arg1) if ((lparg1 = getCGRectFields(env, arg1, &_arg1)) == NULL) return; 490 CGContextFillRect((CGContextRef)arg0, *lparg1); 491 } 492 493 JNIEXPORT void JNICALL OS_NATIVE(CGContextTranslateCTM) 494 (JNIEnv *env, jclass that, jlong arg0, jdouble arg1, jdouble arg2) 495 { 496 CGContextTranslateCTM((CGContextRef)arg0, (CGFloat)arg1, (CGFloat)arg2); 497 } 498 499 JNIEXPORT void JNICALL OS_NATIVE(CGContextRelease) 500 (JNIEnv *env, jclass that, jlong arg0) 501 { 502 CGContextRelease((CGContextRef)arg0); 503 } 504 505 JNIEXPORT void JNICALL OS_NATIVE(CGColorSpaceRelease) 506 (JNIEnv *env, jclass that, jlong arg0) 507 { 508 CGColorSpaceRelease((CGColorSpaceRef)arg0); 509 } 510 511 JNIEXPORT jlong JNICALL OS_NATIVE(CGDataProviderCreateWithURL) 512 (JNIEnv *env, jclass that, jlong cfURL) { 513 return (jlong)CGDataProviderCreateWithURL((CFURLRef)cfURL); 514 } 515 516 JNIEXPORT jlong JNICALL OS_NATIVE(kCFTypeDictionaryKeyCallBacks) 517 (JNIEnv *env, jclass that) 518 { 519 return (jlong)&kCFTypeDictionaryKeyCallBacks; 520 } 521 522 JNIEXPORT jlong JNICALL OS_NATIVE(kCFTypeDictionaryValueCallBacks) 523 (JNIEnv *env, jclass that) 524 { 525 return (jlong)&kCFTypeDictionaryValueCallBacks; 526 } 527 528 JNIEXPORT jlong JNICALL OS_NATIVE(CFDictionaryCreateMutable) 529 (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlong arg3) 530 { 531 return (jlong)CFDictionaryCreateMutable((CFAllocatorRef)arg0, (CFIndex)arg1, (CFDictionaryKeyCallBacks*)arg2, (CFDictionaryValueCallBacks*)arg3); 532 } 533 534 JNIEXPORT void JNICALL OS_NATIVE(CFDictionaryAddValue) 535 (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2) 536 { 537 CFDictionaryAddValue((CFMutableDictionaryRef)arg0, (void*)arg1, (void*)arg2); 538 } 539 540 JNIEXPORT jlong JNICALL OS_NATIVE(CFDictionaryGetValue) 541 (JNIEnv *env, jclass that, jlong arg0, jlong arg1) 542 { 543 return (jlong)CFDictionaryGetValue((CFDictionaryRef)arg0, (void*)arg1); 544 } 545 546 JNIEXPORT jlong JNICALL OS_NATIVE(kCTFontAttributeName) 547 (JNIEnv *env, jclass that) 548 { 549 return (jlong)kCTFontAttributeName; 550 } 551 552 JNIEXPORT jlong JNICALL OS_NATIVE(kCTParagraphStyleAttributeName) 553 (JNIEnv *env, jclass that) 554 { 555 return (jlong)kCTParagraphStyleAttributeName; 556 } 557 558 JNIEXPORT jlong JNICALL OS_NATIVE(CFAttributedStringCreate) 559 (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2) 560 { 561 return (jlong)CFAttributedStringCreate((CFAllocatorRef)arg0, (CFStringRef)arg1, (CFDictionaryRef)arg2); 562 } 563 564 JNIEXPORT jlong JNICALL OS_NATIVE(CTLineCreateWithAttributedString) 565 (JNIEnv *env, jclass that, jlong arg0) 566 { 567 return (jlong)CTLineCreateWithAttributedString((CFAttributedStringRef)arg0); 568 } 569 570 JNIEXPORT jlong JNICALL OS_NATIVE(CTLineGetGlyphRuns) 571 (JNIEnv *env, jclass that, jlong arg0) 572 { 573 return (jlong)CTLineGetGlyphRuns((CTLineRef)arg0); 574 } 575 576 JNIEXPORT jdouble JNICALL OS_NATIVE(CTLineGetTypographicBounds) 577 (JNIEnv *env, jclass that, jlong arg0) 578 { 579 return (jdouble)CTLineGetTypographicBounds((CTLineRef)arg0, NULL, NULL, NULL); 580 } 581 582 JNIEXPORT jlong JNICALL OS_NATIVE(CTLineGetGlyphCount) 583 (JNIEnv *env, jclass that, jlong arg0) 584 { 585 return (jlong)CTLineGetGlyphCount((CTLineRef)arg0); 586 } 587 588 JNIEXPORT jlong JNICALL OS_NATIVE(CFArrayGetCount) 589 (JNIEnv *env, jclass that, jlong arg0) 590 { 591 return (jlong)CFArrayGetCount((CFArrayRef)arg0); 592 } 593 594 JNIEXPORT jlong JNICALL OS_NATIVE(CFArrayGetValueAtIndex) 595 (JNIEnv *env, jclass that, jlong arg0, jlong arg1) 596 { 597 return (jlong)CFArrayGetValueAtIndex((CFArrayRef)arg0, (CFIndex)arg1); 598 } 599 600 JNIEXPORT jlong JNICALL OS_NATIVE(CTRunGetGlyphCount) 601 (JNIEnv *env, jclass that, jlong arg0) 602 { 603 return (jlong)CTRunGetGlyphCount((CTRunRef)arg0); 604 } 605 606 JNIEXPORT jlong JNICALL OS_NATIVE(CTRunGetAttributes) 607 (JNIEnv *env, jclass that, jlong arg0) 608 { 609 return (jlong)CTRunGetAttributes((CTRunRef)arg0); 610 } 611 612 /**************************************************************************/ 613 /* */ 614 /* Custom Functions */ 615 /* */ 616 /**************************************************************************/ 617 618 619 JNIEXPORT jlong JNICALL OS_NATIVE(CFStringCreateWithCharacters__J_3CJJ) 620 (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jlong arg2, jlong arg3) 621 { 622 jchar *lparg1=NULL; 623 jlong rc = 0; 624 if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail; 625 UniChar* str = lparg1 + arg2; 626 rc = (jlong)CFStringCreateWithCharacters((CFAllocatorRef)arg0, str, (CFIndex)arg3); 627 fail: 628 if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, 0); 629 return rc; 630 } 631 632 JNIEXPORT jint JNICALL OS_NATIVE(CTRunGetGlyphs) 633 (JNIEnv *env, jclass that, jlong runRef, jint slotMask, jint start, jintArray bufferRef) 634 { 635 CTRunRef run = (CTRunRef)runRef; 636 const CGGlyph * glyphs = CTRunGetGlyphsPtr(run); 637 int i = 0; 638 if (glyphs) { 639 jint* buffer = (*env)->GetPrimitiveArrayCritical(env, bufferRef, NULL); 640 if (buffer) { 641 CFIndex count = CTRunGetGlyphCount(run); 642 while(i < count) { 643 buffer[start + i] = slotMask | (glyphs[i] & 0xFFFF); 644 i++; 645 } 646 (*env)->ReleasePrimitiveArrayCritical(env, bufferRef, buffer, 0); 647 } 648 } 649 return i; 650 } 651 652 JNIEXPORT jint JNICALL OS_NATIVE(CTRunGetPositions) 653 (JNIEnv *env, jclass that, jlong runRef, jint start, jfloatArray bufferRef) 654 { 655 CTRunRef run = (CTRunRef)runRef; 656 const CGPoint* positions = CTRunGetPositionsPtr(run); 657 int j = 0; 658 if (positions) { 659 jfloat* buffer = (*env)->GetPrimitiveArrayCritical(env, bufferRef, NULL); 660 if (buffer) { 661 CFIndex count = CTRunGetGlyphCount(run); 662 int i = 0; 663 while (i < count) { 664 CGPoint pos = positions[i++]; 665 buffer[start + j++] = pos.x; 666 buffer[start + j++] = pos.y; 667 } 668 (*env)->ReleasePrimitiveArrayCritical(env, bufferRef, buffer, 0); 669 } 670 } 671 return j; 672 } 673 674 JNIEXPORT jint JNICALL OS_NATIVE(CTRunGetStringIndices) 675 (JNIEnv *env, jclass that, jlong runRef, jint start, jintArray bufferRef) 676 { 677 CTRunRef run = (CTRunRef)runRef; 678 const CFIndex* indices = CTRunGetStringIndicesPtr(run); 679 CFIndex count = CTRunGetGlyphCount(run); 680 if (count == 0) { 681 return 0; 682 } 683 684 CFIndex* tempIndices = NULL; 685 if (!indices) { 686 tempIndices = (CFIndex*) malloc(count * sizeof(CFIndex)); 687 if (!tempIndices) { 688 return 0; 689 } 690 691 CTRunGetStringIndices(run, CFRangeMake(0, 0), tempIndices); 692 indices = tempIndices; 693 } 694 695 int i = 0; 696 if (indices) { 697 jint* buffer = (*env)->GetPrimitiveArrayCritical(env, bufferRef, NULL); 698 if (buffer) { 699 while(i < count) { 700 buffer[start + i] = indices[i]; 701 i++; 702 } 703 (*env)->ReleasePrimitiveArrayCritical(env, bufferRef, buffer, 0); 704 } 705 706 if (tempIndices) { 707 free(tempIndices); 708 } 709 } 710 return i; 711 } 712 713 JNIEXPORT jstring JNICALL OS_NATIVE(CTFontCopyAttributeDisplayName) 714 (JNIEnv *env, jclass that, jlong arg0) 715 { 716 CFStringRef stringRef = CTFontCopyAttribute((CTFontRef)arg0, kCTFontDisplayNameAttribute); 717 if (stringRef == NULL) return NULL; 718 CFIndex length = CFStringGetLength(stringRef); 719 UniChar buffer[length]; 720 CFStringGetCharacters(stringRef, CFRangeMake(0, length), buffer); 721 CFRelease(stringRef); 722 return (*env)->NewString(env, (jchar *)buffer, length); 723 } 724 725 JNIEXPORT jbyteArray JNICALL OS_NATIVE(CGBitmapContextGetData) 726 (JNIEnv *env, jclass that, jlong arg0, jint dstWidth, jint dstHeight, jint bpp) 727 { 728 jbyteArray result = NULL; 729 if (dstWidth < 0) return NULL; 730 if (dstHeight < 0) return NULL; 731 if (bpp != 8 && bpp != 24) return NULL; 732 CGContextRef context = (CGContextRef)arg0; 733 if (context == NULL) return NULL; 734 jbyte *srcData = (jbyte*)CGBitmapContextGetData(context); 735 736 if (srcData) { 737 /* Use one byte per pixel for grayscale */ 738 size_t srcWidth = CGBitmapContextGetWidth(context); 739 if (srcWidth < dstWidth) return NULL; 740 size_t srcHeight = CGBitmapContextGetHeight(context); 741 if (srcHeight < dstHeight) return NULL; 742 size_t srcBytesPerRow = CGBitmapContextGetBytesPerRow(context); 743 size_t srcStep = CGBitmapContextGetBitsPerPixel(context) / 8; 744 int srcOffset = (srcHeight - dstHeight) * srcBytesPerRow; 745 746 747 //bits per pixel, either 8 for gray or 24 for LCD. 748 int dstStep = bpp / 8; 749 size_t size = dstWidth * dstHeight * dstStep; 750 jbyte* data = (jbyte*)calloc(size, sizeof(jbyte)); 751 if (data == NULL) return NULL; 752 753 int x, y, sx; 754 int dstOffset = 0; 755 for (y = 0; y < dstHeight; y++) { 756 for (x = 0, sx = 0; x < dstWidth; x++, dstOffset += dstStep, sx += srcStep) { 757 if (dstStep == 1) { 758 /* BGRA or Gray to Gray */ 759 data[dstOffset] = 0xFF - srcData[srcOffset + sx]; 760 } else { 761 /* BGRA to RGB */ 762 data[dstOffset] = 0xFF - srcData[srcOffset + sx + 2]; 763 data[dstOffset + 1] = 0xFF - srcData[srcOffset + sx + 1]; 764 data[dstOffset + 2] = 0xFF - srcData[srcOffset + sx]; 765 } 766 } 767 srcOffset += srcBytesPerRow; 768 } 769 770 result = (*env)->NewByteArray(env, size); 771 if (result) { 772 (*env)->SetByteArrayRegion(env, result, 0, size, data); 773 } 774 free(data); 775 } 776 return result; 777 } 778 779 JNIEXPORT void JNICALL OS_NATIVE(CGRectApplyAffineTransform) 780 (JNIEnv *env, jclass that, jobject arg0, jobject arg1) 781 { 782 CGRect _arg0, *lparg0=NULL; 783 CGAffineTransform _arg1, *lparg1=NULL; 784 if (arg0) if ((lparg0 = getCGRectFields(env, arg0, &_arg0)) == NULL) goto fail; 785 if (arg1) if ((lparg1 = getCGAffineTransformFields(env, arg1, &_arg1)) == NULL) goto fail; 786 _arg0 = CGRectApplyAffineTransform(*lparg0, *lparg1); 787 fail: 788 /* In Only */ 789 // if (arg1 && lparg1) setCGAffineTransformFields(env, arg1, lparg1); 790 if (arg0 && lparg0) setCGRectFields(env, arg0, lparg0); 791 } 792 793 JNIEXPORT void JNICALL OS_NATIVE(CTFontDrawGlyphs) 794 (JNIEnv *env, jclass that, jlong arg0, jshort arg1, jdouble arg2, jdouble arg3, jlong contextRef) 795 { 796 /* Custom: only takes one glyph at the time */ 797 CGGlyph glyphs[] = {arg1}; 798 CGPoint pos[] = {CGPointMake(arg2, arg3)}; 799 CTFontDrawGlyphs((CTFontRef)arg0, glyphs, pos, 1, (CGContextRef)contextRef); 800 } 801 802 JNIEXPORT jboolean JNICALL OS_NATIVE(CTFontGetBoundingRectForGlyphUsingTables) 803 (JNIEnv *env, jclass that, jlong arg1, jshort arg2, jshort arg3, jintArray arg4) 804 { 805 /* The following code is based on scalerMethods.c#getGlyphBoundingBoxNative */ 806 CTFontRef fontRef = (CTFontRef)arg1; 807 CTFontTableOptions options = kCTFontTableOptionNoOptions; 808 CFDataRef tableData; 809 CFIndex length; 810 811 /* indexToLocFormat is stored in Java for performance */ 812 // tableData = CTFontCopyTable(fontRef, kCTFontTableHead, options); 813 // const UInt8 * head = CFDataGetBytePtr(tableData); 814 // UInt16 indexToLocFormat = CFSwapInt16BigToHost(*((SInt16*)(head + 50))); 815 // printf("here0 indexToLocFormat=%u \n", indexToLocFormat); fflush(stdout); 816 // CFRelease(tableData); 817 UInt16 indexToLocFormat = arg3; 818 819 tableData = CTFontCopyTable(fontRef, kCTFontTableLoca, options); 820 if (tableData == NULL) return FALSE; 821 length = CFDataGetLength(tableData); 822 UInt32 offset1 = 0, offset2 = 0; 823 UInt32 index = arg2 & 0xFFFF; 824 if (indexToLocFormat) { 825 const UInt32 * loca = (const UInt32 *)CFDataGetBytePtr(tableData); 826 if (loca != NULL && (index + 1) < (length / 4)) { 827 offset1 = CFSwapInt32BigToHost(loca[index]); 828 offset2 = CFSwapInt32BigToHost(loca[index + 1]); 829 } 830 } else { 831 const UInt16 * loca = (const UInt16 *)CFDataGetBytePtr(tableData); 832 if (loca != NULL && (index + 1) < (length / 2)) { 833 offset1 = CFSwapInt16BigToHost(loca[index]) << 1; 834 offset2 = CFSwapInt16BigToHost(loca[index + 1]) << 1; 835 } 836 } 837 CFRelease(tableData); 838 jboolean result = FALSE; 839 if (offset2 > offset1 && (offset2 - offset1) >= 10) { 840 tableData = CTFontCopyTable(fontRef, kCTFontTableGlyf, options); 841 if (tableData == NULL) return FALSE; 842 length = CFDataGetLength(tableData); 843 const UInt8 * ptr = CFDataGetBytePtr(tableData); 844 if (ptr != NULL && (offset1 + 10) < length) { 845 const SInt16 * glyf = (const SInt16 *)(ptr + offset1); 846 /* 847 * CFSwapInt16BigToHost returns an unsigned short, need 848 * to cast back to signed short before assigning to jint. 849 */ 850 jint data[] = { 851 (SInt16)CFSwapInt16BigToHost(glyf[1]), 852 (SInt16)CFSwapInt16BigToHost(glyf[2]), 853 (SInt16)CFSwapInt16BigToHost(glyf[3]), 854 (SInt16)CFSwapInt16BigToHost(glyf[4]), 855 }; 856 (*env)->SetIntArrayRegion(env, arg4, 0, 4, data); 857 result = TRUE; 858 } 859 CFRelease(tableData); 860 } 861 return result; 862 } 863 864 JNIEXPORT jdouble JNICALL OS_NATIVE(CTFontGetAdvancesForGlyphs) 865 (JNIEnv *env, jclass that, jlong arg0, jint arg1, jshort arg2, jobject arg3) 866 { 867 /* Custom: only takes one glyph at the time */ 868 jdouble rc = 0; 869 CGGlyph glyphs[] = {arg2}; 870 CGSize _arg3, *lparg3=NULL; 871 if (arg3) if ((lparg3 = getCGSizeFields(env, arg3, &_arg3)) == NULL) goto fail; 872 rc = (jdouble)CTFontGetAdvancesForGlyphs((CTFontRef)arg0, (CTFontOrientation)arg1, glyphs, lparg3, 1); 873 fail: 874 if (arg3 && lparg3) setCGSizeFields(env, arg3, &_arg3); 875 return rc; 876 } 877 878 JNIEXPORT jobject JNICALL OS_NATIVE(CGPathGetPathBoundingBox) 879 (JNIEnv *env, jclass that, jlong arg0) 880 { 881 CGRect result = CGPathGetPathBoundingBox((CGPathRef)arg0); 882 return newCGRect(env, &result); 883 } 884 885 JNIEXPORT jlong JNICALL OS_NATIVE(CTParagraphStyleCreate) 886 (JNIEnv *env, jclass that, jint arg0) 887 { 888 CTWritingDirection dir = (CTWritingDirection)arg0; 889 CTParagraphStyleSetting settings[] = { 890 {kCTParagraphStyleSpecifierBaseWritingDirection, sizeof(dir), &dir} 891 }; 892 return (jlong)CTParagraphStyleCreate(settings, sizeof(settings) / sizeof(settings[0])); 893 } 894 895 /***********************************************/ 896 /* Glyph Outline */ 897 /***********************************************/ 898 899 static const int DEFAULT_LEN_TYPES = 10; 900 static const int DEFAULT_LEN_COORDS = 50; 901 typedef struct _PathData { 902 jbyte* pointTypes; 903 int numTypes; 904 int lenTypes; 905 jfloat* pointCoords; 906 int numCoords; 907 int lenCoords; 908 } PathData; 909 910 void pathApplierFunctionFast(void *i, const CGPathElement *e) { 911 PathData *info = (PathData *)i; 912 if (info->numTypes == info->lenTypes) { 913 info->lenTypes += DEFAULT_LEN_TYPES; 914 info->pointTypes = (jbyte*)realloc(info->pointTypes, info->lenTypes * sizeof(jbyte)); 915 } 916 jint type; 917 int coordCount = 0; 918 switch (e->type) { 919 case kCGPathElementMoveToPoint: 920 type = 0; 921 coordCount = 1; 922 break; 923 case kCGPathElementAddLineToPoint: 924 type = 1; 925 coordCount = 1; 926 break; 927 case kCGPathElementAddQuadCurveToPoint: 928 type = 2; 929 coordCount = 2; 930 break; 931 case kCGPathElementAddCurveToPoint: 932 type = 3; 933 coordCount = 3; 934 break; 935 case kCGPathElementCloseSubpath: 936 type = 4; 937 coordCount = 0; 938 break; 939 } 940 info->pointTypes[info->numTypes++] = type; 941 942 if (info->numCoords + (coordCount * 2) > info->lenCoords) { 943 info->lenCoords += DEFAULT_LEN_COORDS; 944 info->pointCoords = (jfloat*)realloc(info->pointCoords, info->lenCoords * sizeof(jfloat)); 945 } 946 int j; 947 for (j = 0; j < coordCount; j++) { 948 CGPoint pt = e->points[j]; 949 info->pointCoords[info->numCoords++] = pt.x; 950 info->pointCoords[info->numCoords++] = pt.y; 951 } 952 } 953 954 JNIEXPORT jobject JNICALL OS_NATIVE(CGPathApply) 955 (JNIEnv *env, jclass that, jlong arg0) 956 { 957 jobject path2D = NULL; 958 PathData data; 959 data.pointTypes = (jbyte*)malloc(sizeof(jbyte) * DEFAULT_LEN_TYPES); 960 data.numTypes = 0; 961 data.lenTypes = DEFAULT_LEN_TYPES; 962 data.pointCoords = (jfloat*)malloc(sizeof(jfloat) * DEFAULT_LEN_COORDS); 963 data.numCoords = 0; 964 data.lenCoords = DEFAULT_LEN_COORDS; 965 966 CGPathApply((CGPathRef)arg0, &data, pathApplierFunctionFast); 967 968 static jclass path2DClass = NULL; 969 static jmethodID path2DCtr = NULL; 970 if (path2DClass == NULL) { 971 jclass tmpClass = (*env)->FindClass(env, "com/sun/javafx/geom/Path2D"); 972 if ((*env)->ExceptionOccurred(env) || !tmpClass) { 973 fprintf(stderr, "OS_NATIVE error: JNI exception or tmpClass == NULL"); 974 goto fail; 975 } 976 path2DClass = (jclass)(*env)->NewGlobalRef(env, tmpClass); 977 path2DCtr = (*env)->GetMethodID(env, path2DClass, "<init>", "(I[BI[FI)V"); 978 if ((*env)->ExceptionOccurred(env) || !path2DCtr) { 979 fprintf(stderr, "OS_NATIVE error: JNI exception or path2DCtr == NULL"); 980 goto fail; 981 } 982 } 983 984 jbyteArray types = (*env)->NewByteArray(env, data.numTypes); 985 jfloatArray coords = (*env)->NewFloatArray(env, data.numCoords); 986 if (types && coords) { 987 (*env)->SetByteArrayRegion(env, types, 0, data.numTypes, data.pointTypes); 988 if ((*env)->ExceptionOccurred(env)) { 989 fprintf(stderr, "OS_NATIVE error: JNI exception"); 990 goto fail; 991 } 992 (*env)->SetFloatArrayRegion(env, coords, 0, data.numCoords, data.pointCoords); 993 if ((*env)->ExceptionOccurred(env)) { 994 fprintf(stderr, "OS_NATIVE error: JNI exception"); 995 goto fail; 996 } 997 path2D = (*env)->NewObject(env, path2DClass, path2DCtr, 998 0 /*winding rule*/, 999 types, data.numTypes, 1000 coords, data.numCoords); 1001 if ((*env)->ExceptionOccurred(env) || !path2D) { 1002 goto fail; 1003 } 1004 } 1005 fail: 1006 free(data.pointTypes); 1007 free(data.pointCoords); 1008 return path2D; 1009 } 1010 1011 #endif /* TARGET_OS_MAC */ 1012 #endif /* __APPLE__ */ 1013