/* * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package sun.font; import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; import java.awt.Rectangle; import java.awt.geom.Rectangle2D; import java.awt.geom.NoninvertibleTransformException; class NativeStrike extends PhysicalStrike { NativeFont nativeFont; int numGlyphs; AffineTransform invertDevTx; AffineTransform fontTx; /* The following method prepares data used in obtaining FontMetrics. * This is the one case in which we allow anything other than a * simple scale to be used with a native font. We do this because in * order to ensure that clients get the overall metrics they expect * for a font whatever coordinate system (combination of font and * device transform) they use. * X11 fonts can only have a scale applied (remind : non-uniform?) * We strip out everything else and if necessary obtain an inverse * tx which we use to return metrics for the font in the transformed * coordinate system of the font. ie we pass X11 a simple scale, and * then apply the non-scale part of the font TX to that result. */ private int getNativePointSize() { /* Make a copy of the glyphTX in which we will store the * font transform, inverting the devTx if necessary */ double[] mat = new double[4]; desc.glyphTx.getMatrix(mat); fontTx = new AffineTransform(mat); /* Now work backwards to get the font transform */ if (!desc.devTx.isIdentity() && desc.devTx.getType() != AffineTransform.TYPE_TRANSLATION) { try { invertDevTx = desc.devTx.createInverse(); fontTx.concatenate(invertDevTx); } catch (NoninvertibleTransformException e) { e.printStackTrace(); } } /* At this point the fontTx may be a simple +ve scale, or it * may be something more complex. */ Point2D.Float pt = new Point2D.Float(1f,1f); fontTx.deltaTransform(pt, pt); double ptSize = Math.abs(pt.y); int ttype = fontTx.getType(); if ((ttype & ~AffineTransform.TYPE_UNIFORM_SCALE) != 0 || fontTx.getScaleY() <= 0) { /* We need to create an inverse transform that doesn't * include the point size (strictly the uniform scale) */ fontTx.scale(1/ptSize, 1/ptSize); } else { fontTx = null; // no need } return (int)ptSize; } NativeStrike(NativeFont nativeFont, FontStrikeDesc desc) { super(nativeFont, desc); this.nativeFont = nativeFont; /* If this is a delegate for bitmaps, we expect to have * been invoked only for a simple scale. If that's not * true, just bail */ if (nativeFont.isBitmapDelegate) { int ttype = desc.glyphTx.getType(); if ((ttype & ~AffineTransform.TYPE_UNIFORM_SCALE) != 0 || desc.glyphTx.getScaleX() <= 0) { numGlyphs = 0; return; } } int ptSize = getNativePointSize(); byte [] nameBytes = nativeFont.getPlatformNameBytes(ptSize); double scale = Math.abs(desc.devTx.getScaleX()); pScalerContext = createScalerContext(nameBytes, ptSize, scale); if (pScalerContext == 0L) { SunFontManager.getInstance().deRegisterBadFont(nativeFont); pScalerContext = createNullScalerContext(); numGlyphs = 0; if (FontUtilities.isLogging()) { FontUtilities.getLogger() .severe("Could not create native strike " + new String(nameBytes)); } return; } numGlyphs = nativeFont.getMapper().getNumGlyphs(); this.disposer = new NativeStrikeDisposer(nativeFont, desc, pScalerContext); } /* The asymmetry of the following methods is to help preserve * performance with minimal textual changes to the calling code * when moving initialisation of these arrays out of the constructor. * This may be restructured later when there's more room for changes */ private boolean usingIntGlyphImages() { if (intGlyphImages != null) { return true; } else if (longAddresses) { return false; } else { /* We could obtain minGlyphIndex and index relative to that * if we need to save space. */ int glyphLenArray = getMaxGlyph(pScalerContext); /* This shouldn't be necessary - its a precaution */ if (glyphLenArray < numGlyphs) { glyphLenArray = numGlyphs; } intGlyphImages = new int[glyphLenArray]; this.disposer.intGlyphImages = intGlyphImages; return true; } } private long[] getLongGlyphImages() { if (longGlyphImages == null && longAddresses) { /* We could obtain minGlyphIndex and index relative to that * if we need to save space. */ int glyphLenArray = getMaxGlyph(pScalerContext); /* This shouldn't be necessary - its a precaution */ if (glyphLenArray < numGlyphs) { glyphLenArray = numGlyphs; } longGlyphImages = new long[glyphLenArray]; this.disposer.longGlyphImages = longGlyphImages; } return longGlyphImages; } NativeStrike(NativeFont nativeFont, FontStrikeDesc desc, boolean nocache) { super(nativeFont, desc); this.nativeFont = nativeFont; int ptSize = (int)desc.glyphTx.getScaleY(); double scale = desc.devTx.getScaleX(); // uniform scale byte [] nameBytes = nativeFont.getPlatformNameBytes(ptSize); pScalerContext = createScalerContext(nameBytes, ptSize, scale); int numGlyphs = nativeFont.getMapper().getNumGlyphs(); } /* We want the native font to be responsible for reporting the * font metrics, even if it often delegates to another font. * The code here isn't yet implementing exactly that. If the glyph * transform was something native couldn't handle, there's no native * context from which to obtain metrics. Need to revise this to obtain * the metrics and transform them. But currently in such a case it * gets the metrics from a different font - its glyph delegate font. */ StrikeMetrics getFontMetrics() { if (strikeMetrics == null) { if (pScalerContext != 0) { strikeMetrics = nativeFont.getFontMetrics(pScalerContext); } if (strikeMetrics != null && fontTx != null) { strikeMetrics.convertToUserSpace(fontTx); } } return strikeMetrics; } private native long createScalerContext(byte[] nameBytes, int ptSize, double scale); private native int getMaxGlyph(long pScalerContext); private native long createNullScalerContext(); void getGlyphImagePtrs(int[] glyphCodes, long[] images,int len) { for (int i=0; i= 0x10000) { cp = 0xffff; } return delegateStrike.getGlyphAdvance(cp); } Rectangle2D.Float getGlyphOutlineBounds(int glyphCode) { return delegateStrike.getGlyphOutlineBounds(glyphCode); } GeneralPath getGlyphOutline(int glyphCode, float x, float y) { return delegateStrike.getGlyphOutline(glyphCode, x, y); } GeneralPath getGlyphVectorOutline(int[] glyphs, float x, float y) { return delegateStrike.getGlyphVectorOutline(glyphs, x, y); } }