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/javax/swing/text/html/Map.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/swing/text/html/Map.java+503−0
@@ -0,0 +1,503 @@
1/*
2 * Copyright (c) 1998, 2008, 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 */
25package javax.swing.text.html;
26
27import java.awt.Polygon;
28import java.io.Serializable;
29import java.util.StringTokenizer;
30import java.util.Vector;
31import javax.swing.text.AttributeSet;
32
33/**
34 * Map is used to represent a map element that is part of an HTML document.
35 * Once a Map has been created, and any number of areas have been added,
36 * you can test if a point falls inside the map via the contains method.
37 *
38 * @author Scott Violet
39 */
40class Map implements Serializable {
41 /** Name of the Map. */
42 private String name;
43 /** An array of AttributeSets. */
44 private Vector<AttributeSet> areaAttributes;
45 /** An array of RegionContainments, will slowly grow to match the
46 * length of areaAttributes as needed. */
47 private Vector<RegionContainment> areas;
48
49 public Map() {
50 }
51
52 public Map(String name) {
53 this.name = name;
54 }
55
56 /**
57 * Returns the name of the Map.
58 */
59 public String getName() {
60 return name;
61 }
62
63 /**
64 * Defines a region of the Map, based on the passed in AttributeSet.
65 */
66 public void addArea(AttributeSet as) {
67 if (as == null) {
68 return;
69 }
70 if (areaAttributes == null) {
71 areaAttributes = new Vector<AttributeSet>(2);
72 }
73 areaAttributes.addElement(as.copyAttributes());
74 }
75
76 /**
77 * Removes the previously created area.
78 */
79 public void removeArea(AttributeSet as) {
80 if (as != null && areaAttributes != null) {
81 int numAreas = (areas != null) ? areas.size() : 0;
82 for (int counter = areaAttributes.size() - 1; counter >= 0;
83 counter--) {
84 if (areaAttributes.elementAt(counter).isEqual(as)){
85 areaAttributes.removeElementAt(counter);
86 if (counter < numAreas) {
87 areas.removeElementAt(counter);
88 }
89 }
90 }
91 }
92 }
93
94 /**
95 * Returns the AttributeSets representing the differet areas of the Map.
96 */
97 public AttributeSet[] getAreas() {
98 int numAttributes = (areaAttributes != null) ? areaAttributes.size() :
99 0;
100 if (numAttributes != 0) {
101 AttributeSet[] retValue = new AttributeSet[numAttributes];
102
103 areaAttributes.copyInto(retValue);
104 return retValue;
105 }
106 return null;
107 }
108
109 /**
110 * Returns the AttributeSet that contains the passed in location,
111 * <code>x</code>, <code>y</code>. <code>width</code>, <code>height</code>
112 * gives the size of the region the map is defined over. If a matching
113 * area is found, the AttribueSet for it is returned.
114 */
115 public AttributeSet getArea(int x, int y, int width, int height) {
116 int numAttributes = (areaAttributes != null) ?
117 areaAttributes.size() : 0;
118
119 if (numAttributes > 0) {
120 int numAreas = (areas != null) ? areas.size() : 0;
121
122 if (areas == null) {
123 areas = new Vector<RegionContainment>(numAttributes);
124 }
125 for (int counter = 0; counter < numAttributes; counter++) {
126 if (counter >= numAreas) {
127 areas.addElement(createRegionContainment
128 (areaAttributes.elementAt(counter)));
129 }
130 RegionContainment rc = areas.elementAt(counter);
131 if (rc != null && rc.contains(x, y, width, height)) {
132 return areaAttributes.elementAt(counter);
133 }
134 }
135 }
136 return null;
137 }
138
139 /**
140 * Creates and returns an instance of RegionContainment that can be
141 * used to test if a particular point lies inside a region.
142 */
143 protected RegionContainment createRegionContainment
144 (AttributeSet attributes) {
145 Object shape = attributes.getAttribute(HTML.Attribute.SHAPE);
146
147 if (shape == null) {
148 shape = "rect";
149 }
150 if (shape instanceof String) {
151 String shapeString = ((String)shape).toLowerCase();
152 RegionContainment rc = null;
153
154 try {
155 if (shapeString.equals("rect")) {
156 rc = new RectangleRegionContainment(attributes);
157 }
158 else if (shapeString.equals("circle")) {
159 rc = new CircleRegionContainment(attributes);
160 }
161 else if (shapeString.equals("poly")) {
162 rc = new PolygonRegionContainment(attributes);
163 }
164 else if (shapeString.equals("default")) {
165 rc = DefaultRegionContainment.sharedInstance();
166 }
167 } catch (RuntimeException re) {
168 // Something wrong with attributes.
169 rc = null;
170 }
171 return rc;
172 }
173 return null;
174 }
175
176 /**
177 * Creates and returns an array of integers from the String
178 * <code>stringCoords</code>. If one of the values represents a
179 * % the returned value with be negative. If a parse error results
180 * from trying to parse one of the numbers null is returned.
181 */
182 static protected int[] extractCoords(Object stringCoords) {
183 if (stringCoords == null || !(stringCoords instanceof String)) {
184 return null;
185 }
186
187 StringTokenizer st = new StringTokenizer((String)stringCoords,
188 ", \t\n\r");
189 int[] retValue = null;
190 int numCoords = 0;
191
192 while(st.hasMoreElements()) {
193 String token = st.nextToken();
194 int scale;
195
196 if (token.endsWith("%")) {
197 scale = -1;
198 token = token.substring(0, token.length() - 1);
199 }
200 else {
201 scale = 1;
202 }
203 try {
204 int intValue = Integer.parseInt(token);
205
206 if (retValue == null) {
207 retValue = new int[4];
208 }
209 else if(numCoords == retValue.length) {
210 int[] temp = new int[retValue.length * 2];
211
212 System.arraycopy(retValue, 0, temp, 0, retValue.length);
213 retValue = temp;
214 }
215 retValue[numCoords++] = intValue * scale;
216 } catch (NumberFormatException nfe) {
217 return null;
218 }
219 }
220 if (numCoords > 0 && numCoords != retValue.length) {
221 int[] temp = new int[numCoords];
222
223 System.arraycopy(retValue, 0, temp, 0, numCoords);
224 retValue = temp;
225 }
226 return retValue;
227 }
228
229
230 /**
231 * Defines the interface used for to check if a point is inside a
232 * region.
233 */
234 interface RegionContainment {
235 /**
236 * Returns true if the location <code>x</code>, <code>y</code>
237 * falls inside the region defined in the receiver.
238 * <code>width</code>, <code>height</code> is the size of
239 * the enclosing region.
240 */
241 public boolean contains(int x, int y, int width, int height);
242 }
243
244
245 /**
246 * Used to test for containment in a rectangular region.
247 */
248 static class RectangleRegionContainment implements RegionContainment {
249 /** Will be non-null if one of the values is a percent, and any value
250 * that is non null indicates it is a percent
251 * (order is x, y, width, height). */
252 float[] percents;
253 /** Last value of width passed in. */
254 int lastWidth;
255 /** Last value of height passed in. */
256 int lastHeight;
257 /** Top left. */
258 int x0;
259 int y0;
260 /** Bottom right. */
261 int x1;
262 int y1;
263
264 public RectangleRegionContainment(AttributeSet as) {
265 int[] coords = Map.extractCoords(as.getAttribute(HTML.
266 Attribute.COORDS));
267
268 percents = null;
269 if (coords == null || coords.length != 4) {
270 throw new RuntimeException("Unable to parse rectangular area");
271 }
272 else {
273 x0 = coords[0];
274 y0 = coords[1];
275 x1 = coords[2];
276 y1 = coords[3];
277 if (x0 < 0 || y0 < 0 || x1 < 0 || y1 < 0) {
278 percents = new float[4];
279 lastWidth = lastHeight = -1;
280 for (int counter = 0; counter < 4; counter++) {
281 if (coords[counter] < 0) {
282 percents[counter] = Math.abs
283 (coords[counter]) / 100.0f;
284 }
285 else {
286 percents[counter] = -1.0f;
287 }
288 }
289 }
290 }
291 }
292
293 public boolean contains(int x, int y, int width, int height) {
294 if (percents == null) {
295 return contains(x, y);
296 }
297 if (lastWidth != width || lastHeight != height) {
298 lastWidth = width;
299 lastHeight = height;
300 if (percents[0] != -1.0f) {
301 x0 = (int)(percents[0] * width);
302 }
303 if (percents[1] != -1.0f) {
304 y0 = (int)(percents[1] * height);
305 }
306 if (percents[2] != -1.0f) {
307 x1 = (int)(percents[2] * width);
308 }
309 if (percents[3] != -1.0f) {
310 y1 = (int)(percents[3] * height);
311 }
312 }
313 return contains(x, y);
314 }
315
316 public boolean contains(int x, int y) {
317 return ((x >= x0 && x <= x1) &&
318 (y >= y0 && y <= y1));
319 }
320 }
321
322
323 /**
324 * Used to test for containment in a polygon region.
325 */
326 static class PolygonRegionContainment extends Polygon implements
327 RegionContainment {
328 /** If any value is a percent there will be an entry here for the
329 * percent value. Use percentIndex to find out the index for it. */
330 float[] percentValues;
331 int[] percentIndexs;
332 /** Last value of width passed in. */
333 int lastWidth;
334 /** Last value of height passed in. */
335 int lastHeight;
336
337 public PolygonRegionContainment(AttributeSet as) {
338 int[] coords = Map.extractCoords(as.getAttribute(HTML.Attribute.
339 COORDS));
340
341 if (coords == null || coords.length == 0 ||
342 coords.length % 2 != 0) {
343 throw new RuntimeException("Unable to parse polygon area");
344 }
345 else {
346 int numPercents = 0;
347
348 lastWidth = lastHeight = -1;
349 for (int counter = coords.length - 1; counter >= 0;
350 counter--) {
351 if (coords[counter] < 0) {
352 numPercents++;
353 }
354 }
355
356 if (numPercents > 0) {
357 percentIndexs = new int[numPercents];
358 percentValues = new float[numPercents];
359 for (int counter = coords.length - 1, pCounter = 0;
360 counter >= 0; counter--) {
361 if (coords[counter] < 0) {
362 percentValues[pCounter] = coords[counter] /
363 -100.0f;
364 percentIndexs[pCounter] = counter;
365 pCounter++;
366 }
367 }
368 }
369 else {
370 percentIndexs = null;
371 percentValues = null;
372 }
373 npoints = coords.length / 2;
374 xpoints = new int[npoints];
375 ypoints = new int[npoints];
376
377 for (int counter = 0; counter < npoints; counter++) {
378 xpoints[counter] = coords[counter + counter];
379 ypoints[counter] = coords[counter + counter + 1];
380 }
381 }
382 }
383
384 public boolean contains(int x, int y, int width, int height) {
385 if (percentValues == null || (lastWidth == width &&
386 lastHeight == height)) {
387 return contains(x, y);
388 }
389 // Force the bounding box to be recalced.
390 bounds = null;
391 lastWidth = width;
392 lastHeight = height;
393 float fWidth = (float)width;
394 float fHeight = (float)height;
395 for (int counter = percentValues.length - 1; counter >= 0;
396 counter--) {
397 if (percentIndexs[counter] % 2 == 0) {
398 // x
399 xpoints[percentIndexs[counter] / 2] =
400 (int)(percentValues[counter] * fWidth);
401 }
402 else {
403 // y
404 ypoints[percentIndexs[counter] / 2] =
405 (int)(percentValues[counter] * fHeight);
406 }
407 }
408 return contains(x, y);
409 }
410 }
411
412
413 /**
414 * Used to test for containment in a circular region.
415 */
416 static class CircleRegionContainment implements RegionContainment {
417 /** X origin of the circle. */
418 int x;
419 /** Y origin of the circle. */
420 int y;
421 /** Radius of the circle. */
422 int radiusSquared;
423 /** Non-null indicates one of the values represents a percent. */
424 float[] percentValues;
425 /** Last value of width passed in. */
426 int lastWidth;
427 /** Last value of height passed in. */
428 int lastHeight;
429
430 public CircleRegionContainment(AttributeSet as) {
431 int[] coords = Map.extractCoords(as.getAttribute(HTML.Attribute.
432 COORDS));
433
434 if (coords == null || coords.length != 3) {
435 throw new RuntimeException("Unable to parse circular area");
436 }
437 x = coords[0];
438 y = coords[1];
439 radiusSquared = coords[2] * coords[2];
440 if (coords[0] < 0 || coords[1] < 0 || coords[2] < 0) {
441 lastWidth = lastHeight = -1;
442 percentValues = new float[3];
443 for (int counter = 0; counter < 3; counter++) {
444 if (coords[counter] < 0) {
445 percentValues[counter] = coords[counter] /
446 -100.0f;
447 }
448 else {
449 percentValues[counter] = -1.0f;
450 }
451 }
452 }
453 else {
454 percentValues = null;
455 }
456 }
457
458 public boolean contains(int x, int y, int width, int height) {
459 if (percentValues != null && (lastWidth != width ||
460 lastHeight != height)) {
461 int newRad = Math.min(width, height) / 2;
462
463 lastWidth = width;
464 lastHeight = height;
465 if (percentValues[0] != -1.0f) {
466 this.x = (int)(percentValues[0] * width);
467 }
468 if (percentValues[1] != -1.0f) {
469 this.y = (int)(percentValues[1] * height);
470 }
471 if (percentValues[2] != -1.0f) {
472 radiusSquared = (int)(percentValues[2] *
473 Math.min(width, height));
474 radiusSquared *= radiusSquared;
475 }
476 }
477 return (((x - this.x) * (x - this.x) +
478 (y - this.y) * (y - this.y)) <= radiusSquared);
479 }
480 }
481
482
483 /**
484 * An implementation that will return true if the x, y location is
485 * inside a rectangle defined by origin 0, 0, and width equal to
486 * width passed in, and height equal to height passed in.
487 */
488 static class DefaultRegionContainment implements RegionContainment {
489 /** A global shared instance. */
490 static DefaultRegionContainment si = null;
491
492 public static DefaultRegionContainment sharedInstance() {
493 if (si == null) {
494 si = new DefaultRegionContainment();
495 }
496 return si;
497 }
498
499 public boolean contains(int x, int y, int width, int height) {
500 return (x <= width && x >= 0 && y >= 0 && y <= width);
501 }
502 }
503}