rev 60042 : 8248802: Add log helper methods to FontUtilities.java
1 /* 2 * Copyright (c) 2003, 2020, 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 package sun.font; 27 28 import java.awt.geom.AffineTransform; 29 import java.awt.geom.GeneralPath; 30 import java.awt.geom.Point2D; 31 import java.awt.Rectangle; 32 import java.awt.geom.Rectangle2D; 33 import java.awt.geom.NoninvertibleTransformException; 34 35 class NativeStrike extends PhysicalStrike { 36 37 NativeFont nativeFont; 38 int numGlyphs; 39 AffineTransform invertDevTx; 40 AffineTransform fontTx; 41 42 /* The following method prepares data used in obtaining FontMetrics. 43 * This is the one case in which we allow anything other than a 44 * simple scale to be used with a native font. We do this because in 45 * order to ensure that clients get the overall metrics they expect 46 * for a font whatever coordinate system (combination of font and 47 * device transform) they use. 48 * X11 fonts can only have a scale applied (remind : non-uniform?) 49 * We strip out everything else and if necessary obtain an inverse 50 * tx which we use to return metrics for the font in the transformed 51 * coordinate system of the font. ie we pass X11 a simple scale, and 52 * then apply the non-scale part of the font TX to that result. 53 */ 54 private int getNativePointSize() { 55 /* Make a copy of the glyphTX in which we will store the 56 * font transform, inverting the devTx if necessary 57 */ 58 double[] mat = new double[4]; 59 desc.glyphTx.getMatrix(mat); 60 fontTx = new AffineTransform(mat); 61 62 /* Now work backwards to get the font transform */ 63 if (!desc.devTx.isIdentity() && 64 desc.devTx.getType() != AffineTransform.TYPE_TRANSLATION) { 65 try { 66 invertDevTx = desc.devTx.createInverse(); 67 fontTx.concatenate(invertDevTx); 68 } catch (NoninvertibleTransformException e) { 69 e.printStackTrace(); 70 } 71 } 72 73 /* At this point the fontTx may be a simple +ve scale, or it 74 * may be something more complex. 75 */ 76 Point2D.Float pt = new Point2D.Float(1f,1f); 77 fontTx.deltaTransform(pt, pt); 78 double ptSize = Math.abs(pt.y); 79 int ttype = fontTx.getType(); 80 if ((ttype & ~AffineTransform.TYPE_UNIFORM_SCALE) != 0 || 81 fontTx.getScaleY() <= 0) { 82 /* We need to create an inverse transform that doesn't 83 * include the point size (strictly the uniform scale) 84 */ 85 fontTx.scale(1/ptSize, 1/ptSize); 86 } else { 87 fontTx = null; // no need 88 } 89 return (int)ptSize; 90 } 91 92 NativeStrike(NativeFont nativeFont, FontStrikeDesc desc) { 93 super(nativeFont, desc); 94 this.nativeFont = nativeFont; 95 96 97 /* If this is a delegate for bitmaps, we expect to have 98 * been invoked only for a simple scale. If that's not 99 * true, just bail 100 */ 101 if (nativeFont.isBitmapDelegate) { 102 int ttype = desc.glyphTx.getType(); 103 if ((ttype & ~AffineTransform.TYPE_UNIFORM_SCALE) != 0 || 104 desc.glyphTx.getScaleX() <= 0) { 105 numGlyphs = 0; 106 return; 107 } 108 } 109 110 int ptSize = getNativePointSize(); 111 byte [] nameBytes = nativeFont.getPlatformNameBytes(ptSize); 112 double scale = Math.abs(desc.devTx.getScaleX()); 113 pScalerContext = createScalerContext(nameBytes, ptSize, scale); 114 if (pScalerContext == 0L) { 115 SunFontManager.getInstance().deRegisterBadFont(nativeFont); 116 pScalerContext = createNullScalerContext(); 117 numGlyphs = 0; 118 FontUtilities.logSevere("Could not create native strike " + 119 new String(nameBytes)); 120 return; 121 } 122 numGlyphs = nativeFont.getMapper().getNumGlyphs(); 123 this.disposer = new NativeStrikeDisposer(nativeFont, desc, 124 pScalerContext); 125 } 126 127 /* The asymmetry of the following methods is to help preserve 128 * performance with minimal textual changes to the calling code 129 * when moving initialisation of these arrays out of the constructor. 130 * This may be restructured later when there's more room for changes 131 */ 132 private boolean usingIntGlyphImages() { 133 if (intGlyphImages != null) { 134 return true; 135 } else if (longAddresses) { 136 return false; 137 } else { 138 /* We could obtain minGlyphIndex and index relative to that 139 * if we need to save space. 140 */ 141 int glyphLenArray = getMaxGlyph(pScalerContext); 142 143 /* This shouldn't be necessary - its a precaution */ 144 if (glyphLenArray < numGlyphs) { 145 glyphLenArray = numGlyphs; 146 } 147 intGlyphImages = new int[glyphLenArray]; 148 this.disposer.intGlyphImages = intGlyphImages; 149 return true; 150 } 151 } 152 153 private long[] getLongGlyphImages() { 154 if (longGlyphImages == null && longAddresses) { 155 156 /* We could obtain minGlyphIndex and index relative to that 157 * if we need to save space. 158 */ 159 int glyphLenArray = getMaxGlyph(pScalerContext); 160 161 /* This shouldn't be necessary - its a precaution */ 162 if (glyphLenArray < numGlyphs) { 163 glyphLenArray = numGlyphs; 164 } 165 longGlyphImages = new long[glyphLenArray]; 166 this.disposer.longGlyphImages = longGlyphImages; 167 } 168 return longGlyphImages; 169 } 170 171 NativeStrike(NativeFont nativeFont, FontStrikeDesc desc, 172 boolean nocache) { 173 super(nativeFont, desc); 174 this.nativeFont = nativeFont; 175 176 int ptSize = (int)desc.glyphTx.getScaleY(); 177 double scale = desc.devTx.getScaleX(); // uniform scale 178 byte [] nameBytes = nativeFont.getPlatformNameBytes(ptSize); 179 pScalerContext = createScalerContext(nameBytes, ptSize, scale); 180 181 int numGlyphs = nativeFont.getMapper().getNumGlyphs(); 182 } 183 184 /* We want the native font to be responsible for reporting the 185 * font metrics, even if it often delegates to another font. 186 * The code here isn't yet implementing exactly that. If the glyph 187 * transform was something native couldn't handle, there's no native 188 * context from which to obtain metrics. Need to revise this to obtain 189 * the metrics and transform them. But currently in such a case it 190 * gets the metrics from a different font - its glyph delegate font. 191 */ 192 StrikeMetrics getFontMetrics() { 193 if (strikeMetrics == null) { 194 if (pScalerContext != 0) { 195 strikeMetrics = nativeFont.getFontMetrics(pScalerContext); 196 } 197 if (strikeMetrics != null && fontTx != null) { 198 strikeMetrics.convertToUserSpace(fontTx); 199 } 200 } 201 return strikeMetrics; 202 } 203 204 private native long createScalerContext(byte[] nameBytes, 205 int ptSize, double scale); 206 207 private native int getMaxGlyph(long pScalerContext); 208 209 private native long createNullScalerContext(); 210 211 void getGlyphImagePtrs(int[] glyphCodes, long[] images,int len) { 212 for (int i=0; i<len; i++) { 213 images[i] = getGlyphImagePtr(glyphCodes[i]); 214 } 215 } 216 217 long getGlyphImagePtr(int glyphCode) { 218 long glyphPtr; 219 220 if (usingIntGlyphImages()) { 221 if ((glyphPtr = intGlyphImages[glyphCode] & INTMASK) != 0L) { 222 return glyphPtr; 223 } else { 224 glyphPtr = nativeFont.getGlyphImage(pScalerContext,glyphCode); 225 /* Synchronize in case some other thread has updated this 226 * cache entry already - unlikely but possible. 227 */ 228 synchronized (this) { 229 if (intGlyphImages[glyphCode] == 0) { 230 intGlyphImages[glyphCode] = (int)glyphPtr; 231 return glyphPtr; 232 } else { 233 StrikeCache.freeIntPointer((int)glyphPtr); 234 return intGlyphImages[glyphCode] & INTMASK; 235 } 236 } 237 } 238 } 239 /* must be using long (8 byte) addresses */ 240 else if ((glyphPtr = getLongGlyphImages()[glyphCode]) != 0L) { 241 return glyphPtr; 242 } else { 243 glyphPtr = nativeFont.getGlyphImage(pScalerContext, glyphCode); 244 245 synchronized (this) { 246 if (longGlyphImages[glyphCode] == 0L) { 247 longGlyphImages[glyphCode] = glyphPtr; 248 return glyphPtr; 249 } else { 250 StrikeCache.freeLongPointer(glyphPtr); 251 return longGlyphImages[glyphCode]; 252 } 253 } 254 } 255 } 256 257 /* This is used when a FileFont uses the native names to create a 258 * delegate NativeFont/Strike to get images from native. This is used 259 * because Solaris TrueType fonts have external PCF bitmaps rather than 260 * embedded bitmaps. This is really only important for CJK fonts as 261 * for most scripts the external X11 bitmaps aren't much better - if 262 * at all - than the results from hinting the outlines. 263 */ 264 long getGlyphImagePtrNoCache(int glyphCode) { 265 return nativeFont.getGlyphImageNoDefault(pScalerContext, glyphCode); 266 } 267 268 void getGlyphImageBounds(int glyphcode, Point2D.Float pt, 269 Rectangle result) { 270 } 271 272 Point2D.Float getGlyphMetrics(int glyphCode) { 273 Point2D.Float pt = new Point2D.Float(getGlyphAdvance(glyphCode), 0f); 274 return pt; 275 } 276 277 float getGlyphAdvance(int glyphCode) { 278 return nativeFont.getGlyphAdvance(pScalerContext, glyphCode); 279 } 280 281 Rectangle2D.Float getGlyphOutlineBounds(int glyphCode) { 282 return nativeFont.getGlyphOutlineBounds(pScalerContext, glyphCode); 283 } 284 285 GeneralPath getGlyphOutline(int glyphCode, float x, float y) { 286 return new GeneralPath(); 287 } 288 289 GeneralPath getGlyphVectorOutline(int[] glyphs, float x, float y) { 290 return new GeneralPath(); 291 } 292 293 } --- EOF ---