199 lines · 7.6 KB · Java
RawDownload
/* * Copyright (c) 2003, Oracle and/or its affiliates. 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.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.font; import java.awt.geom.AffineTransform;import java.awt.geom.Point2D; /* These are font metrics: they are in user space, not device space. * Hence they are not truly "strike" metrics. However it is convenient to * treat them as such since we need to have a scaler context to obtain them * and also to cache them. The old implementation obtained a C++ strike object * that matched the Font TX + pt size only. It was wasteful of strike objects. * This new implementation still has separate StrikeMetrics for 2 fonts that * are really the same but are used in different device transforms, but at * least it doesn't create a whole new strike just to get the metrics for * a strike in a transformed graphics. * So these metrics do not take into account the device transform. They * are considered inherent properties of the font. Hence it may be that we * should use the device transform to obtain the most accurate metrics, but * typically 1.1 APIs do not provide for this. So some APIs may want to * ignore the dev. tx and others may want to use it, and then apply an * inverse transform. For now we ignore the dev. tx. * "Font" metrics are representative of a typical glyph in the font. * Generally speaking these values are the choice of the font designer and * are stored in the font, from which we retrieve the values. They do * not necessarily equate to the maximum bounds of all glyphs in the font. * Note that the ascent fields are typically a -ve value as we use a top-left * origin user space, and text is positioned relative to its baseline. */public final class StrikeMetrics {     public float ascentX;    public float ascentY;    public float descentX;    public float descentY;    public float baselineX;    public float baselineY;    public float leadingX;    public float leadingY;    public float maxAdvanceX;    public float maxAdvanceY;      /* The no-args constructor is used by CompositeStrike, which then     * merges in the metrics of physical fonts.     * The approach here is the same as earlier releases but it is flawed     * take for example the following which ignores leading for simplicity.     * Say we have a composite with an element asc=-9, dsc=2, and another with     * asc=-7, dsc=3.  The merged font is (-9,3) for height of -(-9)+3=12.     * Suppose this same font has been derived with a 180% rotation     * Now its signs for ascent/descent are reversed. Its (9,-2) and (7,-3)     * Its merged values are (using the code in this class) (7,-2) for     * a height of -(7)+-2 = =-9!     * We need to have a more intelligent merging algorithm,     * which so far as I can see needs to apply an inverse of the font     * tx, do its merging, and then reapply the font tx.     * This wouldn't often be a problem as there rarely is a font TX, and     * the tricky part is getting the information. Probably the no-args     * constructor needs to pass a TX in to be applied to all merges.     * CompositeStrike would be left with the problem of figuring out what     * tx to use.     * But at least for now we are probably no worse than 1.4 ...     * REMIND: FIX THIS.     */    StrikeMetrics() {        ascentX = ascentY = Integer.MAX_VALUE;        descentX = descentY = leadingX = leadingY = Integer.MIN_VALUE;        baselineX = baselineX = maxAdvanceX = maxAdvanceY = Integer.MIN_VALUE;    }     StrikeMetrics(float ax, float ay, float dx, float dy, float bx, float by,                  float lx, float ly, float mx, float my) {       ascentX = ax;       ascentY = ay;       descentX = dx;       descentY = dy;       baselineX = bx;       baselineY = by;       leadingX = lx;       leadingY = ly;       maxAdvanceX = mx;       maxAdvanceY = my;    }     public float getAscent() {        return -ascentY;    }     public float getDescent() {        return descentY;    }     public float getLeading() {        return leadingY;    }     public float getMaxAdvance() {        return maxAdvanceX;    }     /*     * Currently only used to merge together slot metrics to create     * the metrics for a composite font.     */     void merge(StrikeMetrics other) {         if (other == null) {             return;         }         if (other.ascentX < ascentX) {             ascentX = other.ascentX;         }         if (other.ascentY < ascentY) {             ascentY = other.ascentY;         }         if (other.descentX > descentX) {             descentX = other.descentX;         }         if (other.descentY > descentY) {             descentY = other.descentY;         }         if (other.baselineX > baselineX) {             baselineX = other.baselineX;         }         if (other.baselineY > baselineY) {             baselineY = other.baselineY;         }         if (other.leadingX > leadingX) {             leadingX = other.leadingX;         }         if (other.leadingY > leadingY) {             leadingY = other.leadingY;         }         if (other.maxAdvanceX > maxAdvanceX) {             maxAdvanceX = other.maxAdvanceX;         }         if (other.maxAdvanceY > maxAdvanceY) {             maxAdvanceY = other.maxAdvanceY;         }    }     /* Used to transform the values back into user space.     * This is done ONCE by the strike so clients should not need     * to worry about this     */    void convertToUserSpace(AffineTransform invTx) {        Point2D.Float pt2D = new Point2D.Float();         pt2D.x = ascentX; pt2D.y = ascentY;        invTx.deltaTransform(pt2D, pt2D);        ascentX = pt2D.x; ascentY = pt2D.y;         pt2D.x = descentX; pt2D.y = descentY;        invTx.deltaTransform(pt2D, pt2D);        descentX = pt2D.x; descentY = pt2D.y;         pt2D.x = baselineX; pt2D.y = baselineY;        invTx.deltaTransform(pt2D, pt2D);        baselineX = pt2D.x; baselineY = pt2D.y;         pt2D.x = leadingX; pt2D.y = leadingY;        invTx.deltaTransform(pt2D, pt2D);        leadingX = pt2D.x; leadingY = pt2D.y;         pt2D.x = maxAdvanceX; pt2D.y = maxAdvanceY;        invTx.deltaTransform(pt2D, pt2D);        maxAdvanceX = pt2D.x; maxAdvanceY = pt2D.y;    }     public String toString() {        return "ascent:x="      + ascentX +     " y=" + ascentY +               " descent:x="    + descentX +    " y=" + descentY +               " baseline:x="   + baselineX +   " y=" + baselineY +               " leading:x="    + leadingX +    " y=" + leadingY +               " maxAdvance:x=" + maxAdvanceX + " y=" + maxAdvanceY;    }}