Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/native_NOTIOS/sun/font/AWTStrike.m
38829 views
/*1* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#import <JavaNativeFoundation/JavaNativeFoundation.h>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#include "fontscalerdefs.h"3334/* Use THIS_FILE when it is available. */35#ifndef THIS_FILE36#define THIS_FILE __FILE__37#endif3839@implementation AWTStrike4041static CGAffineTransform sInverseTX = { 1, 0, 0, -1, 0, 0 };4243- (id) initWithFont:(AWTFont *)awtFont44tx:(CGAffineTransform)tx45invDevTx:(CGAffineTransform)invDevTx46style:(JRSFontRenderingStyle)style47aaStyle:(jint)aaStyle {4849self = [super init];50if (self) {51fAWTFont = [awtFont retain];52fStyle = style;53fAAStyle = aaStyle;5455fTx = tx; // composited glyph and device transform5657fAltTx = tx;58fAltTx.b *= -1;59fAltTx.d *= -1;6061invDevTx.b *= -1;62invDevTx.c *= -1;63fFontTx = CGAffineTransformConcat(CGAffineTransformConcat(tx, invDevTx), sInverseTX);64fDevTx = CGAffineTransformInvert(CGAffineTransformConcat(invDevTx, sInverseTX));6566// the "font size" is the square root of the determinant of the matrix67fSize = sqrt(fabs(fFontTx.a * fFontTx.d - fFontTx.b * fFontTx.c));68}69return self;70}7172- (void) dealloc {73[fAWTFont release];74fAWTFont = nil;7576[super dealloc];77}7879+ (AWTStrike *) awtStrikeForFont:(AWTFont *)awtFont80tx:(CGAffineTransform)tx81invDevTx:(CGAffineTransform)invDevTx82style:(JRSFontRenderingStyle)style83aaStyle:(jint)aaStyle {8485return [[[AWTStrike alloc] initWithFont:awtFont86tx:tx invDevTx:invDevTx87style:style88aaStyle:aaStyle] autorelease];89}9091@end929394#define AWT_FONT_CLEANUP_SETUP \95BOOL _fontThrowJavaException = NO;9697#define AWT_FONT_CLEANUP_CHECK(a) \98if ((a) == NULL) { \99_fontThrowJavaException = YES; \100goto cleanup; \101} \102if ((*env)->ExceptionCheck(env) == JNI_TRUE) { \103goto cleanup; \104}105106#define AWT_FONT_CLEANUP_FINISH \107if (_fontThrowJavaException == YES) { \108char s[512]; \109sprintf(s, "%s-%s:%d", THIS_FILE, __FUNCTION__, __LINE__); \110[JNFException raise:env as:kRuntimeException reason:s]; \111}112113114/*115* Creates an affine transform from the corresponding doubles sent116* from CStrike.getGlyphTx().117*/118static inline CGAffineTransform119GetTxFromDoubles(JNIEnv *env, jdoubleArray txArray)120{121if (txArray == NULL) {122return CGAffineTransformIdentity;123}124125jdouble *txPtr = (*env)->GetPrimitiveArrayCritical(env, txArray, NULL);126if (txPtr == NULL) {127return CGAffineTransformIdentity;128}129130CGAffineTransform tx =131CGAffineTransformMake(txPtr[0], txPtr[1], txPtr[2],132txPtr[3], txPtr[4], txPtr[5]);133tx = CGAffineTransformConcat(sInverseTX, tx);134135(*env)->ReleasePrimitiveArrayCritical(env, txArray, txPtr, JNI_ABORT);136137return tx;138}139140/*141* Class: sun_font_CStrike142* Method: getNativeGlyphAdvance143* Signature: (JI)F144*/145JNIEXPORT jfloat JNICALL146Java_sun_font_CStrike_getNativeGlyphAdvance147(JNIEnv *env, jclass clazz, jlong awtStrikePtr, jint glyphCode)148{149CGSize advance;150JNF_COCOA_ENTER(env);151AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);152AWTFont *awtFont = awtStrike->fAWTFont;153154// negative glyph codes are really unicodes, which were placed there by the mapper155// to indicate we should use CoreText to substitute the character156CGGlyph glyph;157const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph);158CTFontGetAdvancesForGlyphs(fallback, kCTFontDefaultOrientation, &glyph, &advance, 1);159CFRelease(fallback);160advance = CGSizeApplyAffineTransform(advance, awtStrike->fFontTx);161if (!JRSFontStyleUsesFractionalMetrics(awtStrike->fStyle)) {162advance.width = round(advance.width);163}164165JNF_COCOA_EXIT(env);166return advance.width;167}168169/*170* Class: sun_font_CStrike171* Method: getNativeGlyphImageBounds172* Signature: (JJILjava/awt/geom/Rectangle2D/Float;DD)V173*/174JNIEXPORT void JNICALL175Java_sun_font_CStrike_getNativeGlyphImageBounds176(JNIEnv *env, jclass clazz,177jlong awtStrikePtr, jint glyphCode,178jobject result /*Rectangle*/, jdouble x, jdouble y)179{180JNF_COCOA_ENTER(env);181182AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);183AWTFont *awtFont = awtStrike->fAWTFont;184185CGAffineTransform tx = awtStrike->fAltTx;186tx.tx += x;187tx.ty += y;188189// negative glyph codes are really unicodes, which were placed there by the mapper190// to indicate we should use CoreText to substitute the character191CGGlyph glyph;192const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph);193194CGRect bbox;195JRSFontGetBoundingBoxesForGlyphsAndStyle(fallback, &tx, awtStrike->fStyle, &glyph, 1, &bbox);196CFRelease(fallback);197198// the origin of this bounding box is relative to the bottom-left corner baseline199CGFloat decender = -bbox.origin.y;200bbox.origin.y = -bbox.size.height + decender;201202// Rectangle2D.Float.setRect(float x, float y, float width, float height);203static JNF_CLASS_CACHE(sjc_Rectangle2D_Float, "java/awt/geom/Rectangle2D$Float"); // cache class id for Rectangle204static JNF_MEMBER_CACHE(sjr_Rectangle2DFloat_setRect, sjc_Rectangle2D_Float, "setRect", "(FFFF)V");205JNFCallVoidMethod(env, result, sjr_Rectangle2DFloat_setRect, (jfloat)bbox.origin.x, (jfloat)bbox.origin.y, (jfloat)bbox.size.width, (jfloat)bbox.size.height);206207JNF_COCOA_EXIT(env);208}209210/*211* Class: sun_font_CStrike212* Method: getNativeGlyphOutline213* Signature: (JJIDD)Ljava/awt/geom/GeneralPath;214*/215JNIEXPORT jobject JNICALL216Java_sun_font_CStrike_getNativeGlyphOutline217(JNIEnv *env, jclass clazz,218jlong awtStrikePtr, jint glyphCode, jdouble xPos, jdouble yPos)219{220jobject generalPath = NULL;221222JNF_COCOA_ENTER(env);223224AWTPathRef path = NULL;225jfloatArray pointCoords = NULL;226jbyteArray pointTypes = NULL;227228AWT_FONT_CLEANUP_SETUP;229230AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);231AWTFont *awtfont = awtStrike->fAWTFont;232233AWT_FONT_CLEANUP_CHECK(awtfont);234235// inverting the shear order and sign to compensate for the flipped coordinate system236CGAffineTransform tx = awtStrike->fTx;237tx.tx += xPos;238tx.ty += yPos;239240// get the right font and glyph for this "Java GlyphCode"241242CGGlyph glyph;243const CTFontRef font = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtfont, glyphCode, &glyph);244245// get the advance of this glyph246CGSize advance;247CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, &glyph, &advance, 1);248249// Create AWTPath250path = AWTPathCreate(CGSizeMake(xPos, yPos));251AWT_FONT_CLEANUP_CHECK(path);252253// Get the paths254tx = awtStrike->fTx;255tx = CGAffineTransformConcat(tx, sInverseTX);256AWTGetGlyphOutline(&glyph, (NSFont *)font, &advance, &tx, 0, 1, &path);257CFRelease(font);258259pointCoords = (*env)->NewFloatArray(env, path->fNumberOfDataElements);260AWT_FONT_CLEANUP_CHECK(pointCoords);261262(*env)->SetFloatArrayRegion(env, pointCoords, 0, path->fNumberOfDataElements, (jfloat*)path->fSegmentData);263264// Copy the pointTypes to the general path265pointTypes = (*env)->NewByteArray(env, path->fNumberOfSegments);266AWT_FONT_CLEANUP_CHECK(pointTypes);267268(*env)->SetByteArrayRegion(env, pointTypes, 0, path->fNumberOfSegments, (jbyte*)path->fSegmentType);269270static JNF_CLASS_CACHE(jc_GeneralPath, "java/awt/geom/GeneralPath");271static JNF_CTOR_CACHE(jc_GeneralPath_ctor, jc_GeneralPath, "(I[BI[FI)V");272generalPath = JNFNewObject(env, jc_GeneralPath_ctor, java_awt_geom_PathIterator_WIND_NON_ZERO, pointTypes, path->fNumberOfSegments, pointCoords, path->fNumberOfDataElements); // AWT_THREADING Safe (known object)273274// Cleanup275cleanup:276if (path != NULL) {277AWTPathFree(path);278path = NULL;279}280281if (pointCoords != NULL) {282(*env)->DeleteLocalRef(env, pointCoords);283pointCoords = NULL;284}285286if (pointTypes != NULL) {287(*env)->DeleteLocalRef(env, pointTypes);288pointTypes = NULL;289}290291AWT_FONT_CLEANUP_FINISH;292JNF_COCOA_EXIT(env);293return generalPath;294}295296/*297* Class: sun_font_CStrike298* Method: getGlyphImagePtrsNative299* Signature: (JJ[J[II)V300*/301JNIEXPORT void JNICALL302Java_sun_font_CStrike_getGlyphImagePtrsNative303(JNIEnv *env, jclass clazz,304jlong awtStrikePtr, jlongArray glyphInfoLongArray,305jintArray glyphCodes, jint len)306{307JNF_COCOA_ENTER(env);308309AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);310311jlong *glyphInfos =312(*env)->GetPrimitiveArrayCritical(env, glyphInfoLongArray, NULL);313314jint *rawGlyphCodes =315(*env)->GetPrimitiveArrayCritical(env, glyphCodes, NULL);316@try {317if (rawGlyphCodes != NULL && glyphInfos != NULL) {318CGGlyphImages_GetGlyphImagePtrs(glyphInfos, awtStrike,319rawGlyphCodes, len);320}321}322@finally {323if (rawGlyphCodes != NULL) {324(*env)->ReleasePrimitiveArrayCritical(env, glyphCodes,325rawGlyphCodes, JNI_ABORT);326}327if (glyphInfos != NULL) {328// Do not use JNI_COMMIT, as that will not free the buffer copy329// when +ProtectJavaHeap is on.330(*env)->ReleasePrimitiveArrayCritical(env, glyphInfoLongArray,331glyphInfos, 0);332}333}334335JNF_COCOA_EXIT(env);336}337338/*339* Class: sun_font_CStrike340* Method: createNativeStrikePtr341* Signature: (J[D[DII)J342*/343JNIEXPORT jlong JNICALL Java_sun_font_CStrike_createNativeStrikePtr344(JNIEnv *env, jclass clazz, jlong nativeFontPtr, jdoubleArray glyphTxArray, jdoubleArray invDevTxArray, jint aaStyle, jint fmHint)345{346AWTStrike *awtStrike = nil;347JNF_COCOA_ENTER(env);348349AWTFont *awtFont = (AWTFont *)jlong_to_ptr(nativeFontPtr);350JRSFontRenderingStyle style = JRSFontGetRenderingStyleForHints(fmHint, aaStyle);351352CGAffineTransform glyphTx = GetTxFromDoubles(env, glyphTxArray);353CGAffineTransform invDevTx = GetTxFromDoubles(env, invDevTxArray);354355awtStrike = [AWTStrike awtStrikeForFont:awtFont tx:glyphTx invDevTx:invDevTx style:style aaStyle:aaStyle]; // autoreleased356357if (awtStrike)358{359CFRetain(awtStrike); // GC360}361362JNF_COCOA_EXIT(env);363return ptr_to_jlong(awtStrike);364}365366/*367* Class: sun_font_CStrike368* Method: disposeNativeStrikePtr369* Signature: (J)V370*/371JNIEXPORT void JNICALL372Java_sun_font_CStrike_disposeNativeStrikePtr373(JNIEnv *env, jclass clazz, jlong awtStrike)374{375JNF_COCOA_ENTER(env);376377if (awtStrike) {378CFRelease((AWTStrike *)jlong_to_ptr(awtStrike)); // GC379}380381JNF_COCOA_EXIT(env);382}383384/*385* Class: sun_font_CStrike386* Method: getFontMetrics387* Signature: (J)Lsun/font/StrikeMetrics;388*/389JNIEXPORT jobject JNICALL390Java_sun_font_CStrike_getFontMetrics391(JNIEnv *env, jclass clazz, jlong awtStrikePtr)392{393jobject metrics = NULL;394395JNF_COCOA_ENTER(env);396AWT_FONT_CLEANUP_SETUP;397398AWTFont *awtfont = ((AWTStrike *)jlong_to_ptr(awtStrikePtr))->fAWTFont;399AWT_FONT_CLEANUP_CHECK(awtfont);400401CGFontRef cgFont = awtfont->fNativeCGFont;402403jfloat ay=0.0, dy=0.0, mx=0.0, ly=0.0;404int unitsPerEm = CGFontGetUnitsPerEm(cgFont);405CGFloat scaleX = (1.0 / unitsPerEm);406CGFloat scaleY = (1.0 / unitsPerEm);407408// Ascent409ay = -(CGFloat)CGFontGetAscent(cgFont) * scaleY;410411// Descent412dy = -(CGFloat)CGFontGetDescent(cgFont) * scaleY;413414// Leading415ly = (CGFloat)CGFontGetLeading(cgFont) * scaleY;416417// Max Advance for Font Direction (Strictly horizontal)418mx = [awtfont->fFont maximumAdvancement].width;419420/*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 to424* 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*/429430JNF_CLASS_CACHE(sjc_StrikeMetrics, "sun/font/StrikeMetrics");431JNF_CTOR_CACHE(strikeMetricsCtr, sjc_StrikeMetrics, "(FFFFFFFFFF)V");432metrics = JNFNewObject(env, strikeMetricsCtr,4330.0, ay, 0.0, dy, 1.0,4340.0, 0.0, ly, mx, 0.0);435436cleanup:437AWT_FONT_CLEANUP_FINISH;438JNF_COCOA_EXIT(env);439440return metrics;441}442443extern void AccelGlyphCache_RemoveAllInfos(GlyphInfo* glyph);444/*445* Class: sun_font_CStrikeDisposer446* Method: removeGlyphInfoFromCache447* Signature: (J)V448*/449JNIEXPORT void JNICALL Java_sun_font_CStrikeDisposer_removeGlyphInfoFromCache450(JNIEnv *env, jclass cls, jlong glyphInfo)451{452JNF_COCOA_ENTER(env);453454AccelGlyphCache_RemoveAllCellInfos((GlyphInfo*)jlong_to_ptr(glyphInfo));455456JNF_COCOA_EXIT(env);457}458459460