1 /* 2 * Copyright (c) 2011, 2012, 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.Font; 29 import java.awt.font.FontRenderContext; 30 import java.awt.geom.AffineTransform; 31 import java.awt.geom.GeneralPath;; 32 import java.awt.geom.Point2D; 33 import java.awt.geom.Rectangle2D; 34 35 // Right now this class is final to avoid a problem with native code. 36 // For some reason the JNI IsInstanceOf was not working correctly 37 // so we are checking the class specifically. If we subclass this 38 // we need to modify the native code in CFontWrapper.m 39 public final class CFont extends PhysicalFont { 40 41 /* CFontStrike doesn't call these methods so they are unimplemented. 42 * They are here to meet the requirements of PhysicalFont, needed 43 * because a CFont can sometimes be returned where a PhysicalFont 44 * is expected. 45 */ 46 StrikeMetrics getFontMetrics(long pScalerContext) { 47 throw new InternalError("Not implemented"); 48 } 49 50 float getGlyphAdvance(long pScalerContext, int glyphCode) { 51 throw new InternalError("Not implemented"); 52 } 53 54 void getGlyphMetrics(long pScalerContext, int glyphCode, 55 Point2D.Float metrics) { 56 throw new InternalError("Not implemented"); 57 } 58 59 long getGlyphImage(long pScalerContext, int glyphCode) { 60 throw new InternalError("Not implemented"); 61 } 62 63 Rectangle2D.Float getGlyphOutlineBounds(long pScalerContext, 64 int glyphCode) { 65 throw new InternalError("Not implemented"); 66 } 67 68 GeneralPath getGlyphOutline(long pScalerContext, int glyphCode, 69 float x, float y) { 70 throw new InternalError("Not implemented"); 71 } 72 73 GeneralPath getGlyphVectorOutline(long pScalerContext, 74 int[] glyphs, int numGlyphs, 75 float x, float y) { 76 throw new InternalError("Not implemented"); 77 } 78 79 private static native long createNativeFont(final String nativeFontName, 80 final int style); 81 private static native void disposeNativeFont(final long nativeFontPtr); 82 83 private boolean isFakeItalic; 84 private String nativeFontName; 85 private long nativeFontPtr; 86 87 private native float getWidthNative(final long nativeFontPtr); 88 private native float getWeightNative(final long nativeFontPtr); 89 90 private int fontWidth = -1; 91 private int fontWeight = -1; 92 93 @Override 94 public int getWidth() { 95 if (fontWidth == -1) { 96 // Apple use a range of -1 -> +1, where 0.0 is normal 97 // OpenType uses a % range from 50% -> 200% where 100% is normal 98 // and maps these onto the integer values 1->9. 99 // Since that is what Font2D.getWidth() expects, remap to that. 100 float fw = getWidthNative(getNativeFontPtr()); 101 if (fw == 0.0) { // short cut the common case 102 fontWidth = Font2D.FWIDTH_NORMAL; 103 return fontWidth; 104 } 105 fw += 1.0; fw *= 100.0; 106 if (fw <= 50.0) { 107 fontWidth = 1; 108 } else if (fw <= 62.5) { 109 fontWidth = 2; 110 } else if (fw <= 75.0) { 111 fontWidth = 3; 112 } else if (fw <= 87.5) { 113 fontWidth = 4; 114 } else if (fw <= 100.0) { 115 fontWidth = 5; 116 } else if (fw <= 112.5) { 117 fontWidth = 6; 118 } else if (fw <= 125.0) { 119 fontWidth = 7; 120 } else if (fw <= 150.0) { 121 fontWidth = 8; 122 } else { 123 fontWidth = 9; 124 } 125 } 126 return fontWidth; 127 } 128 129 @Override 130 public int getWeight() { 131 if (fontWeight == -1) { 132 // Apple use a range of -1 -> +1, where 0 is medium/regular 133 // Map this on to the OpenType range of 100->900 where 134 // 500 is medium/regular. 135 // We'll actually map to 0->1000 but that's close enough. 136 float fw = getWeightNative(getNativeFontPtr()); 137 if (fw == 0) { 138 return Font2D.FWEIGHT_NORMAL; 139 } 140 fw += 1.0; fw *= 500; 141 fontWeight = (int)fw; 142 } 143 return fontWeight; 144 } 145 146 // this constructor is called from CFontWrapper.m 147 public CFont(String name) { 148 this(name, name); 149 } 150 151 public CFont(String name, String inFamilyName) { 152 handle = new Font2DHandle(this); 153 fullName = name; 154 familyName = inFamilyName; 155 nativeFontName = fullName; 156 setStyle(); 157 } 158 159 /* Called from CFontManager too */ 160 public CFont(CFont other, String logicalFamilyName) { 161 handle = new Font2DHandle(this); 162 fullName = logicalFamilyName; 163 familyName = logicalFamilyName; 164 nativeFontName = other.nativeFontName; 165 style = other.style; 166 isFakeItalic = other.isFakeItalic; 167 } 168 169 public CFont createItalicVariant() { 170 CFont font = new CFont(this, familyName); 171 font.nativeFontName = fullName; 172 font.fullName = 173 fullName + (style == Font.BOLD ? "" : "-") + "Italic-Derived"; 174 font.style |= Font.ITALIC; 175 font.isFakeItalic = true; 176 return font; 177 } 178 179 protected synchronized long getNativeFontPtr() { 180 if (nativeFontPtr == 0L) { 181 nativeFontPtr = createNativeFont(nativeFontName, style); 182 } 183 return nativeFontPtr; 184 } 185 186 protected synchronized void finalize() { 187 if (nativeFontPtr != 0) { 188 disposeNativeFont(nativeFontPtr); 189 } 190 nativeFontPtr = 0; 191 } 192 193 protected CharToGlyphMapper getMapper() { 194 if (mapper == null) { 195 mapper = new CCharToGlyphMapper(this); 196 } 197 return mapper; 198 } 199 200 protected FontStrike createStrike(FontStrikeDesc desc) { 201 if (isFakeItalic) { 202 desc = new FontStrikeDesc(desc); 203 desc.glyphTx.concatenate(AffineTransform.getShearInstance(-0.2, 0)); 204 } 205 return new CStrike(this, desc); 206 } 207 208 // <rdar://problem/5321707> sun.font.Font2D caches the last used strike, 209 // but does not check if the properties of the strike match the properties 210 // of the incoming java.awt.Font object (size, style, etc). 211 // Simple answer: don't cache. 212 private static FontRenderContext DEFAULT_FRC = 213 new FontRenderContext(null, false, false); 214 public FontStrike getStrike(final Font font) { 215 return getStrike(font, DEFAULT_FRC); 216 } 217 218 public String toString() { 219 return "CFont { fullName: " + fullName + 220 ", familyName: " + familyName + ", style: " + style + 221 " } aka: " + super.toString(); 222 } 223 }