| /* | |
| * | |
| * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions | |
| * are met: | |
| * | |
| * - Redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer. | |
| * | |
| * - Redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution. | |
| * | |
| * - Neither the name of Oracle nor the names of its | |
| * contributors may be used to endorse or promote products derived | |
| * from this software without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
| * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| */ | |
| package java2d; | |
| import static java.awt.Color.BLACK; | |
| import static java.awt.Color.GRAY; | |
| import static java.awt.Color.RED; | |
| import static java.awt.Color.WHITE; | |
| import static java.awt.Color.YELLOW; | |
| import java.awt.AlphaComposite; | |
| import java.awt.BorderLayout; | |
| import java.awt.Color; | |
| import java.awt.Composite; | |
| import java.awt.Dimension; | |
| import java.awt.Font; | |
| import java.awt.FontMetrics; | |
| import java.awt.GradientPaint; | |
| import java.awt.Graphics; | |
| import java.awt.Graphics2D; | |
| import java.awt.Image; | |
| import java.awt.Paint; | |
| import java.awt.Point; | |
| import java.awt.Rectangle; | |
| import java.awt.RenderingHints; | |
| import java.awt.Shape; | |
| import java.awt.TexturePaint; | |
| import java.awt.Toolkit; | |
| import java.awt.event.ActionEvent; | |
| import java.awt.event.ActionListener; | |
| import java.awt.event.MouseAdapter; | |
| import java.awt.event.MouseEvent; | |
| import java.awt.event.WindowAdapter; | |
| import java.awt.event.WindowEvent; | |
| import java.awt.event.WindowListener; | |
| import java.awt.font.FontRenderContext; | |
| import java.awt.font.TextLayout; | |
| import java.awt.geom.AffineTransform; | |
| import java.awt.geom.Arc2D; | |
| import java.awt.geom.Ellipse2D; | |
| import java.awt.geom.FlatteningPathIterator; | |
| import java.awt.geom.GeneralPath; | |
| import java.awt.geom.Line2D; | |
| import java.awt.geom.PathIterator; | |
| import java.awt.geom.Point2D; | |
| import java.awt.geom.Rectangle2D; | |
| import java.awt.image.BufferedImage; | |
| import java.util.ArrayList; | |
| import java.util.Arrays; | |
| import java.util.List; | |
| import javax.swing.JButton; | |
| import javax.swing.JFrame; | |
| import javax.swing.JPanel; | |
| import javax.swing.JScrollPane; | |
| import javax.swing.JSlider; | |
| import javax.swing.JTable; | |
| import javax.swing.border.BevelBorder; | |
| import javax.swing.border.CompoundBorder; | |
| import javax.swing.border.EmptyBorder; | |
| import javax.swing.border.EtchedBorder; | |
| import javax.swing.border.TitledBorder; | |
| import javax.swing.event.ChangeEvent; | |
| import javax.swing.event.ChangeListener; | |
| import javax.swing.event.TableModelEvent; | |
| import javax.swing.table.AbstractTableModel; | |
| import javax.swing.table.TableColumn; | |
| import javax.swing.table.TableModel; | |
| /** | |
| * Introduction to the J2Ddemo. | |
| * | |
| * @author Brian Lichtenwalter | |
| * @author Alexander Kouznetsov | |
| */ | |
| @SuppressWarnings("serial") | |
| public class Intro extends JPanel { | |
| private static final Color myBlack = new Color(20, 20, 20); | |
| private static final Color myWhite = new Color(240, 240, 255); | |
| private static final Color myRed = new Color(149, 43, 42); | |
| private static final Color myBlue = new Color(94, 105, 176); | |
| private static final Color myYellow = new Color(255, 255, 140); | |
| private ScenesTable scenesTable; | |
| private boolean doTable; | |
| private final Surface surface; | |
| public Intro() { | |
| EmptyBorder eb = new EmptyBorder(80, 110, 80, 110); | |
| BevelBorder bb = new BevelBorder(BevelBorder.LOWERED); | |
| setBorder(new CompoundBorder(eb, bb)); | |
| setLayout(new BorderLayout()); | |
| setBackground(GRAY); | |
| setToolTipText("click for scene table"); | |
| add(surface = new Surface()); | |
| addMouseListener(new MouseAdapter() { | |
| @Override | |
| public void mouseClicked(MouseEvent e) { | |
| removeAll(); | |
| if ((doTable = !doTable)) { | |
| setToolTipText("click for animation"); | |
| surface.stop(); | |
| if (scenesTable == null) { | |
| scenesTable = new ScenesTable(Intro.this); | |
| } | |
| add(scenesTable); | |
| } else { | |
| setToolTipText("click for scene table"); | |
| surface.start(); | |
| add(surface); | |
| } | |
| revalidate(); | |
| repaint(); | |
| } | |
| }); | |
| } | |
| public void start() { | |
| if (!doTable) { | |
| surface.start(); | |
| } | |
| } | |
| public void stop() { | |
| if (!doTable) { | |
| surface.stop(); | |
| } | |
| } | |
| public static void main(String[] argv) { | |
| final Intro intro = new Intro(); | |
| WindowListener l = new WindowAdapter() { | |
| @Override | |
| public void windowClosing(WindowEvent e) { | |
| System.exit(0); | |
| } | |
| @Override | |
| public void windowDeiconified(WindowEvent e) { | |
| intro.start(); | |
| } | |
| @Override | |
| public void windowIconified(WindowEvent e) { | |
| intro.stop(); | |
| } | |
| }; | |
| JFrame f = new JFrame("Java2D(TM) Demo - Intro"); | |
| f.addWindowListener(l); | |
| f.getContentPane().add("Center", intro); | |
| f.pack(); | |
| Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); | |
| int w = 720; | |
| int h = 510; | |
| f.setLocation(screenSize.width / 2 - w / 2, screenSize.height / 2 - h | |
| / 2); | |
| f.setSize(w, h); | |
| f.setVisible(true); | |
| intro.start(); | |
| } | |
| /** | |
| * ScenesTable is the list of scenes known to the Director. | |
| * Scene participation, scene name and scene pause amount columns. | |
| * Global animation delay for scene's steps. | |
| */ | |
| static class ScenesTable extends JPanel implements ActionListener, | |
| ChangeListener { | |
| private final Intro intro; | |
| private JTable table; | |
| private TableModel dataModel; | |
| @SuppressWarnings("LeakingThisInConstructor") | |
| public ScenesTable(final Intro intro) { | |
| this.intro = intro; | |
| setBackground(WHITE); | |
| setLayout(new BorderLayout()); | |
| final String[] names = { "", "Scenes", "Pause" }; | |
| dataModel = new AbstractTableModel() { | |
| @Override | |
| public int getColumnCount() { | |
| return names.length; | |
| } | |
| @Override | |
| public int getRowCount() { | |
| return intro.surface.director.size(); | |
| } | |
| @Override | |
| public Object getValueAt(int row, int col) { | |
| Surface.Scene scene = intro.surface.director.get(row); | |
| if (col == 0) { | |
| return scene.participate; | |
| } else if (col == 1) { | |
| return scene.name; | |
| } else { | |
| return scene.pauseAmt; | |
| } | |
| } | |
| @Override | |
| public String getColumnName(int col) { | |
| return names[col]; | |
| } | |
| @Override | |
| public Class<?> getColumnClass(int c) { | |
| return getValueAt(0, c).getClass(); | |
| } | |
| @Override | |
| public boolean isCellEditable(int row, int col) { | |
| return col != 1 ? true : false; | |
| } | |
| @Override | |
| public void setValueAt(Object aValue, int row, int col) { | |
| Surface.Scene scene = intro.surface.director.get(row); | |
| if (col == 0) { | |
| scene.participate = aValue; | |
| } else if (col == 1) { | |
| scene.name = aValue; | |
| } else { | |
| scene.pauseAmt = aValue; | |
| } | |
| } | |
| }; | |
| table = new JTable(dataModel); | |
| TableColumn col = table.getColumn(""); | |
| col.setWidth(16); | |
| col.setMinWidth(16); | |
| col.setMaxWidth(20); | |
| col = table.getColumn("Pause"); | |
| col.setWidth(60); | |
| col.setMinWidth(60); | |
| col.setMaxWidth(60); | |
| table.sizeColumnsToFit(0); | |
| JScrollPane scrollpane = new JScrollPane(table); | |
| add(scrollpane); | |
| JPanel panel = new JPanel(new BorderLayout()); | |
| JButton b = new JButton("Unselect All"); | |
| b.setHorizontalAlignment(JButton.LEFT); | |
| Font font = new Font(Font.SERIF, Font.PLAIN, 10); | |
| b.setFont(font); | |
| b.addActionListener(this); | |
| panel.add("West", b); | |
| JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 200, | |
| (int) intro.surface.sleepAmt); | |
| slider.addChangeListener(this); | |
| TitledBorder tb = new TitledBorder(new EtchedBorder()); | |
| tb.setTitleFont(font); | |
| tb.setTitle("Anim delay = " + String.valueOf(intro.surface.sleepAmt) | |
| + " ms"); | |
| slider.setBorder(tb); | |
| slider.setPreferredSize(new Dimension(140, 40)); | |
| slider.setMinimumSize(new Dimension(100, 40)); | |
| slider.setMaximumSize(new Dimension(180, 40)); | |
| panel.add("East", slider); | |
| add("South", panel); | |
| } | |
| @Override | |
| public void actionPerformed(ActionEvent e) { | |
| JButton b = (JButton) e.getSource(); | |
| b.setSelected(!b.isSelected()); | |
| b.setText(b.isSelected() ? "Select All" : "Unselect All"); | |
| for (int i = 0; i < intro.surface.director.size(); i++) { | |
| Surface.Scene scene = intro.surface.director.get(i); | |
| scene.participate = Boolean.valueOf(!b.isSelected()); | |
| } | |
| table.tableChanged(new TableModelEvent(dataModel)); | |
| } | |
| @Override | |
| public void stateChanged(ChangeEvent e) { | |
| JSlider slider = (JSlider) e.getSource(); | |
| int value = slider.getValue(); | |
| TitledBorder tb = (TitledBorder) slider.getBorder(); | |
| tb.setTitle("Anim delay = " + String.valueOf(value) + " ms"); | |
| intro.surface.sleepAmt = (long) value; | |
| slider.repaint(); | |
| } | |
| } // End ScenesTable class | |
| /** | |
| * Surface is the stage where the Director plays its scenes. | |
| */ | |
| static class Surface extends JPanel implements Runnable { | |
| private final Image dukeanim, duke; | |
| private BufferedImage bimg; | |
| public Director director; | |
| public int index; | |
| public long sleepAmt = 30; | |
| private Thread thread; | |
| @SuppressWarnings("LeakingThisInConstructor") | |
| public Surface() { | |
| setBackground(myBlack); | |
| setLayout(new BorderLayout()); | |
| addMouseListener(new MouseAdapter() { | |
| @Override | |
| public void mouseClicked(MouseEvent e) { | |
| if (thread == null) { | |
| start(); | |
| } else { | |
| stop(); | |
| } | |
| } | |
| }); | |
| dukeanim = DemoImages.getImage("duke.running.gif", this); | |
| duke = DemoImages.getImage("duke.png", this); | |
| director = new Director(this); | |
| } | |
| public FontMetrics getMetrics(Font font) { | |
| return getFontMetrics(font); | |
| } | |
| @Override | |
| public void paint(Graphics g) { | |
| Dimension d = getSize(); | |
| if (d.width <= 0 || d.height <= 0) { | |
| return; | |
| } | |
| if (bimg == null || bimg.getWidth() != d.width || bimg.getHeight() | |
| != d.height) { | |
| bimg = getGraphicsConfiguration().createCompatibleImage(d.width, | |
| d.height); | |
| // reset future scenes | |
| for (int i = index + 1; i < director.size(); i++) { | |
| (director.get(i)).reset(d.width, d.height); | |
| } | |
| } | |
| Scene scene = director.get(index); | |
| if (scene.index <= scene.length) { | |
| if (thread != null) { | |
| scene.step(d.width, d.height); | |
| } | |
| Graphics2D g2 = bimg.createGraphics(); | |
| g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, | |
| RenderingHints.VALUE_ANTIALIAS_ON); | |
| g2.setBackground(getBackground()); | |
| g2.clearRect(0, 0, d.width, d.height); | |
| scene.render(d.width, d.height, g2); | |
| if (thread != null) { | |
| // increment scene.index after scene.render | |
| scene.index++; | |
| } | |
| g2.dispose(); | |
| } | |
| g.drawImage(bimg, 0, 0, this); | |
| } | |
| public void start() { | |
| if (thread == null) { | |
| thread = new Thread(this); | |
| thread.setPriority(Thread.MIN_PRIORITY); | |
| thread.setName("Intro"); | |
| thread.start(); | |
| } | |
| } | |
| public synchronized void stop() { | |
| if (thread != null) { | |
| thread.interrupt(); | |
| } | |
| thread = null; | |
| notifyAll(); | |
| } | |
| public void reset() { | |
| index = 0; | |
| Dimension d = getSize(); | |
| for (Scene scene : director) { | |
| scene.reset(d.width, d.height); | |
| } | |
| } | |
| @Override | |
| @SuppressWarnings("SleepWhileHoldingLock") | |
| public void run() { | |
| Thread me = Thread.currentThread(); | |
| while (thread == me && !isShowing() || getSize().width <= 0) { | |
| try { | |
| Thread.sleep(500); | |
| } catch (InterruptedException e) { | |
| return; | |
| } | |
| } | |
| if (index == 0) { | |
| reset(); | |
| } | |
| while (thread == me) { | |
| Scene scene = director.get(index); | |
| if (((Boolean) scene.participate).booleanValue()) { | |
| repaint(); | |
| try { | |
| Thread.sleep(sleepAmt); | |
| } catch (InterruptedException e) { | |
| break; | |
| } | |
| if (scene.index > scene.length) { | |
| scene.pause(); | |
| if (++index >= director.size()) { | |
| reset(); | |
| } | |
| } | |
| } else { | |
| if (++index >= director.size()) { | |
| reset(); | |
| } | |
| } | |
| } | |
| thread = null; | |
| } | |
| /** | |
| * Part is a piece of the scene. Classes must implement Part | |
| * in order to participate in a scene. | |
| */ | |
| interface Part { | |
| public void reset(int newwidth, int newheight); | |
| public void step(int w, int h); | |
| public void render(int w, int h, Graphics2D g2); | |
| public int getBegin(); | |
| public int getEnd(); | |
| } | |
| /** | |
| * Director is the holder of the scenes, their names & pause amounts | |
| * between scenes. | |
| */ | |
| static class Director extends ArrayList<Scene> { | |
| GradientPaint gp = new GradientPaint(0, 40, myBlue, 38, 2, myBlack); | |
| Font f1 = new Font(Font.SERIF, Font.PLAIN, 200); | |
| Font f2 = new Font(Font.SERIF, Font.PLAIN, 120); | |
| Font f3 = new Font(Font.SERIF, Font.PLAIN, 72); | |
| public Director(Surface surf) { | |
| Object[][][] partsInfo = { | |
| { { "J - scale text on gradient", "0" }, | |
| { new GpE(GpE.BURI, myBlack, myBlue, 0, 20), | |
| new TxE("J", f1, TxE.SCI, myYellow, 2, 20) } }, | |
| { { "2 - scale & rotate text on gradient", "0" }, | |
| { new GpE(GpE.BURI, myBlue, myBlack, 0, 22), | |
| new TxE("2", f1, TxE.RI | TxE.SCI, myYellow, 2, 22) } }, | |
| { { "D - scale text on gradient", "0" }, | |
| { new GpE(GpE.BURI, myBlack, myBlue, 0, 20), | |
| new TxE("D", f1, TxE.SCI, myYellow, 2, 20) } }, | |
| { { "J2D demo - scale & rotate text on gradient", "1000" }, | |
| { new GpE(GpE.SIH, myBlue, myBlack, 0, 40), | |
| new TxE("J2D demo", f2, TxE.RI | TxE.SCI, myYellow, 0, 40) } }, | |
| { { "Previous scene dither dissolve out", "0" }, | |
| { new DdE(0, 20, 1, surf) } }, | |
| { { "Graphics Features", "999" }, | |
| { new Temp(Temp.RECT, null, 0, 15), | |
| new Temp(Temp.IMG, surf.duke, 2, 15), | |
| new Temp(Temp.RNA | Temp.INA, surf.duke, 16, 130), | |
| new Features(Features.GRAPHICS, 16, 130, surf) } }, | |
| { { "J2D demo - texture text on gradient", "1000" }, | |
| { new GpE(GpE.WI, myBlue, myBlack, 0, 20), | |
| new GpE(GpE.WD, myBlue, myBlack, 21, 40), | |
| new TpE(TpE.OI | TpE.NF, myBlack, myYellow, 4, 0, 10), | |
| new TpE(TpE.OD | TpE.NF, myBlack, myYellow, 4, 11, 20), | |
| new TpE(TpE.OI | TpE.NF | TpE.HAF, myBlack, myYellow, 5, | |
| 21, 40), | |
| new TxE("J2D demo", f2, 0, null, 0, 40) } }, | |
| { { "Previous scene random close out", "0" }, | |
| { new CoE(CoE.RAND, 0, 20, surf) } }, | |
| { { "Text Features", "999" }, | |
| { new Temp(Temp.RECT, null, 0, 15), | |
| new Temp(Temp.IMG, surf.duke, 2, 15), | |
| new Temp(Temp.RNA | Temp.INA, surf.duke, 16, 130), | |
| new Features(Features.TEXT, 16, 130, surf) } }, | |
| { { "J2D demo - composite text on texture", "1000" }, | |
| { new TpE(TpE.RI, myBlack, gp, 40, 0, 20), | |
| new TpE(TpE.RD, myBlack, gp, 40, 21, 40), | |
| new TpE(TpE.RI, myBlack, gp, 40, 41, 60), | |
| new TxE("J2D demo", f2, TxE.AC, myYellow, 0, 60) } }, | |
| { { "Previous scene dither dissolve out", "0" }, | |
| { new DdE(0, 20, 4, surf) } }, | |
| { { "Imaging Features", "999" }, | |
| { new Temp(Temp.RECT, null, 0, 15), | |
| new Temp(Temp.IMG, surf.duke, 2, 15), | |
| new Temp(Temp.RNA | Temp.INA, surf.duke, 16, 130), | |
| new Features(Features.IMAGES, 16, 130, surf) } }, | |
| { { "J2D demo - text on gradient", "1000" }, | |
| { new GpE(GpE.SDH, myBlue, myBlack, 0, 20), | |
| new GpE(GpE.SIH, myBlue, myBlack, 21, 40), | |
| new GpE(GpE.SDH, myBlue, myBlack, 41, 50), | |
| new GpE(GpE.INC | GpE.NF, myRed, myYellow, 0, 50), | |
| new TxE("J2D demo", f2, TxE.NOP, null, 0, 50) } }, | |
| { { "Previous scene ellipse close out", "0" }, | |
| { new CoE(CoE.OVAL, 0, 20, surf) } }, | |
| { { "Color Features", "999" }, | |
| { new Temp(Temp.RECT, null, 0, 15), | |
| new Temp(Temp.IMG, surf.duke, 2, 15), | |
| new Temp(Temp.RNA | Temp.INA, surf.duke, 16, 99), | |
| new Features(Features.COLOR, 16, 99, surf) } }, | |
| { { "J2D demo - composite and rotate text on paints", "2000" }, | |
| { new GpE(GpE.BURI, myBlack, myBlue, 0, 20), | |
| new GpE(GpE.BURD, myBlack, myBlue, 21, 30), | |
| new TpE(TpE.OI | TpE.HAF, myBlack, myBlue, 10, 31, 40), | |
| new TxE("J2D demo", f2, TxE.AC | TxE.RI, myYellow, 0, 40) } }, | |
| { { "Previous scene subimage transform out", "0" }, | |
| { new SiE(60, 60, 0, 40, surf) } }, | |
| { { "CREDITS - transform in", "1000" }, | |
| { new LnE(LnE.ACI | LnE.ZOOMI | LnE.RI, 0, 60), | |
| new TxE("CREDITS", f3, TxE.AC | TxE.SCI, RED, 20, 30), | |
| new TxE("CREDITS", f3, TxE.SCXD, RED, 31, 38), | |
| new TxE("CREDITS", f3, TxE.SCXI, RED, 39, 48), | |
| new TxE("CREDITS", f3, TxE.SCXD, RED, 49, 54), | |
| new TxE("CREDITS", f3, TxE.SCXI, RED, 55, 60) } }, | |
| { { "CREDITS - transform out", "0" }, | |
| { new LnE(LnE.ACD | LnE.ZOOMD | LnE.RD, 0, 45), | |
| new TxE("CREDITS", f3, 0, RED, 0, 9), | |
| new TxE("CREDITS", f3, TxE.SCD | TxE.RD, RED, 10, 30) } }, | |
| { { "Contributors", "1000" }, | |
| { new Temp(Temp.RECT, null, 0, 30), | |
| new Temp(Temp.IMG, surf.dukeanim, 4, 30), | |
| new Temp(Temp.RNA | Temp.INA, surf.dukeanim, 31, 200), | |
| new Contributors(34, 200, surf) } }, }; | |
| for (Object[][] partInfo : partsInfo) { | |
| List<Part> parts = new ArrayList<Part>(); | |
| for (Object part : partInfo[1]) { | |
| parts.add((Part) part); | |
| } | |
| add(new Scene(parts, partInfo[0][0], partInfo[0][1])); | |
| } | |
| } | |
| } | |
| /** | |
| * Scene is the manager of the parts. | |
| */ | |
| static class Scene extends Object { | |
| public Object name; | |
| public Object participate = Boolean.TRUE; | |
| public Object pauseAmt; | |
| public List<Part> parts; | |
| public int index; | |
| public int length; | |
| public Scene(List<Part> parts, Object name, Object pauseAmt) { | |
| this.name = name; | |
| this.parts = parts; | |
| this.pauseAmt = pauseAmt; | |
| for (Part part : parts) { | |
| int partLength = part.getEnd(); | |
| if (partLength > length) { | |
| length = partLength; | |
| } | |
| } | |
| } | |
| public void reset(int w, int h) { | |
| index = 0; | |
| for (int i = 0; i < parts.size(); i++) { | |
| (parts.get(i)).reset(w, h); | |
| } | |
| } | |
| public void step(int w, int h) { | |
| for (int i = 0; i < parts.size(); i++) { | |
| Part part = parts.get(i); | |
| if (index >= part.getBegin() && index <= part.getEnd()) { | |
| part.step(w, h); | |
| } | |
| } | |
| } | |
| public void render(int w, int h, Graphics2D g2) { | |
| for (int i = 0; i < parts.size(); i++) { | |
| Part part = parts.get(i); | |
| if (index >= part.getBegin() && index <= part.getEnd()) { | |
| part.render(w, h, g2); | |
| } | |
| } | |
| } | |
| public void pause() { | |
| try { | |
| Thread.sleep(Long.parseLong((String) pauseAmt)); | |
| } catch (Exception ignored) { | |
| } | |
| System.gc(); | |
| } | |
| } // End Scene class | |
| /** | |
| * Text Effect. Transformation of characters. Clip or fill. | |
| */ | |
| static final class TxE implements Part { | |
| static final int INC = 1; | |
| static final int DEC = 2; | |
| static final int R = 4; // rotate | |
| static final int RI = R | INC; | |
| static final int RD = R | DEC; | |
| static final int SC = 8; // scale | |
| static final int SCI = SC | INC; | |
| static final int SCD = SC | DEC; | |
| static final int SCX = 16; // scale invert x | |
| static final int SCXI = SCX | SC | INC; | |
| static final int SCXD = SCX | SC | DEC; | |
| static final int SCY = 32; // scale invert y | |
| static final int SCYI = SCY | SC | INC; | |
| static final int SCYD = SCY | SC | DEC; | |
| static final int AC = 64; // AlphaComposite | |
| static final int CLIP = 128; // Clipping | |
| static final int NOP = 512; // No Paint | |
| private int beginning, ending; | |
| private int type; | |
| private double rIncr, sIncr; | |
| private double sx, sy, rotate; | |
| private Shape[] shapes, txShapes; | |
| private int sw; | |
| private int numRev; | |
| private Paint paint; | |
| public TxE(String text, | |
| Font font, | |
| int type, | |
| Paint paint, | |
| int beg, | |
| int end) { | |
| this.type = type; | |
| this.paint = paint; | |
| this.beginning = beg; | |
| this.ending = end; | |
| setIncrements(2); | |
| char[] chars = text.toCharArray(); | |
| shapes = new Shape[chars.length]; | |
| txShapes = new Shape[chars.length]; | |
| FontRenderContext frc = new FontRenderContext(null, true, true); | |
| TextLayout tl = new TextLayout(text, font, frc); | |
| sw = (int) tl.getOutline(null).getBounds().getWidth(); | |
| for (int j = 0; j < chars.length; j++) { | |
| String s = String.valueOf(chars[j]); | |
| shapes[j] = new TextLayout(s, font, frc).getOutline(null); | |
| } | |
| } | |
| public void setIncrements(double numRevolutions) { | |
| this.numRev = (int) numRevolutions; | |
| rIncr = 360.0 / ((ending - beginning) / numRevolutions); | |
| sIncr = 1.0 / (ending - beginning); | |
| if ((type & SCX) != 0 || (type & SCY) != 0) { | |
| sIncr *= 2; | |
| } | |
| if ((type & DEC) != 0) { | |
| rIncr = -rIncr; | |
| sIncr = -sIncr; | |
| } | |
| } | |
| @Override | |
| public void reset(int w, int h) { | |
| if (type == SCXI) { | |
| sx = -1.0; | |
| sy = 1.0; | |
| } else if (type == SCYI) { | |
| sx = 1.0; | |
| sy = -1.0; | |
| } else { | |
| sx = sy = (type & DEC) != 0 ? 1.0 : 0.0; | |
| } | |
| rotate = 0; | |
| } | |
| @Override | |
| public void step(int w, int h) { | |
| float charWidth = w / 2 - sw / 2; | |
| for (int i = 0; i < shapes.length; i++) { | |
| AffineTransform at = new AffineTransform(); | |
| Rectangle2D maxBounds = shapes[i].getBounds(); | |
| at.translate(charWidth, h / 2 + maxBounds.getHeight() / 2); | |
| charWidth += (float) maxBounds.getWidth() + 1; | |
| Shape shape = at.createTransformedShape(shapes[i]); | |
| Rectangle2D b1 = shape.getBounds2D(); | |
| if ((type & R) != 0) { | |
| at.rotate(Math.toRadians(rotate)); | |
| } | |
| if ((type & SC) != 0) { | |
| at.scale(sx, sy); | |
| } | |
| shape = at.createTransformedShape(shapes[i]); | |
| Rectangle2D b2 = shape.getBounds2D(); | |
| double xx = (b1.getX() + b1.getWidth() / 2) | |
| - (b2.getX() + b2.getWidth() / 2); | |
| double yy = (b1.getY() + b1.getHeight() / 2) | |
| - (b2.getY() + b2.getHeight() / 2); | |
| AffineTransform toCenterAT = new AffineTransform(); | |
| toCenterAT.translate(xx, yy); | |
| toCenterAT.concatenate(at); | |
| txShapes[i] = toCenterAT.createTransformedShape(shapes[i]); | |
| } | |
| // avoid over rotation | |
| if (Math.abs(rotate) <= numRev * 360) { | |
| rotate += rIncr; | |
| if ((type & SCX) != 0) { | |
| sx += sIncr; | |
| } else if ((type & SCY) != 0) { | |
| sy += sIncr; | |
| } else { | |
| sx += sIncr; | |
| sy += sIncr; | |
| } | |
| } | |
| } | |
| @Override | |
| public void render(int w, int h, Graphics2D g2) { | |
| Composite saveAC = null; | |
| if ((type & AC) != 0 && sx > 0 && sx < 1) { | |
| saveAC = g2.getComposite(); | |
| g2.setComposite(AlphaComposite.getInstance( | |
| AlphaComposite.SRC_OVER, (float) sx)); | |
| } | |
| GeneralPath path = null; | |
| if ((type & CLIP) != 0) { | |
| path = new GeneralPath(); | |
| } | |
| if (paint != null) { | |
| g2.setPaint(paint); | |
| } | |
| for (int i = 0; i < txShapes.length; i++) { | |
| if ((type & CLIP) != 0) { | |
| path.append(txShapes[i], false); | |
| } else { | |
| g2.fill(txShapes[i]); | |
| } | |
| } | |
| if ((type & CLIP) != 0) { | |
| g2.clip(path); | |
| } | |
| if (saveAC != null) { | |
| g2.setComposite(saveAC); | |
| } | |
| } | |
| @Override | |
| public int getBegin() { | |
| return beginning; | |
| } | |
| @Override | |
| public int getEnd() { | |
| return ending; | |
| } | |
| } // End TxE class | |
| /** | |
| * GradientPaint Effect. Burst, split, horizontal and | |
| * vertical gradient fill effects. | |
| */ | |
| static class GpE implements Part { | |
| static final int INC = 1; // increasing | |
| static final int DEC = 2; // decreasing | |
| static final int CNT = 4; // center | |
| static final int WID = 8; // width | |
| static final int WI = WID | INC; | |
| static final int WD = WID | DEC; | |
| static final int HEI = 16; // height | |
| static final int HI = HEI | INC; | |
| static final int HD = HEI | DEC; | |
| static final int SPL = 32 | CNT; // split | |
| static final int SIW = SPL | INC | WID; | |
| static final int SDW = SPL | DEC | WID; | |
| static final int SIH = SPL | INC | HEI; | |
| static final int SDH = SPL | DEC | HEI; | |
| static final int BUR = 64 | CNT; // burst | |
| static final int BURI = BUR | INC; | |
| static final int BURD = BUR | DEC; | |
| static final int NF = 128; // no fill | |
| private Color c1, c2; | |
| private int beginning, ending; | |
| private float incr, index; | |
| private List<Rectangle2D> rect = new ArrayList<Rectangle2D>(); | |
| private List<GradientPaint> grad = new ArrayList<GradientPaint>(); | |
| private int type; | |
| public GpE(int type, Color c1, Color c2, int beg, int end) { | |
| this.type = type; | |
| this.c1 = c1; | |
| this.c2 = c2; | |
| this.beginning = beg; | |
| this.ending = end; | |
| } | |
| @Override | |
| public void reset(int w, int h) { | |
| incr = 1.0f / (ending - beginning); | |
| if ((type & CNT) != 0) { | |
| incr /= 2.3f; | |
| } | |
| if ((type & CNT) != 0 && (type & INC) != 0) { | |
| index = 0.5f; | |
| } else if ((type & DEC) != 0) { | |
| index = 1.0f; | |
| incr = -incr; | |
| } else { | |
| index = 0.0f; | |
| } | |
| index += incr; | |
| } | |
| @Override | |
| public void step(int w, int h) { | |
| rect.clear(); | |
| grad.clear(); | |
| if ((type & WID) != 0) { | |
| float w2 = 0, x1 = 0, x2 = 0; | |
| if ((type & SPL) != 0) { | |
| w2 = w * 0.5f; | |
| x1 = w * (1.0f - index); | |
| x2 = w * index; | |
| } else { | |
| w2 = w * index; | |
| x1 = x2 = w2; | |
| } | |
| rect.add(new Rectangle2D.Float(0, 0, w2, h)); | |
| rect.add(new Rectangle2D.Float(w2, 0, w - w2, h)); | |
| grad.add(new GradientPaint(0, 0, c1, x1, 0, c2)); | |
| grad.add(new GradientPaint(x2, 0, c2, w, 0, c1)); | |
| } else if ((type & HEI) != 0) { | |
| float h2 = 0, y1 = 0, y2 = 0; | |
| if ((type & SPL) != 0) { | |
| h2 = h * 0.5f; | |
| y1 = h * (1.0f - index); | |
| y2 = h * index; | |
| } else { | |
| h2 = h * index; | |
| y1 = y2 = h2; | |
| } | |
| rect.add(new Rectangle2D.Float(0, 0, w, h2)); | |
| rect.add(new Rectangle2D.Float(0, h2, w, h - h2)); | |
| grad.add(new GradientPaint(0, 0, c1, 0, y1, c2)); | |
| grad.add(new GradientPaint(0, y2, c2, 0, h, c1)); | |
| } else if ((type & BUR) != 0) { | |
| float w2 = w / 2; | |
| float h2 = h / 2; | |
| rect.add(new Rectangle2D.Float(0, 0, w2, h2)); | |
| rect.add(new Rectangle2D.Float(w2, 0, w2, h2)); | |
| rect.add(new Rectangle2D.Float(0, h2, w2, h2)); | |
| rect.add(new Rectangle2D.Float(w2, h2, w2, h2)); | |
| float x1 = w * (1.0f - index); | |
| float x2 = w * index; | |
| float y1 = h * (1.0f - index); | |
| float y2 = h * index; | |
| grad.add(new GradientPaint(0, 0, c1, x1, y1, c2)); | |
| grad.add(new GradientPaint(w, 0, c1, x2, y1, c2)); | |
| grad.add(new GradientPaint(0, h, c1, x1, y2, c2)); | |
| grad.add(new GradientPaint(w, h, c1, x2, y2, c2)); | |
| } else if ((type & NF) != 0) { | |
| float y = h * index; | |
| grad.add(new GradientPaint(0, 0, c1, 0, y, c2)); | |
| } | |
| if ((type & INC) != 0 || (type & DEC) != 0) { | |
| index += incr; | |
| } | |
| } | |
| @Override | |
| public void render(int w, int h, Graphics2D g2) { | |
| g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, | |
| RenderingHints.VALUE_ANTIALIAS_OFF); | |
| for (int i = 0; i < grad.size(); i++) { | |
| g2.setPaint(grad.get(i)); | |
| if ((type & NF) == 0) { | |
| g2.fill(rect.get(i)); | |
| } | |
| } | |
| g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, | |
| RenderingHints.VALUE_ANTIALIAS_ON); | |
| } | |
| @Override | |
| public int getBegin() { | |
| return beginning; | |
| } | |
| @Override | |
| public int getEnd() { | |
| return ending; | |
| } | |
| } // End GpE class | |
| /** | |
| * TexturePaint Effect. Expand and collapse a texture. | |
| */ | |
| static final class TpE implements Part { | |
| static final int INC = 1; // increasing | |
| static final int DEC = 2; // decreasing | |
| static final int OVAL = 4; // oval | |
| static final int RECT = 8; // rectangle | |
| static final int HAF = 16; // half oval or rect size | |
| static final int NF = 32; // no fill | |
| static final int OI = OVAL | INC; | |
| static final int OD = OVAL | DEC; | |
| static final int RI = RECT | INC; | |
| static final int RD = RECT | DEC; | |
| private Paint p1, p2; | |
| private int beginning, ending; | |
| private float incr, index; | |
| private TexturePaint texture; | |
| private int type; | |
| private int size; | |
| private BufferedImage bimg; | |
| private Rectangle rect; | |
| public TpE(int type, Paint p1, Paint p2, int size, | |
| int beg, int end) { | |
| this.type = type; | |
| this.p1 = p1; | |
| this.p2 = p2; | |
| this.beginning = beg; | |
| this.ending = end; | |
| setTextureSize(size); | |
| } | |
| public void setTextureSize(int size) { | |
| this.size = size; | |
| bimg = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB); | |
| rect = new Rectangle(0, 0, size, size); | |
| } | |
| @Override | |
| public void reset(int w, int h) { | |
| incr = (float) (size) / (float) (ending - beginning); | |
| if ((type & HAF) != 0) { | |
| incr /= 2; | |
| } | |
| if ((type & DEC) != 0) { | |
| index = size; | |
| if ((type & HAF) != 0) { | |
| index /= 2; | |
| } | |
| incr = -incr; | |
| } else { | |
| index = 0.0f; | |
| } | |
| index += incr; | |
| } | |
| @Override | |
| public void step(int w, int h) { | |
| Graphics2D g2 = bimg.createGraphics(); | |
| g2.setPaint(p1); | |
| g2.fillRect(0, 0, size, size); | |
| g2.setPaint(p2); | |
| if ((type & OVAL) != 0) { | |
| g2.fill(new Ellipse2D.Float(0, 0, index, index)); | |
| } else if ((type & RECT) != 0) { | |
| g2.fill(new Rectangle2D.Float(0, 0, index, index)); | |
| } | |
| texture = new TexturePaint(bimg, rect); | |
| g2.dispose(); | |
| index += incr; | |
| } | |
| @Override | |
| public void render(int w, int h, Graphics2D g2) { | |
| g2.setPaint(texture); | |
| if ((type & NF) == 0) { | |
| g2.fillRect(0, 0, w, h); | |
| } | |
| } | |
| @Override | |
| public int getBegin() { | |
| return beginning; | |
| } | |
| @Override | |
| public int getEnd() { | |
| return ending; | |
| } | |
| } // End TpE class | |
| /** | |
| * Close out effect. Close out the buffered image with different | |
| * geometry shapes. | |
| */ | |
| static class CoE implements Part { | |
| private final Surface surf; | |
| static final int WID = 1; | |
| static final int HEI = 2; | |
| static final int OVAL = 4; | |
| static final int RECT = 8; | |
| static final int RAND = 16; | |
| static final int ARC = 32; | |
| private int type; | |
| private int beginning, ending; | |
| private BufferedImage bimg; | |
| private Shape shape; | |
| private double zoom, extent; | |
| private double zIncr, eIncr; | |
| private boolean doRandom; | |
| public CoE(int type, int beg, int end, Surface surf) { | |
| this.type = type; | |
| this.beginning = beg; | |
| this.ending = end; | |
| this.surf = surf; | |
| zIncr = -(2.0 / (ending - beginning)); | |
| eIncr = 360.0 / (ending - beginning); | |
| doRandom = (type & RAND) != 0; | |
| } | |
| @Override | |
| public void reset(int w, int h) { | |
| if (doRandom) { | |
| int num = (int) (Math.random() * 5.0); | |
| switch (num) { | |
| case 0: | |
| type = OVAL; | |
| break; | |
| case 1: | |
| type = RECT; | |
| break; | |
| case 2: | |
| type = RECT | WID; | |
| break; | |
| case 3: | |
| type = RECT | HEI; | |
| break; | |
| case 4: | |
| type = ARC; | |
| break; | |
| default: | |
| type = OVAL; | |
| } | |
| } | |
| shape = null; | |
| bimg = null; | |
| extent = 360.0; | |
| zoom = 2.0; | |
| } | |
| @Override | |
| public void step(int w, int h) { | |
| if (bimg == null) { | |
| int biw = surf.bimg.getWidth(); | |
| int bih = surf.bimg.getHeight(); | |
| bimg = new BufferedImage(biw, bih, | |
| BufferedImage.TYPE_INT_RGB); | |
| Graphics2D big = bimg.createGraphics(); | |
| big.drawImage(surf.bimg, 0, 0, null); | |
| } | |
| double z = Math.min(w, h) * zoom; | |
| if ((type & OVAL) != 0) { | |
| shape = new Ellipse2D.Double(w / 2 - z / 2, h / 2 - z / 2, z, | |
| z); | |
| } else if ((type & ARC) != 0) { | |
| shape = new Arc2D.Double(-100, -100, w + 200, h + 200, 90, | |
| extent, Arc2D.PIE); | |
| extent -= eIncr; | |
| } else if ((type & RECT) != 0) { | |
| if ((type & WID) != 0) { | |
| shape = new Rectangle2D.Double(w / 2 - z / 2, 0, z, h); | |
| } else if ((type & HEI) != 0) { | |
| shape = new Rectangle2D.Double(0, h / 2 - z / 2, w, z); | |
| } else { | |
| shape = new Rectangle2D.Double(w / 2 - z / 2, h / 2 - z | |
| / 2, z, z); | |
| } | |
| } | |
| zoom += zIncr; | |
| } | |
| @Override | |
| public void render(int w, int h, Graphics2D g2) { | |
| g2.clip(shape); | |
| g2.drawImage(bimg, 0, 0, null); | |
| } | |
| @Override | |
| public int getBegin() { | |
| return beginning; | |
| } | |
| @Override | |
| public int getEnd() { | |
| return ending; | |
| } | |
| } // End CoE class | |
| /** | |
| * Dither Dissolve Effect. For each successive step in the animation, | |
| * a pseudo-random starting horizontal position is chosen using list, | |
| * and then the corresponding points created from xlist and ylist are | |
| * blacked out for the current "chunk". The x and y chunk starting | |
| * positions are each incremented by the associated chunk size, and | |
| * this process is repeated for the number of "steps" in the | |
| * animation, causing an equal number of pseudo-randomly picked | |
| * "blocks" to be blacked out during each step of the animation. | |
| */ | |
| static class DdE implements Part { | |
| private final Surface surf; | |
| private int beginning, ending; | |
| private BufferedImage bimg; | |
| private Graphics2D big; | |
| private List<Integer> list, xlist, ylist; | |
| private int xeNum, yeNum; // element number | |
| private int xcSize, ycSize; // chunk size | |
| private int inc; | |
| private int blocksize; | |
| public DdE(int beg, int end, int blocksize, Surface surf) { | |
| this.beginning = beg; | |
| this.ending = end; | |
| this.blocksize = blocksize; | |
| this.surf = surf; | |
| } | |
| private void createShuffledLists() { | |
| int width = bimg.getWidth(); | |
| int height = bimg.getHeight(); | |
| xlist = new ArrayList<Integer>(width); | |
| ylist = new ArrayList<Integer>(height); | |
| list = new ArrayList<Integer>(ending - beginning + 1); | |
| for (int i = 0; i < width; i++) { | |
| xlist.add(i, i); | |
| } | |
| for (int i = 0; i < height; i++) { | |
| ylist.add(i, i); | |
| } | |
| for (int i = 0; i < (ending - beginning + 1); i++) { | |
| list.add(i, i); | |
| } | |
| java.util.Collections.shuffle(xlist); | |
| java.util.Collections.shuffle(ylist); | |
| java.util.Collections.shuffle(list); | |
| } | |
| @Override | |
| public void reset(int w, int h) { | |
| bimg = null; | |
| } | |
| @Override | |
| public void step(int w, int h) { | |
| if (inc > ending) { | |
| bimg = null; | |
| } | |
| if (bimg == null) { | |
| int biw = surf.bimg.getWidth(); | |
| int bih = surf.bimg.getHeight(); | |
| bimg = new BufferedImage(biw, bih, | |
| BufferedImage.TYPE_INT_RGB); | |
| createShuffledLists(); | |
| big = bimg.createGraphics(); | |
| big.drawImage(surf.bimg, 0, 0, null); | |
| xcSize = (xlist.size() / (ending - beginning)) + 1; | |
| ycSize = (ylist.size() / (ending - beginning)) + 1; | |
| xeNum = 0; | |
| inc = 0; | |
| } | |
| xeNum = xcSize * (list.get(inc)).intValue(); | |
| yeNum = -ycSize; | |
| inc++; | |
| } | |
| @Override | |
| public void render(int w, int h, Graphics2D g2) { | |
| big.setColor(myBlack); | |
| for (int k = 0; k <= (ending - beginning); k++) { | |
| if ((xeNum + xcSize) > xlist.size()) { | |
| xeNum = 0; | |
| } else { | |
| xeNum += xcSize; | |
| } | |
| yeNum += ycSize; | |
| for (int i = xeNum; i < xeNum + xcSize && i < xlist.size(); | |
| i++) { | |
| for (int j = yeNum; j < yeNum + ycSize && j | |
| < ylist.size(); j++) { | |
| int xval = (xlist.get(i)).intValue(); | |
| int yval = (ylist.get(j)).intValue(); | |
| if (((xval % blocksize) == 0) && ((yval % blocksize) | |
| == 0)) { | |
| big.fillRect(xval, yval, blocksize, blocksize); | |
| } | |
| } | |
| } | |
| } | |
| g2.drawImage(bimg, 0, 0, null); | |
| } | |
| @Override | |
| public int getBegin() { | |
| return beginning; | |
| } | |
| @Override | |
| public int getEnd() { | |
| return ending; | |
| } | |
| } // End DdE class | |
| /** | |
| * Subimage effect. Subimage the scene's buffered | |
| * image then rotate and scale down the subimages. | |
| */ | |
| static class SiE implements Part { | |
| private final Surface surf; | |
| private int beginning, ending; | |
| private BufferedImage bimg; | |
| private double rIncr, sIncr; | |
| private double scale, rotate; | |
| private int siw, sih; | |
| private List<BufferedImage> subs = new ArrayList<BufferedImage>(20); | |
| private List<Point> pts = new ArrayList<Point>(20); | |
| public SiE(int siw, int sih, int beg, int end, Surface surf) { | |
| this.siw = siw; | |
| this.sih = sih; | |
| this.beginning = beg; | |
| this.ending = end; | |
| this.surf = surf; | |
| rIncr = 360.0 / (ending - beginning); | |
| sIncr = 1.0 / (ending - beginning); | |
| } | |
| @Override | |
| public void reset(int w, int h) { | |
| scale = 1.0; | |
| rotate = 0.0; | |
| bimg = null; | |
| subs.clear(); | |
| pts.clear(); | |
| } | |
| @Override | |
| public void step(int w, int h) { | |
| if (bimg == null) { | |
| int biw = surf.bimg.getWidth(); | |
| int bih = surf.bimg.getHeight(); | |
| bimg = new BufferedImage(biw, bih, | |
| BufferedImage.TYPE_INT_RGB); | |
| Graphics2D big = bimg.createGraphics(); | |
| big.drawImage(surf.bimg, 0, 0, null); | |
| for (int x = 0; x < w && scale > 0.0; x += siw) { | |
| int ww = x + siw < w ? siw : w - x; | |
| for (int y = 0; y < h; y += sih) { | |
| int hh = y + sih < h ? sih : h - y; | |
| subs.add(bimg.getSubimage(x, y, ww, hh)); | |
| pts.add(new Point(x, y)); | |
| } | |
| } | |
| } | |
| rotate += rIncr; | |
| scale -= sIncr; | |
| } | |
| @Override | |
| public void render(int w, int h, Graphics2D g2) { | |
| AffineTransform saveTx = g2.getTransform(); | |
| g2.setColor(myBlue); | |
| for (int i = 0; i < subs.size() && scale > 0.0; i++) { | |
| BufferedImage bi = subs.get(i); | |
| Point p = pts.get(i); | |
| int ww = bi.getWidth(); | |
| int hh = bi.getHeight(); | |
| AffineTransform at = new AffineTransform(); | |
| at.rotate(Math.toRadians(rotate), p.x + ww / 2, p.y + hh / 2); | |
| at.translate(p.x, p.y); | |
| at.scale(scale, scale); | |
| Rectangle b1 = new Rectangle(0, 0, ww, hh); | |
| Shape shape = at.createTransformedShape(b1); | |
| Rectangle2D b2 = shape.getBounds2D(); | |
| double xx = (p.x + ww / 2) - (b2.getX() + b2.getWidth() / 2); | |
| double yy = (p.y + hh / 2) | |
| - (b2.getY() + b2.getHeight() / 2); | |
| AffineTransform toCenterAT = new AffineTransform(); | |
| toCenterAT.translate(xx, yy); | |
| toCenterAT.concatenate(at); | |
| g2.setTransform(toCenterAT); | |
| g2.drawImage(bi, 0, 0, null); | |
| g2.draw(b1); | |
| } | |
| g2.setTransform(saveTx); | |
| } | |
| @Override | |
| public int getBegin() { | |
| return beginning; | |
| } | |
| @Override | |
| public int getEnd() { | |
| return ending; | |
| } | |
| } // End SiE class | |
| /** | |
| * Line Effect. Flattened ellipse with lines from the center | |
| * to the edge. Expand or collapse the ellipse. Fade in or out | |
| * the lines. | |
| */ | |
| static class LnE implements Part { | |
| static final int INC = 1; | |
| static final int DEC = 2; | |
| static final int R = 4; // rotate | |
| static final int ZOOM = 8; // zoom | |
| static final int AC = 32; // AlphaComposite | |
| static final int RI = R | INC; | |
| static final int RD = R | DEC; | |
| static final int ZOOMI = ZOOM | INC; | |
| static final int ZOOMD = ZOOM | DEC; | |
| static final int ACI = AC | INC; | |
| static final int ACD = AC | DEC; | |
| private int beginning, ending; | |
| private double rIncr, rotate; | |
| private double zIncr, zoom; | |
| private List<Point2D.Double> pts = new ArrayList<Point2D.Double>(); | |
| private float alpha, aIncr; | |
| private int type; | |
| public LnE(int type, int beg, int end) { | |
| this.type = type; | |
| this.beginning = beg; | |
| this.ending = end; | |
| float range = ending - beginning; | |
| rIncr = 360.0f / range; | |
| aIncr = 0.9f / range; | |
| zIncr = 2.0f / range; | |
| if ((type & DEC) != 0) { | |
| rIncr = -rIncr; | |
| aIncr = -aIncr; | |
| zIncr = -zIncr; | |
| } | |
| } | |
| public void generatePts(int w, int h, double sizeF) { | |
| pts.clear(); | |
| double size = Math.min(w, h) * sizeF; | |
| Ellipse2D ellipse = new Ellipse2D.Double(w / 2 - size / 2, h / 2 - size | |
| / 2, size, size); | |
| PathIterator pi = ellipse.getPathIterator(null, 0.8); | |
| while (!pi.isDone()) { | |
| double[] pt = new double[6]; | |
| switch (pi.currentSegment(pt)) { | |
| case FlatteningPathIterator.SEG_MOVETO: | |
| case FlatteningPathIterator.SEG_LINETO: | |
| pts.add(new Point2D.Double(pt[0], pt[1])); | |
| } | |
| pi.next(); | |
| } | |
| } | |
| @Override | |
| public void reset(int w, int h) { | |
| if ((type & DEC) != 0) { | |
| rotate = 360; | |
| alpha = 1.0f; | |
| zoom = 2.0; | |
| } else { | |
| rotate = alpha = 0; | |
| zoom = 0; | |
| } | |
| if ((type & ZOOM) == 0) { | |
| generatePts(w, h, 0.5); | |
| } | |
| } | |
| @Override | |
| public void step(int w, int h) { | |
| if ((type & ZOOM) != 0) { | |
| generatePts(w, h, zoom += zIncr); | |
| } | |
| if ((type & RI) != 0 || (type & RI) != 0) { | |
| rotate += rIncr; | |
| } | |
| if ((type & ACI) != 0 || (type & ACD) != 0) { | |
| alpha += aIncr; | |
| } | |
| } | |
| @Override | |
| public void render(int w, int h, Graphics2D g2) { | |
| Composite saveAC = null; | |
| if ((type & AC) != 0 && alpha >= 0 && alpha <= 1) { | |
| saveAC = g2.getComposite(); | |
| g2.setComposite(AlphaComposite.getInstance( | |
| AlphaComposite.SRC_OVER, alpha)); | |
| } | |
| AffineTransform saveTx = null; | |
| if ((type & R) != 0) { | |
| saveTx = g2.getTransform(); | |
| AffineTransform at = new AffineTransform(); | |
| at.rotate(Math.toRadians(rotate), w / 2, h / 2); | |
| g2.setTransform(at); | |
| } | |
| Point2D p1 = new Point2D.Double(w / 2, h / 2); | |
| g2.setColor(YELLOW); | |
| for (Point2D pt : pts) { | |
| g2.draw(new Line2D.Float(p1, pt)); | |
| } | |
| if (saveTx != null) { | |
| g2.setTransform(saveTx); | |
| } | |
| if (saveAC != null) { | |
| g2.setComposite(saveAC); | |
| } | |
| } | |
| @Override | |
| public int getBegin() { | |
| return beginning; | |
| } | |
| @Override | |
| public int getEnd() { | |
| return ending; | |
| } | |
| } // End LnE class | |
| /** | |
| * Template for Features & Contributors consisting of translating | |
| * blue and red rectangles and an image going from transparent to | |
| * opaque. | |
| */ | |
| static class Temp implements Part { | |
| static final int NOANIM = 1; | |
| static final int RECT = 2; | |
| static final int IMG = 4; | |
| static final int RNA = RECT | NOANIM; | |
| static final int INA = IMG | NOANIM; | |
| private int beginning, ending; | |
| private float alpha, aIncr; | |
| private int type; | |
| private Rectangle rect1, rect2; | |
| private int x, y, xIncr, yIncr; | |
| private Image img; | |
| public Temp(int type, Image img, int beg, int end) { | |
| this.type = type; | |
| this.img = img; | |
| this.beginning = beg; | |
| this.ending = end; | |
| aIncr = 0.9f / (ending - beginning); | |
| if ((type & NOANIM) != 0) { | |
| alpha = 1.0f; | |
| } | |
| } | |
| @Override | |
| public void reset(int w, int h) { | |
| rect1 = new Rectangle(8, 20, w - 20, 30); | |
| rect2 = new Rectangle(20, 8, 30, h - 20); | |
| if ((type & NOANIM) == 0) { | |
| alpha = 0.0f; | |
| xIncr = w / (ending - beginning); | |
| yIncr = h / (ending - beginning); | |
| x = w + (int) (xIncr * 1.4); | |
| y = h + (int) (yIncr * 1.4); | |
| } | |
| } | |
| @Override | |
| public void step(int w, int h) { | |
| if ((type & NOANIM) != 0) { | |
| return; | |
| } | |
| if ((type & RECT) != 0) { | |
| rect1.setLocation(x -= xIncr, 20); | |
| rect2.setLocation(20, y -= yIncr); | |
| } | |
| if ((type & IMG) != 0) { | |
| alpha += aIncr; | |
| } | |
| } | |
| @Override | |
| public void render(int w, int h, Graphics2D g2) { | |
| if ((type & RECT) != 0) { | |
| g2.setColor(myBlue); | |
| g2.fill(rect1); | |
| g2.setColor(myRed); | |
| g2.fill(rect2); | |
| } | |
| if ((type & IMG) != 0) { | |
| Composite saveAC = g2.getComposite(); | |
| if (alpha >= 0 && alpha <= 1) { | |
| g2.setComposite(AlphaComposite.getInstance( | |
| AlphaComposite.SRC_OVER, alpha)); | |
| } | |
| g2.drawImage(img, 30, 30, null); | |
| g2.setComposite(saveAC); | |
| } | |
| } | |
| @Override | |
| public int getBegin() { | |
| return beginning; | |
| } | |
| @Override | |
| public int getEnd() { | |
| return ending; | |
| } | |
| } // End Temp class | |
| /** | |
| * Features of Java2D(TM). Single character advancement effect. | |
| */ | |
| static class Features implements Part { | |
| static final int GRAPHICS = 0; | |
| static final int TEXT = 1; | |
| static final int IMAGES = 2; | |
| static final int COLOR = 3; | |
| static final Font font1 = new Font(Font.SERIF, Font.BOLD, 38); | |
| static final Font font2 = new Font(Font.SERIF, Font.PLAIN, 24); | |
| private final FontMetrics fm1; | |
| private final FontMetrics fm2; | |
| private static final String[][] table = { { "Graphics", "Antialiased rendering", | |
| "Bezier paths", | |
| "Transforms", "Compositing", "Stroking parameters" }, | |
| { "Text", "Extended font support", | |
| "Advanced text layout", "Dynamic font loading", | |
| "AttributeSets for font customization" }, | |
| { "Images", "Flexible image layouts", | |
| "Extended imaging operations", | |
| " Convolutions, Lookup Tables", | |
| "RenderableImage interface" }, | |
| { "Color", "ICC profile support", "Color conversion", | |
| "Arbitrary color spaces" } }; | |
| private String[] list; | |
| private int beginning, ending; | |
| private int strH; | |
| private int endIndex, listIndex; | |
| private List<String> v = new ArrayList<String>(); | |
| public Features(int type, int beg, int end, Surface surf) { | |
| list = table[type]; | |
| this.beginning = beg; | |
| this.ending = end; | |
| fm1 = surf.getMetrics(font1); | |
| fm2 = surf.getMetrics(font2); | |
| } | |
| @Override | |
| public void reset(int w, int h) { | |
| strH = (fm2.getAscent() + fm2.getDescent()); | |
| endIndex = 1; | |
| listIndex = 0; | |
| v.clear(); | |
| v.add(list[listIndex].substring(0, endIndex)); | |
| } | |
| @Override | |
| public void step(int w, int h) { | |
| if (listIndex < list.length) { | |
| if (++endIndex > list[listIndex].length()) { | |
| if (++listIndex < list.length) { | |
| endIndex = 1; | |
| v.add(list[listIndex].substring(0, endIndex)); | |
| } | |
| } else { | |
| v.set(listIndex, list[listIndex].substring(0, endIndex)); | |
| } | |
| } | |
| } | |
| @Override | |
| public void render(int w, int h, Graphics2D g2) { | |
| g2.setColor(myWhite); | |
| g2.setFont(font1); | |
| g2.drawString(v.get(0), 90, 85); | |
| g2.setFont(font2); | |
| for (int i = 1, y = 90; i < v.size(); i++) { | |
| g2.drawString(v.get(i), 120, y += strH); | |
| } | |
| } | |
| @Override | |
| public int getBegin() { | |
| return beginning; | |
| } | |
| @Override | |
| public int getEnd() { | |
| return ending; | |
| } | |
| } // End Features class | |
| /** | |
| * Scrolling text of Java2D(TM) contributors. | |
| */ | |
| static class Contributors implements Part { | |
| private static final String[] members = { | |
| "Brian Lichtenwalter", "Jeannette Hung", | |
| "Thanh Nguyen", "Jim Graham", "Jerry Evans", | |
| "John Raley", "Michael Peirce", "Robert Kim", | |
| "Jennifer Ball", "Deborah Adair", "Paul Charlton", | |
| "Dmitry Feld", "Gregory Stone", "Richard Blanchard", | |
| "Link Perry", "Phil Race", "Vincent Hardy", | |
| "Parry Kejriwal", "Doug Felt", "Rekha Rangarajan", | |
| "Paula Patel", "Michael Bundschuh", "Joe Warzecha", | |
| "Joey Beheler", "Aastha Bhardwaj", "Daniel Rice", | |
| "Chris Campbell", "Shinsuke Fukuda", "Dmitri Trembovetski", | |
| "Chet Haase", "Jennifer Godinez", "Nicholas Talian", | |
| "Raul Vera", "Ankit Patel", "Ilya Bagrak", | |
| "Praveen Mohan", "Rakesh Menon" | |
| }; | |
| private static final Font font = new Font(Font.SERIF, Font.PLAIN, 26); | |
| private final FontMetrics fm; | |
| private int beginning, ending; | |
| private int nStrs, strH, index, yh, height; | |
| private List<String> v = new ArrayList<String>(); | |
| private List<String> cast = | |
| new ArrayList<String>(members.length + 3); | |
| private int counter, cntMod; | |
| private GradientPaint gp; | |
| public Contributors(int beg, int end, Surface surf) { | |
| this.beginning = beg; | |
| this.ending = end; | |
| fm = surf.getMetrics(font); | |
| Arrays.sort(members); | |
| cast.add("CONTRIBUTORS"); | |
| cast.add(" "); | |
| cast.addAll(Arrays.asList(members)); | |
| cast.add(" "); | |
| cast.add(" "); | |
| cntMod = (ending - beginning) / cast.size() - 1; | |
| } | |
| @Override | |
| public void reset(int w, int h) { | |
| v.clear(); | |
| strH = (fm.getAscent() + fm.getDescent()); | |
| nStrs = (h - 40) / strH + 1; | |
| height = strH * (nStrs - 1) + 48; | |
| index = 0; | |
| gp = new GradientPaint(0, h / 2, WHITE, 0, h + 20, BLACK); | |
| counter = 0; | |
| } | |
| @Override | |
| public void step(int w, int h) { | |
| if (counter++ % cntMod == 0) { | |
| if (index < cast.size()) { | |
| v.add(cast.get(index)); | |
| } | |
| if ((v.size() == nStrs || index >= cast.size()) && !v. | |
| isEmpty()) { | |
| v.remove(0); | |
| } | |
| ++index; | |
| } | |
| } | |
| @Override | |
| public void render(int w, int h, Graphics2D g2) { | |
| g2.setPaint(gp); | |
| g2.setFont(font); | |
| double remainder = counter % cntMod; | |
| double incr = 1.0 - remainder / cntMod; | |
| incr = incr == 1.0 ? 0 : incr; | |
| int y = (int) (incr * strH); | |
| if (index >= cast.size()) { | |
| y = yh + y; | |
| } else { | |
| y = yh = height - v.size() * strH + y; | |
| } | |
| for (String s : v) { | |
| g2.drawString(s, w / 2 - fm.stringWidth(s) / 2, y += strH); | |
| } | |
| } | |
| @Override | |
| public int getBegin() { | |
| return beginning; | |
| } | |
| @Override | |
| public int getEnd() { | |
| return ending; | |
| } | |
| } // End Contributors class | |
| } // End Surface class | |
| } // End Intro class | |