< prev index next >

src/java.desktop/macosx/native/libawt_lwawt/awt/CTextPipe.m

Print this page
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


  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 //  Native side of the Quartz text pipe, paints on Quartz Surface Datas.
  27 //  Interesting Docs : /Developer/Documentation/Cocoa/TasksAndConcepts/ProgrammingTopics/FontHandling/FontHandling.html
  28 
  29 #import "sun_awt_SunHints.h"
  30 #import "sun_lwawt_macosx_CTextPipe.h"
  31 #import "sun_java2d_OSXSurfaceData.h"
  32 
  33 #import <JavaNativeFoundation/JavaNativeFoundation.h>
  34 
  35 #import "CoreTextSupport.h"
  36 #import "QuartzSurfaceData.h"
  37 #include "AWTStrike.h"

  38 
  39 static const CGAffineTransform sInverseTX = { 1, 0, 0, -1, 0, 0 };
  40 
  41 
  42 #pragma mark --- CoreText Support ---
  43 
  44 
  45 // Translates a Unicode into a CGGlyph/CTFontRef pair
  46 // Returns the substituted font, and places the appropriate glyph into "glyphRef"
  47 CTFontRef JavaCT_CopyCTFallbackFontAndGlyphForUnicode
  48 (const AWTFont *font, const UTF16Char *charRef, CGGlyph *glyphRef, int count) {
  49     CTFontRef fallback = JRSFontCreateFallbackFontForCharacters((CTFontRef)font->fFont, charRef, count);
  50     if (fallback == NULL)
  51     {
  52         // use the original font if we somehow got duped into trying to fallback something we can't
  53         fallback = (CTFontRef)font->fFont;
  54         CFRetain(fallback);
  55     }
  56 
  57     CTFontGetGlyphsForCharacters(fallback, charRef, glyphRef, count);


 305     CGContextRestoreGState(cgRef);
 306 
 307     qsdo->FinishSurface(env, qsdo);
 308 }
 309 
 310 #pragma mark --- Glyph Vector Pipeline ---
 311 
 312 /*-----------------------------------
 313     Glyph Vector Pipeline
 314 
 315     doDrawGlyphs() has been separated into several pipelined functions to increase performance,
 316     and improve accountability for JNI resources, malloc'd memory, and error handling.
 317 
 318     Each stage of the pipeline is responsible for doing only one major thing, like allocating buffers,
 319     aquiring transform arrays from JNI, filling buffers, or striking glyphs. All resources or memory
 320     acquired at a given stage, must be released in that stage. Any error that occurs (like a failed malloc)
 321     is to be handled in the stage it occurs in, and is to return immediatly after freeing it's resources.
 322 
 323 -----------------------------------*/
 324 
 325 static JNF_CLASS_CACHE(jc_StandardGlyphVector, "sun/font/StandardGlyphVector");

 326 
 327 // Checks the GlyphVector Java object for any transforms that were applied to individual characters. If none are present,
 328 // strike the glyphs immediately in Core Graphics. Otherwise, obtain the arrays, and defer to above.
 329 static inline void doDrawGlyphsPipe_checkForPerGlyphTransforms
 330 (JNIEnv *env, QuartzSDOps *qsdo, const AWTStrike *strike, jobject gVector, BOOL useSubstituion, int *uniChars, CGGlyph *glyphs, CGSize *advances, size_t length)
 331 {
 332     // if we have no character substitution, and no per-glyph transformations - strike now!
 333     static JNF_MEMBER_CACHE(jm_StandardGlyphVector_gti, jc_StandardGlyphVector, "gti", "Lsun/font/StandardGlyphVector$GlyphTransformInfo;");
 334     jobject gti = JNFGetObjectField(env, gVector, jm_StandardGlyphVector_gti);

 335     if (gti == 0)
 336     {
 337         if (useSubstituion)
 338         {
 339             // quasi-simple case, substitution, but no per-glyph transforms
 340             JavaCT_DrawGlyphVector(qsdo, strike, TRUE, uniChars, glyphs, advances, NULL, NULL, length);
 341         }
 342         else
 343         {
 344             // fast path, straight to CG without per-glyph transforms
 345             CGContextShowGlyphsWithAdvances(qsdo->cgRef, glyphs, advances, length);
 346         }
 347         return;
 348     }
 349 
 350     static JNF_CLASS_CACHE(jc_StandardGlyphVector_GlyphTransformInfo, "sun/font/StandardGlyphVector$GlyphTransformInfo");
 351     static JNF_MEMBER_CACHE(jm_StandardGlyphVector_GlyphTransformInfo_transforms, jc_StandardGlyphVector_GlyphTransformInfo, "transforms", "[D");
 352     jdoubleArray g_gtiTransformsArray = JNFGetObjectField(env, gti, jm_StandardGlyphVector_GlyphTransformInfo_transforms); //(*env)->GetObjectField(env, gti, g_gtiTransforms);
 353     if (g_gtiTransformsArray == NULL) {
 354         return;
 355     }
 356     jdouble *g_gvTransformsAsDoubles = (*env)->GetPrimitiveArrayCritical(env, g_gtiTransformsArray, NULL);
 357     if (g_gvTransformsAsDoubles == NULL) {
 358         (*env)->DeleteLocalRef(env, g_gtiTransformsArray);
 359         return;
 360     }
 361 
 362     static JNF_MEMBER_CACHE(jm_StandardGlyphVector_GlyphTransformInfo_indices, jc_StandardGlyphVector_GlyphTransformInfo, "indices", "[I");
 363     jintArray g_gtiTXIndicesArray = JNFGetObjectField(env, gti, jm_StandardGlyphVector_GlyphTransformInfo_indices);
 364     jint *g_gvTXIndicesAsInts = (*env)->GetPrimitiveArrayCritical(env, g_gtiTXIndicesArray, NULL);
 365     if (g_gvTXIndicesAsInts == NULL) {
 366         (*env)->ReleasePrimitiveArrayCritical(env, g_gtiTransformsArray, g_gvTransformsAsDoubles, JNI_ABORT);
 367         (*env)->DeleteLocalRef(env, g_gtiTransformsArray);
 368         (*env)->DeleteLocalRef(env, g_gtiTXIndicesArray);
 369         return;
 370     }
 371     // slowest case, we have per-glyph transforms, and possibly glyph substitution as well
 372     JavaCT_DrawGlyphVector(qsdo, strike, useSubstituion, uniChars, glyphs, advances, g_gvTXIndicesAsInts, g_gvTransformsAsDoubles, length);
 373 
 374     (*env)->ReleasePrimitiveArrayCritical(env, g_gtiTransformsArray, g_gvTransformsAsDoubles, JNI_ABORT);
 375     (*env)->ReleasePrimitiveArrayCritical(env, g_gtiTXIndicesArray, g_gvTXIndicesAsInts, JNI_ABORT);
 376 
 377     (*env)->DeleteLocalRef(env, g_gtiTransformsArray);
 378     (*env)->DeleteLocalRef(env, g_gtiTXIndicesArray);
 379 }
 380 
 381 // Retrieves advances for translated unicodes
 382 // Uses "glyphs" as a temporary buffer for the glyph-to-unicode translation
 383 void JavaCT_GetAdvancesForUnichars


 420     BOOL complex = NO;
 421     for (i = 0; i < length; i++)
 422     {
 423         jint code = glyphsAsInts[i];
 424         if (code < 0)
 425         {
 426             complex = YES;
 427             uniChars[i] = -code;
 428             glyphs[i] = 0;
 429         }
 430         else
 431         {
 432             uniChars[i] = 0;
 433             glyphs[i] = code;
 434         }
 435     }
 436 
 437     (*env)->ReleasePrimitiveArrayCritical(env, glyphsArray, glyphsAsInts, JNI_ABORT);
 438 
 439     // fill the advance buffer
 440     static JNF_MEMBER_CACHE(jm_StandardGlyphVector_positions, jc_StandardGlyphVector, "positions", "[F");
 441     jfloatArray posArray = JNFGetObjectField(env, gVector, jm_StandardGlyphVector_positions);

 442     jfloat *positions = NULL;
 443     if (posArray != NULL) {
 444         // in this case, the positions have already been pre-calculated for us on the Java side
 445         positions = (*env)->GetPrimitiveArrayCritical(env, posArray, NULL);
 446         if (positions == NULL) {
 447             (*env)->DeleteLocalRef(env, posArray);
 448         }
 449     }
 450     if (positions != NULL) {
 451         CGPoint prev;
 452         prev.x = positions[0];
 453         prev.y = positions[1];
 454 
 455         // <rdar://problem/4294061> take the first point, and move the context to that location
 456         CGContextTranslateCTM(qsdo->cgRef, prev.x, prev.y);
 457 
 458         CGAffineTransform invTx = CGAffineTransformInvert(strike->fFontTx);
 459 
 460         // for each position, figure out the advance (since CG won't take positions directly)
 461         size_t i;


 480         // in this case, we have to go and calculate the positions ourselves
 481         // there were no pre-calculated positions from the glyph buffer on the Java side
 482         AWTFont *awtFont = strike->fAWTFont;
 483         CTFontGetAdvancesForGlyphs((CTFontRef)awtFont->fFont, kCTFontDefaultOrientation, glyphs, advances, length);
 484 
 485         if (complex)
 486         {
 487             JavaCT_GetAdvancesForUnichars(awtFont->fFont, uniChars, glyphs, length, advances);
 488         }
 489     }
 490 
 491     // continue on to the next stage of the pipe
 492     doDrawGlyphsPipe_checkForPerGlyphTransforms(env, qsdo, strike, gVector, complex, uniChars, glyphs, advances, length);
 493 }
 494 
 495 // Obtains the glyph array to determine the number of glyphs we are dealing with. If we are dealing a large number of glyphs,
 496 // we malloc a buffer to hold the glyphs and their advances, otherwise we use stack allocated buffers.
 497 static inline void doDrawGlyphsPipe_getGlyphVectorLengthAndAlloc
 498 (JNIEnv *env, QuartzSDOps *qsdo, const AWTStrike *strike, jobject gVector)
 499 {
 500     static JNF_MEMBER_CACHE(jm_StandardGlyphVector_glyphs, jc_StandardGlyphVector, "glyphs", "[I");
 501     jintArray glyphsArray = JNFGetObjectField(env, gVector, jm_StandardGlyphVector_glyphs);

 502     jsize length = (*env)->GetArrayLength(env, glyphsArray);
 503 
 504     if (length == 0)
 505     {
 506         // nothing to draw
 507         (*env)->DeleteLocalRef(env, glyphsArray);
 508         return;
 509     }
 510 
 511     if (length < MAX_STACK_ALLOC_GLYPH_BUFFER_SIZE)
 512     {
 513         // if we are small enough, fit everything onto the stack
 514         CGGlyph glyphs[length];
 515         int uniChars[length];
 516         CGSize advances[length];
 517         doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers(env, qsdo, strike, gVector, glyphs, uniChars, advances, length, glyphsArray);
 518     }
 519     else
 520     {
 521         // otherwise, we should malloc and free buffers for this large run


 564     CGAffineTransform tx = strike->fFontTx;
 565     tx.tx += x;
 566     tx.ty += y;
 567     CGContextConcatCTM(cgRef, tx);
 568 
 569     doDrawGlyphsPipe_getGlyphVectorLengthAndAlloc(env, qsdo, strike, gVector);
 570 }
 571 
 572 
 573 #pragma mark --- CTextPipe JNI ---
 574 
 575 
 576 /*
 577  * Class:     sun_lwawt_macosx_CTextPipe
 578  * Method:    doDrawString
 579  * Signature: (Lsun/java2d/SurfaceData;JLjava/lang/String;DD)V
 580  */
 581 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CTextPipe_doDrawString
 582 (JNIEnv *env, jobject jthis, jobject jsurfacedata, jlong awtStrikePtr, jstring str, jdouble x, jdouble y)
 583 {



 584     QuartzSDOps *qsdo = (QuartzSDOps *)SurfaceData_GetOps(env, jsurfacedata);
 585     AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
 586 
 587 JNF_COCOA_ENTER(env);
 588 
 589     jsize len = (*env)->GetStringLength(env, str);
 590 
 591     if (len < MAX_STACK_ALLOC_GLYPH_BUFFER_SIZE) // optimized for stack allocation <rdar://problem/4285041>
 592     {
 593         jchar unichars[len];
 594         (*env)->GetStringRegion(env, str, 0, len, unichars);
 595         JNF_CHECK_AND_RETHROW_EXCEPTION(env);
 596 
 597         // Draw the text context
 598         DrawTextContext(env, qsdo, awtStrike, unichars, len, x, y);
 599     }
 600     else
 601     {
 602         // Get string to draw and the length
 603         const jchar *unichars = JNFGetStringUTF16UniChars(env, str);




 604 
 605         // Draw the text context
 606         DrawTextContext(env, qsdo, awtStrike, unichars, len, x, y);
 607 
 608         JNFReleaseStringUTF16UniChars(env, str, unichars);
 609     }
 610 
 611 JNF_COCOA_RENDERER_EXIT(env);
 612 }
 613 
 614 
 615 /*
 616  * Class:     sun_lwawt_macosx_CTextPipe
 617  * Method:    doUnicodes
 618  * Signature: (Lsun/java2d/SurfaceData;J[CIIFF)V
 619  */
 620 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CTextPipe_doUnicodes
 621 (JNIEnv *env, jobject jthis, jobject jsurfacedata, jlong awtStrikePtr, jcharArray unicodes, jint offset, jint length, jfloat x, jfloat y)
 622 {
 623     QuartzSDOps *qsdo = (QuartzSDOps *)SurfaceData_GetOps(env, jsurfacedata);
 624     AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
 625 
 626 JNF_COCOA_ENTER(env);
 627 
 628     // Setup the text context
 629     if (length < MAX_STACK_ALLOC_GLYPH_BUFFER_SIZE) // optimized for stack allocation
 630     {
 631         jchar copyUnichars[length];
 632         (*env)->GetCharArrayRegion(env, unicodes, offset, length, copyUnichars);
 633         JNF_CHECK_AND_RETHROW_EXCEPTION(env);
 634         DrawTextContext(env, qsdo, awtStrike, copyUnichars, length, x, y);
 635     }
 636     else
 637     {
 638         jchar *copyUnichars = malloc(length * sizeof(jchar));
 639         if (!copyUnichars) {
 640             [JNFException raise:env as:kOutOfMemoryError reason:"Failed to malloc memory to create the glyphs for string drawing"];

 641         }
 642 
 643         @try {
 644             (*env)->GetCharArrayRegion(env, unicodes, offset, length, copyUnichars);
 645             JNF_CHECK_AND_RETHROW_EXCEPTION(env);
 646             DrawTextContext(env, qsdo, awtStrike, copyUnichars, length, x, y);
 647         } @finally {
 648             free(copyUnichars);
 649         }
 650     }
 651 
 652 JNF_COCOA_RENDERER_EXIT(env);
 653 }
 654 
 655 /*
 656  * Class:     sun_lwawt_macosx_CTextPipe
 657  * Method:    doOneUnicode
 658  * Signature: (Lsun/java2d/SurfaceData;JCFF)V
 659  */
 660 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CTextPipe_doOneUnicode
 661 (JNIEnv *env, jobject jthis, jobject jsurfacedata, jlong awtStrikePtr, jchar aUnicode, jfloat x, jfloat y)
 662 {
 663     QuartzSDOps *qsdo = (QuartzSDOps *)SurfaceData_GetOps(env, jsurfacedata);
 664     AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
 665 
 666 JNF_COCOA_ENTER(env);
 667 
 668     DrawTextContext(env, qsdo, awtStrike, &aUnicode, 1, x, y);
 669 
 670 JNF_COCOA_RENDERER_EXIT(env);
 671 }
 672 
 673 /*
 674  * Class: sun_lwawt_macosx_CTextPipe
 675  * Method: doDrawGlyphs
 676  * Signature: (Lsun/java2d/SurfaceData;JLjava/awt/font/GlyphVector;FF)V
 677  */
 678 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CTextPipe_doDrawGlyphs
 679 (JNIEnv *env, jobject jthis, jobject jsurfacedata, jlong awtStrikePtr, jobject gVector, jfloat x, jfloat y)
 680 {
 681     QuartzSDOps *qsdo = (QuartzSDOps *)SurfaceData_GetOps(env, jsurfacedata);
 682     AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
 683 
 684 JNF_COCOA_ENTER(env);
 685 
 686     qsdo->BeginSurface(env, qsdo, SD_Text);
 687     if (qsdo->cgRef == NULL)
 688     {
 689         qsdo->FinishSurface(env, qsdo);
 690         return;
 691     }
 692 
 693     CGContextSaveGState(qsdo->cgRef);
 694     JRSFontSetRenderingStyleOnContext(qsdo->cgRef, JRSFontGetRenderingStyleForHints(sun_awt_SunHints_INTVAL_FRACTIONALMETRICS_ON, sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_ON));
 695 
 696     doDrawGlyphsPipe_applyFontTransforms(env, qsdo, awtStrike, gVector, x, y);
 697 
 698     CGContextRestoreGState(qsdo->cgRef);
 699 
 700     qsdo->FinishSurface(env, qsdo);
 701 
 702 JNF_COCOA_RENDERER_EXIT(env);
 703 }


  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 //  Native side of the Quartz text pipe, paints on Quartz Surface Datas.
  27 //  Interesting Docs : /Developer/Documentation/Cocoa/TasksAndConcepts/ProgrammingTopics/FontHandling/FontHandling.html
  28 
  29 #import "sun_awt_SunHints.h"
  30 #import "sun_lwawt_macosx_CTextPipe.h"
  31 #import "sun_java2d_OSXSurfaceData.h"
  32 


  33 #import "CoreTextSupport.h"
  34 #import "QuartzSurfaceData.h"
  35 #include "AWTStrike.h"
  36 #import "JNIUtilities.h"
  37 
  38 static const CGAffineTransform sInverseTX = { 1, 0, 0, -1, 0, 0 };
  39 
  40 
  41 #pragma mark --- CoreText Support ---
  42 
  43 
  44 // Translates a Unicode into a CGGlyph/CTFontRef pair
  45 // Returns the substituted font, and places the appropriate glyph into "glyphRef"
  46 CTFontRef JavaCT_CopyCTFallbackFontAndGlyphForUnicode
  47 (const AWTFont *font, const UTF16Char *charRef, CGGlyph *glyphRef, int count) {
  48     CTFontRef fallback = JRSFontCreateFallbackFontForCharacters((CTFontRef)font->fFont, charRef, count);
  49     if (fallback == NULL)
  50     {
  51         // use the original font if we somehow got duped into trying to fallback something we can't
  52         fallback = (CTFontRef)font->fFont;
  53         CFRetain(fallback);
  54     }
  55 
  56     CTFontGetGlyphsForCharacters(fallback, charRef, glyphRef, count);


 304     CGContextRestoreGState(cgRef);
 305 
 306     qsdo->FinishSurface(env, qsdo);
 307 }
 308 
 309 #pragma mark --- Glyph Vector Pipeline ---
 310 
 311 /*-----------------------------------
 312     Glyph Vector Pipeline
 313 
 314     doDrawGlyphs() has been separated into several pipelined functions to increase performance,
 315     and improve accountability for JNI resources, malloc'd memory, and error handling.
 316 
 317     Each stage of the pipeline is responsible for doing only one major thing, like allocating buffers,
 318     aquiring transform arrays from JNI, filling buffers, or striking glyphs. All resources or memory
 319     acquired at a given stage, must be released in that stage. Any error that occurs (like a failed malloc)
 320     is to be handled in the stage it occurs in, and is to return immediatly after freeing it's resources.
 321 
 322 -----------------------------------*/
 323 
 324 static jclass jc_StandardGlyphVector = NULL;
 325 #define GET_SGV_CLASS() GET_CLASS(jc_StandardGlyphVector, "sun/font/StandardGlyphVector");
 326 
 327 // Checks the GlyphVector Java object for any transforms that were applied to individual characters. If none are present,
 328 // strike the glyphs immediately in Core Graphics. Otherwise, obtain the arrays, and defer to above.
 329 static inline void doDrawGlyphsPipe_checkForPerGlyphTransforms
 330 (JNIEnv *env, QuartzSDOps *qsdo, const AWTStrike *strike, jobject gVector, BOOL useSubstituion, int *uniChars, CGGlyph *glyphs, CGSize *advances, size_t length)
 331 {
 332     // if we have no character substitution, and no per-glyph transformations - strike now!
 333     GET_SGV_CLASS();
 334     DECLARE_FIELD(jm_StandardGlyphVector_gti, jc_StandardGlyphVector, "gti", "Lsun/font/StandardGlyphVector$GlyphTransformInfo;");
 335     jobject gti = (*env)->GetObjectField(env, gVector, jm_StandardGlyphVector_gti);
 336     if (gti == 0)
 337     {
 338         if (useSubstituion)
 339         {
 340             // quasi-simple case, substitution, but no per-glyph transforms
 341             JavaCT_DrawGlyphVector(qsdo, strike, TRUE, uniChars, glyphs, advances, NULL, NULL, length);
 342         }
 343         else
 344         {
 345             // fast path, straight to CG without per-glyph transforms
 346             CGContextShowGlyphsWithAdvances(qsdo->cgRef, glyphs, advances, length);
 347         }
 348         return;
 349     }
 350 
 351     DECLARE_CLASS(jc_StandardGlyphVector_GlyphTransformInfo, "sun/font/StandardGlyphVector$GlyphTransformInfo");
 352     DECLARE_FIELD(jm_StandardGlyphVector_GlyphTransformInfo_transforms, jc_StandardGlyphVector_GlyphTransformInfo, "transforms", "[D");
 353     jdoubleArray g_gtiTransformsArray = (*env)->GetObjectField(env, gti, jm_StandardGlyphVector_GlyphTransformInfo_transforms); //(*env)->GetObjectField(env, gti, g_gtiTransforms);
 354     if (g_gtiTransformsArray == NULL) {
 355         return;
 356     }
 357     jdouble *g_gvTransformsAsDoubles = (*env)->GetPrimitiveArrayCritical(env, g_gtiTransformsArray, NULL);
 358     if (g_gvTransformsAsDoubles == NULL) {
 359         (*env)->DeleteLocalRef(env, g_gtiTransformsArray);
 360         return;
 361     }
 362 
 363     DECLARE_FIELD(jm_StandardGlyphVector_GlyphTransformInfo_indices, jc_StandardGlyphVector_GlyphTransformInfo, "indices", "[I");
 364     jintArray g_gtiTXIndicesArray = (*env)->GetObjectField(env, gti, jm_StandardGlyphVector_GlyphTransformInfo_indices);
 365     jint *g_gvTXIndicesAsInts = (*env)->GetPrimitiveArrayCritical(env, g_gtiTXIndicesArray, NULL);
 366     if (g_gvTXIndicesAsInts == NULL) {
 367         (*env)->ReleasePrimitiveArrayCritical(env, g_gtiTransformsArray, g_gvTransformsAsDoubles, JNI_ABORT);
 368         (*env)->DeleteLocalRef(env, g_gtiTransformsArray);
 369         (*env)->DeleteLocalRef(env, g_gtiTXIndicesArray);
 370         return;
 371     }
 372     // slowest case, we have per-glyph transforms, and possibly glyph substitution as well
 373     JavaCT_DrawGlyphVector(qsdo, strike, useSubstituion, uniChars, glyphs, advances, g_gvTXIndicesAsInts, g_gvTransformsAsDoubles, length);
 374 
 375     (*env)->ReleasePrimitiveArrayCritical(env, g_gtiTransformsArray, g_gvTransformsAsDoubles, JNI_ABORT);
 376     (*env)->ReleasePrimitiveArrayCritical(env, g_gtiTXIndicesArray, g_gvTXIndicesAsInts, JNI_ABORT);
 377 
 378     (*env)->DeleteLocalRef(env, g_gtiTransformsArray);
 379     (*env)->DeleteLocalRef(env, g_gtiTXIndicesArray);
 380 }
 381 
 382 // Retrieves advances for translated unicodes
 383 // Uses "glyphs" as a temporary buffer for the glyph-to-unicode translation
 384 void JavaCT_GetAdvancesForUnichars


 421     BOOL complex = NO;
 422     for (i = 0; i < length; i++)
 423     {
 424         jint code = glyphsAsInts[i];
 425         if (code < 0)
 426         {
 427             complex = YES;
 428             uniChars[i] = -code;
 429             glyphs[i] = 0;
 430         }
 431         else
 432         {
 433             uniChars[i] = 0;
 434             glyphs[i] = code;
 435         }
 436     }
 437 
 438     (*env)->ReleasePrimitiveArrayCritical(env, glyphsArray, glyphsAsInts, JNI_ABORT);
 439 
 440     // fill the advance buffer
 441     GET_SGV_CLASS();
 442     DECLARE_FIELD(jm_StandardGlyphVector_positions, jc_StandardGlyphVector, "positions", "[F");
 443     jfloatArray posArray = (*env)->GetObjectField(env, gVector, jm_StandardGlyphVector_positions);
 444     jfloat *positions = NULL;
 445     if (posArray != NULL) {
 446         // in this case, the positions have already been pre-calculated for us on the Java side
 447         positions = (*env)->GetPrimitiveArrayCritical(env, posArray, NULL);
 448         if (positions == NULL) {
 449             (*env)->DeleteLocalRef(env, posArray);
 450         }
 451     }
 452     if (positions != NULL) {
 453         CGPoint prev;
 454         prev.x = positions[0];
 455         prev.y = positions[1];
 456 
 457         // <rdar://problem/4294061> take the first point, and move the context to that location
 458         CGContextTranslateCTM(qsdo->cgRef, prev.x, prev.y);
 459 
 460         CGAffineTransform invTx = CGAffineTransformInvert(strike->fFontTx);
 461 
 462         // for each position, figure out the advance (since CG won't take positions directly)
 463         size_t i;


 482         // in this case, we have to go and calculate the positions ourselves
 483         // there were no pre-calculated positions from the glyph buffer on the Java side
 484         AWTFont *awtFont = strike->fAWTFont;
 485         CTFontGetAdvancesForGlyphs((CTFontRef)awtFont->fFont, kCTFontDefaultOrientation, glyphs, advances, length);
 486 
 487         if (complex)
 488         {
 489             JavaCT_GetAdvancesForUnichars(awtFont->fFont, uniChars, glyphs, length, advances);
 490         }
 491     }
 492 
 493     // continue on to the next stage of the pipe
 494     doDrawGlyphsPipe_checkForPerGlyphTransforms(env, qsdo, strike, gVector, complex, uniChars, glyphs, advances, length);
 495 }
 496 
 497 // Obtains the glyph array to determine the number of glyphs we are dealing with. If we are dealing a large number of glyphs,
 498 // we malloc a buffer to hold the glyphs and their advances, otherwise we use stack allocated buffers.
 499 static inline void doDrawGlyphsPipe_getGlyphVectorLengthAndAlloc
 500 (JNIEnv *env, QuartzSDOps *qsdo, const AWTStrike *strike, jobject gVector)
 501 {
 502     GET_SGV_CLASS();
 503     DECLARE_FIELD(jm_StandardGlyphVector_glyphs, jc_StandardGlyphVector, "glyphs", "[I");
 504     jintArray glyphsArray = (*env)->GetObjectField(env, gVector, jm_StandardGlyphVector_glyphs);
 505     jsize length = (*env)->GetArrayLength(env, glyphsArray);
 506 
 507     if (length == 0)
 508     {
 509         // nothing to draw
 510         (*env)->DeleteLocalRef(env, glyphsArray);
 511         return;
 512     }
 513 
 514     if (length < MAX_STACK_ALLOC_GLYPH_BUFFER_SIZE)
 515     {
 516         // if we are small enough, fit everything onto the stack
 517         CGGlyph glyphs[length];
 518         int uniChars[length];
 519         CGSize advances[length];
 520         doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers(env, qsdo, strike, gVector, glyphs, uniChars, advances, length, glyphsArray);
 521     }
 522     else
 523     {
 524         // otherwise, we should malloc and free buffers for this large run


 567     CGAffineTransform tx = strike->fFontTx;
 568     tx.tx += x;
 569     tx.ty += y;
 570     CGContextConcatCTM(cgRef, tx);
 571 
 572     doDrawGlyphsPipe_getGlyphVectorLengthAndAlloc(env, qsdo, strike, gVector);
 573 }
 574 
 575 
 576 #pragma mark --- CTextPipe JNI ---
 577 
 578 
 579 /*
 580  * Class:     sun_lwawt_macosx_CTextPipe
 581  * Method:    doDrawString
 582  * Signature: (Lsun/java2d/SurfaceData;JLjava/lang/String;DD)V
 583  */
 584 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CTextPipe_doDrawString
 585 (JNIEnv *env, jobject jthis, jobject jsurfacedata, jlong awtStrikePtr, jstring str, jdouble x, jdouble y)
 586 {
 587     if (str == NULL) {
 588         return;
 589     }
 590     QuartzSDOps *qsdo = (QuartzSDOps *)SurfaceData_GetOps(env, jsurfacedata);
 591     AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
 592 
 593 JNI_COCOA_ENTER(env);
 594 
 595     jsize len = (*env)->GetStringLength(env, str);
 596 
 597     if (len < MAX_STACK_ALLOC_GLYPH_BUFFER_SIZE) // optimized for stack allocation <rdar://problem/4285041>
 598     {
 599         jchar unichars[len];
 600         (*env)->GetStringRegion(env, str, 0, len, unichars);
 601         CHECK_EXCEPTION();
 602 
 603         // Draw the text context
 604         DrawTextContext(env, qsdo, awtStrike, unichars, len, x, y);
 605     }
 606     else
 607     {
 608         // Get string to draw and the length
 609         const jchar *unichars = (*env)->GetStringChars(env, str, NULL);
 610         if (unichars == NULL) {
 611             JNU_ThrowOutOfMemoryError(env, "Could not get string chars");
 612             return;
 613         }
 614 
 615         // Draw the text context
 616         DrawTextContext(env, qsdo, awtStrike, unichars, len, x, y);
 617 
 618         (*env)->ReleaseStringChars(env, str, unichars);
 619     }
 620 
 621 JNI_COCOA_RENDERER_EXIT(env);
 622 }
 623 
 624 
 625 /*
 626  * Class:     sun_lwawt_macosx_CTextPipe
 627  * Method:    doUnicodes
 628  * Signature: (Lsun/java2d/SurfaceData;J[CIIFF)V
 629  */
 630 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CTextPipe_doUnicodes
 631 (JNIEnv *env, jobject jthis, jobject jsurfacedata, jlong awtStrikePtr, jcharArray unicodes, jint offset, jint length, jfloat x, jfloat y)
 632 {
 633     QuartzSDOps *qsdo = (QuartzSDOps *)SurfaceData_GetOps(env, jsurfacedata);
 634     AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
 635 
 636 JNI_COCOA_ENTER(env);
 637 
 638     // Setup the text context
 639     if (length < MAX_STACK_ALLOC_GLYPH_BUFFER_SIZE) // optimized for stack allocation
 640     {
 641         jchar copyUnichars[length];
 642         (*env)->GetCharArrayRegion(env, unicodes, offset, length, copyUnichars);
 643         CHECK_EXCEPTION();
 644         DrawTextContext(env, qsdo, awtStrike, copyUnichars, length, x, y);
 645     }
 646     else
 647     {
 648         jchar *copyUnichars = malloc(length * sizeof(jchar));
 649         if (!copyUnichars) {
 650             JNU_ThrowOutOfMemoryError(env, "Failed to malloc memory to create the glyphs for string drawing");
 651             return;
 652         }
 653 
 654         @try {
 655             (*env)->GetCharArrayRegion(env, unicodes, offset, length, copyUnichars);
 656             CHECK_EXCEPTION();
 657             DrawTextContext(env, qsdo, awtStrike, copyUnichars, length, x, y);
 658         } @finally {
 659             free(copyUnichars);
 660         }
 661     }
 662 
 663 JNI_COCOA_RENDERER_EXIT(env);
 664 }
 665 
 666 /*
 667  * Class:     sun_lwawt_macosx_CTextPipe
 668  * Method:    doOneUnicode
 669  * Signature: (Lsun/java2d/SurfaceData;JCFF)V
 670  */
 671 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CTextPipe_doOneUnicode
 672 (JNIEnv *env, jobject jthis, jobject jsurfacedata, jlong awtStrikePtr, jchar aUnicode, jfloat x, jfloat y)
 673 {
 674     QuartzSDOps *qsdo = (QuartzSDOps *)SurfaceData_GetOps(env, jsurfacedata);
 675     AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
 676 
 677 JNI_COCOA_ENTER(env);
 678 
 679     DrawTextContext(env, qsdo, awtStrike, &aUnicode, 1, x, y);
 680 
 681 JNI_COCOA_RENDERER_EXIT(env);
 682 }
 683 
 684 /*
 685  * Class: sun_lwawt_macosx_CTextPipe
 686  * Method: doDrawGlyphs
 687  * Signature: (Lsun/java2d/SurfaceData;JLjava/awt/font/GlyphVector;FF)V
 688  */
 689 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CTextPipe_doDrawGlyphs
 690 (JNIEnv *env, jobject jthis, jobject jsurfacedata, jlong awtStrikePtr, jobject gVector, jfloat x, jfloat y)
 691 {
 692     QuartzSDOps *qsdo = (QuartzSDOps *)SurfaceData_GetOps(env, jsurfacedata);
 693     AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
 694 
 695 JNI_COCOA_ENTER(env);
 696 
 697     qsdo->BeginSurface(env, qsdo, SD_Text);
 698     if (qsdo->cgRef == NULL)
 699     {
 700         qsdo->FinishSurface(env, qsdo);
 701         return;
 702     }
 703 
 704     CGContextSaveGState(qsdo->cgRef);
 705     JRSFontSetRenderingStyleOnContext(qsdo->cgRef, JRSFontGetRenderingStyleForHints(sun_awt_SunHints_INTVAL_FRACTIONALMETRICS_ON, sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_ON));
 706 
 707     doDrawGlyphsPipe_applyFontTransforms(env, qsdo, awtStrike, gVector, x, y);
 708 
 709     CGContextRestoreGState(qsdo->cgRef);
 710 
 711     qsdo->FinishSurface(env, qsdo);
 712 
 713 JNI_COCOA_RENDERER_EXIT(env);
 714 }
< prev index next >