blob: 2b52e6c49f88ddc0142bb76a18437efa01749e6b [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2005 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.Font;
29import java.awt.font.FontRenderContext;
30import java.awt.geom.AffineTransform;
31import static sun.awt.SunHints.*;
32
33/*
34 * This class encapsulates every thing needed that distinguishes a strike.
35 * It can be used as a key to locate a FontStrike in a Hashmap/cache.
36 * It is not mutatable, but contains mutatable AffineTransform objects,
37 * which for performance reasons it does not keep private copies of.
38 * Therefore code constructing these must pass in transforms it guarantees
39 * not to mutate.
40 */
41public class FontStrikeDesc {
42
43 /* Values to use as a mask that is used for faster comparison of
44 * two strikes using just an int equality test.
45 * The ones we don't use are listed here but commented out.
46 * ie style is already built and hint "OFF" values are zero.
47 * Note that this is used as a strike key and the same strike is used
48 * for HRGB and HBGR, so only the orientation needed (H or V) is needed
49 * to construct and distinguish a FontStrikeDesc. The rgb ordering
50 * needed for rendering is stored in the graphics state.
51 */
52// static final int STYLE_PLAIN = Font.PLAIN; // 0x0000
53// static final int STYLE_BOLD = Font.BOLD; // 0x0001
54// static final int STYLE_ITALIC = Font.ITALIC; // 0x0002
55// static final int STYLE_BOLDITALIC = Font.BOLD|Font.ITALIC; // 0x0003
56// static final int AA_OFF = 0x0000;
57 static final int AA_ON = 0x0010;
58 static final int AA_LCD_H = 0x0020;
59 static final int AA_LCD_V = 0x0040;
60// static final int FRAC_METRICS_OFF = 0x0000;
61 static final int FRAC_METRICS_ON = 0x0100;
62 static final int FRAC_METRICS_SP = 0x0200;
63
64 /* devTx is to get an inverse transform to get user space values
65 * for metrics. Its not used otherwise, as the glyphTx is the important
66 * one. But it does mean that a strike representing a 6pt font and identity
67 * graphics transform is not equal to one for a 12 pt font and 2x scaled
68 * graphics transform. Its likely to be very rare that this causes
69 * duplication.
70 */
71 AffineTransform devTx;
72 AffineTransform glyphTx; // all of ptSize, Font tx and Graphics tx.
73 int style;
74 int aaHint;
75 int fmHint;
76 private int hashCode;
77 private int valuemask;
78
79 public int hashCode() {
80 /* Can cache hashcode since a strike(desc) is immutable.*/
81 if (hashCode == 0) {
82 hashCode = glyphTx.hashCode() + devTx.hashCode() + valuemask;
83 }
84 return hashCode;
85 }
86
87 public boolean equals(Object obj) {
88 try {
89 FontStrikeDesc desc = (FontStrikeDesc)obj;
90 return (desc.valuemask == this.valuemask &&
91 desc.glyphTx.equals(this.glyphTx) &&
92 desc.devTx.equals(this.devTx));
93 } catch (Exception e) {
94 /* class cast or NP exceptions should not happen often, if ever,
95 * and I am hoping that this is faster than an instanceof check.
96 */
97 return false;
98 }
99 }
100
101 FontStrikeDesc() {
102 // used with init
103 }
104
105
106 /* This maps a public text AA hint value into one of the subset of values
107 * used to index strikes. For the purpose of the strike cache there are
108 * only 4 values : OFF, ON, LCD_HRGB, LCD_VRGB.
109 * Font and ptSize are needed to resolve the 'gasp' table. The ptSize
110 * must therefore include device and font transforms.
111 */
112 public static int getAAHintIntVal(Object aa, Font2D font2D, int ptSize) {
113 if (aa == VALUE_TEXT_ANTIALIAS_OFF ||
114 aa == VALUE_TEXT_ANTIALIAS_DEFAULT) {
115 return INTVAL_TEXT_ANTIALIAS_OFF;
116 } else if (aa == VALUE_TEXT_ANTIALIAS_ON) {
117 return INTVAL_TEXT_ANTIALIAS_ON;
118 } else if (aa == VALUE_TEXT_ANTIALIAS_GASP) {
119 if (font2D.useAAForPtSize(ptSize)) {
120 return INTVAL_TEXT_ANTIALIAS_ON;
121 } else {
122 return INTVAL_TEXT_ANTIALIAS_OFF;
123 }
124 } else if (aa == VALUE_TEXT_ANTIALIAS_LCD_HRGB ||
125 aa == VALUE_TEXT_ANTIALIAS_LCD_HBGR) {
126 return INTVAL_TEXT_ANTIALIAS_LCD_HRGB;
127 } else if (aa == VALUE_TEXT_ANTIALIAS_LCD_VRGB ||
128 aa == VALUE_TEXT_ANTIALIAS_LCD_VBGR) {
129 return INTVAL_TEXT_ANTIALIAS_LCD_VRGB;
130 } else {
131 return INTVAL_TEXT_ANTIALIAS_OFF;
132 }
133 }
134
135 /* This maps a public text AA hint value into one of the subset of values
136 * used to index strikes. For the purpose of the strike cache there are
137 * only 4 values : OFF, ON, LCD_HRGB, LCD_VRGB.
138 * Font and FontRenderContext are needed to resolve the 'gasp' table.
139 * This is similar to the method above, but used by callers which have not
140 * already calculated the glyph device point size.
141 */
142 public static int getAAHintIntVal(Font2D font2D, Font font,
143 FontRenderContext frc) {
144 Object aa = frc.getAntiAliasingHint();
145 if (aa == VALUE_TEXT_ANTIALIAS_OFF ||
146 aa == VALUE_TEXT_ANTIALIAS_DEFAULT) {
147 return INTVAL_TEXT_ANTIALIAS_OFF;
148 } else if (aa == VALUE_TEXT_ANTIALIAS_ON) {
149 return INTVAL_TEXT_ANTIALIAS_ON;
150 } else if (aa == VALUE_TEXT_ANTIALIAS_GASP) {
151 /* FRC.isIdentity() would have been useful */
152 int ptSize;
153 AffineTransform tx = frc.getTransform();
154 if (tx.isIdentity() && !font.isTransformed()) {
155 ptSize = font.getSize();
156 } else {
157 /* one or both transforms is not identity */
158 float size = font.getSize2D();
159 if (tx.isIdentity()) {
160 tx = font.getTransform();
161 tx.scale(size, size);
162 } else {
163 tx.scale(size, size);
164 if (font.isTransformed()) {
165 tx.concatenate(font.getTransform());
166 }
167 }
168 double shearx = tx.getShearX();
169 double scaley = tx.getScaleY();
170 if (shearx != 0) {
171 scaley = Math.sqrt(shearx * shearx + scaley * scaley);
172 }
173 ptSize = (int)(Math.abs(scaley)+0.5);
174 }
175 if (font2D.useAAForPtSize(ptSize)) {
176 return INTVAL_TEXT_ANTIALIAS_ON;
177 } else {
178 return INTVAL_TEXT_ANTIALIAS_OFF;
179 }
180 } else if (aa == VALUE_TEXT_ANTIALIAS_LCD_HRGB ||
181 aa == VALUE_TEXT_ANTIALIAS_LCD_HBGR) {
182 return INTVAL_TEXT_ANTIALIAS_LCD_HRGB;
183 } else if (aa == VALUE_TEXT_ANTIALIAS_LCD_VRGB ||
184 aa == VALUE_TEXT_ANTIALIAS_LCD_VBGR) {
185 return INTVAL_TEXT_ANTIALIAS_LCD_VRGB;
186 } else {
187 return INTVAL_TEXT_ANTIALIAS_OFF;
188 }
189 }
190
191 public static int getFMHintIntVal(Object fm) {
192 if (fm == VALUE_FRACTIONALMETRICS_OFF ||
193 fm == VALUE_FRACTIONALMETRICS_DEFAULT) {
194 return INTVAL_FRACTIONALMETRICS_OFF;
195 } else {
196 return INTVAL_FRACTIONALMETRICS_ON;
197 }
198 }
199
200 public FontStrikeDesc(AffineTransform devAt, AffineTransform at,
201 int fStyle, int aa, int fm) {
202 devTx = devAt;
203 glyphTx = at; // not cloning glyphTx. Callers trusted to not mutate it.
204 style = fStyle;
205 aaHint = aa;
206 fmHint = fm;
207 valuemask = fStyle;
208 switch (aa) {
209 case INTVAL_TEXT_ANTIALIAS_OFF :
210 break;
211 case INTVAL_TEXT_ANTIALIAS_ON :
212 valuemask |= AA_ON;
213 break;
214 case INTVAL_TEXT_ANTIALIAS_LCD_HRGB :
215 case INTVAL_TEXT_ANTIALIAS_LCD_HBGR :
216 valuemask |= AA_LCD_H;
217 break;
218 case INTVAL_TEXT_ANTIALIAS_LCD_VRGB :
219 case INTVAL_TEXT_ANTIALIAS_LCD_VBGR :
220 valuemask |= AA_LCD_V;
221 break;
222 default: break;
223 }
224 if (fm == INTVAL_FRACTIONALMETRICS_ON) {
225 valuemask |= FRAC_METRICS_ON;
226 }
227 }
228
229 FontStrikeDesc(FontStrikeDesc desc) {
230 devTx = desc.devTx;
231 // Clone the TX in this case as this is called when its known
232 // that "desc" is being re-used by its creator.
233 glyphTx = (AffineTransform)desc.glyphTx.clone();
234 style = desc.style;
235 aaHint = desc.aaHint;
236 fmHint = desc.fmHint;
237 hashCode = desc.hashCode;
238 valuemask = desc.valuemask;
239 }
240
241
242 public String toString() {
243 return "FontStrikeDesc: Style="+style+ " AA="+aaHint+ " FM="+fmHint+
244 " devTx="+devTx+ " devTx.FontTx.ptSize="+glyphTx;
245 }
246}