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