1 /* 2 * 3 * Copyright (c) 2007, 2018, 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; gi.setPaint(new GradientPaint(0, 0, oc, w * .35f, h * .35f, ic))99 gi.setPaint(new GradientPaint(0, 0, oc, w * .35f, h * .35f, ic)); 100 gi.fillRect(0, 0, w / 2, h / 2); gi.setPaint(new GradientPaint(w, 0, oc, w * .65f, h * .35f, ic))101 gi.setPaint(new GradientPaint(w, 0, oc, w * .65f, h * .35f, ic)); 102 gi.fillRect(w / 2, 0, w / 2, h / 2); gi.setPaint(new GradientPaint(0, h, oc, w * .35f, h * .65f, ic))103 gi.setPaint(new GradientPaint(0, h, oc, w * .35f, h * .65f, ic)); 104 gi.fillRect(0, h / 2, w / 2, h / 2); gi.setPaint(new GradientPaint(w, h, oc, w * .65f, h * .65f, ic))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 FadeAnim()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 setImages(int num)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 setStrings(int num)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 setShapes(int num)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 reset(int w, int h)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 step(int w, int h)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 render(int w, int h, Graphics2D g2)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 main(String[] argv)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 TextData(String str, Font font, Component cmp)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 ObjectData(Object object, Paint paint)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 getRandomXY(int w, int h)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 487