rev 54094 : 8257853: Remove dependencies on JNF's JNI utility functions in AWT and 2D code
rev 54096 : 8259651: [macOS] Replace JNF_COCOA_ENTER/EXIT macros
rev 54098 : 8260616: Removing remaining JNF dependencies in the java.desktop module
8259729: Missed JNFInstanceOf -> IsInstanceOf conversion

   1 /*
   2  * Copyright (c) 2011, 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 #import "java_awt_geom_PathIterator.h"
  27 #import "sun_font_CStrike.h"
  28 #import "sun_font_CStrikeDisposer.h"
  29 #import "CGGlyphImages.h"
  30 #import "CGGlyphOutlines.h"
  31 #import "CoreTextSupport.h"
  32 #import "JNIUtilities.h"
  33 #include "fontscalerdefs.h"
  34 
  35 @implementation AWTStrike
  36 
  37 static CGAffineTransform sInverseTX = { 1, 0, 0, -1, 0, 0 };
  38 
  39 - (id) initWithFont:(AWTFont *)awtFont
  40                  tx:(CGAffineTransform)tx
  41            invDevTx:(CGAffineTransform)invDevTx
  42               style:(JRSFontRenderingStyle)style
  43             aaStyle:(jint)aaStyle {
  44 
  45     self = [super init];
  46     if (self) {
  47         fAWTFont = [awtFont retain];
  48         fStyle = style;
  49         fAAStyle = aaStyle;
  50 
  51         fTx = tx; // composited glyph and device transform
  52 
  53         fAltTx = tx;
  54         fAltTx.b *= -1;
  55         fAltTx.d *= -1;
  56 
  57         invDevTx.b *= -1;
  58         invDevTx.c *= -1;
  59         fFontTx = CGAffineTransformConcat(CGAffineTransformConcat(tx, invDevTx), sInverseTX);
  60         fDevTx = CGAffineTransformInvert(CGAffineTransformConcat(invDevTx, sInverseTX));
  61 
  62         // the "font size" is the square root of the determinant of the matrix
  63         fSize = sqrt(fabs(fFontTx.a * fFontTx.d - fFontTx.b * fFontTx.c));
  64     }
  65     return self;
  66 }
  67 
  68 - (void) dealloc {
  69     [fAWTFont release];
  70     fAWTFont = nil;
  71 
  72     [super dealloc];
  73 }
  74 
  75 + (AWTStrike *) awtStrikeForFont:(AWTFont *)awtFont
  76                               tx:(CGAffineTransform)tx
  77                         invDevTx:(CGAffineTransform)invDevTx
  78                            style:(JRSFontRenderingStyle)style
  79                          aaStyle:(jint)aaStyle {
  80 
  81     return [[[AWTStrike alloc] initWithFont:awtFont
  82                                          tx:tx invDevTx:invDevTx
  83                                       style:style
  84                                     aaStyle:aaStyle] autorelease];
  85 }
  86 
  87 @end
  88 
  89 
  90 #define AWT_FONT_CLEANUP_SETUP \
  91     BOOL _fontThrowJavaException = NO;
  92 
  93 #define AWT_FONT_CLEANUP_CHECK(a)                                       \
  94     if ((a) == NULL) {                                                  \
  95         _fontThrowJavaException = YES;                                  \
  96         goto cleanup;                                                   \
  97     }                                                                   \
  98     if ((*env)->ExceptionCheck(env) == JNI_TRUE) {                      \
  99         goto cleanup;                                                   \
 100     }
 101 
 102 #define AWT_FONT_CLEANUP_FINISH                                         \
 103     if (_fontThrowJavaException == YES) {                               \
 104         char s[512];                                                    \
 105         sprintf(s, "%s-%s:%d", __FILE__, __FUNCTION__, __LINE__);       \
 106         JNU_ThrowByName(env, "java/lang/RuntimeException", s);          \
 107     }
 108 
 109 
 110 /*
 111  * Creates an affine transform from the corresponding doubles sent
 112  * from CStrike.getGlyphTx().
 113  */
 114 static inline CGAffineTransform
 115 GetTxFromDoubles(JNIEnv *env, jdoubleArray txArray)
 116 {
 117     if (txArray == NULL) {
 118         return CGAffineTransformIdentity;
 119     }
 120 
 121     jdouble *txPtr = (*env)->GetPrimitiveArrayCritical(env, txArray, NULL);
 122     if (txPtr == NULL) {
 123         return CGAffineTransformIdentity;
 124     }
 125 
 126     CGAffineTransform tx =
 127         CGAffineTransformMake(txPtr[0], txPtr[1], txPtr[2],
 128                               txPtr[3], txPtr[4], txPtr[5]);
 129     tx = CGAffineTransformConcat(sInverseTX, tx);
 130 
 131     (*env)->ReleasePrimitiveArrayCritical(env, txArray, txPtr, JNI_ABORT);
 132 
 133     return tx;
 134 }
 135 
 136 /*
 137  * Class:     sun_font_CStrike
 138  * Method:    getNativeGlyphAdvance
 139  * Signature: (JI)F
 140  */
 141 JNIEXPORT jfloat JNICALL
 142 Java_sun_font_CStrike_getNativeGlyphAdvance
 143     (JNIEnv *env, jclass clazz, jlong awtStrikePtr, jint glyphCode)
 144 {
 145     CGSize advance;
 146 JNI_COCOA_ENTER(env);
 147     AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
 148     AWTFont *awtFont = awtStrike->fAWTFont;
 149 
 150     // negative glyph codes are really unicodes, which were placed there by the mapper
 151     // to indicate we should use CoreText to substitute the character
 152     CGGlyph glyph;
 153     const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph);
 154     CTFontGetAdvancesForGlyphs(fallback, kCTFontDefaultOrientation, &glyph, &advance, 1);
 155     CFRelease(fallback);
 156     advance = CGSizeApplyAffineTransform(advance, awtStrike->fFontTx);
 157     if (!JRSFontStyleUsesFractionalMetrics(awtStrike->fStyle)) {
 158         advance.width = round(advance.width);
 159     }
 160 
 161 JNI_COCOA_EXIT(env);
 162     return advance.width;
 163 }
 164 
 165 /*
 166  * Class:     sun_font_CStrike
 167  * Method:    getNativeGlyphImageBounds
 168  * Signature: (JJILjava/awt/geom/Rectangle2D/Float;DD)V
 169  */
 170 JNIEXPORT void JNICALL
 171 Java_sun_font_CStrike_getNativeGlyphImageBounds
 172     (JNIEnv *env, jclass clazz,
 173      jlong awtStrikePtr, jint glyphCode,
 174      jobject result /*Rectangle*/, jdouble x, jdouble y)
 175 {
 176 JNI_COCOA_ENTER(env);
 177 
 178     AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
 179     AWTFont *awtFont = awtStrike->fAWTFont;
 180 
 181     CGAffineTransform tx = awtStrike->fAltTx;
 182     tx.tx += x;
 183     tx.ty += y;
 184 
 185     // negative glyph codes are really unicodes, which were placed there by the mapper
 186     // to indicate we should use CoreText to substitute the character
 187     CGGlyph glyph;
 188     const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph);
 189 
 190     CGRect bbox;
 191     JRSFontGetBoundingBoxesForGlyphsAndStyle(fallback, &tx, awtStrike->fStyle, &glyph, 1, &bbox);
 192     CFRelease(fallback);
 193 
 194     // the origin of this bounding box is relative to the bottom-left corner baseline
 195     CGFloat decender = -bbox.origin.y;
 196     bbox.origin.y = -bbox.size.height + decender;
 197 
 198     // Rectangle2D.Float.setRect(float x, float y, float width, float height);
 199     DECLARE_CLASS(sjc_Rectangle2D_Float, "java/awt/geom/Rectangle2D$Float");    // cache class id for Rectangle
 200     DECLARE_METHOD(sjr_Rectangle2DFloat_setRect, sjc_Rectangle2D_Float, "setRect", "(FFFF)V");
 201     (*env)->CallVoidMethod(env, result, sjr_Rectangle2DFloat_setRect,
 202              (jfloat)bbox.origin.x, (jfloat)bbox.origin.y, (jfloat)bbox.size.width, (jfloat)bbox.size.height);
 203     CHECK_EXCEPTION();
 204 
 205 JNI_COCOA_EXIT(env);
 206 }
 207 
 208 /*
 209  * Class:     sun_font_CStrike
 210  * Method:    getNativeGlyphOutline
 211  * Signature: (JJIDD)Ljava/awt/geom/GeneralPath;
 212  */
 213 JNIEXPORT jobject JNICALL
 214 Java_sun_font_CStrike_getNativeGlyphOutline
 215     (JNIEnv *env, jclass clazz,
 216      jlong awtStrikePtr, jint glyphCode, jdouble xPos, jdouble yPos)
 217 {
 218     jobject generalPath = NULL;
 219 
 220 JNI_COCOA_ENTER(env);
 221 
 222     AWTPathRef path = NULL;
 223     jfloatArray pointCoords = NULL;
 224     jbyteArray pointTypes = NULL;
 225 
 226     DECLARE_CLASS_RETURN(jc_GeneralPath, "java/awt/geom/GeneralPath", NULL);
 227     DECLARE_METHOD_RETURN(jc_GeneralPath_ctor, jc_GeneralPath, "<init>", "(I[BI[FI)V", NULL);
 228 
 229 AWT_FONT_CLEANUP_SETUP;
 230 
 231     AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
 232     AWTFont *awtfont = awtStrike->fAWTFont;
 233 
 234 AWT_FONT_CLEANUP_CHECK(awtfont);
 235 
 236     // inverting the shear order and sign to compensate for the flipped coordinate system
 237     CGAffineTransform tx = awtStrike->fTx;
 238     tx.tx += xPos;
 239     tx.ty += yPos;
 240 
 241     // get the right font and glyph for this "Java GlyphCode"
 242 
 243     CGGlyph glyph;
 244     const CTFontRef font = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtfont, glyphCode, &glyph);
 245 
 246     // get the advance of this glyph
 247     CGSize advance;
 248     CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, &glyph, &advance, 1);
 249 
 250     // Create AWTPath
 251     path = AWTPathCreate(CGSizeMake(xPos, yPos));
 252 AWT_FONT_CLEANUP_CHECK(path);
 253 
 254     // Get the paths
 255     tx = awtStrike->fTx;
 256     tx = CGAffineTransformConcat(tx, sInverseTX);
 257     AWTGetGlyphOutline(&glyph, (NSFont *)font, &advance, &tx, 0, 1, &path);
 258     CFRelease(font);
 259 
 260     pointCoords = (*env)->NewFloatArray(env, path->fNumberOfDataElements);
 261 AWT_FONT_CLEANUP_CHECK(pointCoords);
 262 
 263     (*env)->SetFloatArrayRegion(env, pointCoords, 0, path->fNumberOfDataElements, (jfloat*)path->fSegmentData);
 264 
 265     // Copy the pointTypes to the general path
 266     pointTypes = (*env)->NewByteArray(env, path->fNumberOfSegments);
 267 AWT_FONT_CLEANUP_CHECK(pointTypes);
 268 
 269     (*env)->SetByteArrayRegion(env, pointTypes, 0, path->fNumberOfSegments, (jbyte*)path->fSegmentType);
 270 
 271     generalPath = (*env)->NewObject(env, jc_GeneralPath, jc_GeneralPath_ctor, java_awt_geom_PathIterator_WIND_NON_ZERO, pointTypes,
 272                     path->fNumberOfSegments, pointCoords, path->fNumberOfDataElements); // AWT_THREADING Safe (known object)

 273 
 274     // Cleanup
 275 cleanup:
 276     if (path != NULL) {
 277         AWTPathFree(path);
 278         path = NULL;
 279     }
 280 
 281     if (pointCoords != NULL) {
 282         (*env)->DeleteLocalRef(env, pointCoords);
 283         pointCoords = NULL;
 284     }
 285 
 286     if (pointTypes != NULL) {
 287         (*env)->DeleteLocalRef(env, pointTypes);
 288         pointTypes = NULL;
 289     }
 290 
 291     AWT_FONT_CLEANUP_FINISH;
 292 JNI_COCOA_EXIT(env);
 293     return generalPath;
 294 }
 295 
 296 /*
 297  * Class:     sun_font_CStrike
 298  * Method:    getGlyphImagePtrsNative
 299  * Signature: (JJ[J[II)V
 300  */
 301 JNIEXPORT void JNICALL
 302 Java_sun_font_CStrike_getGlyphImagePtrsNative
 303     (JNIEnv *env, jclass clazz,
 304      jlong awtStrikePtr, jlongArray glyphInfoLongArray,
 305      jintArray glyphCodes, jint len)
 306 {
 307 JNI_COCOA_ENTER(env);
 308 
 309     AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
 310 
 311     jlong *glyphInfos =
 312         (*env)->GetPrimitiveArrayCritical(env, glyphInfoLongArray, NULL);
 313 
 314     jint *rawGlyphCodes =
 315             (*env)->GetPrimitiveArrayCritical(env, glyphCodes, NULL);
 316     @try {
 317         if (rawGlyphCodes != NULL && glyphInfos != NULL) {
 318             CGGlyphImages_GetGlyphImagePtrs(glyphInfos, awtStrike,
 319                     rawGlyphCodes, len);
 320         }
 321     }
 322     @finally {
 323         if (rawGlyphCodes != NULL) {
 324             (*env)->ReleasePrimitiveArrayCritical(env, glyphCodes,
 325                                                   rawGlyphCodes, JNI_ABORT);
 326         }
 327         if (glyphInfos != NULL) {
 328             // Do not use JNI_COMMIT, as that will not free the buffer copy
 329             // when +ProtectJavaHeap is on.
 330             (*env)->ReleasePrimitiveArrayCritical(env, glyphInfoLongArray,
 331                                                   glyphInfos, 0);
 332         }
 333     }
 334 
 335 JNI_COCOA_EXIT(env);
 336 }
 337 
 338 /*
 339  * Class:     sun_font_CStrike
 340  * Method:    createNativeStrikePtr
 341  * Signature: (J[D[DII)J
 342  */
 343 JNIEXPORT jlong JNICALL Java_sun_font_CStrike_createNativeStrikePtr
 344 (JNIEnv *env, jclass clazz, jlong nativeFontPtr, jdoubleArray glyphTxArray, jdoubleArray invDevTxArray, jint aaStyle, jint fmHint)
 345 {
 346     AWTStrike *awtStrike = nil;
 347 JNI_COCOA_ENTER(env);
 348 
 349     AWTFont *awtFont = (AWTFont *)jlong_to_ptr(nativeFontPtr);
 350     JRSFontRenderingStyle style = JRSFontGetRenderingStyleForHints(fmHint, aaStyle);
 351 
 352     CGAffineTransform glyphTx = GetTxFromDoubles(env, glyphTxArray);
 353     CGAffineTransform invDevTx = GetTxFromDoubles(env, invDevTxArray);
 354 
 355     awtStrike = [AWTStrike awtStrikeForFont:awtFont tx:glyphTx invDevTx:invDevTx style:style aaStyle:aaStyle]; // autoreleased
 356 
 357     if (awtStrike)
 358     {
 359         CFRetain(awtStrike); // GC
 360     }
 361 
 362 JNI_COCOA_EXIT(env);
 363     return ptr_to_jlong(awtStrike);
 364 }
 365 
 366 /*
 367  * Class:     sun_font_CStrike
 368  * Method:    disposeNativeStrikePtr
 369  * Signature: (J)V
 370  */
 371 JNIEXPORT void JNICALL
 372 Java_sun_font_CStrike_disposeNativeStrikePtr
 373     (JNIEnv *env, jclass clazz, jlong awtStrike)
 374 {
 375 JNI_COCOA_ENTER(env);
 376 
 377     if (awtStrike) {
 378         CFRelease((AWTStrike *)jlong_to_ptr(awtStrike)); // GC
 379     }
 380 
 381 JNI_COCOA_EXIT(env);
 382 }
 383 
 384 /*
 385  * Class:     sun_font_CStrike
 386  * Method:    getFontMetrics
 387  * Signature: (J)Lsun/font/StrikeMetrics;
 388  */
 389 JNIEXPORT jobject JNICALL
 390 Java_sun_font_CStrike_getFontMetrics
 391     (JNIEnv *env, jclass clazz, jlong awtStrikePtr)
 392 {
 393     jobject metrics = NULL;
 394 
 395 JNI_COCOA_ENTER(env);
 396     AWT_FONT_CLEANUP_SETUP;
 397 
 398     AWTFont *awtfont = ((AWTStrike *)jlong_to_ptr(awtStrikePtr))->fAWTFont;
 399     AWT_FONT_CLEANUP_CHECK(awtfont);
 400 
 401     CGFontRef cgFont = awtfont->fNativeCGFont;
 402 
 403     jfloat ay=0.0, dy=0.0, mx=0.0, ly=0.0;
 404     int unitsPerEm = CGFontGetUnitsPerEm(cgFont);
 405     CGFloat scaleX = (1.0 / unitsPerEm);
 406     CGFloat scaleY = (1.0 / unitsPerEm);
 407 
 408     // Ascent
 409     ay = -(CGFloat)CGFontGetAscent(cgFont) * scaleY;
 410 
 411     // Descent
 412     dy = -(CGFloat)CGFontGetDescent(cgFont) * scaleY;
 413 
 414     // Leading
 415     ly = (CGFloat)CGFontGetLeading(cgFont) * scaleY;
 416 
 417     // Max Advance for Font Direction (Strictly horizontal)
 418     mx = [awtfont->fFont maximumAdvancement].width;
 419 
 420     /*
 421      * ascent:   no need to set ascentX - it will be zero.
 422      * descent:  no need to set descentX - it will be zero.
 423      * baseline: old releases "made up" a number and also seemed to
 424      *           make it up for "X" and set "Y" to 0.
 425      * leadingX: no need to set leadingX - it will be zero.
 426      * leadingY: made-up number, but being compatible with what 1.4.x did.
 427      * advance:  no need to set yMaxLinearAdvanceWidth - it will be zero.
 428      */
 429 
 430     DECLARE_CLASS_RETURN(sjc_StrikeMetrics, "sun/font/StrikeMetrics", NULL);
 431     DECLARE_METHOD_RETURN(strikeMetricsCtr, sjc_StrikeMetrics, "<init>", "(FFFFFFFFFF)V", NULL);
 432     metrics = (*env)->NewObject(env, sjc_StrikeMetrics, strikeMetricsCtr,
 433                            0.0, ay, 0.0, dy, 1.0,
 434                            0.0, 0.0, ly, mx, 0.0);
 435 
 436 cleanup:
 437     AWT_FONT_CLEANUP_FINISH;
 438 JNI_COCOA_EXIT(env);
 439 
 440     return metrics;
 441 }
 442 
 443 extern void AccelGlyphCache_RemoveAllInfos(GlyphInfo* glyph);
 444 /*
 445  * Class:     sun_font_CStrikeDisposer
 446  * Method:    removeGlyphInfoFromCache
 447  * Signature: (J)V
 448  */
 449 JNIEXPORT void JNICALL Java_sun_font_CStrikeDisposer_removeGlyphInfoFromCache
 450 (JNIEnv *env, jclass cls, jlong glyphInfo)
 451 {
 452     JNI_COCOA_ENTER(env);
 453 
 454     AccelGlyphCache_RemoveAllCellInfos((GlyphInfo*)jlong_to_ptr(glyphInfo));
 455 
 456     JNI_COCOA_EXIT(env);
 457 }
--- EOF ---