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                                                 final boolean isFakeItalic);
  82     private static native void disposeNativeFont(final long nativeFontPtr);
  83 
  84     private boolean isFakeItalic;
  85     private String nativeFontName;
  86     private long nativeFontPtr;
  87 
  88     // this constructor is called from CFontWrapper.m
  89     public CFont(String name) {
  90         this(name, name);
  91     }
  92 
  93     public CFont(String name, String inFamilyName) {
  94         handle = new Font2DHandle(this);
  95         fullName = name;
  96         familyName = inFamilyName;
  97         nativeFontName = inFamilyName;
  98         setStyle();
  99     }
 100 
 101     public CFont(CFont other, String logicalFamilyName) {
 102         handle = new Font2DHandle(this);
 103         fullName = logicalFamilyName;
 104         familyName = logicalFamilyName;
 105         nativeFontName = other.nativeFontName;
 106         style = other.style;
 107         isFakeItalic = other.isFakeItalic;
 108     }
 109 
 110     public CFont createItalicVariant() {
 111         CFont font = new CFont(this, familyName);
 112         font.fullName =
 113             fullName + (style == Font.BOLD ? "" : "-") + "Italic-Derived";
 114         font.style |= Font.ITALIC;
 115         font.isFakeItalic = true;
 116         return font;
 117     }
 118 
 119     protected synchronized long getNativeFontPtr() {
 120         if (nativeFontPtr == 0L) {
 121             nativeFontPtr = createNativeFont(nativeFontName, style, isFakeItalic);
 122 }
 123         return nativeFontPtr;
 124     }
 125 
 126     protected synchronized void finalize() {
 127         if (nativeFontPtr != 0) {
 128             disposeNativeFont(nativeFontPtr);
 129         }
 130         nativeFontPtr = 0;
 131     }
 132 
 133     protected CharToGlyphMapper getMapper() {
 134         if (mapper == null) {
 135             mapper = new CCharToGlyphMapper(this);
 136         }
 137         return mapper;
 138     }
 139 
 140     protected FontStrike createStrike(FontStrikeDesc desc) {
 141         if (isFakeItalic) {
 142             desc = new FontStrikeDesc(desc);
 143             desc.glyphTx.concatenate(AffineTransform.getShearInstance(-0.2, 0));
 144         }
 145         return new CStrike(this, desc);
 146     }
 147 
 148     // <rdar://problem/5321707> sun.font.Font2D caches the last used strike,
 149     // but does not check if the properties of the strike match the properties
 150     // of the incoming java.awt.Font object (size, style, etc).
 151     // Simple answer: don't cache.
 152     private static FontRenderContext DEFAULT_FRC =
 153         new FontRenderContext(null, false, false);
 154     public FontStrike getStrike(final Font font) {
 155         return getStrike(font, DEFAULT_FRC);
 156     }
 157 
 158     public String toString() {
 159         return "CFont { fullName: " + fullName +
 160             ",  familyName: " + familyName + ", style: " + style +
 161             " } aka: " + super.toString();
 162     }
 163 }