blob: 62276ec03786f03488f99e5c2ab442500bb27147 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.font;
27
28import java.awt.geom.AffineTransform;
29import java.awt.geom.Point2D;
30
31/* These are font metrics: they are in user space, not device space.
32 * Hence they are not truly "strike" metrics. However it is convenient to
33 * treat them as such since we need to have a scaler context to obtain them
34 * and also to cache them. The old implementation obtained a C++ strike object
35 * that matched the Font TX + pt size only. It was wasteful of strike objects.
36 * This new implementation still has separate StrikeMetrics for 2 fonts that
37 * are really the same but are used in different device transforms, but at
38 * least it doesn't create a whole new strike just to get the metrics for
39 * a strike in a transformed graphics.
40 * So these metrics do not take into account the device transform. They
41 * are considered inherent properties of the font. Hence it may be that we
42 * should use the device transform to obtain the most accurate metrics, but
43 * typically 1.1 APIs do not provide for this. So some APIs may want to
44 * ignore the dev. tx and others may want to use it, and then apply an
45 * inverse transform. For now we ignore the dev. tx.
46 * "Font" metrics are representative of a typical glyph in the font.
47 * Generally speaking these values are the choice of the font designer and
48 * are stored in the font, from which we retrieve the values. They do
49 * not necessarily equate to the maximum bounds of all glyphs in the font.
50 * Note that the ascent fields are typically a -ve value as we use a top-left
51 * origin user space, and text is positioned relative to its baseline.
52 */
53public final class StrikeMetrics {
54
55 public float ascentX;
56 public float ascentY;
57 public float descentX;
58 public float descentY;
59 public float baselineX;
60 public float baselineY;
61 public float leadingX;
62 public float leadingY;
63 public float maxAdvanceX;
64 public float maxAdvanceY;
65
66
67 /* The no-args constructor is used by CompositeStrike, which then
68 * merges in the metrics of physical fonts.
69 * The approach here is the same as earlier releases but it is flawed
70 * take for example the following which ignores leading for simplicity.
71 * Say we have a composite with an element asc=-9, dsc=2, and another with
72 * asc=-7, dsc=3. The merged font is (-9,3) for height of -(-9)+3=12.
73 * Suppose this same font has been derived with a 180% rotation
74 * Now its signs for ascent/descent are reversed. Its (9,-2) and (7,-3)
75 * Its merged values are (using the code in this class) (7,-2) for
76 * a height of -(7)+-2 = =-9!
77 * We need to have a more intelligent merging algorithm,
78 * which so far as I can see needs to apply an inverse of the font
79 * tx, do its merging, and then reapply the font tx.
80 * This wouldn't often be a problem as there rarely is a font TX, and
81 * the tricky part is getting the information. Probably the no-args
82 * constructor needs to pass a TX in to be applied to all merges.
83 * CompositeStrike would be left with the problem of figuring out what
84 * tx to use.
85 * But at least for now we are probably no worse than 1.4 ...
86 * REMIND: FIX THIS.
87 */
88 StrikeMetrics() {
89 ascentX = ascentY = Integer.MAX_VALUE;
90 descentX = descentY = leadingX = leadingY = Integer.MIN_VALUE;
91 baselineX = baselineX = maxAdvanceX = maxAdvanceY = Integer.MIN_VALUE;
92 }
93
94 StrikeMetrics(float ax, float ay, float dx, float dy, float bx, float by,
95 float lx, float ly, float mx, float my) {
96 ascentX = ax;
97 ascentY = ay;
98 descentX = dx;
99 descentY = dy;
100 baselineX = bx;
101 baselineY = by;
102 leadingX = lx;
103 leadingY = ly;
104 maxAdvanceX = mx;
105 maxAdvanceY = my;
106 }
107
108 public float getAscent() {
109 return -ascentY;
110 }
111
112 public float getDescent() {
113 return descentY;
114 }
115
116 public float getLeading() {
117 return leadingY;
118 }
119
120 public float getMaxAdvance() {
121 return maxAdvanceX;
122 }
123
124 /*
125 * Currently only used to merge together slot metrics to create
126 * the metrics for a composite font.
127 */
128 void merge(StrikeMetrics other) {
129 if (other == null) {
130 return;
131 }
132 if (other.ascentX < ascentX) {
133 ascentX = other.ascentX;
134 }
135 if (other.ascentY < ascentY) {
136 ascentY = other.ascentY;
137 }
138 if (other.descentX > descentX) {
139 descentX = other.descentX;
140 }
141 if (other.descentY > descentY) {
142 descentY = other.descentY;
143 }
144 if (other.baselineX > baselineX) {
145 baselineX = other.baselineX;
146 }
147 if (other.baselineY > baselineY) {
148 baselineY = other.baselineY;
149 }
150 if (other.leadingX > leadingX) {
151 leadingX = other.leadingX;
152 }
153 if (other.leadingY > leadingY) {
154 leadingY = other.leadingY;
155 }
156 if (other.maxAdvanceX > maxAdvanceX) {
157 maxAdvanceX = other.maxAdvanceX;
158 }
159 if (other.maxAdvanceY > maxAdvanceY) {
160 maxAdvanceY = other.maxAdvanceY;
161 }
162 }
163
164 /* Used to transform the values back into user space.
165 * This is done ONCE by the strike so clients should not need
166 * to worry about this
167 */
168 void convertToUserSpace(AffineTransform invTx) {
169 Point2D.Float pt2D = new Point2D.Float();
170
171 pt2D.x = ascentX; pt2D.y = ascentY;
172 invTx.deltaTransform(pt2D, pt2D);
173 ascentX = pt2D.x; ascentY = pt2D.y;
174
175 pt2D.x = descentX; pt2D.y = descentY;
176 invTx.deltaTransform(pt2D, pt2D);
177 descentX = pt2D.x; descentY = pt2D.y;
178
179 pt2D.x = baselineX; pt2D.y = baselineY;
180 invTx.deltaTransform(pt2D, pt2D);
181 baselineX = pt2D.x; baselineY = pt2D.y;
182
183 pt2D.x = leadingX; pt2D.y = leadingY;
184 invTx.deltaTransform(pt2D, pt2D);
185 leadingX = pt2D.x; leadingY = pt2D.y;
186
187 pt2D.x = maxAdvanceX; pt2D.y = maxAdvanceY;
188 invTx.deltaTransform(pt2D, pt2D);
189 maxAdvanceX = pt2D.x; maxAdvanceY = pt2D.y;
190 }
191
192 public String toString() {
193 return "ascent:x=" + ascentX + " y=" + ascentY +
194 " descent:x=" + descentX + " y=" + descentY +
195 " baseline:x=" + baselineX + " y=" + baselineY +
196 " leading:x=" + leadingX + " y=" + leadingY +
197 " maxAdvance:x=" + maxAdvanceX + " y=" + maxAdvanceY;
198 }
199}