Coverage Report - org.apache.tapestry.contrib.services.impl.RoundedCornerGenerator
 
Classes in this File Line Coverage Branch Coverage Complexity
RoundedCornerGenerator
0%
0/238
0%
0/66
5.875
 
 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  
  * Class responsible for bulk of java2d manipulation work when used in the {@link RoundedCornerService}. 
 16  
  */
 17  0
 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  
     // css2 color spec - http://www.w3.org/TR/REC-CSS2/syndata.html#color-units
 30  0
     private static final Map _cssSpecMap = new HashMap();
 31  
 
 32  
     static {
 33  0
         _cssSpecMap.put("aqua", new Color(0,255,255));
 34  0
         _cssSpecMap.put("black", Color.black);
 35  0
         _cssSpecMap.put("blue", Color.blue);
 36  0
         _cssSpecMap.put("fuchsia", new Color(255,0,255));
 37  0
         _cssSpecMap.put("gray", Color.gray);
 38  0
         _cssSpecMap.put("green", Color.green);
 39  0
         _cssSpecMap.put("lime", new Color(0,255,0));
 40  0
         _cssSpecMap.put("maroon", new Color(128,0,0));
 41  0
         _cssSpecMap.put("navy", new Color(0,0,128));
 42  0
         _cssSpecMap.put("olive", new Color(128,128,0));
 43  0
         _cssSpecMap.put("purple", new Color(128,0,128));
 44  0
         _cssSpecMap.put("red", Color.red);
 45  0
         _cssSpecMap.put("silver", new Color(192,192,192));
 46  0
         _cssSpecMap.put("teal", new Color(0,128,128));
 47  0
         _cssSpecMap.put("white", Color.white);
 48  0
         _cssSpecMap.put("yellow", Color.yellow);
 49  
 
 50  0
         ImageIO.setUseCache(false);
 51  
     }
 52  
 
 53  0
     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  0
         width = width * 2;
 67  0
         height = height * 2;
 68  0
         float startAngle = getStartAngle(angle);
 69  0
         Color bgColor = backgroundColor == null ? null : decodeColor(backgroundColor);
 70  
 
 71  0
         if (shadowWidth <= 0) {
 72  
 
 73  0
             BufferedImage arc = drawArc(color, width, height, angle, false, -1);
 74  0
             BufferedImage ret = arc;
 75  
 
 76  0
             Arc2D.Float arcArea = new Arc2D.Float(0, 0, width, height, startAngle, 90, Arc2D.PIE);
 77  0
             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  0
             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  0
         Color arcColor = decodeColor(color);
 158  0
         float startAngle = getStartAngle(angle);
 159  
 
 160  0
         int canvasWidth = width;
 161  0
         int canvasHeight = height;
 162  0
         float startX = 0;
 163  0
         float startY = 0;
 164  0
         int shadowSize = 0;
 165  
 
 166  0
         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  0
         BufferedImage img = new BufferedImage( canvasWidth, canvasHeight, BufferedImage.TYPE_INT_ARGB);
 195  0
         Graphics2D g2 = (Graphics2D) img.createGraphics();
 196  
 
 197  0
         float extent = 90;
 198  0
         if (masking) {
 199  
 
 200  0
             extent = 120;
 201  0
             startAngle -= 20;
 202  
         }
 203  
 
 204  0
         Arc2D.Float fillArea = new Arc2D.Float(startX, startY, width, height, startAngle, extent, Arc2D.PIE);
 205  
 
 206  
         // draw arc
 207  0
         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
 208  0
         g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
 209  
 
 210  0
         g2.setColor(arcColor);
 211  0
         g2.setComposite(AlphaComposite.Src);
 212  0
         g2.fill(fillArea);
 213  
 
 214  0
         g2.dispose();
 215  
 
 216  0
         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  
         // draw shadow arc
 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  
         // clip shadow
 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  
         // draw everything
 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  
      * Matches the incoming string against one of the constants defined; tl, tr, bl, br.
 408  
      *
 409  
      * @param code The code for the angle of the arc to generate, if no match is found the default is
 410  
      *          {@link #TOP_RIGHT} - or 0 degrees.
 411  
      * @return The pre-defined 90 degree angle starting degree point.
 412  
      */
 413  
     public float getStartAngle(String code)
 414  
     {
 415  0
         if (TOP_LEFT.equalsIgnoreCase(code))
 416  0
             return ANGLE_TOP_LEFT;
 417  0
         if (TOP_RIGHT.equalsIgnoreCase(code))
 418  0
             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  
      * Decodes the specified input color string into a compatible awt color object. Valid inputs
 429  
      * are any in the css2 color spec or hex strings.
 430  
      *
 431  
      * @param color The color to match.
 432  
      * @return The decoded color object, may be black if decoding fails.
 433  
      */
 434  
     public Color decodeColor(String color)
 435  
     {
 436  0
         Color specColor = (Color) _cssSpecMap.get(color);
 437  0
         if (specColor != null)
 438  0
             return specColor;
 439  
 
 440  0
         String hexColor = color.startsWith("0x") ? color : "0x" + color;
 441  
 
 442  0
         return Color.decode(hexColor);
 443  
     }
 444  
 }