1 /* 2 * Copyright (c) 2013, 2014, 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 jlong JNICALL OS_NATIVE(CTFontCreateWithName) 368 (JNIEnv *env, jclass that, jlong arg0, jdouble arg1, jobject arg2) 369 { 370 CGAffineTransform _arg2, *lparg2=NULL; 371 jlong rc = 0; 372 if (arg2) if ((lparg2 = getCGAffineTransformFields(env, arg2, &_arg2)) == NULL) goto fail; 373 rc = (jlong)CTFontCreateWithName((CFStringRef)arg0, (CGFloat)arg1, (CGAffineTransform*)lparg2); 374 fail: 375 /* In only */ 376 // if (arg2 && lparg2) setCGAffineTransformFields(env, arg2, lparg2); 377 return rc; 378 } 379 380 JNIEXPORT void JNICALL OS_NATIVE(CFRelease) 381 (JNIEnv *env, jclass that, jlong arg0) 382 { 383 CFRelease((CFTypeRef)arg0); 384 } 385 386 JNIEXPORT jlong JNICALL OS_NATIVE(CFURLCreateWithFileSystemPath) 387 (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jboolean arg3) 388 { 389 return (jlong)CFURLCreateWithFileSystemPath((CFAllocatorRef)arg0, (CFStringRef)arg1, (CFURLPathStyle)arg2, (Boolean)arg3); 390 } 391 392 JNIEXPORT jboolean JNICALL OS_NATIVE(CTFontManagerRegisterFontsForURL) 393 (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2) 394 { 395 return (jboolean)CTFontManagerRegisterFontsForURL((CFURLRef)arg0, (CTFontManagerScope)arg1, (CFErrorRef*)arg2); 396 } 397 398 JNIEXPORT jlong JNICALL OS_NATIVE(CTFontCreatePathForGlyph) 399 (JNIEnv *env, jclass that, jlong arg0, jshort arg1, jobject arg2) 400 { 401 CGAffineTransform _arg2, *lparg2=NULL; 402 jlong rc = 0; 403 if (arg2) if ((lparg2 = getCGAffineTransformFields(env, arg2, &_arg2)) == NULL) goto fail; 404 rc = (jlong)CTFontCreatePathForGlyph((CTFontRef)arg0, (CGGlyph)arg1, (CGAffineTransform*)lparg2); 405 fail: 406 /* In Only */ 407 // if (arg2 && lparg2) setCGAffineTransformFields(env, arg2, lparg2); 408 return rc; 409 } 410 411 JNIEXPORT void JNICALL OS_NATIVE(CGPathRelease) 412 (JNIEnv *env, jclass that, jlong arg0) 413 { 414 CGPathRelease((CGPathRef)arg0); 415 } 416 417 JNIEXPORT jlong JNICALL OS_NATIVE(CGColorSpaceCreateDeviceRGB) 418 (JNIEnv *env, jclass that) 419 { 420 return (jlong)CGColorSpaceCreateDeviceRGB(); 421 } 422 423 JNIEXPORT jlong JNICALL OS_NATIVE(CGColorSpaceCreateDeviceGray) 424 (JNIEnv *env, jclass that) 425 { 426 return (jlong)CGColorSpaceCreateDeviceGray(); 427 } 428 429 JNIEXPORT jlong JNICALL OS_NATIVE(CGBitmapContextCreate) 430 (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlong arg3, jlong arg4, jlong arg5, jint arg6) 431 { 432 return (jlong)CGBitmapContextCreate((void*)arg0, (size_t)arg1, (size_t)arg2, (size_t)arg3, (size_t)arg4, (CGColorSpaceRef)arg5, (CGBitmapInfo)arg6); 433 } 434 435 JNIEXPORT void JNICALL OS_NATIVE(CGContextSetAllowsFontSmoothing) 436 (JNIEnv *env, jclass that, jlong arg0, jboolean arg1) 437 { 438 CGContextSetAllowsFontSmoothing((CGContextRef)arg0, (_Bool)arg1); 439 } 440 441 JNIEXPORT void JNICALL OS_NATIVE(CGContextSetAllowsAntialiasing) 442 (JNIEnv *env, jclass that, jlong arg0, jboolean arg1) 443 { 444 CGContextSetAllowsAntialiasing((CGContextRef)arg0, (_Bool)arg1); 445 } 446 447 JNIEXPORT void JNICALL OS_NATIVE(CGContextSetAllowsFontSubpixelPositioning) 448 (JNIEnv *env, jclass that, jlong arg0, jboolean arg1) 449 { 450 CGContextSetAllowsFontSubpixelPositioning((CGContextRef)arg0, (_Bool)arg1); 451 } 452 453 JNIEXPORT void JNICALL OS_NATIVE(CGContextSetAllowsFontSubpixelQuantization) 454 (JNIEnv *env, jclass that, jlong arg0, jboolean arg1) 455 { 456 CGContextSetAllowsFontSubpixelQuantization((CGContextRef)arg0, (_Bool)arg1); 457 } 458 459 JNIEXPORT void JNICALL OS_NATIVE(CGContextSetRGBFillColor) 460 (JNIEnv *env, jclass that, jlong arg0, jdouble arg1, jdouble arg2, jdouble arg3, jdouble arg4) 461 { 462 CGContextSetRGBFillColor((CGContextRef)arg0, (CGFloat)arg1, (CGFloat)arg2, (CGFloat)arg3, (CGFloat)arg4); 463 } 464 465 JNIEXPORT void JNICALL OS_NATIVE(CGContextFillRect) 466 (JNIEnv *env, jclass that, jlong arg0, jobject arg1) 467 { 468 CGRect _arg1, *lparg1=NULL; 469 /* In Only */ 470 if (arg1) if ((lparg1 = getCGRectFields(env, arg1, &_arg1)) == NULL) return; 471 CGContextFillRect((CGContextRef)arg0, *lparg1); 472 } 473 474 JNIEXPORT void JNICALL OS_NATIVE(CGContextTranslateCTM) 475 (JNIEnv *env, jclass that, jlong arg0, jdouble arg1, jdouble arg2) 476 { 477 CGContextTranslateCTM((CGContextRef)arg0, (CGFloat)arg1, (CGFloat)arg2); 478 } 479 480 JNIEXPORT void JNICALL OS_NATIVE(CGContextRelease) 481 (JNIEnv *env, jclass that, jlong arg0) 482 { 483 CGContextRelease((CGContextRef)arg0); 484 } 485 486 JNIEXPORT void JNICALL OS_NATIVE(CGColorSpaceRelease) 487 (JNIEnv *env, jclass that, jlong arg0) 488 { 489 CGColorSpaceRelease((CGColorSpaceRef)arg0); 490 } 491 492 JNIEXPORT jlong JNICALL OS_NATIVE(kCFTypeDictionaryKeyCallBacks) 493 (JNIEnv *env, jclass that) 494 { 495 return (jlong)&kCFTypeDictionaryKeyCallBacks; 496 } 497 498 JNIEXPORT jlong JNICALL OS_NATIVE(kCFTypeDictionaryValueCallBacks) 499 (JNIEnv *env, jclass that) 500 { 501 return (jlong)&kCFTypeDictionaryValueCallBacks; 502 } 503 504 JNIEXPORT jlong JNICALL OS_NATIVE(CFDictionaryCreateMutable) 505 (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jlong arg3) 506 { 507 return (jlong)CFDictionaryCreateMutable((CFAllocatorRef)arg0, (CFIndex)arg1, (CFDictionaryKeyCallBacks*)arg2, (CFDictionaryValueCallBacks*)arg3); 508 } 509 510 JNIEXPORT void JNICALL OS_NATIVE(CFDictionaryAddValue) 511 (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2) 512 { 513 CFDictionaryAddValue((CFMutableDictionaryRef)arg0, (void*)arg1, (void*)arg2); 514 } 515 516 JNIEXPORT jlong JNICALL OS_NATIVE(CFDictionaryGetValue) 517 (JNIEnv *env, jclass that, jlong arg0, jlong arg1) 518 { 519 return (jlong)CFDictionaryGetValue((CFDictionaryRef)arg0, (void*)arg1); 520 } 521 522 JNIEXPORT jlong JNICALL OS_NATIVE(kCTFontAttributeName) 523 (JNIEnv *env, jclass that) 524 { 525 return (jlong)kCTFontAttributeName; 526 } 527 528 JNIEXPORT jlong JNICALL OS_NATIVE(kCTParagraphStyleAttributeName) 529 (JNIEnv *env, jclass that) 530 { 531 return (jlong)kCTParagraphStyleAttributeName; 532 } 533 534 JNIEXPORT jlong JNICALL OS_NATIVE(CFAttributedStringCreate) 535 (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2) 536 { 537 return (jlong)CFAttributedStringCreate((CFAllocatorRef)arg0, (CFStringRef)arg1, (CFDictionaryRef)arg2); 538 } 539 540 JNIEXPORT jlong JNICALL OS_NATIVE(CTLineCreateWithAttributedString) 541 (JNIEnv *env, jclass that, jlong arg0) 542 { 543 return (jlong)CTLineCreateWithAttributedString((CFAttributedStringRef)arg0); 544 } 545 546 JNIEXPORT jlong JNICALL OS_NATIVE(CTLineGetGlyphRuns) 547 (JNIEnv *env, jclass that, jlong arg0) 548 { 549 return (jlong)CTLineGetGlyphRuns((CTLineRef)arg0); 550 } 551 552 JNIEXPORT jdouble JNICALL OS_NATIVE(CTLineGetTypographicBounds) 553 (JNIEnv *env, jclass that, jlong arg0) 554 { 555 return (jdouble)CTLineGetTypographicBounds((CTLineRef)arg0, NULL, NULL, NULL); 556 } 557 558 JNIEXPORT jlong JNICALL OS_NATIVE(CTLineGetGlyphCount) 559 (JNIEnv *env, jclass that, jlong arg0) 560 { 561 return (jlong)CTLineGetGlyphCount((CTLineRef)arg0); 562 } 563 564 JNIEXPORT jlong JNICALL OS_NATIVE(CFArrayGetCount) 565 (JNIEnv *env, jclass that, jlong arg0) 566 { 567 return (jlong)CFArrayGetCount((CFArrayRef)arg0); 568 } 569 570 JNIEXPORT jlong JNICALL OS_NATIVE(CFArrayGetValueAtIndex) 571 (JNIEnv *env, jclass that, jlong arg0, jlong arg1) 572 { 573 return (jlong)CFArrayGetValueAtIndex((CFArrayRef)arg0, (CFIndex)arg1); 574 } 575 576 JNIEXPORT jlong JNICALL OS_NATIVE(CTRunGetGlyphCount) 577 (JNIEnv *env, jclass that, jlong arg0) 578 { 579 return (jlong)CTRunGetGlyphCount((CTRunRef)arg0); 580 } 581 582 JNIEXPORT jlong JNICALL OS_NATIVE(CTRunGetAttributes) 583 (JNIEnv *env, jclass that, jlong arg0) 584 { 585 return (jlong)CTRunGetAttributes((CTRunRef)arg0); 586 } 587 588 /**************************************************************************/ 589 /* */ 590 /* Custom Functions */ 591 /* */ 592 /**************************************************************************/ 593 594 595 JNIEXPORT jlong JNICALL OS_NATIVE(CFStringCreateWithCharacters__J_3CJJ) 596 (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jlong arg2, jlong arg3) 597 { 598 jchar *lparg1=NULL; 599 jlong rc = 0; 600 if (arg1) if ((lparg1 = (*env)->GetPrimitiveArrayCritical(env, arg1, NULL)) == NULL) goto fail; 601 UniChar* str = lparg1 + arg2; 602 rc = (jlong)CFStringCreateWithCharacters((CFAllocatorRef)arg0, str, (CFIndex)arg3); 603 fail: 604 if (arg1 && lparg1) (*env)->ReleasePrimitiveArrayCritical(env, arg1, lparg1, 0); 605 return rc; 606 } 607 608 JNIEXPORT jint JNICALL OS_NATIVE(CTRunGetGlyphs) 609 (JNIEnv *env, jclass that, jlong runRef, jint slotMask, jint start, jintArray bufferRef) 610 { 611 CTRunRef run = (CTRunRef)runRef; 612 const CGGlyph * glyphs = CTRunGetGlyphsPtr(run); 613 int i = 0; 614 if (glyphs) { 615 jint* buffer = (*env)->GetPrimitiveArrayCritical(env, bufferRef, NULL); 616 if (buffer) { 617 CFIndex count = CTRunGetGlyphCount(run); 618 while(i < count) { 619 buffer[start + i] = slotMask | (glyphs[i] & 0xFFFF); 620 i++; 621 } 622 (*env)->ReleasePrimitiveArrayCritical(env, bufferRef, buffer, 0); 623 } 624 } 625 return i; 626 } 627 628 JNIEXPORT jint JNICALL OS_NATIVE(CTRunGetPositions) 629 (JNIEnv *env, jclass that, jlong runRef, jint start, jfloatArray bufferRef) 630 { 631 CTRunRef run = (CTRunRef)runRef; 632 const CGPoint* positions = CTRunGetPositionsPtr(run); 633 int j = 0; 634 if (positions) { 635 jfloat* buffer = (*env)->GetPrimitiveArrayCritical(env, bufferRef, NULL); 636 if (buffer) { 637 CFIndex count = CTRunGetGlyphCount(run); 638 int i = 0; 639 while (i < count) { 640 CGPoint pos = positions[i++]; 641 buffer[start + j++] = pos.x; 642 buffer[start + j++] = pos.y; 643 } 644 (*env)->ReleasePrimitiveArrayCritical(env, bufferRef, buffer, 0); 645 } 646 } 647 return j; 648 } 649 650 JNIEXPORT jint JNICALL OS_NATIVE(CTRunGetStringIndices) 651 (JNIEnv *env, jclass that, jlong runRef, jint start, jintArray bufferRef) 652 { 653 CTRunRef run = (CTRunRef)runRef; 654 const CFIndex* indices = CTRunGetStringIndicesPtr(run); 655 int i = 0; 656 if (indices) { 657 jint* buffer = (*env)->GetPrimitiveArrayCritical(env, bufferRef, NULL); 658 if (buffer) { 659 CFIndex count = CTRunGetGlyphCount(run); 660 while(i < count) { 661 buffer[start + i] = indices[i]; 662 i++; 663 } 664 (*env)->ReleasePrimitiveArrayCritical(env, bufferRef, buffer, 0); 665 } 666 } 667 return i; 668 } 669 670 JNIEXPORT jstring JNICALL OS_NATIVE(CTFontCopyAttributeDisplayName) 671 (JNIEnv *env, jclass that, jlong arg0) 672 { 673 CFStringRef stringRef = CTFontCopyAttribute((CTFontRef)arg0, kCTFontDisplayNameAttribute); 674 if (stringRef == NULL) return NULL; 675 CFIndex length = CFStringGetLength(stringRef); 676 UniChar buffer[length]; 677 CFStringGetCharacters(stringRef, CFRangeMake(0, length), buffer); 678 CFRelease(stringRef); 679 return (*env)->NewString(env, (jchar *)buffer, length); 680 } 681 682 JNIEXPORT jbyteArray JNICALL OS_NATIVE(CGBitmapContextGetData) 683 (JNIEnv *env, jclass that, jlong arg0, jint dstWidth, jint dstHeight, jint bpp) 684 { 685 jbyteArray result = NULL; 686 if (dstWidth < 0) return NULL; 687 if (dstHeight < 0) return NULL; 688 if (bpp != 8 && bpp != 24) return NULL; 689 CGContextRef context = (CGContextRef)arg0; 690 if (context == NULL) return NULL; 691 jbyte *srcData = (jbyte*)CGBitmapContextGetData(context); 692 693 if (srcData) { 694 /* Use one byte per pixel for grayscale */ 695 size_t srcWidth = CGBitmapContextGetWidth(context); 696 if (srcWidth < dstWidth) return NULL; 697 size_t srcHeight = CGBitmapContextGetHeight(context); 698 if (srcHeight < dstHeight) return NULL; 699 size_t srcBytesPerRow = CGBitmapContextGetBytesPerRow(context); 700 size_t srcStep = CGBitmapContextGetBitsPerPixel(context) / 8; 701 int srcOffset = (srcHeight - dstHeight) * srcBytesPerRow; 702 703 704 //bits per pixel, either 8 for gray or 24 for LCD. 705 int dstStep = bpp / 8; 706 size_t size = dstWidth * dstHeight * dstStep; 707 jbyte* data = (jbyte*)calloc(size, sizeof(jbyte)); 708 if (data == NULL) return NULL; 709 710 int x, y, sx; 711 int dstOffset = 0; 712 for (y = 0; y < dstHeight; y++) { 713 for (x = 0, sx = 0; x < dstWidth; x++, dstOffset += dstStep, sx += srcStep) { 714 if (dstStep == 1) { 715 /* BGRA or Gray to Gray */ 716 data[dstOffset] = 0xFF - srcData[srcOffset + sx]; 717 } else { 718 /* BGRA to RGB */ 719 data[dstOffset] = 0xFF - srcData[srcOffset + sx + 2]; 720 data[dstOffset + 1] = 0xFF - srcData[srcOffset + sx + 1]; 721 data[dstOffset + 2] = 0xFF - srcData[srcOffset + sx]; 722 } 723 } 724 srcOffset += srcBytesPerRow; 725 } 726 727 result = (*env)->NewByteArray(env, size); 728 if (result) { 729 (*env)->SetByteArrayRegion(env, result, 0, size, data); 730 } 731 free(data); 732 } 733 return result; 734 } 735 736 JNIEXPORT void JNICALL OS_NATIVE(CGRectApplyAffineTransform) 737 (JNIEnv *env, jclass that, jobject arg0, jobject arg1) 738 { 739 CGRect _arg0, *lparg0=NULL; 740 CGAffineTransform _arg1, *lparg1=NULL; 741 if (arg0) if ((lparg0 = getCGRectFields(env, arg0, &_arg0)) == NULL) goto fail; 742 if (arg1) if ((lparg1 = getCGAffineTransformFields(env, arg1, &_arg1)) == NULL) goto fail; 743 _arg0 = CGRectApplyAffineTransform(*lparg0, *lparg1); 744 fail: 745 /* In Only */ 746 // if (arg1 && lparg1) setCGAffineTransformFields(env, arg1, lparg1); 747 if (arg0 && lparg0) setCGRectFields(env, arg0, lparg0); 748 } 749 750 JNIEXPORT void JNICALL OS_NATIVE(CTFontDrawGlyphs) 751 (JNIEnv *env, jclass that, jlong arg0, jshort arg1, jdouble arg2, jdouble arg3, jlong contextRef) 752 { 753 /* Custom: only takes one glyph at the time */ 754 CGGlyph glyphs[] = {arg1}; 755 CGPoint pos[] = {CGPointMake(arg2, arg3)}; 756 CTFontDrawGlyphs((CTFontRef)arg0, glyphs, pos, 1, (CGContextRef)contextRef); 757 } 758 759 JNIEXPORT jboolean JNICALL OS_NATIVE(CTFontGetBoundingRectForGlyphUsingTables) 760 (JNIEnv *env, jclass that, jlong arg1, jshort arg2, jshort arg3, jintArray arg4) 761 { 762 /* The following code is based on scalerMethods.c#getGlyphBoundingBoxNative */ 763 CTFontRef fontRef = (CTFontRef)arg1; 764 CTFontTableOptions options = kCTFontTableOptionNoOptions; 765 CFDataRef tableData; 766 CFIndex length; 767 768 /* indexToLocFormat is stored in Java for performance */ 769 // tableData = CTFontCopyTable(fontRef, kCTFontTableHead, options); 770 // const UInt8 * head = CFDataGetBytePtr(tableData); 771 // UInt16 indexToLocFormat = CFSwapInt16BigToHost(*((SInt16*)(head + 50))); 772 // printf("here0 indexToLocFormat=%u \n", indexToLocFormat); fflush(stdout); 773 // CFRelease(tableData); 774 UInt16 indexToLocFormat = arg3; 775 776 tableData = CTFontCopyTable(fontRef, kCTFontTableLoca, options); 777 if (tableData == NULL) return FALSE; 778 length = CFDataGetLength(tableData); 779 UInt32 offset1 = 0, offset2 = 0; 780 UInt32 index = arg2 & 0xFFFF; 781 if (indexToLocFormat) { 782 const UInt32 * loca = (const UInt32 *)CFDataGetBytePtr(tableData); 783 if (loca != NULL && (index + 1) < (length / 4)) { 784 offset1 = CFSwapInt32BigToHost(loca[index]); 785 offset2 = CFSwapInt32BigToHost(loca[index + 1]); 786 } 787 } else { 788 const UInt16 * loca = (const UInt16 *)CFDataGetBytePtr(tableData); 789 if (loca != NULL && (index + 1) < (length / 2)) { 790 offset1 = CFSwapInt16BigToHost(loca[index]) << 1; 791 offset2 = CFSwapInt16BigToHost(loca[index + 1]) << 1; 792 } 793 } 794 CFRelease(tableData); 795 jboolean result = FALSE; 796 if (offset2 > offset1 && (offset2 - offset1) >= 10) { 797 tableData = CTFontCopyTable(fontRef, kCTFontTableGlyf, options); 798 if (tableData == NULL) return FALSE; 799 length = CFDataGetLength(tableData); 800 const UInt8 * ptr = CFDataGetBytePtr(tableData); 801 if (ptr != NULL && (offset1 + 10) < length) { 802 const SInt16 * glyf = (const SInt16 *)(ptr + offset1); 803 /* 804 * CFSwapInt16BigToHost returns an unsigned short, need 805 * to cast back to signed short before assigning to jint. 806 */ 807 jint data[] = { 808 (SInt16)CFSwapInt16BigToHost(glyf[1]), 809 (SInt16)CFSwapInt16BigToHost(glyf[2]), 810 (SInt16)CFSwapInt16BigToHost(glyf[3]), 811 (SInt16)CFSwapInt16BigToHost(glyf[4]), 812 }; 813 (*env)->SetIntArrayRegion(env, arg4, 0, 4, data); 814 result = TRUE; 815 } 816 CFRelease(tableData); 817 } 818 return result; 819 } 820 821 JNIEXPORT jdouble JNICALL OS_NATIVE(CTFontGetAdvancesForGlyphs) 822 (JNIEnv *env, jclass that, jlong arg0, jint arg1, jshort arg2, jobject arg3) 823 { 824 /* Custom: only takes one glyph at the time */ 825 jdouble rc = 0; 826 CGGlyph glyphs[] = {arg2}; 827 CGSize _arg3, *lparg3=NULL; 828 if (arg3) if ((lparg3 = getCGSizeFields(env, arg3, &_arg3)) == NULL) goto fail; 829 rc = (jdouble)CTFontGetAdvancesForGlyphs((CTFontRef)arg0, (CTFontOrientation)arg1, glyphs, lparg3, 1); 830 fail: 831 if (arg3 && lparg3) setCGSizeFields(env, arg3, &_arg3); 832 return rc; 833 } 834 835 JNIEXPORT jobject JNICALL OS_NATIVE(CGPathGetPathBoundingBox) 836 (JNIEnv *env, jclass that, jlong arg0) 837 { 838 CGRect result = CGPathGetPathBoundingBox((CGPathRef)arg0); 839 return newCGRect(env, &result); 840 } 841 842 JNIEXPORT jlong JNICALL OS_NATIVE(CTParagraphStyleCreate) 843 (JNIEnv *env, jclass that, jint arg0) 844 { 845 CTWritingDirection dir = (CTWritingDirection)arg0; 846 CTParagraphStyleSetting settings[] = { 847 {kCTParagraphStyleSpecifierBaseWritingDirection, sizeof(dir), &dir} 848 }; 849 return (jlong)CTParagraphStyleCreate(settings, sizeof(settings) / sizeof(settings[0])); 850 } 851 852 /***********************************************/ 853 /* Glyph Outline */ 854 /***********************************************/ 855 856 static const int DEFAULT_LEN_TYPES = 10; 857 static const int DEFAULT_LEN_COORDS = 50; 858 typedef struct _PathData { 859 jbyte* pointTypes; 860 int numTypes; 861 int lenTypes; 862 jfloat* pointCoords; 863 int numCoords; 864 int lenCoords; 865 } PathData; 866 867 void pathApplierFunctionFast(void *i, const CGPathElement *e) { 868 PathData *info = (PathData *)i; 869 if (info->numTypes == info->lenTypes) { 870 info->lenTypes += DEFAULT_LEN_TYPES; 871 info->pointTypes = (jbyte*)realloc(info->pointTypes, info->lenTypes * sizeof(jbyte)); 872 } 873 jint type; 874 int coordCount = 0; 875 switch (e->type) { 876 case kCGPathElementMoveToPoint: 877 type = 0; 878 coordCount = 1; 879 break; 880 case kCGPathElementAddLineToPoint: 881 type = 1; 882 coordCount = 1; 883 break; 884 case kCGPathElementAddQuadCurveToPoint: 885 type = 2; 886 coordCount = 2; 887 break; 888 case kCGPathElementAddCurveToPoint: 889 type = 3; 890 coordCount = 3; 891 break; 892 case kCGPathElementCloseSubpath: 893 type = 4; 894 coordCount = 0; 895 break; 896 } 897 info->pointTypes[info->numTypes++] = type; 898 899 if (info->numCoords + (coordCount * 2) > info->lenCoords) { 900 info->lenCoords += DEFAULT_LEN_COORDS; 901 info->pointCoords = (jfloat*)realloc(info->pointCoords, info->lenCoords * sizeof(jfloat)); 902 } 903 int j; 904 for (j = 0; j < coordCount; j++) { 905 CGPoint pt = e->points[j]; 906 info->pointCoords[info->numCoords++] = pt.x; 907 info->pointCoords[info->numCoords++] = pt.y; 908 } 909 } 910 911 JNIEXPORT jobject JNICALL OS_NATIVE(CGPathApply) 912 (JNIEnv *env, jclass that, jlong arg0) 913 { 914 jobject path2D = NULL; 915 PathData data; 916 data.pointTypes = (jbyte*)malloc(sizeof(jbyte) * DEFAULT_LEN_TYPES); 917 data.numTypes = 0; 918 data.lenTypes = DEFAULT_LEN_TYPES; 919 data.pointCoords = (jfloat*)malloc(sizeof(jfloat) * DEFAULT_LEN_COORDS); 920 data.numCoords = 0; 921 data.lenCoords = DEFAULT_LEN_COORDS; 922 923 CGPathApply((CGPathRef)arg0, &data, pathApplierFunctionFast); 924 925 static jclass path2DClass = NULL; 926 static jmethodID path2DCtr = NULL; 927 if (path2DClass == NULL) { 928 jclass tmpClass = (*env)->FindClass(env, "com/sun/javafx/geom/Path2D"); 929 if ((*env)->ExceptionOccurred(env) || !tmpClass) { 930 fprintf(stderr, "OS_NATIVE error: JNI exception or tmpClass == NULL"); 931 goto fail; 932 } 933 path2DClass = (jclass)(*env)->NewGlobalRef(env, tmpClass); 934 path2DCtr = (*env)->GetMethodID(env, path2DClass, "<init>", "(I[BI[FI)V"); 935 if ((*env)->ExceptionOccurred(env) || !path2DCtr) { 936 fprintf(stderr, "OS_NATIVE error: JNI exception or path2DCtr == NULL"); 937 goto fail; 938 } 939 } 940 941 jbyteArray types = (*env)->NewByteArray(env, data.numTypes); 942 jfloatArray coords = (*env)->NewFloatArray(env, data.numCoords); 943 if (types && coords) { 944 (*env)->SetByteArrayRegion(env, types, 0, data.numTypes, data.pointTypes); 945 if ((*env)->ExceptionOccurred(env)) { 946 fprintf(stderr, "OS_NATIVE error: JNI exception"); 947 goto fail; 948 } 949 (*env)->SetFloatArrayRegion(env, coords, 0, data.numCoords, data.pointCoords); 950 if ((*env)->ExceptionOccurred(env)) { 951 fprintf(stderr, "OS_NATIVE error: JNI exception"); 952 goto fail; 953 } 954 path2D = (*env)->NewObject(env, path2DClass, path2DCtr, 955 0 /*winding rule*/, 956 types, data.numTypes, 957 coords, data.numCoords); 958 if ((*env)->ExceptionOccurred(env) || !path2D) { 959 goto fail; 960 } 961 } 962 fail: 963 free(data.pointTypes); 964 free(data.pointCoords); 965 return path2D; 966 } 967 968 #endif /* TARGET_OS_MAC */ 969 #endif /* __APPLE__ */ 970