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.Composite;
  33 
  34 
  35 import static java.awt.Color.BLACK;
  36 import static java.awt.Color.BLUE;
  37 import static java.awt.Color.CYAN;
  38 import static java.awt.Color.GREEN;
  39 import static java.awt.Color.LIGHT_GRAY;
  40 import static java.awt.Color.MAGENTA;
  41 import static java.awt.Color.ORANGE;
  42 import static java.awt.Color.PINK;
  43 import static java.awt.Color.RED;
  44 import static java.awt.Color.WHITE;
  45 import static java.awt.Color.YELLOW;
  46 import java.awt.AlphaComposite;
  47 import java.awt.BasicStroke;
  48 import java.awt.BorderLayout;
  49 import java.awt.Color;
  50 import java.awt.Component;
  51 import java.awt.Dimension;
  52 import java.awt.Font;
  53 import java.awt.FontMetrics;
  54 import java.awt.GradientPaint;
  55 import java.awt.Graphics2D;
  56 import java.awt.Image;
  57 import java.awt.Paint;
  58 import java.awt.Rectangle;
  59 import java.awt.Shape;
  60 import java.awt.TexturePaint;
  61 import java.awt.geom.Arc2D;
  62 import java.awt.geom.CubicCurve2D;
  63 import java.awt.geom.Ellipse2D;
  64 import java.awt.geom.GeneralPath;
  65 import java.awt.geom.QuadCurve2D;
  66 import java.awt.geom.Rectangle2D;
  67 import java.awt.geom.RoundRectangle2D;
  68 import java.awt.image.BufferedImage;
  69 import java.util.ArrayList;
  70 import java.util.List;
  71 import java2d.AnimatingControlsSurface;
  72 import java2d.CustomControls;
  73 import javax.swing.Box;
  74 import javax.swing.BoxLayout;
  75 import javax.swing.JSlider;
  76 import javax.swing.JToolBar;
  77 import javax.swing.SwingConstants;
  78 import javax.swing.border.EtchedBorder;
  79 import javax.swing.border.TitledBorder;
  80 import javax.swing.event.ChangeEvent;
  81 import javax.swing.event.ChangeListener;
  82 
  83 
  84 /**
  85  * Animation of compositing shapes, text and images fading in and out.
  86  */
  87 @SuppressWarnings("serial")
  88 public final class FadeAnim extends AnimatingControlsSurface {
  89 
  90     private static final TexturePaint texturePaint;
  91 
  92     static {
  93         int w = 10;
  94         int h = 10;
  95         BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
  96         Graphics2D gi = bi.createGraphics();
  97         Color oc = BLUE;
  98         Color ic = GREEN;
  99         gi.setPaint(new GradientPaint(0, 0, oc, w * .35f, h * .35f, ic));
 100         gi.fillRect(0, 0, w / 2, h / 2);
 101         gi.setPaint(new GradientPaint(w, 0, oc, w * .65f, h * .35f, ic));
 102         gi.fillRect(w / 2, 0, w / 2, h / 2);
 103         gi.setPaint(new GradientPaint(0, h, oc, w * .35f, h * .65f, ic));
 104         gi.fillRect(0, h / 2, w / 2, h / 2);
 105         gi.setPaint(new GradientPaint(w, h, oc, w * .65f, h * .65f, ic));
 106         gi.fillRect(w / 2, h / 2, w / 2, h / 2);
 107         texturePaint = new TexturePaint(bi, new Rectangle(0, 0, w, h));
 108     }
 109     private static BasicStroke bs = new BasicStroke(6);
 110     private static Font fonts[] = {
 111         new Font(Font.SERIF, Font.PLAIN, 64),
 112         new Font(Font.SERIF, Font.BOLD | Font.ITALIC, 24),
 113         new Font(Font.MONOSPACED, Font.BOLD, 36),
 114         new Font(Font.SANS_SERIF, Font.BOLD | Font.ITALIC, 48),
 115         new Font(Font.SANS_SERIF, Font.PLAIN, 52) };
 116     private static String strings[] = {
 117         "Alpha", "Composite", "Src", "SrcOver",
 118         "SrcIn", "SrcOut", "Clear", "DstOver", "DstIn" };
 119     private static String imgs[] = {
 120         "jumptojavastrip.png", "duke.png", "star7.png" };
 121     private static Paint paints[] = {
 122         RED, BLUE, GREEN, MAGENTA,
 123         ORANGE, PINK, CYAN, texturePaint,
 124         YELLOW, LIGHT_GRAY, WHITE };
 125     private List<ObjectData> objects = new ArrayList<ObjectData>(20);
 126     private int numShapes, numStrings, numImages;
 127 
 128     public FadeAnim() {
 129         setBackground(BLACK);
 130         setStrings(2);
 131         setImages(3);
 132         setShapes(8);
 133         setControls(new Component[] { new DemoControls(this) });
 134         setConstraints(new String[] { BorderLayout.EAST });
 135     }
 136 
 137     public void setImages(int num) {
 138 
 139         if (num < numImages) {
 140             List<ObjectData> images = new ArrayList<ObjectData>(objects.size());
 141             for (ObjectData obj : objects) {
 142                 if (obj.object instanceof Image) {
 143                     images.add(obj);
 144                 }
 145             }
 146             objects.removeAll(images.subList(num, images.size()));
 147         } else {
 148             Dimension d = getSize();
 149             for (int i = numImages; i < num; i++) {
 150                 Object obj = getImage(imgs[i % imgs.length]);
 151                 if (imgs[i % imgs.length].equals("jumptojavastrip.png")) {
 152                     int iw = ((Image) obj).getWidth(null);
 153                     int ih = ((Image) obj).getHeight(null);
 154                     BufferedImage bimage = new BufferedImage(iw, ih,
 155                             BufferedImage.TYPE_INT_RGB);
 156                     bimage.createGraphics().drawImage((Image) obj, 0, 0, null);
 157                     obj = bimage;
 158                 }
 159                 ObjectData od = new ObjectData(obj, BLACK);
 160                 od.reset(d.width, d.height);
 161                 objects.add(od);
 162             }
 163         }
 164         numImages = num;
 165     }
 166 
 167     public void setStrings(int num) {
 168 
 169         if (num < numStrings) {
 170             List<ObjectData> textDatas = new ArrayList<ObjectData>(
 171                     objects.size());
 172             //for (int i = 0; i < objects.size(); i++) {
 173             for (ObjectData obj : objects) {
 174                 if (obj.object instanceof TextData) {
 175                     textDatas.add(obj);
 176                 }
 177             }
 178             objects.removeAll(textDatas.subList(num, textDatas.size()));
 179         } else {
 180             Dimension d = getSize();
 181             for (int i = numStrings; i < num; i++) {
 182                 int j = i % fonts.length;
 183                 int k = i % strings.length;
 184                 Object obj = new TextData(strings[k], fonts[j], this);
 185                 ObjectData od = new ObjectData(obj, paints[i % paints.length]);
 186                 od.reset(d.width, d.height);
 187                 objects.add(od);
 188             }
 189         }
 190         numStrings = num;
 191     }
 192 
 193     public void setShapes(int num) {
 194 
 195         if (num < numShapes) {
 196             List<ObjectData> shapes = new ArrayList<ObjectData>(objects.size());
 197             //for (int i = 0; i < objects.size(); i++) {
 198             for (ObjectData obj : objects) {
 199                 if (obj.object instanceof Shape) {
 200                     shapes.add(obj);
 201                 }
 202             }
 203             objects.removeAll(shapes.subList(num, shapes.size()));
 204         } else {
 205             Dimension d = getSize();
 206             for (int i = numShapes; i < num; i++) {
 207                 Object obj = null;
 208                 switch (i % 7) {
 209                     case 0:
 210                         obj = new GeneralPath();
 211                         break;
 212                     case 1:
 213                         obj = new Rectangle2D.Double();
 214                         break;
 215                     case 2:
 216                         obj = new Ellipse2D.Double();
 217                         break;
 218                     case 3:
 219                         obj = new Arc2D.Double();
 220                         break;
 221                     case 4:
 222                         obj = new RoundRectangle2D.Double();
 223                         break;
 224                     case 5:
 225                         obj = new CubicCurve2D.Double();
 226                         break;
 227                     case 6:
 228                         obj = new QuadCurve2D.Double();
 229                         break;
 230                 }
 231                 ObjectData od = new ObjectData(obj, paints[i % paints.length]);
 232                 od.reset(d.width, d.height);
 233                 objects.add(od);
 234             }
 235         }
 236         numShapes = num;
 237     }
 238 
 239     @Override
 240     public void reset(int w, int h) {
 241         for (int i = 0; i < objects.size(); i++) {
 242             objects.get(i).reset(w, h);
 243         }
 244     }
 245 
 246     @Override
 247     public void step(int w, int h) {
 248         for (int i = 0; i < objects.size(); i++) {
 249             objects.get(i).step(w, h);
 250         }
 251     }
 252 
 253     @Override
 254     public void render(int w, int h, Graphics2D g2) {
 255         for (int i = 0; i < objects.size(); i++) {
 256             ObjectData od = objects.get(i);
 257             AlphaComposite ac = AlphaComposite.getInstance(
 258                     AlphaComposite.SRC_OVER, od.alpha);
 259             g2.setComposite(ac);
 260             g2.setPaint(od.paint);
 261             g2.translate(od.x, od.y);
 262 
 263             if (od.object instanceof Image) {
 264                 g2.drawImage((Image) od.object, 0, 0, this);
 265             } else if (od.object instanceof TextData) {
 266                 g2.setFont(((TextData) od.object).font);
 267                 g2.drawString(((TextData) od.object).string, 0, 0);
 268             } else if (od.object instanceof QuadCurve2D
 269                     || od.object instanceof CubicCurve2D) {
 270                 g2.setStroke(bs);
 271                 g2.draw((Shape) od.object);
 272             } else if (od.object instanceof Shape) {
 273                 g2.fill((Shape) od.object);
 274             }
 275             g2.translate(-od.x, -od.y);
 276         }
 277     }
 278 
 279     public static void main(String argv[]) {
 280         createDemoFrame(new FadeAnim());
 281     }
 282 
 283 
 284     static class TextData extends Object {
 285 
 286         public String string;
 287         public Font font;
 288         public int width, height;
 289 
 290         public TextData(String str, Font font, Component cmp) {
 291             string = str;
 292             this.font = font;
 293             FontMetrics fm = cmp.getFontMetrics(font);
 294             width = fm.stringWidth(str);
 295             height = fm.getHeight();
 296         }
 297     }
 298 
 299 
 300     static class ObjectData extends Object {
 301 
 302         final int UP = 0;
 303         final int DOWN = 1;
 304         Object object;
 305         BufferedImage bimg;
 306         Paint paint;
 307         double x, y;
 308         float alpha;
 309         int alphaDirection;
 310         int imgX;
 311 
 312         public ObjectData(Object object, Paint paint) {
 313             this.object = object;
 314             this.paint = paint;
 315             if (object instanceof BufferedImage) {
 316                 bimg = (BufferedImage) object;
 317                 this.object = bimg.getSubimage(0, 0, 80, 80);
 318             }
 319             getRandomXY(300, 250);
 320             alpha = (float) Math.random();
 321             alphaDirection = Math.random() > 0.5 ? UP : DOWN;
 322         }
 323 
 324         private void getRandomXY(int w, int h) {
 325             if (object instanceof TextData) {
 326                 x = Math.random() * (w - ((TextData) object).width);
 327                 y = Math.random() * h;
 328                 y = y < ((TextData) object).height ? ((TextData) object).height
 329                         : y;
 330             } else if (object instanceof Image) {
 331                 x = Math.random() * (w - ((Image) object).getWidth(null));
 332                 y = Math.random() * (h - ((Image) object).getHeight(null));
 333             } else if (object instanceof Shape) {
 334                 Rectangle bounds = ((Shape) object).getBounds();
 335                 x = Math.random() * (w - bounds.width);
 336                 y = Math.random() * (h - bounds.height);
 337             }
 338         }
 339 
 340         public void reset(int w, int h) {
 341             getRandomXY(w, h);
 342             double ww = 20 + Math.random() * ((w == 0 ? 400 : w) / 4);
 343             double hh = 20 + Math.random() * ((h == 0 ? 300 : h) / 4);
 344             if (object instanceof Ellipse2D) {
 345                 ((Ellipse2D) object).setFrame(0, 0, ww, hh);
 346             } else if (object instanceof Rectangle2D) {
 347                 ((Rectangle2D) object).setRect(0, 0, ww, ww);
 348             } else if (object instanceof RoundRectangle2D) {
 349                 ((RoundRectangle2D) object).setRoundRect(0, 0, hh, hh, 20, 20);
 350             } else if (object instanceof Arc2D) {
 351                 ((Arc2D) object).setArc(0, 0, hh, hh, 45, 270, Arc2D.PIE);
 352             } else if (object instanceof QuadCurve2D) {
 353                 ((QuadCurve2D) object).setCurve(0, 0, w * .2, h * .4, w * .4, 0);
 354             } else if (object instanceof CubicCurve2D) {
 355                 ((CubicCurve2D) object).setCurve(0, 0, 30, -60, 60, 60, 90, 0);
 356             } else if (object instanceof GeneralPath) {
 357                 GeneralPath p = new GeneralPath();
 358                 float size = (float) ww;
 359                 p.moveTo(-size / 2.0f, -size / 8.0f);
 360                 p.lineTo(+size / 2.0f, -size / 8.0f);
 361                 p.lineTo(-size / 4.0f, +size / 2.0f);
 362                 p.lineTo(+0.0f, -size / 2.0f);
 363                 p.lineTo(+size / 4.0f, +size / 2.0f);
 364                 p.closePath();
 365                 object = p;
 366             }
 367         }
 368 
 369         public void step(int w, int h) {
 370             if (object instanceof BufferedImage) {
 371                 if ((imgX += 80) == 800) {
 372                     imgX = 0;
 373                 }
 374                 object = bimg.getSubimage(imgX, 0, 80, 80);
 375             }
 376             if (alphaDirection == UP) {
 377                 if ((alpha += 0.05) > .99) {
 378                     alphaDirection = DOWN;
 379                     alpha = 1.0f;
 380                 }
 381             } else if (alphaDirection == DOWN) {
 382                 if ((alpha -= .05) < 0.01) {
 383                     alphaDirection = UP;
 384                     alpha = 0;
 385                     getRandomXY(w, h);
 386                 }
 387             }
 388         }
 389     }
 390 
 391 
 392     static class DemoControls extends CustomControls implements ChangeListener {
 393 
 394         FadeAnim demo;
 395         JSlider shapeSlider, stringSlider, imageSlider;
 396         Font font = new Font(Font.SERIF, Font.BOLD, 10);
 397 
 398         @SuppressWarnings("LeakingThisInConstructor")
 399         public DemoControls(FadeAnim demo) {
 400             super(demo.name);
 401             this.demo = demo;
 402             setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
 403             add(Box.createVerticalStrut(5));
 404 
 405             JToolBar toolbar = new JToolBar(SwingConstants.VERTICAL);
 406             toolbar.setFloatable(false);
 407             shapeSlider = new JSlider(SwingConstants.HORIZONTAL, 0, 20,
 408                     demo.numShapes);
 409             shapeSlider.addChangeListener(this);
 410             TitledBorder tb = new TitledBorder(new EtchedBorder());
 411             tb.setTitleFont(font);
 412             tb.setTitle(String.valueOf(demo.numShapes) + " Shapes");
 413             shapeSlider.setBorder(tb);
 414             shapeSlider.setPreferredSize(new Dimension(80, 45));
 415             shapeSlider.setOpaque(true);
 416             toolbar.addSeparator();
 417             toolbar.add(shapeSlider);
 418             toolbar.addSeparator();
 419 
 420             stringSlider = new JSlider(SwingConstants.HORIZONTAL, 0, 10,
 421                     demo.numStrings);
 422             stringSlider.addChangeListener(this);
 423             tb = new TitledBorder(new EtchedBorder());
 424             tb.setTitleFont(font);
 425             tb.setTitle(String.valueOf(demo.numStrings) + " Strings");
 426             stringSlider.setBorder(tb);
 427             stringSlider.setPreferredSize(new Dimension(80, 45));
 428             stringSlider.setOpaque(true);
 429             toolbar.add(stringSlider);
 430             toolbar.addSeparator();
 431 
 432             imageSlider = new JSlider(SwingConstants.HORIZONTAL, 0, 10,
 433                     demo.numImages);
 434             imageSlider.addChangeListener(this);
 435             tb = new TitledBorder(new EtchedBorder());
 436             tb.setTitleFont(font);
 437             tb.setTitle(String.valueOf(demo.numImages) + " Images");
 438             imageSlider.setBorder(tb);
 439             imageSlider.setPreferredSize(new Dimension(80, 45));
 440             imageSlider.setOpaque(true);
 441             toolbar.add(imageSlider);
 442             toolbar.addSeparator();
 443 
 444             add(toolbar);
 445         }
 446 
 447         @Override
 448         public void stateChanged(ChangeEvent e) {
 449             JSlider slider = (JSlider) e.getSource();
 450             int value = slider.getValue();
 451             TitledBorder tb = (TitledBorder) slider.getBorder();
 452             if (slider.equals(shapeSlider)) {
 453                 tb.setTitle(String.valueOf(value) + " Shapes");
 454                 demo.setShapes(value);
 455             } else if (slider.equals(stringSlider)) {
 456                 tb.setTitle(String.valueOf(value) + " Strings");
 457                 demo.setStrings(value);
 458             } else if (slider.equals(imageSlider)) {
 459                 tb.setTitle(String.valueOf(value) + " Images");
 460                 demo.setImages(value);
 461             }
 462             slider.repaint();
 463             if (!demo.animating.running()) {
 464                 demo.repaint();
 465             }
 466         }
 467 
 468         @Override
 469         public Dimension getPreferredSize() {
 470             return new Dimension(80, 0);
 471         }
 472 
 473         @Override
 474         public void run() {
 475             try {
 476                 Thread.sleep(999);
 477             } catch (InterruptedException e) {
 478                 return;
 479             }
 480             shapeSlider.setValue((int) (Math.random() * 5));
 481             stringSlider.setValue(10);
 482             thread = null;
 483         }
 484     } // End DemoControls
 485 } // End FadeAnim
 486