0N/A/*
2362N/A * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.font;
0N/A
0N/Aimport java.awt.geom.AffineTransform;
0N/Aimport java.awt.geom.Point2D;
0N/A
0N/A/* These are font metrics: they are in user space, not device space.
0N/A * Hence they are not truly "strike" metrics. However it is convenient to
0N/A * treat them as such since we need to have a scaler context to obtain them
0N/A * and also to cache them. The old implementation obtained a C++ strike object
0N/A * that matched the Font TX + pt size only. It was wasteful of strike objects.
0N/A * This new implementation still has separate StrikeMetrics for 2 fonts that
0N/A * are really the same but are used in different device transforms, but at
0N/A * least it doesn't create a whole new strike just to get the metrics for
0N/A * a strike in a transformed graphics.
0N/A * So these metrics do not take into account the device transform. They
0N/A * are considered inherent properties of the font. Hence it may be that we
0N/A * should use the device transform to obtain the most accurate metrics, but
0N/A * typically 1.1 APIs do not provide for this. So some APIs may want to
0N/A * ignore the dev. tx and others may want to use it, and then apply an
0N/A * inverse transform. For now we ignore the dev. tx.
0N/A * "Font" metrics are representative of a typical glyph in the font.
0N/A * Generally speaking these values are the choice of the font designer and
0N/A * are stored in the font, from which we retrieve the values. They do
0N/A * not necessarily equate to the maximum bounds of all glyphs in the font.
0N/A * Note that the ascent fields are typically a -ve value as we use a top-left
0N/A * origin user space, and text is positioned relative to its baseline.
0N/A */
0N/Apublic final class StrikeMetrics {
0N/A
0N/A public float ascentX;
0N/A public float ascentY;
0N/A public float descentX;
0N/A public float descentY;
0N/A public float baselineX;
0N/A public float baselineY;
0N/A public float leadingX;
0N/A public float leadingY;
0N/A public float maxAdvanceX;
0N/A public float maxAdvanceY;
0N/A
0N/A
0N/A /* The no-args constructor is used by CompositeStrike, which then
0N/A * merges in the metrics of physical fonts.
0N/A * The approach here is the same as earlier releases but it is flawed
0N/A * take for example the following which ignores leading for simplicity.
0N/A * Say we have a composite with an element asc=-9, dsc=2, and another with
0N/A * asc=-7, dsc=3. The merged font is (-9,3) for height of -(-9)+3=12.
0N/A * Suppose this same font has been derived with a 180% rotation
0N/A * Now its signs for ascent/descent are reversed. Its (9,-2) and (7,-3)
0N/A * Its merged values are (using the code in this class) (7,-2) for
0N/A * a height of -(7)+-2 = =-9!
0N/A * We need to have a more intelligent merging algorithm,
0N/A * which so far as I can see needs to apply an inverse of the font
0N/A * tx, do its merging, and then reapply the font tx.
0N/A * This wouldn't often be a problem as there rarely is a font TX, and
0N/A * the tricky part is getting the information. Probably the no-args
0N/A * constructor needs to pass a TX in to be applied to all merges.
0N/A * CompositeStrike would be left with the problem of figuring out what
0N/A * tx to use.
0N/A * But at least for now we are probably no worse than 1.4 ...
0N/A * REMIND: FIX THIS.
0N/A */
0N/A StrikeMetrics() {
0N/A ascentX = ascentY = Integer.MAX_VALUE;
0N/A descentX = descentY = leadingX = leadingY = Integer.MIN_VALUE;
0N/A baselineX = baselineX = maxAdvanceX = maxAdvanceY = Integer.MIN_VALUE;
0N/A }
0N/A
0N/A StrikeMetrics(float ax, float ay, float dx, float dy, float bx, float by,
0N/A float lx, float ly, float mx, float my) {
0N/A ascentX = ax;
0N/A ascentY = ay;
0N/A descentX = dx;
0N/A descentY = dy;
0N/A baselineX = bx;
0N/A baselineY = by;
0N/A leadingX = lx;
0N/A leadingY = ly;
0N/A maxAdvanceX = mx;
0N/A maxAdvanceY = my;
0N/A }
0N/A
0N/A public float getAscent() {
0N/A return -ascentY;
0N/A }
0N/A
0N/A public float getDescent() {
0N/A return descentY;
0N/A }
0N/A
0N/A public float getLeading() {
0N/A return leadingY;
0N/A }
0N/A
0N/A public float getMaxAdvance() {
0N/A return maxAdvanceX;
0N/A }
0N/A
0N/A /*
0N/A * Currently only used to merge together slot metrics to create
0N/A * the metrics for a composite font.
0N/A */
0N/A void merge(StrikeMetrics other) {
0N/A if (other == null) {
0N/A return;
0N/A }
0N/A if (other.ascentX < ascentX) {
0N/A ascentX = other.ascentX;
0N/A }
0N/A if (other.ascentY < ascentY) {
0N/A ascentY = other.ascentY;
0N/A }
0N/A if (other.descentX > descentX) {
0N/A descentX = other.descentX;
0N/A }
0N/A if (other.descentY > descentY) {
0N/A descentY = other.descentY;
0N/A }
0N/A if (other.baselineX > baselineX) {
0N/A baselineX = other.baselineX;
0N/A }
0N/A if (other.baselineY > baselineY) {
0N/A baselineY = other.baselineY;
0N/A }
0N/A if (other.leadingX > leadingX) {
0N/A leadingX = other.leadingX;
0N/A }
0N/A if (other.leadingY > leadingY) {
0N/A leadingY = other.leadingY;
0N/A }
0N/A if (other.maxAdvanceX > maxAdvanceX) {
0N/A maxAdvanceX = other.maxAdvanceX;
0N/A }
0N/A if (other.maxAdvanceY > maxAdvanceY) {
0N/A maxAdvanceY = other.maxAdvanceY;
0N/A }
0N/A }
0N/A
0N/A /* Used to transform the values back into user space.
0N/A * This is done ONCE by the strike so clients should not need
0N/A * to worry about this
0N/A */
0N/A void convertToUserSpace(AffineTransform invTx) {
0N/A Point2D.Float pt2D = new Point2D.Float();
0N/A
0N/A pt2D.x = ascentX; pt2D.y = ascentY;
0N/A invTx.deltaTransform(pt2D, pt2D);
0N/A ascentX = pt2D.x; ascentY = pt2D.y;
0N/A
0N/A pt2D.x = descentX; pt2D.y = descentY;
0N/A invTx.deltaTransform(pt2D, pt2D);
0N/A descentX = pt2D.x; descentY = pt2D.y;
0N/A
0N/A pt2D.x = baselineX; pt2D.y = baselineY;
0N/A invTx.deltaTransform(pt2D, pt2D);
0N/A baselineX = pt2D.x; baselineY = pt2D.y;
0N/A
0N/A pt2D.x = leadingX; pt2D.y = leadingY;
0N/A invTx.deltaTransform(pt2D, pt2D);
0N/A leadingX = pt2D.x; leadingY = pt2D.y;
0N/A
0N/A pt2D.x = maxAdvanceX; pt2D.y = maxAdvanceY;
0N/A invTx.deltaTransform(pt2D, pt2D);
0N/A maxAdvanceX = pt2D.x; maxAdvanceY = pt2D.y;
0N/A }
0N/A
0N/A public String toString() {
0N/A return "ascent:x=" + ascentX + " y=" + ascentY +
0N/A " descent:x=" + descentX + " y=" + descentY +
0N/A " baseline:x=" + baselineX + " y=" + baselineY +
0N/A " leading:x=" + leadingX + " y=" + leadingY +
0N/A " maxAdvance:x=" + maxAdvanceX + " y=" + maxAdvanceY;
0N/A }
0N/A}