1 /*
   2  *
   3  * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  *
   9  *   - Redistributions of source code must retain the above copyright
  10  *     notice, this list of conditions and the following disclaimer.
  11  *
  12  *   - Redistributions in binary form must reproduce the above copyright
  13  *     notice, this list of conditions and the following disclaimer in the
  14  *     documentation and/or other materials provided with the distribution.
  15  *
  16  *   - Neither the name of Oracle nor the names of its
  17  *     contributors may be used to endorse or promote products derived
  18  *     from this software without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  21  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31  */
  32 package java2d.demos.Clipping;
  33 
  34 
  35 import java.awt.*;
  36 import java.awt.event.*;
  37 import java.awt.geom.*;
  38 import java.awt.image.BufferedImage;
  39 import javax.swing.*;
  40 import java2d.AnimatingControlsSurface;
  41 import java2d.CustomControls;
  42 import static java.lang.Math.random;
  43 import static java.awt.Color.*;
  44 
  45 
  46 /**
  47  * Animated clipping of an image & composited shapes.
  48  */
  49 @SuppressWarnings("serial")
  50 public class ClipAnim extends AnimatingControlsSurface {
  51 
  52     private static Image dimg, cimg;
  53     static TexturePaint texturePaint;
  54 
  55     static {
  56         BufferedImage bi = new BufferedImage(5, 5, BufferedImage.TYPE_INT_RGB);
  57         Graphics2D big = bi.createGraphics();
  58         big.setBackground(YELLOW);
  59         big.clearRect(0, 0, 5, 5);
  60         big.setColor(RED);
  61         big.fillRect(0, 0, 3, 3);
  62         texturePaint = new TexturePaint(bi, new Rectangle(0, 0, 5, 5));
  63     }
  64     private AnimVal animval[] = new AnimVal[3];
  65     protected boolean doObjects = true;
  66     private Font originalFont = new Font(Font.SERIF, Font.PLAIN, 12);
  67     private Font font;
  68     private GradientPaint gradient;
  69     private int strX, strY;
  70     private int dukeX, dukeY, dukeWidth, dukeHeight;
  71 
  72     public ClipAnim() {
  73         cimg = getImage("clouds.jpg");
  74         dimg = getImage("duke.png");
  75         setBackground(WHITE);
  76         animval[0] = new AnimVal(true);
  77         animval[1] = new AnimVal(false);
  78         animval[2] = new AnimVal(false);
  79         setControls(new Component[] { new DemoControls(this) });
  80     }
  81 
  82     @Override
  83     public void reset(int w, int h) {
  84         for (AnimVal a : animval) {
  85             a.reset(w, h);
  86         }
  87         gradient = new GradientPaint(0, h / 2, RED, w * .4f, h * .9f, YELLOW);
  88         double scale = 0.4;
  89         dukeHeight = (int) (scale * h);
  90         dukeWidth = (int) (dimg.getWidth(this) * scale * h / dimg.getHeight(this));
  91         dukeX = (int) (w * .25 - dukeWidth / 2);
  92         dukeY = (int) (h * .25 - dukeHeight / 2);
  93         FontMetrics fm = getFontMetrics(originalFont);
  94         double sw = fm.stringWidth("CLIPPING");
  95         double sh = fm.getAscent() + fm.getDescent();
  96         double sx = (w / 2 - 30) / sw;
  97         double sy = (h / 2 - 30) / sh;
  98         AffineTransform Tx = AffineTransform.getScaleInstance(sx, sy);
  99         font = originalFont.deriveFont(Tx);
 100         fm = getFontMetrics(font);
 101         strX = (int) (w * .75 - fm.stringWidth("CLIPPING") / 2);
 102         strY = (int) (h * .72 + fm.getAscent() / 2);
 103     }
 104 
 105     @Override
 106     public void step(int w, int h) {
 107         for (AnimVal a : animval) {
 108             if (a.isSelected) {
 109                 a.step(w, h);
 110             }
 111         }
 112     }
 113 
 114     @Override
 115     public void render(int w, int h, Graphics2D g2) {
 116 
 117         GeneralPath p1 = new GeneralPath();
 118         GeneralPath p2 = new GeneralPath();
 119 
 120         for (AnimVal a : animval) {
 121             if (a.isSelected) {
 122                 double x = a.x;
 123                 double y = a.y;
 124                 double ew = a.ew;
 125                 double eh = a.eh;
 126                 p1.append(new Ellipse2D.Double(x, y, ew, eh), false);
 127                 p2.append(new Rectangle2D.Double(x + 5, y + 5, ew - 10, eh - 10),
 128                         false);
 129             }
 130         }
 131         if (animval[0].isSelected || animval[1].isSelected
 132                 || animval[2].isSelected) {
 133             g2.setClip(p1);
 134             g2.clip(p2);
 135         }
 136 
 137         if (doObjects) {
 138             int w2 = w / 2;
 139             int h2 = h / 2;
 140             g2.drawImage(cimg, 0, 0, w2, h2, null);
 141             g2.drawImage(dimg, dukeX, dukeY, dukeWidth, dukeHeight, null);
 142 
 143             g2.setPaint(texturePaint);
 144             g2.fillRect(w2, 0, w2, h2);
 145 
 146             g2.setPaint(gradient);
 147             g2.fillRect(0, h2, w2, h2);
 148 
 149             g2.setColor(LIGHT_GRAY);
 150             g2.fillRect(w2, h2, w2, h2);
 151             g2.setColor(RED);
 152             g2.drawOval(w2, h2, w2 - 1, h2 - 1);
 153             g2.setFont(font);
 154             g2.drawString("CLIPPING", strX, strY);
 155         } else {
 156             g2.setColor(LIGHT_GRAY);
 157             g2.fillRect(0, 0, w, h);
 158         }
 159     }
 160 
 161     public static void main(String argv[]) {
 162         createDemoFrame(new ClipAnim());
 163     }
 164 
 165 
 166     public class AnimVal {
 167 
 168         double ix = 5.0;
 169         double iy = 3.0;
 170         double iw = 5.0;
 171         double ih = 3.0;
 172         double x, y;
 173         double ew, eh;   // ellipse width & height
 174         boolean isSelected;
 175 
 176         public AnimVal(boolean isSelected) {
 177             this.isSelected = isSelected;
 178         }
 179 
 180         public void step(int w, int h) {
 181             x += ix;
 182             y += iy;
 183             ew += iw;
 184             eh += ih;
 185 
 186             if (ew > w / 2) {
 187                 ew = w / 2;
 188                 iw = random() * -w / 16 - 1;
 189             }
 190             if (ew < w / 8) {
 191                 ew = w / 8;
 192                 iw = random() * w / 16 + 1;
 193             }
 194             if (eh > h / 2) {
 195                 eh = h / 2;
 196                 ih = random() * -h / 16 - 1;
 197             }
 198             if (eh < h / 8) {
 199                 eh = h / 8;
 200                 ih = random() * h / 16 + 1;
 201             }
 202 
 203             if ((x + ew) > w) {
 204                 x = (w - ew) - 1;
 205                 ix = random() * -w / 32 - 1;
 206             }
 207             if ((y + eh) > h) {
 208                 y = (h - eh) - 2;
 209                 iy = random() * -h / 32 - 1;
 210             }
 211             if (x < 0) {
 212                 x = 2;
 213                 ix = random() * w / 32 + 1;
 214             }
 215             if (y < 0) {
 216                 y = 2;
 217                 iy = random() * h / 32 + 1;
 218             }
 219         }
 220 
 221         public void reset(int w, int h) {
 222             x = random() * w;
 223             y = random() * h;
 224             ew = (random() * w) / 2;
 225             eh = (random() * h) / 2;
 226         }
 227     }
 228 
 229 
 230     static final class DemoControls extends CustomControls implements
 231             ActionListener {
 232 
 233         ClipAnim demo;
 234         JToolBar toolbar;
 235 
 236         public DemoControls(ClipAnim demo) {
 237             super(demo.name);
 238             this.demo = demo;
 239             add(toolbar = new JToolBar());
 240             toolbar.setFloatable(false);
 241             addTool("Objects", true);
 242             addTool("Clip1", true);
 243             addTool("Clip2", false);
 244             addTool("Clip3", false);
 245         }
 246 
 247         public void addTool(String str, boolean state) {
 248             JToggleButton b =
 249                     (JToggleButton) toolbar.add(new JToggleButton(str));
 250             b.setFocusPainted(false);
 251             b.setSelected(state);
 252             b.addActionListener(this);
 253             int width = b.getPreferredSize().width;
 254             Dimension prefSize = new Dimension(width, 21);
 255             b.setPreferredSize(prefSize);
 256             b.setMaximumSize(prefSize);
 257             b.setMinimumSize(prefSize);
 258         }
 259 
 260         @Override
 261         public void actionPerformed(ActionEvent e) {
 262             JToggleButton b = (JToggleButton) e.getSource();
 263             if (b.getText().equals("Objects")) {
 264                 demo.doObjects = b.isSelected();
 265             } else if (b.getText().equals("Clip1")) {
 266                 demo.animval[0].isSelected = b.isSelected();
 267             } else if (b.getText().equals("Clip2")) {
 268                 demo.animval[1].isSelected = b.isSelected();
 269             } else if (b.getText().equals("Clip3")) {
 270                 demo.animval[2].isSelected = b.isSelected();
 271             }
 272             if (!demo.animating.running()) {
 273                 demo.repaint();
 274             }
 275         }
 276 
 277         @Override
 278         public Dimension getPreferredSize() {
 279             return new Dimension(200, 40);
 280         }
 281 
 282         @Override
 283         public void run() {
 284             try {
 285                 Thread.sleep(5000);
 286             } catch (InterruptedException e) {
 287                 return;
 288             }
 289             ((AbstractButton) toolbar.getComponentAtIndex(2)).doClick();
 290             try {
 291                 Thread.sleep(5000);
 292             } catch (InterruptedException e) {
 293                 return;
 294             }
 295             if (getSize().width > 400) {
 296                 ((AbstractButton) toolbar.getComponentAtIndex(3)).doClick();
 297             }
 298             thread = null;
 299         }
 300     } // End DemoControls
 301 } // End ClipAnim
 302