/* * 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; }}
/*
* 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;
}
}