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.Paint; 33 34 35 import static java.awt.Color.BLACK; 36 import static java.awt.Color.GRAY; 37 import static java.awt.Color.LIGHT_GRAY; 38 import static java.awt.Color.WHITE; 39 import java.awt.Color; 40 import java.awt.Component; 41 import java.awt.Dimension; 42 import java.awt.Graphics; 43 import java.awt.Graphics2D; 44 import java.awt.Image; 45 import java.awt.Rectangle; 46 import java.awt.TexturePaint; 47 import java.awt.event.ActionEvent; 48 import java.awt.event.ActionListener; 49 import java.awt.image.BufferedImage; 50 import java2d.AnimatingControlsSurface; 51 import java2d.CustomControls; 52 import javax.swing.AbstractButton; 53 import javax.swing.Icon; 54 import javax.swing.JComboBox; 55 import javax.swing.JMenu; 56 import javax.swing.JMenuBar; 57 import javax.swing.JMenuItem; 58 import javax.swing.JToggleButton; 59 import javax.swing.JToolBar; 60 import javax.swing.plaf.metal.MetalBorders.ButtonBorder; 61 62 63 /** 64 * TexturePaint animation with controls for transformations. 65 */ 66 @SuppressWarnings("serial") 67 public final class TextureAnim extends AnimatingControlsSurface { 68 69 public static final Color colorblend = new Color(0f, 0f, 1f, .5f); 70 protected static BufferedImage textureImg; 71 protected int bNum; 72 protected int tilesize; 73 private boolean newtexture; 74 private TexturePaint texturePaint; 75 private Rectangle tilerect; 76 private boolean bouncesize = false; 77 private boolean bouncerect = true; 78 private boolean rotate = false; 79 private boolean shearx = false; 80 private boolean sheary = false; 81 private boolean showanchor = true; 82 private AnimVal w, h, x, y, rot, shx, shy; 83 private static Image[] img = new Image[2]; 84 85 public TextureAnim() { 86 img[0] = getImage("duke.gif"); // 8 bit gif 87 img[1] = getImage("duke.png"); // 24 bit png 88 89 textureImg = makeImage(32, 0); 90 tilesize = textureImg.getWidth(); 91 w = new AnimVal(0, 200, 3, 10, tilesize); 92 h = new AnimVal(0, 200, 3, 10, tilesize); 93 x = new AnimVal(0, 200, 3, 10, 0); 94 y = new AnimVal(0, 200, 3, 10, 0); 95 rot = new AnimVal(-360, 360, 5, 15, 0); 96 shx = new AnimVal(-50, 50, 3, 10, 0); 97 shy = new AnimVal(-50, 50, 3, 10, 0); 98 tilerect = new Rectangle(x.getInt(), y.getInt(), 99 w.getInt(), h.getInt()); 100 texturePaint = new TexturePaint(textureImg, tilerect); 101 setControls(new Component[] { new DemoControls(this) }); 102 } 103 104 protected BufferedImage makeImage(int size, int num) { 105 newtexture = true; 106 switch (bNum = num) { 107 case 0: 108 return makeRGBImage(size); 109 case 1: 110 return makeGIFImage(size); 111 case 2: 112 return makePNGImage(size); 113 } 114 return null; 115 } 116 117 private BufferedImage makeRGBImage(int size) { 118 BufferedImage bi = new BufferedImage(size, size, 119 BufferedImage.TYPE_INT_RGB); 120 Graphics2D big = bi.createGraphics(); 121 big.setColor(WHITE); 122 big.fillRect(0, 0, size, size); 123 for (int j = 0; j < size; j++) { 124 float RED = j / (float) size; 125 for (int i = 0; i < size; i++) { 126 float GREEN = i / (float) size; 127 big.setColor(new Color(1.0f - RED, 1.0f - GREEN, 0.0f, 1.0f)); 128 big.drawLine(i, j, i, j); 129 } 130 } 131 return bi; 132 } 133 134 private BufferedImage makeGIFImage(int d) { 135 BufferedImage bi = new BufferedImage(d, d, BufferedImage.TYPE_INT_RGB); 136 Graphics2D big = bi.createGraphics(); 137 big.drawImage(img[0], 0, 0, d, d, new Color(204, 204, 255), null); 138 return bi; 139 } 140 141 private BufferedImage makePNGImage(int d) { 142 BufferedImage bi = new BufferedImage(d, d, BufferedImage.TYPE_INT_RGB); 143 Graphics2D big = bi.createGraphics(); 144 big.drawImage(img[1], 0, 0, d, d, LIGHT_GRAY, null); 145 return bi; 146 } 147 148 @Override 149 public void reset(int width, int height) { 150 x.newlimits(-width / 4, width / 4 - w.getInt()); 151 y.newlimits(-height / 4, height / 4 - h.getInt()); 152 } 153 154 @Override 155 public void step(int width, int height) { 156 if (tilesize != textureImg.getWidth()) { 157 tilesize = textureImg.getWidth(); 158 } 159 if (bouncesize) { 160 w.anim(); 161 h.anim(); 162 x.newlimits(-width / 4, width / 4 - w.getInt()); 163 y.newlimits(-height / 4, height / 4 - h.getInt()); 164 } else { 165 if (w.getInt() != tilesize) { 166 w.set(tilesize); 167 x.newlimits(-width / 4, width / 4 - w.getInt()); 168 } 169 if (h.getInt() != tilesize) { 170 h.set(tilesize); 171 y.newlimits(-height / 4, height / 4 - h.getInt()); 172 } 173 } 174 if (bouncerect) { 175 x.anim(); 176 y.anim(); 177 } 178 if (newtexture || x.getInt() != tilerect.x || y.getInt() != tilerect.y || w. 179 getInt() != tilerect.width || h.getInt() != tilerect.height) { 180 newtexture = false; 181 int X = x.getInt(); 182 int Y = y.getInt(); 183 int W = w.getInt(); 184 int H = h.getInt(); 185 tilerect = new Rectangle(X, Y, W, H); 186 texturePaint = new TexturePaint(textureImg, tilerect); 187 } 188 } 189 190 @Override 191 public void render(int width, int height, Graphics2D g2) { 192 193 g2.translate(width / 2, height / 2); 194 if (rotate) { 195 rot.anim(); 196 g2.rotate(Math.toRadians(rot.getFlt())); 197 } else { 198 rot.set(0); 199 } 200 if (shearx) { 201 shx.anim(); 202 g2.shear(shx.getFlt() / 100, 0.0f); 203 } else { 204 shx.set(0); 205 } 206 if (sheary) { 207 shy.anim(); 208 g2.shear(0.0f, shy.getFlt() / 100); 209 } else { 210 shy.set(0); 211 } 212 g2.setPaint(texturePaint); 213 g2.fillRect(-1000, -1000, 2000, 2000); 214 if (showanchor) { 215 g2.setColor(BLACK); 216 g2.setColor(colorblend); 217 g2.fill(tilerect); 218 } 219 } 220 221 public static void main(String[] argv) { 222 createDemoFrame(new TextureAnim()); 223 } 224 225 226 static final class AnimVal { 227 228 float curval; 229 float lowval; 230 float highval; 231 float currate; 232 float lowrate; 233 float highrate; 234 235 public AnimVal(int lowval, int highval, 236 int lowrate, int highrate) { 237 this.lowval = lowval; 238 this.highval = highval; 239 this.lowrate = lowrate; 240 this.highrate = highrate; 241 this.curval = randval(lowval, highval); 242 this.currate = randval(lowrate, highrate); 243 } 244 245 public AnimVal(int lowval, int highval, 246 int lowrate, int highrate, 247 int pos) { 248 this(lowval, highval, lowrate, highrate); 249 set(pos); 250 } 251 252 public float randval(float low, float high) { 253 return (float) (low + Math.random() * (high - low)); 254 } 255 256 public float getFlt() { 257 return curval; 258 } 259 260 public int getInt() { 261 return (int) curval; 262 } 263 264 public void anim() { 265 curval += currate; 266 clip(); 267 } 268 269 public void set(float val) { 270 curval = val; 271 clip(); 272 } 273 274 public void clip() { 275 if (curval > highval) { 276 curval = highval - (curval - highval); 277 if (curval < lowval) { 278 curval = highval; 279 } 280 currate = -randval(lowrate, highrate); 281 } else if (curval < lowval) { 282 curval = lowval + (lowval - curval); 283 if (curval > highval) { 284 curval = lowval; 285 } 286 currate = randval(lowrate, highrate); 287 } 288 } 289 290 public void newlimits(int lowval, int highval) { 291 this.lowval = lowval; 292 this.highval = highval; 293 clip(); 294 } 295 } // End AnimVal class 296 297 298 final class DemoControls extends CustomControls implements ActionListener { 299 300 TextureAnim demo; 301 JToolBar toolbar; 302 JComboBox<String> combo; 303 JMenu menu; 304 JMenuItem[] menuitems; 305 int iconSize = 20; 306 ButtonBorder buttonBorder = new ButtonBorder(); 307 308 @SuppressWarnings("LeakingThisInConstructor") 309 public DemoControls(TextureAnim demo) { 310 super(demo.name); 311 this.demo = demo; 312 menuitems = new JMenuItem[3]; 313 add(toolbar = new JToolBar()); 314 toolbar.setFloatable(false); 315 addTool("BO", "bounce", true); 316 addTool("SA", "show anchor", true); 317 addTool("RS", "resize", false); 318 addTool("RO", "rotate", false); 319 addTool("SX", "shear x", false); 320 addTool("SY", "shear y", false); 321 add(combo = new JComboBox<>()); 322 combo.addActionListener(this); 323 combo.addItem("8"); 324 combo.addItem("16"); 325 combo.addItem("32"); 326 combo.addItem("64"); 327 combo.addItem("80"); 328 combo.setSelectedIndex(2); 329 330 JMenuBar menuBar = new JMenuBar(); 331 menu = menuBar.add(new JMenu()); 332 for (int i = 0; i < 3; i++) { 333 BufferedImage bimg = demo.makeImage(iconSize, i); 334 TexturedIcon icon = new TexturedIcon(bimg); 335 menuitems[i] = menu.add(new JMenuItem(icon)); 336 menuitems[i].addActionListener(this); 337 } 338 menu.setIcon(menuitems[0].getIcon()); 339 add(menuBar); 340 demo.bNum = 0; 341 } 342 343 public void addTool(String str, String toolTip, boolean state) { 344 JToggleButton b = 345 (JToggleButton) toolbar.add(new JToggleButton(str)); 346 b.setBorder(buttonBorder); 347 b.setFocusPainted(false); 348 b.setSelected(state); 349 b.setToolTipText(toolTip); 350 b.addActionListener(this); 351 int width = b.getPreferredSize().width+10; 352 Dimension prefSize = new Dimension(width, 21); 353 b.setPreferredSize(prefSize); 354 b.setMaximumSize(prefSize); 355 b.setMinimumSize(prefSize); 356 } 357 358 @Override 359 public void actionPerformed(ActionEvent e) { 360 Object obj = e.getSource(); 361 if (obj instanceof JComboBox) { 362 String selItem = (String) combo.getSelectedItem(); 363 if (selItem != null) { 364 int size = Integer.parseInt(selItem); 365 TextureAnim.textureImg = demo.makeImage(size, demo.bNum); 366 } 367 } else if (obj instanceof JMenuItem) { 368 for (int i = 0; i < menuitems.length; i++) { 369 if (obj.equals(menuitems[i])) { 370 TextureAnim.textureImg = 371 demo.makeImage(demo.tilesize, i); 372 menu.setIcon(menuitems[i].getIcon()); 373 break; 374 } 375 } 376 } else { 377 JToggleButton b = (JToggleButton) obj; 378 if (b.getText().equals("BO")) { 379 demo.bouncerect = b.isSelected(); 380 } else if (b.getText().equals("SA")) { 381 demo.showanchor = b.isSelected(); 382 } else if (b.getText().equals("RS")) { 383 demo.bouncesize = b.isSelected(); 384 } else if (b.getText().equals("RO")) { 385 demo.rotate = b.isSelected(); 386 } else if (b.getText().equals("SX")) { 387 demo.shearx = b.isSelected(); 388 } else if (b.getText().equals("SY")) { 389 demo.sheary = b.isSelected(); 390 } 391 } 392 if (!demo.animating.running()) { 393 demo.repaint(); 394 } 395 } 396 397 @Override 398 public Dimension getPreferredSize() { 399 return new Dimension(200, 41); 400 } 401 402 @Override 403 @SuppressWarnings("SleepWhileHoldingLock") 404 public void run() { 405 Thread me = Thread.currentThread(); 406 while (thread == me) { 407 for (int i = 2; i < toolbar.getComponentCount(); i++) { 408 try { 409 Thread.sleep(4444); 410 } catch (InterruptedException e) { 411 return; 412 } 413 ((AbstractButton) toolbar.getComponentAtIndex(i)).doClick(); 414 } 415 } 416 thread = null; 417 } 418 419 420 class TexturedIcon implements Icon { 421 422 BufferedImage bi; 423 424 public TexturedIcon(BufferedImage bi) { 425 this.bi = bi; 426 } 427 428 @Override 429 public void paintIcon(Component c, Graphics g, int x, int y) { 430 Graphics2D g2 = (Graphics2D) g; 431 Rectangle r = new Rectangle(x, y, iconSize, iconSize); 432 g2.setPaint(new TexturePaint(bi, r)); 433 g2.fillRect(x, y, iconSize, iconSize); 434 g2.setColor(GRAY); 435 g2.draw3DRect(x, y, iconSize - 1, iconSize - 1, true); 436 } 437 438 @Override 439 public int getIconWidth() { 440 return iconSize; 441 } 442 443 @Override 444 public int getIconHeight() { 445 return iconSize; 446 } 447 } // End TexturedIcon class 448 } // End DemoControls class 449 } // End TextureAnim class 450