1 |
|
package org.apache.tapestry.contrib.services.impl; |
2 |
|
|
3 |
|
import org.apache.hivemind.util.Defense; |
4 |
|
|
5 |
|
import javax.imageio.ImageIO; |
6 |
|
import java.awt.*; |
7 |
|
import java.awt.geom.Arc2D; |
8 |
|
import java.awt.geom.Rectangle2D; |
9 |
|
import java.awt.geom.RoundRectangle2D; |
10 |
|
import java.awt.image.BufferedImage; |
11 |
|
import java.util.HashMap; |
12 |
|
import java.util.Map; |
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
1 |
public class RoundedCornerGenerator { |
18 |
|
|
19 |
|
public static final String TOP_LEFT = "tl"; |
20 |
|
public static final String TOP_RIGHT = "tr"; |
21 |
|
public static final String BOTTOM_LEFT = "bl"; |
22 |
|
public static final String BOTTOM_RIGHT = "br"; |
23 |
|
|
24 |
|
public static final String LEFT = "left"; |
25 |
|
public static final String RIGHT = "right"; |
26 |
|
public static final String TOP = "top"; |
27 |
|
public static final String BOTTOM = "bottom"; |
28 |
|
|
29 |
|
|
30 |
1 |
private static final Map _cssSpecMap = new HashMap(); |
31 |
|
|
32 |
|
static { |
33 |
1 |
_cssSpecMap.put("aqua", new Color(0,255,255)); |
34 |
1 |
_cssSpecMap.put("black", Color.black); |
35 |
1 |
_cssSpecMap.put("blue", Color.blue); |
36 |
1 |
_cssSpecMap.put("fuchsia", new Color(255,0,255)); |
37 |
1 |
_cssSpecMap.put("gray", Color.gray); |
38 |
1 |
_cssSpecMap.put("green", Color.green); |
39 |
1 |
_cssSpecMap.put("lime", new Color(0,255,0)); |
40 |
1 |
_cssSpecMap.put("maroon", new Color(128,0,0)); |
41 |
1 |
_cssSpecMap.put("navy", new Color(0,0,128)); |
42 |
1 |
_cssSpecMap.put("olive", new Color(128,128,0)); |
43 |
1 |
_cssSpecMap.put("purple", new Color(128,0,128)); |
44 |
1 |
_cssSpecMap.put("red", Color.red); |
45 |
1 |
_cssSpecMap.put("silver", new Color(192,192,192)); |
46 |
1 |
_cssSpecMap.put("teal", new Color(0,128,128)); |
47 |
1 |
_cssSpecMap.put("white", Color.white); |
48 |
1 |
_cssSpecMap.put("yellow", Color.yellow); |
49 |
|
|
50 |
1 |
ImageIO.setUseCache(false); |
51 |
|
} |
52 |
|
|
53 |
1 |
private static Color SHADOW_COLOR = new Color(0x000000); |
54 |
|
|
55 |
|
private static final float DEFAULT_OPACITY = 0.5f; |
56 |
|
|
57 |
|
private static final float ANGLE_TOP_LEFT = 90f; |
58 |
|
private static final float ANGLE_TOP_RIGHT = 0f; |
59 |
|
private static final float ANGLE_BOTTOM_LEFT = 180f; |
60 |
|
private static final float ANGLE_BOTTOM_RIGHT = 270f; |
61 |
|
|
62 |
|
public BufferedImage buildCorner(String color, String backgroundColor, int width, int height, |
63 |
|
String angle, int shadowWidth, float endOpacity) |
64 |
|
throws Exception |
65 |
|
{ |
66 |
1 |
width = width * 2; |
67 |
1 |
height = height * 2; |
68 |
1 |
float startAngle = getStartAngle(angle); |
69 |
1 |
Color bgColor = backgroundColor == null ? null : decodeColor(backgroundColor); |
70 |
|
|
71 |
1 |
if (shadowWidth <= 0) { |
72 |
|
|
73 |
1 |
BufferedImage arc = drawArc(color, width, height, angle, false, -1); |
74 |
1 |
BufferedImage ret = arc; |
75 |
|
|
76 |
1 |
Arc2D.Float arcArea = new Arc2D.Float(0, 0, width, height, startAngle, 90, Arc2D.PIE); |
77 |
1 |
if (bgColor != null) { |
78 |
|
|
79 |
0 |
ret = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); |
80 |
0 |
Graphics2D g2 = (Graphics2D)ret.createGraphics(); |
81 |
0 |
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
82 |
0 |
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); |
83 |
|
|
84 |
0 |
g2.setColor(bgColor); |
85 |
0 |
g2.fill(arcArea.getBounds2D()); |
86 |
|
|
87 |
0 |
g2.drawImage(arc, 0, 0, null); |
88 |
|
|
89 |
0 |
g2.dispose(); |
90 |
|
|
91 |
0 |
ret = convertType(ret, BufferedImage.TYPE_INT_RGB); |
92 |
|
} |
93 |
|
|
94 |
1 |
return ret.getSubimage((int)arcArea.getBounds2D().getX(), (int)arcArea.getBounds2D().getY(), |
95 |
|
(int)arcArea.getBounds2D().getWidth(), (int)arcArea.getBounds2D().getHeight()); |
96 |
|
} |
97 |
|
|
98 |
0 |
BufferedImage mask = drawArc(color, width, height, angle, true, shadowWidth); |
99 |
0 |
BufferedImage arc = drawArc(color, width, height, angle, false, shadowWidth); |
100 |
|
|
101 |
0 |
float startX = 0; |
102 |
0 |
float startY = 0; |
103 |
0 |
int shadowSize = shadowWidth * 2; |
104 |
0 |
float canvasWidth = width + (shadowSize * 2); |
105 |
0 |
float canvasHeight = height + (shadowSize * 2); |
106 |
|
|
107 |
0 |
if (startAngle == ANGLE_BOTTOM_LEFT) { |
108 |
|
|
109 |
0 |
startY -= (shadowSize * 2); |
110 |
|
|
111 |
0 |
} else if (startAngle == ANGLE_TOP_RIGHT) { |
112 |
|
|
113 |
0 |
startX -= shadowSize * 2; |
114 |
|
|
115 |
0 |
} else if (startAngle == ANGLE_BOTTOM_RIGHT) { |
116 |
|
|
117 |
0 |
startX -= shadowSize * 2; |
118 |
0 |
startY -= shadowSize * 2; |
119 |
|
} |
120 |
|
|
121 |
0 |
BufferedImage ret = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); |
122 |
0 |
Graphics2D g2 = (Graphics2D)ret.createGraphics(); |
123 |
0 |
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
124 |
|
|
125 |
0 |
Arc2D.Float arcArea = new Arc2D.Float(startX, startY, canvasWidth, canvasHeight, startAngle, 90, Arc2D.PIE); |
126 |
|
|
127 |
0 |
if (bgColor != null) { |
128 |
|
|
129 |
0 |
g2.setColor(bgColor); |
130 |
0 |
g2.fill(arcArea.getBounds2D()); |
131 |
|
} |
132 |
|
|
133 |
0 |
BufferedImage shadow = drawArcShadow(mask, color, backgroundColor, width, height, angle, shadowWidth, endOpacity); |
134 |
|
|
135 |
0 |
g2.setClip(arcArea); |
136 |
0 |
g2.drawImage(shadow, 0, 0, null); |
137 |
|
|
138 |
0 |
g2.setClip(null); |
139 |
0 |
g2.drawImage(arc, 0, 0, null); |
140 |
|
|
141 |
0 |
return convertType(ret, BufferedImage.TYPE_INT_RGB).getSubimage((int)arcArea.getBounds2D().getX(), (int)arcArea.getBounds2D().getY(), |
142 |
|
(int)arcArea.getBounds2D().getWidth(), (int)arcArea.getBounds2D().getHeight()); |
143 |
|
} |
144 |
|
|
145 |
|
static BufferedImage convertType(BufferedImage image, int type) { |
146 |
0 |
BufferedImage result = new BufferedImage(image.getWidth(), image.getHeight(), type); |
147 |
0 |
Graphics2D g = result.createGraphics(); |
148 |
0 |
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
149 |
0 |
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); |
150 |
0 |
g.drawRenderedImage(image, null); |
151 |
0 |
g.dispose(); |
152 |
0 |
return result; |
153 |
|
} |
154 |
|
|
155 |
|
BufferedImage drawArc(String color, int width, int height, String angle, boolean masking, int shadowWidth) |
156 |
|
{ |
157 |
1 |
Color arcColor = decodeColor(color); |
158 |
1 |
float startAngle = getStartAngle(angle); |
159 |
|
|
160 |
1 |
int canvasWidth = width; |
161 |
1 |
int canvasHeight = height; |
162 |
1 |
float startX = 0; |
163 |
1 |
float startY = 0; |
164 |
1 |
int shadowSize = 0; |
165 |
|
|
166 |
1 |
if (shadowWidth > 0 && !masking) { |
167 |
|
|
168 |
0 |
shadowSize = shadowWidth * 2; |
169 |
0 |
canvasWidth += shadowSize * 2; |
170 |
0 |
canvasHeight += shadowSize * 2; |
171 |
|
|
172 |
0 |
if (startAngle == ANGLE_TOP_LEFT) { |
173 |
|
|
174 |
0 |
startX += shadowSize; |
175 |
0 |
startY += shadowSize; |
176 |
|
|
177 |
0 |
} else if (startAngle == ANGLE_BOTTOM_LEFT) { |
178 |
|
|
179 |
0 |
startX += shadowSize; |
180 |
0 |
startY -= shadowSize; |
181 |
|
|
182 |
0 |
} else if (startAngle == ANGLE_TOP_RIGHT) { |
183 |
|
|
184 |
0 |
startX -= shadowSize; |
185 |
0 |
startY += shadowSize; |
186 |
|
|
187 |
0 |
} else if (startAngle == ANGLE_BOTTOM_RIGHT) { |
188 |
|
|
189 |
0 |
startX -= shadowSize; |
190 |
0 |
startY -= shadowSize; |
191 |
|
} |
192 |
|
} |
193 |
|
|
194 |
1 |
BufferedImage img = new BufferedImage( canvasWidth, canvasHeight, BufferedImage.TYPE_INT_ARGB); |
195 |
1 |
Graphics2D g2 = (Graphics2D) img.createGraphics(); |
196 |
|
|
197 |
1 |
float extent = 90; |
198 |
1 |
if (masking) { |
199 |
|
|
200 |
0 |
extent = 120; |
201 |
0 |
startAngle -= 20; |
202 |
|
} |
203 |
|
|
204 |
1 |
Arc2D.Float fillArea = new Arc2D.Float(startX, startY, width, height, startAngle, extent, Arc2D.PIE); |
205 |
|
|
206 |
|
|
207 |
1 |
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
208 |
1 |
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); |
209 |
|
|
210 |
1 |
g2.setColor(arcColor); |
211 |
1 |
g2.setComposite(AlphaComposite.Src); |
212 |
1 |
g2.fill(fillArea); |
213 |
|
|
214 |
1 |
g2.dispose(); |
215 |
|
|
216 |
1 |
return img; |
217 |
|
} |
218 |
|
|
219 |
|
BufferedImage drawArcShadow(BufferedImage mask, String color, String backgroundColor, int width, int height, |
220 |
|
String angle, int shadowWidth, float endOpacity) |
221 |
|
{ |
222 |
0 |
float startAngle = getStartAngle(angle); |
223 |
0 |
int shadowSize = shadowWidth * 2; |
224 |
0 |
int sampleY = 0; |
225 |
0 |
int sampleX = 0; |
226 |
0 |
int sampleWidth = width + shadowSize; |
227 |
0 |
int sampleHeight = height + shadowSize; |
228 |
|
|
229 |
0 |
if (startAngle == ANGLE_TOP_LEFT) { |
230 |
|
|
231 |
0 |
} else if (startAngle == ANGLE_BOTTOM_LEFT) { |
232 |
|
|
233 |
0 |
sampleWidth -= shadowSize; |
234 |
0 |
sampleHeight = height; |
235 |
|
|
236 |
0 |
sampleY += shadowSize; |
237 |
|
|
238 |
0 |
} else if (startAngle == ANGLE_TOP_RIGHT) { |
239 |
|
|
240 |
0 |
sampleWidth -= shadowSize; |
241 |
0 |
sampleHeight -= shadowSize; |
242 |
|
|
243 |
0 |
sampleX += shadowSize; |
244 |
0 |
} else if (startAngle == ANGLE_BOTTOM_RIGHT) { |
245 |
|
|
246 |
0 |
sampleWidth -= shadowSize; |
247 |
0 |
sampleHeight -= shadowSize; |
248 |
|
|
249 |
0 |
sampleX += shadowSize; |
250 |
0 |
sampleY += shadowSize; |
251 |
|
} |
252 |
|
|
253 |
0 |
ShadowRenderer shadowRenderer = new ShadowRenderer(shadowWidth, endOpacity, SHADOW_COLOR); |
254 |
0 |
BufferedImage dropShadow = shadowRenderer.createShadow(mask); |
255 |
|
|
256 |
|
|
257 |
|
|
258 |
0 |
BufferedImage img = new BufferedImage( (width * 4), (height * 4), BufferedImage.TYPE_INT_ARGB); |
259 |
0 |
Graphics2D g2 = (Graphics2D) img.createGraphics(); |
260 |
|
|
261 |
0 |
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
262 |
0 |
g2.setComposite(AlphaComposite.Src); |
263 |
0 |
g2.drawImage(dropShadow, 0, 0, null); |
264 |
|
|
265 |
0 |
g2.dispose(); |
266 |
|
|
267 |
0 |
return img.getSubimage(sampleX, sampleY, sampleWidth, sampleHeight); |
268 |
|
} |
269 |
|
|
270 |
|
public BufferedImage buildShadow(String color, String backgroundColor, int width, int height, |
271 |
|
float arcWidth, float arcHeight, |
272 |
|
int shadowWidth, float endOpacity) |
273 |
|
{ |
274 |
0 |
Color fgColor = color == null ? Color.WHITE : decodeColor(color); |
275 |
0 |
Color bgColor = backgroundColor == null ? null : decodeColor(backgroundColor); |
276 |
|
|
277 |
0 |
BufferedImage mask = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); |
278 |
0 |
Graphics2D g2 = mask.createGraphics(); |
279 |
|
|
280 |
0 |
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
281 |
|
|
282 |
0 |
RoundRectangle2D.Float fillArea = new RoundRectangle2D.Float(0, 0, width, height, arcHeight, arcWidth); |
283 |
0 |
g2.setColor(fgColor); |
284 |
0 |
g2.fill(fillArea); |
285 |
0 |
g2.dispose(); |
286 |
|
|
287 |
|
|
288 |
|
|
289 |
0 |
ShadowRenderer shadowRenderer = new ShadowRenderer(shadowWidth, endOpacity, SHADOW_COLOR); |
290 |
0 |
BufferedImage dropShadow = shadowRenderer.createShadow(mask); |
291 |
|
|
292 |
0 |
BufferedImage clipImg = new BufferedImage( width + (shadowWidth * 2), height + (shadowWidth * 2), BufferedImage.TYPE_INT_ARGB); |
293 |
0 |
g2 = clipImg.createGraphics(); |
294 |
|
|
295 |
0 |
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
296 |
0 |
g2.setComposite(AlphaComposite.Src); |
297 |
|
|
298 |
0 |
RoundRectangle2D.Float clip = new RoundRectangle2D.Float(0, 0, width + (shadowWidth * 2), height + (shadowWidth * 2), arcHeight, arcWidth); |
299 |
0 |
g2.setClip(clip); |
300 |
0 |
g2.drawImage(dropShadow, 0, 0, null); |
301 |
0 |
g2.dispose(); |
302 |
|
|
303 |
|
|
304 |
|
|
305 |
0 |
BufferedImage img = new BufferedImage( width + (shadowWidth * 2), height + (shadowWidth * 2), BufferedImage.TYPE_INT_ARGB); |
306 |
0 |
g2 = img.createGraphics(); |
307 |
0 |
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
308 |
|
|
309 |
0 |
if (bgColor != null) |
310 |
|
{ |
311 |
0 |
fillArea = new RoundRectangle2D.Float(0, 0, width + (shadowWidth * 2), height + (shadowWidth * 2), arcHeight, arcWidth); |
312 |
0 |
g2.setColor(bgColor); |
313 |
0 |
g2.fill(fillArea.getBounds2D()); |
314 |
|
} |
315 |
|
|
316 |
0 |
g2.drawImage(clipImg, 0, 0, null); |
317 |
|
|
318 |
0 |
if (fgColor != null) |
319 |
|
{ |
320 |
0 |
fillArea = new RoundRectangle2D.Float(0, 0, width, height, arcHeight, arcWidth); |
321 |
0 |
g2.setColor(fgColor); |
322 |
0 |
g2.fill(fillArea); |
323 |
|
} |
324 |
|
|
325 |
0 |
g2.dispose(); |
326 |
|
|
327 |
0 |
return convertType(img, BufferedImage.TYPE_INT_RGB); |
328 |
|
} |
329 |
|
|
330 |
|
public BufferedImage buildSideShadow(String side, int size, float opacity) |
331 |
|
throws Exception |
332 |
|
{ |
333 |
0 |
Defense.notNull(side, "side"); |
334 |
|
|
335 |
0 |
if (opacity <= 0) |
336 |
0 |
opacity = DEFAULT_OPACITY; |
337 |
|
|
338 |
0 |
int maskWidth = 0; |
339 |
0 |
int maskHeight = 0; |
340 |
0 |
int sampleY = 0; |
341 |
0 |
int sampleX = 0; |
342 |
0 |
int sampleWidth = 0; |
343 |
0 |
int sampleHeight = 0; |
344 |
|
|
345 |
0 |
if (LEFT.equals(side)) { |
346 |
|
|
347 |
0 |
maskWidth = size * 4; |
348 |
0 |
maskHeight = size * 4; |
349 |
0 |
sampleY = maskHeight / 2; |
350 |
0 |
sampleWidth = size * 2; |
351 |
0 |
sampleHeight = 2; |
352 |
0 |
} else if (RIGHT.equals(side)) { |
353 |
|
|
354 |
0 |
maskWidth = size * 4; |
355 |
0 |
maskHeight = size * 4; |
356 |
0 |
sampleY = maskHeight / 2; |
357 |
0 |
sampleX = maskWidth; |
358 |
0 |
sampleWidth = size * 2; |
359 |
0 |
sampleHeight = 2; |
360 |
0 |
} else if (BOTTOM.equals(side)) { |
361 |
|
|
362 |
0 |
maskWidth = size * 4; |
363 |
0 |
maskHeight = size * 4; |
364 |
0 |
sampleY = maskHeight; |
365 |
0 |
sampleX = maskWidth / 2; |
366 |
0 |
sampleWidth = 2; |
367 |
0 |
sampleHeight = size * 2; |
368 |
0 |
} else if (TOP.equals(side)) { |
369 |
|
|
370 |
0 |
maskWidth = size * 4; |
371 |
0 |
maskHeight = size * 4; |
372 |
0 |
sampleY = 0; |
373 |
0 |
sampleX = maskWidth / 2; |
374 |
0 |
sampleWidth = 2; |
375 |
0 |
sampleHeight = size * 2; |
376 |
|
} |
377 |
|
|
378 |
0 |
BufferedImage mask = new BufferedImage( maskWidth, maskHeight, BufferedImage.TYPE_INT_ARGB); |
379 |
0 |
Graphics2D g2 = (Graphics2D) mask.createGraphics(); |
380 |
|
|
381 |
0 |
g2.setColor(Color.white); |
382 |
0 |
g2.fillRect(0, 0, maskWidth, maskHeight); |
383 |
|
|
384 |
0 |
g2.dispose(); |
385 |
|
|
386 |
0 |
ShadowRenderer shadowRenderer = new ShadowRenderer(size, opacity, SHADOW_COLOR); |
387 |
0 |
BufferedImage dropShadow = shadowRenderer.createShadow(mask); |
388 |
|
|
389 |
0 |
BufferedImage render = new BufferedImage(maskWidth * 2, maskHeight * 2, BufferedImage.TYPE_INT_ARGB); |
390 |
0 |
g2 = (Graphics2D)render.createGraphics(); |
391 |
|
|
392 |
0 |
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
393 |
|
|
394 |
0 |
Rectangle2D.Float clip = new Rectangle2D.Float(sampleX, sampleY, sampleWidth, sampleHeight); |
395 |
|
|
396 |
0 |
g2.setColor(Color.white); |
397 |
0 |
g2.fill(clip); |
398 |
|
|
399 |
0 |
g2.drawImage(dropShadow, 0, 0, null); |
400 |
|
|
401 |
0 |
g2.dispose(); |
402 |
|
|
403 |
0 |
return render.getSubimage(sampleX, sampleY, sampleWidth, sampleHeight); |
404 |
|
} |
405 |
|
|
406 |
|
|
407 |
|
|
408 |
|
|
409 |
|
|
410 |
|
|
411 |
|
|
412 |
|
|
413 |
|
public float getStartAngle(String code) |
414 |
|
{ |
415 |
2 |
if (TOP_LEFT.equalsIgnoreCase(code)) |
416 |
0 |
return ANGLE_TOP_LEFT; |
417 |
2 |
if (TOP_RIGHT.equalsIgnoreCase(code)) |
418 |
2 |
return ANGLE_TOP_RIGHT; |
419 |
0 |
if (BOTTOM_LEFT.equalsIgnoreCase(code)) |
420 |
0 |
return ANGLE_BOTTOM_LEFT; |
421 |
0 |
if (BOTTOM_RIGHT.equalsIgnoreCase(code)) |
422 |
0 |
return ANGLE_BOTTOM_RIGHT; |
423 |
|
|
424 |
0 |
return ANGLE_TOP_RIGHT; |
425 |
|
} |
426 |
|
|
427 |
|
|
428 |
|
|
429 |
|
|
430 |
|
|
431 |
|
|
432 |
|
|
433 |
|
|
434 |
|
public Color decodeColor(String color) |
435 |
|
{ |
436 |
1 |
Color specColor = (Color) _cssSpecMap.get(color); |
437 |
1 |
if (specColor != null) |
438 |
0 |
return specColor; |
439 |
|
|
440 |
1 |
String hexColor = color.startsWith("0x") ? color : "0x" + color; |
441 |
|
|
442 |
1 |
return Color.decode(hexColor); |
443 |
|
} |
444 |
|
} |