122 return [NSDictionary dictionaryWithObjectsAndKeys: 123 font, NSFontAttributeName, 124 gOneNumber, (id)kCTForegroundColorFromContextAttributeName, 125 useFractionalMetrics ? gZeroNumber : gOneNumber, @"CTIntegerMetrics", // force integer hack in CoreText to help with Java's integer assumptions 126 gZeroNumber, NSLigatureAttributeName, 127 gZeroNumber, NSKernAttributeName, 128 nil]; 129 } 130 131 // Itterates though each glyph, and if a transform is present for that glyph, apply it to the CGContext, and strike the glyph. 132 // If there is no per-glyph transform, just strike the glyph. Advances must also be transformed on-the-spot as well. 133 void JavaCT_DrawGlyphVector 134 (const QuartzSDOps *qsdo, const AWTStrike *strike, const BOOL useSubstituion, const int uniChars[], const CGGlyph glyphs[], CGSize advances[], const jint g_gvTXIndicesAsInts[], const jdouble g_gvTransformsAsDoubles[], const CFIndex length) 135 { 136 CGPoint pt = { 0, 0 }; 137 138 // get our baseline transform and font 139 CGContextRef cgRef = qsdo->cgRef; 140 CGAffineTransform ctmText = CGContextGetTextMatrix(cgRef); 141 142 /* Save and restore of graphics context is done before the iteration. 143 This seems to work using our test case (see bug ID 7158350) so we are restoring it at 144 the end of the for loop. If we find out that save/restore outside the loop 145 doesn't work on all cases then we will move the Save/Restore inside the loop.*/ 146 CGContextSaveGState(cgRef); 147 CGAffineTransform invTx = CGAffineTransformInvert(strike->fTx); 148 149 NSUInteger i; 150 for (i = 0; i < length; i++) 151 { 152 CGGlyph glyph = glyphs[i]; 153 int uniChar = uniChars[i]; 154 // if we found a unichar instead of a glyph code, get the fallback font, 155 // find the glyph code for the fallback font, and set the font on the current context 156 if (uniChar != 0) 157 { 158 CTFontRef fallback; 159 if (uniChar > 0xFFFF) { 160 UTF16Char charRef[2]; 161 JavaCT_BreakupUnicodeIntoSurrogatePairs(uniChar, charRef); 162 CGGlyph glyphTmp[2]; 163 fallback = JavaCT_CopyCTFallbackFontAndGlyphForUnicode(strike->fAWTFont, (const UTF16Char *)&charRef, (CGGlyph *)&glyphTmp, 2); 164 glyph = glyphTmp[0]; 165 } else { 166 const UTF16Char u = uniChar; 167 fallback = JavaCT_CopyCTFallbackFontAndGlyphForUnicode(strike->fAWTFont, &u, (CGGlyph *)&glyph, 1); 168 } 169 if (fallback) { 170 const CGFontRef cgFallback = CTFontCopyGraphicsFont(fallback, NULL); 171 CFRelease(fallback); 172 173 if (cgFallback) { 174 CGContextSetFont(cgRef, cgFallback); 175 CFRelease(cgFallback); 176 } 177 } 178 } 179 180 // if we have per-glyph transformations 181 int tin = (g_gvTXIndicesAsInts == NULL) ? -1 : (g_gvTXIndicesAsInts[i] - 1) * 6; 182 if (tin < 0) 183 { 184 CGContextShowGlyphsAtPoint(cgRef, pt.x, pt.y, &glyph, 1); 185 } 186 else 187 { 188 CGAffineTransform tx = CGAffineTransformMake( 189 (CGFloat)g_gvTransformsAsDoubles[tin + 0], (CGFloat)g_gvTransformsAsDoubles[tin + 2], 190 (CGFloat)g_gvTransformsAsDoubles[tin + 1], (CGFloat)g_gvTransformsAsDoubles[tin + 3], 191 0, 0); 192 193 CGPoint txOffset = { (CGFloat)g_gvTransformsAsDoubles[tin + 4], (CGFloat)g_gvTransformsAsDoubles[tin + 5] }; 194 195 txOffset = CGPointApplyAffineTransform(txOffset, invTx); 196 | 122 return [NSDictionary dictionaryWithObjectsAndKeys: 123 font, NSFontAttributeName, 124 gOneNumber, (id)kCTForegroundColorFromContextAttributeName, 125 useFractionalMetrics ? gZeroNumber : gOneNumber, @"CTIntegerMetrics", // force integer hack in CoreText to help with Java's integer assumptions 126 gZeroNumber, NSLigatureAttributeName, 127 gZeroNumber, NSKernAttributeName, 128 nil]; 129 } 130 131 // Itterates though each glyph, and if a transform is present for that glyph, apply it to the CGContext, and strike the glyph. 132 // If there is no per-glyph transform, just strike the glyph. Advances must also be transformed on-the-spot as well. 133 void JavaCT_DrawGlyphVector 134 (const QuartzSDOps *qsdo, const AWTStrike *strike, const BOOL useSubstituion, const int uniChars[], const CGGlyph glyphs[], CGSize advances[], const jint g_gvTXIndicesAsInts[], const jdouble g_gvTransformsAsDoubles[], const CFIndex length) 135 { 136 CGPoint pt = { 0, 0 }; 137 138 // get our baseline transform and font 139 CGContextRef cgRef = qsdo->cgRef; 140 CGAffineTransform ctmText = CGContextGetTextMatrix(cgRef); 141 142 BOOL saved = false; 143 144 /* Save and restore of graphics context is done before the iteration. 145 This seems to work using our test case (see bug ID 7158350) so we are restoring it at 146 the end of the for loop. If we find out that save/restore outside the loop 147 doesn't work on all cases then we will move the Save/Restore inside the loop.*/ 148 CGContextSaveGState(cgRef); 149 CGAffineTransform invTx = CGAffineTransformInvert(strike->fTx); 150 151 NSUInteger i; 152 for (i = 0; i < length; i++) 153 { 154 CGGlyph glyph = glyphs[i]; 155 int uniChar = uniChars[i]; 156 // if we found a unichar instead of a glyph code, get the fallback font, 157 // find the glyph code for the fallback font, and set the font on the current context 158 if (uniChar != 0) 159 { 160 CTFontRef fallback; 161 if (uniChar > 0xFFFF) { 162 UTF16Char charRef[2]; 163 JavaCT_BreakupUnicodeIntoSurrogatePairs(uniChar, charRef); 164 CGGlyph glyphTmp[2]; 165 fallback = JavaCT_CopyCTFallbackFontAndGlyphForUnicode(strike->fAWTFont, (const UTF16Char *)&charRef, (CGGlyph *)&glyphTmp, 2); 166 glyph = glyphTmp[0]; 167 } else { 168 const UTF16Char u = uniChar; 169 fallback = JavaCT_CopyCTFallbackFontAndGlyphForUnicode(strike->fAWTFont, &u, (CGGlyph *)&glyph, 1); 170 } 171 if (fallback) { 172 const CGFontRef cgFallback = CTFontCopyGraphicsFont(fallback, NULL); 173 CFRelease(fallback); 174 175 if (cgFallback) { 176 if (!saved) { 177 CGContextSaveGState(cgRef); 178 saved = true; 179 } 180 CGContextSetFont(cgRef, cgFallback); 181 CFRelease(cgFallback); 182 } 183 } 184 } else { 185 if (saved) { 186 CGContextRestoreGState(cgRef); 187 saved = false; 188 } 189 } 190 191 // if we have per-glyph transformations 192 int tin = (g_gvTXIndicesAsInts == NULL) ? -1 : (g_gvTXIndicesAsInts[i] - 1) * 6; 193 if (tin < 0) 194 { 195 CGContextShowGlyphsAtPoint(cgRef, pt.x, pt.y, &glyph, 1); 196 } 197 else 198 { 199 CGAffineTransform tx = CGAffineTransformMake( 200 (CGFloat)g_gvTransformsAsDoubles[tin + 0], (CGFloat)g_gvTransformsAsDoubles[tin + 2], 201 (CGFloat)g_gvTransformsAsDoubles[tin + 1], (CGFloat)g_gvTransformsAsDoubles[tin + 3], 202 0, 0); 203 204 CGPoint txOffset = { (CGFloat)g_gvTransformsAsDoubles[tin + 4], (CGFloat)g_gvTransformsAsDoubles[tin + 5] }; 205 206 txOffset = CGPointApplyAffineTransform(txOffset, invTx); 207 |