History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/font/Underline.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/font/Underline.java+308−0
@@ -0,0 +1,308 @@
1/*
2 * Copyright (c) 1998, 2006, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25/*
26 *
27 * (C) Copyright IBM Corp. 1998, All Rights Reserved
28 */
29
30package sun.font;
31
32import java.awt.BasicStroke;
33import java.awt.Graphics2D;
34import java.awt.Shape;
35import java.awt.Stroke;
36
37import java.awt.geom.GeneralPath;
38import java.awt.geom.Line2D;
39
40import java.awt.font.TextAttribute;
41
42import java.util.concurrent.ConcurrentHashMap;
43
44/**
45 * This class provides drawing and bounds-measurement of
46 * underlines. Additionally, it has a factory method for
47 * obtaining underlines from values of underline attributes.
48 */
49
50abstract class Underline {
51
52 /**
53 * Draws the underline into g2d. The thickness should be obtained
54 * from a LineMetrics object. Note that some underlines ignore the
55 * thickness parameter.
56 * The underline is drawn from (x1, y) to (x2, y).
57 */
58 abstract void drawUnderline(Graphics2D g2d,
59 float thickness,
60 float x1,
61 float x2,
62 float y);
63
64 /**
65 * Returns the bottom of the bounding rectangle for this underline.
66 */
67 abstract float getLowerDrawLimit(float thickness);
68
69 /**
70 * Returns a Shape representing the underline. The thickness should be obtained
71 * from a LineMetrics object. Note that some underlines ignore the
72 * thickness parameter.
73 */
74 abstract Shape getUnderlineShape(float thickness,
75 float x1,
76 float x2,
77 float y);
78
79 // Implementation of underline for standard and Input Method underlines.
80 // These classes are private.
81
82 // IM Underlines ignore thickness param, and instead use
83 // DEFAULT_THICKNESS
84 private static final float DEFAULT_THICKNESS = 1.0f;
85
86 // StandardUnderline's constructor takes a boolean param indicating
87 // whether to override the default thickness. These values clarify
88 // the semantics of the parameter.
89 private static final boolean USE_THICKNESS = true;
90 private static final boolean IGNORE_THICKNESS = false;
91
92 // Implementation of standard underline and all input method underlines
93 // except UNDERLINE_LOW_GRAY.
94 private static final class StandardUnderline extends Underline {
95
96 // the amount by which to move the underline
97 private float shift;
98
99 // the actual line thickness is this value times
100 // the requested thickness
101 private float thicknessMultiplier;
102
103 // if non-null, underline is drawn with a BasicStroke
104 // with this dash pattern
105 private float[] dashPattern;
106
107 // if false, all underlines are DEFAULT_THICKNESS thick
108 // if true, use thickness param
109 private boolean useThickness;
110
111 // cached BasicStroke
112 private BasicStroke cachedStroke;
113
114 StandardUnderline(float shift,
115 float thicknessMultiplier,
116 float[] dashPattern,
117 boolean useThickness) {
118
119 this.shift = shift;
120 this.thicknessMultiplier = thicknessMultiplier;
121 this.dashPattern = dashPattern;
122 this.useThickness = useThickness;
123 this.cachedStroke = null;
124 }
125
126 private BasicStroke createStroke(float lineThickness) {
127
128 if (dashPattern == null) {
129 return new BasicStroke(lineThickness,
130 BasicStroke.CAP_BUTT,
131 BasicStroke.JOIN_MITER);
132 }
133 else {
134 return new BasicStroke(lineThickness,
135 BasicStroke.CAP_BUTT,
136 BasicStroke.JOIN_MITER,
137 10.0f,
138 dashPattern,
139 0);
140 }
141 }
142
143 private float getLineThickness(float thickness) {
144
145 if (useThickness) {
146 return thickness * thicknessMultiplier;
147 }
148 else {
149 return DEFAULT_THICKNESS * thicknessMultiplier;
150 }
151 }
152
153 private Stroke getStroke(float thickness) {
154
155 float lineThickness = getLineThickness(thickness);
156 BasicStroke stroke = cachedStroke;
157 if (stroke == null ||
158 stroke.getLineWidth() != lineThickness) {
159
160 stroke = createStroke(lineThickness);
161 cachedStroke = stroke;
162 }
163
164 return stroke;
165 }
166
167 void drawUnderline(Graphics2D g2d,
168 float thickness,
169 float x1,
170 float x2,
171 float y) {
172
173
174 Stroke saveStroke = g2d.getStroke();
175 g2d.setStroke(getStroke(thickness));
176 g2d.draw(new Line2D.Float(x1, y + shift, x2, y + shift));
177 g2d.setStroke(saveStroke);
178 }
179
180 float getLowerDrawLimit(float thickness) {
181
182 return shift + getLineThickness(thickness);
183 }
184
185 Shape getUnderlineShape(float thickness,
186 float x1,
187 float x2,
188 float y) {
189
190 Stroke ulStroke = getStroke(thickness);
191 Line2D line = new Line2D.Float(x1, y + shift, x2, y + shift);
192 return ulStroke.createStrokedShape(line);
193 }
194 }
195
196 // Implementation of UNDERLINE_LOW_GRAY.
197 private static class IMGrayUnderline extends Underline {
198
199 private BasicStroke stroke;
200
201 IMGrayUnderline() {
202 stroke = new BasicStroke(DEFAULT_THICKNESS,
203 BasicStroke.CAP_BUTT,
204 BasicStroke.JOIN_MITER,
205 10.0f,
206 new float[] {1, 1},
207 0);
208 }
209
210 void drawUnderline(Graphics2D g2d,
211 float thickness,
212 float x1,
213 float x2,
214 float y) {
215
216 Stroke saveStroke = g2d.getStroke();
217 g2d.setStroke(stroke);
218
219 Line2D.Float drawLine = new Line2D.Float(x1, y, x2, y);
220 g2d.draw(drawLine);
221
222 drawLine.y1 += DEFAULT_THICKNESS;
223 drawLine.y2 += DEFAULT_THICKNESS;
224 drawLine.x1 += DEFAULT_THICKNESS;
225
226 g2d.draw(drawLine);
227
228 g2d.setStroke(saveStroke);
229 }
230
231 float getLowerDrawLimit(float thickness) {
232
233 return DEFAULT_THICKNESS * 2;
234 }
235
236 Shape getUnderlineShape(float thickness,
237 float x1,
238 float x2,
239 float y) {
240
241 GeneralPath gp = new GeneralPath();
242
243 Line2D.Float line = new Line2D.Float(x1, y, x2, y);
244 gp.append(stroke.createStrokedShape(line), false);
245
246 line.y1 += DEFAULT_THICKNESS;
247 line.y2 += DEFAULT_THICKNESS;
248 line.x1 += DEFAULT_THICKNESS;
249
250 gp.append(stroke.createStrokedShape(line), false);
251
252 return gp;
253 }
254 }
255
256 // Keep a map of underlines, one for each type
257 // of underline. The Underline objects are Flyweights
258 // (shared across multiple clients), so they should be immutable.
259 // If this implementation changes then clone underline
260 // instances in getUnderline before returning them.
261 private static final ConcurrentHashMap<Object, Underline>
262 UNDERLINES = new ConcurrentHashMap<Object, Underline>(6);
263 private static final Underline[] UNDERLINE_LIST;
264
265 static {
266 Underline[] uls = new Underline[6];
267
268 uls[0] = new StandardUnderline(0, 1, null, USE_THICKNESS);
269 UNDERLINES.put(TextAttribute.UNDERLINE_ON, uls[0]);
270
271 uls[1] = new StandardUnderline(1, 1, null, IGNORE_THICKNESS);
272 UNDERLINES.put(TextAttribute.UNDERLINE_LOW_ONE_PIXEL, uls[1]);
273
274 uls[2] = new StandardUnderline(1, 2, null, IGNORE_THICKNESS);
275 UNDERLINES.put(TextAttribute.UNDERLINE_LOW_TWO_PIXEL, uls[2]);
276
277 uls[3] = new StandardUnderline(1, 1, new float[] { 1, 1 }, IGNORE_THICKNESS);
278 UNDERLINES.put(TextAttribute.UNDERLINE_LOW_DOTTED, uls[3]);
279
280 uls[4] = new IMGrayUnderline();
281 UNDERLINES.put(TextAttribute.UNDERLINE_LOW_GRAY, uls[4]);
282
283 uls[5] = new StandardUnderline(1, 1, new float[] { 4, 4 }, IGNORE_THICKNESS);
284 UNDERLINES.put(TextAttribute.UNDERLINE_LOW_DASHED, uls[5]);
285
286 UNDERLINE_LIST = uls;
287 }
288
289 /**
290 * Return the Underline for the given value of
291 * TextAttribute.INPUT_METHOD_UNDERLINE or
292 * TextAttribute.UNDERLINE.
293 * If value is not an input method underline value or
294 * TextAttribute.UNDERLINE_ON, null is returned.
295 */
296 static Underline getUnderline(Object value) {
297
298 if (value == null) {
299 return null;
300 }
301
302 return (Underline) UNDERLINES.get(value);
303 }
304
305 static Underline getUnderline(int index) {
306 return index < 0 ? null : UNDERLINE_LIST[index];
307 }
308}