Path: blob/master/src/demo/share/jfc/J2Ddemo/java2d/Intro.java
41155 views
/*1*2* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7*8* - Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10*11* - Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* - Neither the name of Oracle nor the names of its16* contributors may be used to endorse or promote products derived17* from this software without specific prior written permission.18*19* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS20* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,21* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR22* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR23* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,24* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,25* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR26* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF27* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING28* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS29* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.30*/31package java2d;323334import static java.awt.Color.BLACK;35import static java.awt.Color.GRAY;36import static java.awt.Color.RED;37import static java.awt.Color.WHITE;38import static java.awt.Color.YELLOW;39import java.awt.AlphaComposite;40import java.awt.BorderLayout;41import java.awt.Color;42import java.awt.Composite;43import java.awt.Dimension;44import java.awt.Font;45import java.awt.FontMetrics;46import java.awt.GradientPaint;47import java.awt.Graphics;48import java.awt.Graphics2D;49import java.awt.Image;50import java.awt.Paint;51import java.awt.Point;52import java.awt.Rectangle;53import java.awt.RenderingHints;54import java.awt.Shape;55import java.awt.TexturePaint;56import java.awt.Toolkit;57import java.awt.event.ActionEvent;58import java.awt.event.ActionListener;59import java.awt.event.MouseAdapter;60import java.awt.event.MouseEvent;61import java.awt.event.WindowAdapter;62import java.awt.event.WindowEvent;63import java.awt.event.WindowListener;64import java.awt.font.FontRenderContext;65import java.awt.font.TextLayout;66import java.awt.geom.AffineTransform;67import java.awt.geom.Arc2D;68import java.awt.geom.Ellipse2D;69import java.awt.geom.FlatteningPathIterator;70import java.awt.geom.GeneralPath;71import java.awt.geom.Line2D;72import java.awt.geom.PathIterator;73import java.awt.geom.Point2D;74import java.awt.geom.Rectangle2D;75import java.awt.image.BufferedImage;76import java.util.ArrayList;77import java.util.Arrays;78import java.util.List;79import javax.swing.JButton;80import javax.swing.JFrame;81import javax.swing.JPanel;82import javax.swing.JScrollPane;83import javax.swing.JSlider;84import javax.swing.JTable;85import javax.swing.border.BevelBorder;86import javax.swing.border.CompoundBorder;87import javax.swing.border.EmptyBorder;88import javax.swing.border.EtchedBorder;89import javax.swing.border.TitledBorder;90import javax.swing.event.ChangeEvent;91import javax.swing.event.ChangeListener;92import javax.swing.event.TableModelEvent;93import javax.swing.table.AbstractTableModel;94import javax.swing.table.TableColumn;95import javax.swing.table.TableModel;969798/**99* Introduction to the J2Ddemo.100*101* @author Brian Lichtenwalter102* @author Alexander Kouznetsov103*/104@SuppressWarnings("serial")105public class Intro extends JPanel {106107private static final Color myBlack = new Color(20, 20, 20);108private static final Color myWhite = new Color(240, 240, 255);109private static final Color myRed = new Color(149, 43, 42);110private static final Color myBlue = new Color(94, 105, 176);111private static final Color myYellow = new Color(255, 255, 140);112private ScenesTable scenesTable;113private boolean doTable;114private final Surface surface;115116public Intro() {117EmptyBorder eb = new EmptyBorder(80, 110, 80, 110);118BevelBorder bb = new BevelBorder(BevelBorder.LOWERED);119setBorder(new CompoundBorder(eb, bb));120setLayout(new BorderLayout());121setBackground(GRAY);122setToolTipText("click for scene table");123add(surface = new Surface());124addMouseListener(new MouseAdapter() {125126@Override127public void mouseClicked(MouseEvent e) {128removeAll();129if ((doTable = !doTable)) {130setToolTipText("click for animation");131surface.stop();132if (scenesTable == null) {133scenesTable = new ScenesTable(Intro.this);134}135add(scenesTable);136} else {137setToolTipText("click for scene table");138surface.start();139add(surface);140}141revalidate();142repaint();143}144});145}146147public void start() {148if (!doTable) {149surface.start();150}151}152153public void stop() {154if (!doTable) {155surface.stop();156}157}158159public static void main(String[] argv) {160final Intro intro = new Intro();161WindowListener l = new WindowAdapter() {162163@Override164public void windowClosing(WindowEvent e) {165System.exit(0);166}167168@Override169public void windowDeiconified(WindowEvent e) {170intro.start();171}172173@Override174public void windowIconified(WindowEvent e) {175intro.stop();176}177};178JFrame f = new JFrame("Java2D(TM) Demo - Intro");179f.addWindowListener(l);180f.getContentPane().add("Center", intro);181f.pack();182Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();183int w = 720;184int h = 510;185f.setLocation(screenSize.width / 2 - w / 2, screenSize.height / 2 - h186/ 2);187f.setSize(w, h);188f.setVisible(true);189intro.start();190}191192193/**194* ScenesTable is the list of scenes known to the Director.195* Scene participation, scene name and scene pause amount columns.196* Global animation delay for scene's steps.197*/198static class ScenesTable extends JPanel implements ActionListener,199ChangeListener {200private final Intro intro;201private JTable table;202private TableModel dataModel;203204@SuppressWarnings("LeakingThisInConstructor")205public ScenesTable(final Intro intro) {206this.intro = intro;207208setBackground(WHITE);209setLayout(new BorderLayout());210final String[] names = { "", "Scenes", "Pause" };211212dataModel = new AbstractTableModel() {213214@Override215public int getColumnCount() {216return names.length;217}218219@Override220public int getRowCount() {221return intro.surface.director.size();222}223224@Override225public Object getValueAt(int row, int col) {226Surface.Scene scene = intro.surface.director.get(row);227if (col == 0) {228return scene.participate;229} else if (col == 1) {230return scene.name;231} else {232return scene.pauseAmt;233}234}235236@Override237public String getColumnName(int col) {238return names[col];239}240241@Override242public Class<?> getColumnClass(int c) {243return getValueAt(0, c).getClass();244}245246@Override247public boolean isCellEditable(int row, int col) {248return col != 1 ? true : false;249}250251@Override252public void setValueAt(Object aValue, int row, int col) {253Surface.Scene scene = intro.surface.director.get(row);254if (col == 0) {255scene.participate = aValue;256} else if (col == 1) {257scene.name = aValue;258} else {259scene.pauseAmt = aValue;260}261}262};263264table = new JTable(dataModel);265TableColumn col = table.getColumn("");266col.setWidth(16);267col.setMinWidth(16);268col.setMaxWidth(20);269col = table.getColumn("Pause");270col.setWidth(60);271col.setMinWidth(60);272col.setMaxWidth(60);273table.sizeColumnsToFit(0);274275JScrollPane scrollpane = new JScrollPane(table);276add(scrollpane);277278JPanel panel = new JPanel(new BorderLayout());279JButton b = new JButton("Unselect All");280b.setHorizontalAlignment(JButton.LEFT);281Font font = new Font(Font.SERIF, Font.PLAIN, 10);282b.setFont(font);283b.addActionListener(this);284panel.add("West", b);285286JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 200,287(int) intro.surface.sleepAmt);288slider.addChangeListener(this);289TitledBorder tb = new TitledBorder(new EtchedBorder());290tb.setTitleFont(font);291tb.setTitle("Anim delay = " + String.valueOf(intro.surface.sleepAmt)292+ " ms");293slider.setBorder(tb);294slider.setPreferredSize(new Dimension(140, 40));295slider.setMinimumSize(new Dimension(100, 40));296slider.setMaximumSize(new Dimension(180, 40));297panel.add("East", slider);298299add("South", panel);300}301302@Override303public void actionPerformed(ActionEvent e) {304JButton b = (JButton) e.getSource();305b.setSelected(!b.isSelected());306b.setText(b.isSelected() ? "Select All" : "Unselect All");307for (int i = 0; i < intro.surface.director.size(); i++) {308Surface.Scene scene = intro.surface.director.get(i);309scene.participate = Boolean.valueOf(!b.isSelected());310}311table.tableChanged(new TableModelEvent(dataModel));312}313314@Override315public void stateChanged(ChangeEvent e) {316JSlider slider = (JSlider) e.getSource();317int value = slider.getValue();318TitledBorder tb = (TitledBorder) slider.getBorder();319tb.setTitle("Anim delay = " + String.valueOf(value) + " ms");320intro.surface.sleepAmt = (long) value;321slider.repaint();322}323} // End ScenesTable class324325326/**327* Surface is the stage where the Director plays its scenes.328*/329static class Surface extends JPanel implements Runnable {330331private final Image dukeanim, duke;332private BufferedImage bimg;333public Director director;334public int index;335public long sleepAmt = 30;336private Thread thread;337338@SuppressWarnings("LeakingThisInConstructor")339public Surface() {340setBackground(myBlack);341setLayout(new BorderLayout());342addMouseListener(new MouseAdapter() {343344@Override345public void mouseClicked(MouseEvent e) {346if (thread == null) {347start();348} else {349stop();350}351}352});353dukeanim = DemoImages.getImage("duke.running.gif", this);354duke = DemoImages.getImage("duke.png", this);355director = new Director(this);356}357358public FontMetrics getMetrics(Font font) {359return getFontMetrics(font);360}361362@Override363public void paint(Graphics g) {364Dimension d = getSize();365if (d.width <= 0 || d.height <= 0) {366return;367}368if (bimg == null || bimg.getWidth() != d.width || bimg.getHeight()369!= d.height) {370bimg = getGraphicsConfiguration().createCompatibleImage(d.width,371d.height);372// reset future scenes373for (int i = index + 1; i < director.size(); i++) {374(director.get(i)).reset(d.width, d.height);375}376}377378Scene scene = director.get(index);379if (scene.index <= scene.length) {380if (thread != null) {381scene.step(d.width, d.height);382}383384Graphics2D g2 = bimg.createGraphics();385g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,386RenderingHints.VALUE_ANTIALIAS_ON);387g2.setBackground(getBackground());388g2.clearRect(0, 0, d.width, d.height);389390scene.render(d.width, d.height, g2);391392if (thread != null) {393// increment scene.index after scene.render394scene.index++;395}396g2.dispose();397}398g.drawImage(bimg, 0, 0, this);399}400401public void start() {402if (thread == null) {403thread = new Thread(this);404thread.setPriority(Thread.MIN_PRIORITY);405thread.setName("Intro");406thread.start();407}408}409410public synchronized void stop() {411if (thread != null) {412thread.interrupt();413}414thread = null;415notifyAll();416}417418public void reset() {419index = 0;420Dimension d = getSize();421for (Scene scene : director) {422scene.reset(d.width, d.height);423}424}425426@Override427@SuppressWarnings("SleepWhileHoldingLock")428public void run() {429430Thread me = Thread.currentThread();431432while (thread == me && !isShowing() || getSize().width <= 0) {433try {434Thread.sleep(500);435} catch (InterruptedException e) {436return;437}438}439440if (index == 0) {441reset();442}443444while (thread == me) {445Scene scene = director.get(index);446if (((Boolean) scene.participate).booleanValue()) {447repaint();448try {449Thread.sleep(sleepAmt);450} catch (InterruptedException e) {451break;452}453if (scene.index > scene.length) {454scene.pause();455if (++index >= director.size()) {456reset();457}458}459} else {460if (++index >= director.size()) {461reset();462}463}464}465thread = null;466}467468469/**470* Part is a piece of the scene. Classes must implement Part471* in order to participate in a scene.472*/473interface Part {474475public void reset(int newwidth, int newheight);476477public void step(int w, int h);478479public void render(int w, int h, Graphics2D g2);480481public int getBegin();482483public int getEnd();484}485486487/**488* Director is the holder of the scenes, their names & pause amounts489* between scenes.490*/491static class Director extends ArrayList<Scene> {492493GradientPaint gp = new GradientPaint(0, 40, myBlue, 38, 2, myBlack);494Font f1 = new Font(Font.SERIF, Font.PLAIN, 200);495Font f2 = new Font(Font.SERIF, Font.PLAIN, 120);496Font f3 = new Font(Font.SERIF, Font.PLAIN, 72);497498public Director(Surface surf) {499Object[][][] partsInfo = {500{ { "J - scale text on gradient", "0" },501{ new GpE(GpE.BURI, myBlack, myBlue, 0, 20),502new TxE("J", f1, TxE.SCI, myYellow, 2, 20) } },503{ { "2 - scale & rotate text on gradient", "0" },504{ new GpE(GpE.BURI, myBlue, myBlack, 0, 22),505new TxE("2", f1, TxE.RI | TxE.SCI, myYellow, 2, 22) } },506{ { "D - scale text on gradient", "0" },507{ new GpE(GpE.BURI, myBlack, myBlue, 0, 20),508new TxE("D", f1, TxE.SCI, myYellow, 2, 20) } },509{ { "J2D demo - scale & rotate text on gradient", "1000" },510{ new GpE(GpE.SIH, myBlue, myBlack, 0, 40),511new TxE("J2D demo", f2, TxE.RI | TxE.SCI, myYellow, 0, 40) } },512{ { "Previous scene dither dissolve out", "0" },513{ new DdE(0, 20, 1, surf) } },514{ { "Graphics Features", "999" },515{ new Temp(Temp.RECT, null, 0, 15),516new Temp(Temp.IMG, surf.duke, 2, 15),517new Temp(Temp.RNA | Temp.INA, surf.duke, 16, 130),518new Features(Features.GRAPHICS, 16, 130, surf) } },519{ { "J2D demo - texture text on gradient", "1000" },520{ new GpE(GpE.WI, myBlue, myBlack, 0, 20),521new GpE(GpE.WD, myBlue, myBlack, 21, 40),522new TpE(TpE.OI | TpE.NF, myBlack, myYellow, 4, 0, 10),523new TpE(TpE.OD | TpE.NF, myBlack, myYellow, 4, 11, 20),524new TpE(TpE.OI | TpE.NF | TpE.HAF, myBlack, myYellow, 5,52521, 40),526new TxE("J2D demo", f2, 0, null, 0, 40) } },527{ { "Previous scene random close out", "0" },528{ new CoE(CoE.RAND, 0, 20, surf) } },529{ { "Text Features", "999" },530{ new Temp(Temp.RECT, null, 0, 15),531new Temp(Temp.IMG, surf.duke, 2, 15),532new Temp(Temp.RNA | Temp.INA, surf.duke, 16, 130),533new Features(Features.TEXT, 16, 130, surf) } },534{ { "J2D demo - composite text on texture", "1000" },535{ new TpE(TpE.RI, myBlack, gp, 40, 0, 20),536new TpE(TpE.RD, myBlack, gp, 40, 21, 40),537new TpE(TpE.RI, myBlack, gp, 40, 41, 60),538new TxE("J2D demo", f2, TxE.AC, myYellow, 0, 60) } },539{ { "Previous scene dither dissolve out", "0" },540{ new DdE(0, 20, 4, surf) } },541{ { "Imaging Features", "999" },542{ new Temp(Temp.RECT, null, 0, 15),543new Temp(Temp.IMG, surf.duke, 2, 15),544new Temp(Temp.RNA | Temp.INA, surf.duke, 16, 130),545new Features(Features.IMAGES, 16, 130, surf) } },546{ { "J2D demo - text on gradient", "1000" },547{ new GpE(GpE.SDH, myBlue, myBlack, 0, 20),548new GpE(GpE.SIH, myBlue, myBlack, 21, 40),549new GpE(GpE.SDH, myBlue, myBlack, 41, 50),550new GpE(GpE.INC | GpE.NF, myRed, myYellow, 0, 50),551new TxE("J2D demo", f2, TxE.NOP, null, 0, 50) } },552{ { "Previous scene ellipse close out", "0" },553{ new CoE(CoE.OVAL, 0, 20, surf) } },554{ { "Color Features", "999" },555{ new Temp(Temp.RECT, null, 0, 15),556new Temp(Temp.IMG, surf.duke, 2, 15),557new Temp(Temp.RNA | Temp.INA, surf.duke, 16, 99),558new Features(Features.COLOR, 16, 99, surf) } },559{ { "J2D demo - composite and rotate text on paints", "2000" },560{ new GpE(GpE.BURI, myBlack, myBlue, 0, 20),561new GpE(GpE.BURD, myBlack, myBlue, 21, 30),562new TpE(TpE.OI | TpE.HAF, myBlack, myBlue, 10, 31, 40),563new TxE("J2D demo", f2, TxE.AC | TxE.RI, myYellow, 0, 40) } },564{ { "Previous scene subimage transform out", "0" },565{ new SiE(60, 60, 0, 40, surf) } },566{ { "CREDITS - transform in", "1000" },567{ new LnE(LnE.ACI | LnE.ZOOMI | LnE.RI, 0, 60),568new TxE("CREDITS", f3, TxE.AC | TxE.SCI, RED, 20, 30),569new TxE("CREDITS", f3, TxE.SCXD, RED, 31, 38),570new TxE("CREDITS", f3, TxE.SCXI, RED, 39, 48),571new TxE("CREDITS", f3, TxE.SCXD, RED, 49, 54),572new TxE("CREDITS", f3, TxE.SCXI, RED, 55, 60) } },573{ { "CREDITS - transform out", "0" },574{ new LnE(LnE.ACD | LnE.ZOOMD | LnE.RD, 0, 45),575new TxE("CREDITS", f3, 0, RED, 0, 9),576new TxE("CREDITS", f3, TxE.SCD | TxE.RD, RED, 10, 30) } },577{ { "Contributors", "1000" },578{ new Temp(Temp.RECT, null, 0, 30),579new Temp(Temp.IMG, surf.dukeanim, 4, 30),580new Temp(Temp.RNA | Temp.INA, surf.dukeanim, 31, 200),581new Contributors(34, 200, surf) } }, };582583for (Object[][] partInfo : partsInfo) {584List<Part> parts = new ArrayList<Part>();585for (Object part : partInfo[1]) {586parts.add((Part) part);587}588add(new Scene(parts, partInfo[0][0], partInfo[0][1]));589}590}591}592593594/**595* Scene is the manager of the parts.596*/597static class Scene extends Object {598599public Object name;600public Object participate = Boolean.TRUE;601public Object pauseAmt;602public List<Part> parts;603public int index;604public int length;605606public Scene(List<Part> parts, Object name, Object pauseAmt) {607this.name = name;608this.parts = parts;609this.pauseAmt = pauseAmt;610for (Part part : parts) {611int partLength = part.getEnd();612if (partLength > length) {613length = partLength;614}615}616}617618public void reset(int w, int h) {619index = 0;620for (int i = 0; i < parts.size(); i++) {621(parts.get(i)).reset(w, h);622}623}624625public void step(int w, int h) {626for (int i = 0; i < parts.size(); i++) {627Part part = parts.get(i);628if (index >= part.getBegin() && index <= part.getEnd()) {629part.step(w, h);630}631}632}633634public void render(int w, int h, Graphics2D g2) {635for (int i = 0; i < parts.size(); i++) {636Part part = parts.get(i);637if (index >= part.getBegin() && index <= part.getEnd()) {638part.render(w, h, g2);639}640}641}642643public void pause() {644try {645Thread.sleep(Long.parseLong((String) pauseAmt));646} catch (Exception ignored) {647}648System.gc();649}650} // End Scene class651652653/**654* Text Effect. Transformation of characters. Clip or fill.655*/656static final class TxE implements Part {657658static final int INC = 1;659static final int DEC = 2;660static final int R = 4; // rotate661static final int RI = R | INC;662static final int RD = R | DEC;663static final int SC = 8; // scale664static final int SCI = SC | INC;665static final int SCD = SC | DEC;666static final int SCX = 16; // scale invert x667static final int SCXI = SCX | SC | INC;668static final int SCXD = SCX | SC | DEC;669static final int SCY = 32; // scale invert y670static final int SCYI = SCY | SC | INC;671static final int SCYD = SCY | SC | DEC;672static final int AC = 64; // AlphaComposite673static final int CLIP = 128; // Clipping674static final int NOP = 512; // No Paint675private int beginning, ending;676private int type;677private double rIncr, sIncr;678private double sx, sy, rotate;679private Shape[] shapes, txShapes;680private int sw;681private int numRev;682private Paint paint;683684public TxE(String text,685Font font,686int type,687Paint paint,688int beg,689int end) {690this.type = type;691this.paint = paint;692this.beginning = beg;693this.ending = end;694695setIncrements(2);696697char[] chars = text.toCharArray();698shapes = new Shape[chars.length];699txShapes = new Shape[chars.length];700FontRenderContext frc = new FontRenderContext(null, true, true);701TextLayout tl = new TextLayout(text, font, frc);702sw = (int) tl.getOutline(null).getBounds().getWidth();703for (int j = 0; j < chars.length; j++) {704String s = String.valueOf(chars[j]);705shapes[j] = new TextLayout(s, font, frc).getOutline(null);706}707}708709public void setIncrements(double numRevolutions) {710this.numRev = (int) numRevolutions;711rIncr = 360.0 / ((ending - beginning) / numRevolutions);712sIncr = 1.0 / (ending - beginning);713if ((type & SCX) != 0 || (type & SCY) != 0) {714sIncr *= 2;715}716if ((type & DEC) != 0) {717rIncr = -rIncr;718sIncr = -sIncr;719}720}721722@Override723public void reset(int w, int h) {724if (type == SCXI) {725sx = -1.0;726sy = 1.0;727} else if (type == SCYI) {728sx = 1.0;729sy = -1.0;730} else {731sx = sy = (type & DEC) != 0 ? 1.0 : 0.0;732}733rotate = 0;734}735736@Override737public void step(int w, int h) {738739float charWidth = w / 2 - sw / 2;740741for (int i = 0; i < shapes.length; i++) {742AffineTransform at = new AffineTransform();743Rectangle2D maxBounds = shapes[i].getBounds();744at.translate(charWidth, h / 2 + maxBounds.getHeight() / 2);745charWidth += (float) maxBounds.getWidth() + 1;746Shape shape = at.createTransformedShape(shapes[i]);747Rectangle2D b1 = shape.getBounds2D();748749if ((type & R) != 0) {750at.rotate(Math.toRadians(rotate));751}752if ((type & SC) != 0) {753at.scale(sx, sy);754}755shape = at.createTransformedShape(shapes[i]);756Rectangle2D b2 = shape.getBounds2D();757758double xx = (b1.getX() + b1.getWidth() / 2)759- (b2.getX() + b2.getWidth() / 2);760double yy = (b1.getY() + b1.getHeight() / 2)761- (b2.getY() + b2.getHeight() / 2);762AffineTransform toCenterAT = new AffineTransform();763toCenterAT.translate(xx, yy);764toCenterAT.concatenate(at);765txShapes[i] = toCenterAT.createTransformedShape(shapes[i]);766}767// avoid over rotation768if (Math.abs(rotate) <= numRev * 360) {769rotate += rIncr;770if ((type & SCX) != 0) {771sx += sIncr;772} else if ((type & SCY) != 0) {773sy += sIncr;774} else {775sx += sIncr;776sy += sIncr;777}778}779}780781@Override782public void render(int w, int h, Graphics2D g2) {783Composite saveAC = null;784if ((type & AC) != 0 && sx > 0 && sx < 1) {785saveAC = g2.getComposite();786g2.setComposite(AlphaComposite.getInstance(787AlphaComposite.SRC_OVER, (float) sx));788}789GeneralPath path = null;790if ((type & CLIP) != 0) {791path = new GeneralPath();792}793if (paint != null) {794g2.setPaint(paint);795}796for (int i = 0; i < txShapes.length; i++) {797if ((type & CLIP) != 0) {798path.append(txShapes[i], false);799} else {800g2.fill(txShapes[i]);801}802}803if ((type & CLIP) != 0) {804g2.clip(path);805}806if (saveAC != null) {807g2.setComposite(saveAC);808}809}810811@Override812public int getBegin() {813return beginning;814}815816@Override817public int getEnd() {818return ending;819}820} // End TxE class821822823/**824* GradientPaint Effect. Burst, split, horizontal and825* vertical gradient fill effects.826*/827static class GpE implements Part {828829static final int INC = 1; // increasing830static final int DEC = 2; // decreasing831static final int CNT = 4; // center832static final int WID = 8; // width833static final int WI = WID | INC;834static final int WD = WID | DEC;835static final int HEI = 16; // height836static final int HI = HEI | INC;837static final int HD = HEI | DEC;838static final int SPL = 32 | CNT; // split839static final int SIW = SPL | INC | WID;840static final int SDW = SPL | DEC | WID;841static final int SIH = SPL | INC | HEI;842static final int SDH = SPL | DEC | HEI;843static final int BUR = 64 | CNT; // burst844static final int BURI = BUR | INC;845static final int BURD = BUR | DEC;846static final int NF = 128; // no fill847private Color c1, c2;848private int beginning, ending;849private float incr, index;850private List<Rectangle2D> rect = new ArrayList<Rectangle2D>();851private List<GradientPaint> grad = new ArrayList<GradientPaint>();852private int type;853854public GpE(int type, Color c1, Color c2, int beg, int end) {855this.type = type;856this.c1 = c1;857this.c2 = c2;858this.beginning = beg;859this.ending = end;860}861862@Override863public void reset(int w, int h) {864incr = 1.0f / (ending - beginning);865if ((type & CNT) != 0) {866incr /= 2.3f;867}868if ((type & CNT) != 0 && (type & INC) != 0) {869index = 0.5f;870} else if ((type & DEC) != 0) {871index = 1.0f;872incr = -incr;873} else {874index = 0.0f;875}876index += incr;877}878879@Override880public void step(int w, int h) {881rect.clear();882grad.clear();883884if ((type & WID) != 0) {885float w2 = 0, x1 = 0, x2 = 0;886if ((type & SPL) != 0) {887w2 = w * 0.5f;888x1 = w * (1.0f - index);889x2 = w * index;890} else {891w2 = w * index;892x1 = x2 = w2;893}894rect.add(new Rectangle2D.Float(0, 0, w2, h));895rect.add(new Rectangle2D.Float(w2, 0, w - w2, h));896grad.add(new GradientPaint(0, 0, c1, x1, 0, c2));897grad.add(new GradientPaint(x2, 0, c2, w, 0, c1));898} else if ((type & HEI) != 0) {899float h2 = 0, y1 = 0, y2 = 0;900if ((type & SPL) != 0) {901h2 = h * 0.5f;902y1 = h * (1.0f - index);903y2 = h * index;904} else {905h2 = h * index;906y1 = y2 = h2;907}908rect.add(new Rectangle2D.Float(0, 0, w, h2));909rect.add(new Rectangle2D.Float(0, h2, w, h - h2));910grad.add(new GradientPaint(0, 0, c1, 0, y1, c2));911grad.add(new GradientPaint(0, y2, c2, 0, h, c1));912} else if ((type & BUR) != 0) {913914float w2 = w / 2;915float h2 = h / 2;916917rect.add(new Rectangle2D.Float(0, 0, w2, h2));918rect.add(new Rectangle2D.Float(w2, 0, w2, h2));919rect.add(new Rectangle2D.Float(0, h2, w2, h2));920rect.add(new Rectangle2D.Float(w2, h2, w2, h2));921922float x1 = w * (1.0f - index);923float x2 = w * index;924float y1 = h * (1.0f - index);925float y2 = h * index;926927grad.add(new GradientPaint(0, 0, c1, x1, y1, c2));928grad.add(new GradientPaint(w, 0, c1, x2, y1, c2));929grad.add(new GradientPaint(0, h, c1, x1, y2, c2));930grad.add(new GradientPaint(w, h, c1, x2, y2, c2));931} else if ((type & NF) != 0) {932float y = h * index;933grad.add(new GradientPaint(0, 0, c1, 0, y, c2));934}935936if ((type & INC) != 0 || (type & DEC) != 0) {937index += incr;938}939}940941@Override942public void render(int w, int h, Graphics2D g2) {943g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,944RenderingHints.VALUE_ANTIALIAS_OFF);945for (int i = 0; i < grad.size(); i++) {946g2.setPaint(grad.get(i));947if ((type & NF) == 0) {948g2.fill(rect.get(i));949}950}951g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,952RenderingHints.VALUE_ANTIALIAS_ON);953}954955@Override956public int getBegin() {957return beginning;958}959960@Override961public int getEnd() {962return ending;963}964} // End GpE class965966967/**968* TexturePaint Effect. Expand and collapse a texture.969*/970static final class TpE implements Part {971972static final int INC = 1; // increasing973static final int DEC = 2; // decreasing974static final int OVAL = 4; // oval975static final int RECT = 8; // rectangle976static final int HAF = 16; // half oval or rect size977static final int NF = 32; // no fill978static final int OI = OVAL | INC;979static final int OD = OVAL | DEC;980static final int RI = RECT | INC;981static final int RD = RECT | DEC;982private Paint p1, p2;983private int beginning, ending;984private float incr, index;985private TexturePaint texture;986private int type;987private int size;988private BufferedImage bimg;989private Rectangle rect;990991public TpE(int type, Paint p1, Paint p2, int size,992int beg, int end) {993this.type = type;994this.p1 = p1;995this.p2 = p2;996this.beginning = beg;997this.ending = end;998setTextureSize(size);999}10001001public void setTextureSize(int size) {1002this.size = size;1003bimg = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);1004rect = new Rectangle(0, 0, size, size);1005}10061007@Override1008public void reset(int w, int h) {1009incr = (float) (size) / (float) (ending - beginning);1010if ((type & HAF) != 0) {1011incr /= 2;1012}1013if ((type & DEC) != 0) {1014index = size;1015if ((type & HAF) != 0) {1016index /= 2;1017}1018incr = -incr;1019} else {1020index = 0.0f;1021}1022index += incr;1023}10241025@Override1026public void step(int w, int h) {1027Graphics2D g2 = bimg.createGraphics();1028g2.setPaint(p1);1029g2.fillRect(0, 0, size, size);1030g2.setPaint(p2);1031if ((type & OVAL) != 0) {1032g2.fill(new Ellipse2D.Float(0, 0, index, index));1033} else if ((type & RECT) != 0) {1034g2.fill(new Rectangle2D.Float(0, 0, index, index));1035}1036texture = new TexturePaint(bimg, rect);1037g2.dispose();1038index += incr;1039}10401041@Override1042public void render(int w, int h, Graphics2D g2) {1043g2.setPaint(texture);1044if ((type & NF) == 0) {1045g2.fillRect(0, 0, w, h);1046}1047}10481049@Override1050public int getBegin() {1051return beginning;1052}10531054@Override1055public int getEnd() {1056return ending;1057}1058} // End TpE class105910601061/**1062* Close out effect. Close out the buffered image with different1063* geometry shapes.1064*/1065static class CoE implements Part {1066private final Surface surf;1067static final int WID = 1;1068static final int HEI = 2;1069static final int OVAL = 4;1070static final int RECT = 8;1071static final int RAND = 16;1072static final int ARC = 32;1073private int type;1074private int beginning, ending;1075private BufferedImage bimg;1076private Shape shape;1077private double zoom, extent;1078private double zIncr, eIncr;1079private boolean doRandom;10801081public CoE(int type, int beg, int end, Surface surf) {1082this.type = type;1083this.beginning = beg;1084this.ending = end;1085this.surf = surf;1086zIncr = -(2.0 / (ending - beginning));1087eIncr = 360.0 / (ending - beginning);1088doRandom = (type & RAND) != 0;1089}10901091@Override1092public void reset(int w, int h) {1093if (doRandom) {1094int num = (int) (Math.random() * 5.0);1095switch (num) {1096case 0:1097type = OVAL;1098break;1099case 1:1100type = RECT;1101break;1102case 2:1103type = RECT | WID;1104break;1105case 3:1106type = RECT | HEI;1107break;1108case 4:1109type = ARC;1110break;1111default:1112type = OVAL;1113}1114}1115shape = null;1116bimg = null;1117extent = 360.0;1118zoom = 2.0;1119}11201121@Override1122public void step(int w, int h) {1123if (bimg == null) {1124int biw = surf.bimg.getWidth();1125int bih = surf.bimg.getHeight();1126bimg = new BufferedImage(biw, bih,1127BufferedImage.TYPE_INT_RGB);1128Graphics2D big = bimg.createGraphics();1129big.drawImage(surf.bimg, 0, 0, null);1130}1131double z = Math.min(w, h) * zoom;1132if ((type & OVAL) != 0) {1133shape = new Ellipse2D.Double(w / 2 - z / 2, h / 2 - z / 2, z,1134z);1135} else if ((type & ARC) != 0) {1136shape = new Arc2D.Double(-100, -100, w + 200, h + 200, 90,1137extent, Arc2D.PIE);1138extent -= eIncr;1139} else if ((type & RECT) != 0) {1140if ((type & WID) != 0) {1141shape = new Rectangle2D.Double(w / 2 - z / 2, 0, z, h);1142} else if ((type & HEI) != 0) {1143shape = new Rectangle2D.Double(0, h / 2 - z / 2, w, z);1144} else {1145shape = new Rectangle2D.Double(w / 2 - z / 2, h / 2 - z1146/ 2, z, z);1147}1148}1149zoom += zIncr;1150}11511152@Override1153public void render(int w, int h, Graphics2D g2) {1154g2.clip(shape);1155g2.drawImage(bimg, 0, 0, null);1156}11571158@Override1159public int getBegin() {1160return beginning;1161}11621163@Override1164public int getEnd() {1165return ending;1166}1167} // End CoE class116811691170/**1171* Dither Dissolve Effect. For each successive step in the animation,1172* a pseudo-random starting horizontal position is chosen using list,1173* and then the corresponding points created from xlist and ylist are1174* blacked out for the current "chunk". The x and y chunk starting1175* positions are each incremented by the associated chunk size, and1176* this process is repeated for the number of "steps" in the1177* animation, causing an equal number of pseudo-randomly picked1178* "blocks" to be blacked out during each step of the animation.1179*/1180static class DdE implements Part {1181private final Surface surf;1182private int beginning, ending;1183private BufferedImage bimg;1184private Graphics2D big;1185private List<Integer> list, xlist, ylist;1186private int xeNum, yeNum; // element number1187private int xcSize, ycSize; // chunk size1188private int inc;1189private int blocksize;11901191public DdE(int beg, int end, int blocksize, Surface surf) {1192this.beginning = beg;1193this.ending = end;1194this.blocksize = blocksize;1195this.surf = surf;1196}11971198private void createShuffledLists() {1199int width = bimg.getWidth();1200int height = bimg.getHeight();1201xlist = new ArrayList<Integer>(width);1202ylist = new ArrayList<Integer>(height);1203list = new ArrayList<Integer>(ending - beginning + 1);1204for (int i = 0; i < width; i++) {1205xlist.add(i, i);1206}1207for (int i = 0; i < height; i++) {1208ylist.add(i, i);1209}1210for (int i = 0; i < (ending - beginning + 1); i++) {1211list.add(i, i);1212}1213java.util.Collections.shuffle(xlist);1214java.util.Collections.shuffle(ylist);1215java.util.Collections.shuffle(list);1216}12171218@Override1219public void reset(int w, int h) {1220bimg = null;1221}12221223@Override1224public void step(int w, int h) {1225if (inc > ending) {1226bimg = null;1227}1228if (bimg == null) {1229int biw = surf.bimg.getWidth();1230int bih = surf.bimg.getHeight();1231bimg = new BufferedImage(biw, bih,1232BufferedImage.TYPE_INT_RGB);1233createShuffledLists();1234big = bimg.createGraphics();1235big.drawImage(surf.bimg, 0, 0, null);1236xcSize = (xlist.size() / (ending - beginning)) + 1;1237ycSize = (ylist.size() / (ending - beginning)) + 1;1238xeNum = 0;1239inc = 0;1240}1241xeNum = xcSize * (list.get(inc)).intValue();1242yeNum = -ycSize;1243inc++;1244}12451246@Override1247public void render(int w, int h, Graphics2D g2) {1248big.setColor(myBlack);12491250for (int k = 0; k <= (ending - beginning); k++) {1251if ((xeNum + xcSize) > xlist.size()) {1252xeNum = 0;1253} else {1254xeNum += xcSize;1255}1256yeNum += ycSize;12571258for (int i = xeNum; i < xeNum + xcSize && i < xlist.size();1259i++) {1260for (int j = yeNum; j < yeNum + ycSize && j1261< ylist.size(); j++) {1262int xval = (xlist.get(i)).intValue();1263int yval = (ylist.get(j)).intValue();1264if (((xval % blocksize) == 0) && ((yval % blocksize)1265== 0)) {1266big.fillRect(xval, yval, blocksize, blocksize);1267}1268}1269}1270}12711272g2.drawImage(bimg, 0, 0, null);1273}12741275@Override1276public int getBegin() {1277return beginning;1278}12791280@Override1281public int getEnd() {1282return ending;1283}1284} // End DdE class128512861287/**1288* Subimage effect. Subimage the scene's buffered1289* image then rotate and scale down the subimages.1290*/1291static class SiE implements Part {1292private final Surface surf;1293private int beginning, ending;1294private BufferedImage bimg;1295private double rIncr, sIncr;1296private double scale, rotate;1297private int siw, sih;1298private List<BufferedImage> subs = new ArrayList<BufferedImage>(20);1299private List<Point> pts = new ArrayList<Point>(20);13001301public SiE(int siw, int sih, int beg, int end, Surface surf) {1302this.siw = siw;1303this.sih = sih;1304this.beginning = beg;1305this.ending = end;1306this.surf = surf;1307rIncr = 360.0 / (ending - beginning);1308sIncr = 1.0 / (ending - beginning);1309}13101311@Override1312public void reset(int w, int h) {1313scale = 1.0;1314rotate = 0.0;1315bimg = null;1316subs.clear();1317pts.clear();1318}13191320@Override1321public void step(int w, int h) {1322if (bimg == null) {1323int biw = surf.bimg.getWidth();1324int bih = surf.bimg.getHeight();1325bimg = new BufferedImage(biw, bih,1326BufferedImage.TYPE_INT_RGB);1327Graphics2D big = bimg.createGraphics();1328big.drawImage(surf.bimg, 0, 0, null);1329for (int x = 0; x < w && scale > 0.0; x += siw) {1330int ww = x + siw < w ? siw : w - x;1331for (int y = 0; y < h; y += sih) {1332int hh = y + sih < h ? sih : h - y;1333subs.add(bimg.getSubimage(x, y, ww, hh));1334pts.add(new Point(x, y));1335}1336}1337}13381339rotate += rIncr;1340scale -= sIncr;1341}13421343@Override1344public void render(int w, int h, Graphics2D g2) {1345AffineTransform saveTx = g2.getTransform();1346g2.setColor(myBlue);1347for (int i = 0; i < subs.size() && scale > 0.0; i++) {1348BufferedImage bi = subs.get(i);1349Point p = pts.get(i);1350int ww = bi.getWidth();1351int hh = bi.getHeight();1352AffineTransform at = new AffineTransform();1353at.rotate(Math.toRadians(rotate), p.x + ww / 2, p.y + hh / 2);1354at.translate(p.x, p.y);1355at.scale(scale, scale);13561357Rectangle b1 = new Rectangle(0, 0, ww, hh);1358Shape shape = at.createTransformedShape(b1);1359Rectangle2D b2 = shape.getBounds2D();1360double xx = (p.x + ww / 2) - (b2.getX() + b2.getWidth() / 2);1361double yy = (p.y + hh / 2)1362- (b2.getY() + b2.getHeight() / 2);1363AffineTransform toCenterAT = new AffineTransform();1364toCenterAT.translate(xx, yy);1365toCenterAT.concatenate(at);13661367g2.setTransform(toCenterAT);1368g2.drawImage(bi, 0, 0, null);1369g2.draw(b1);1370}1371g2.setTransform(saveTx);1372}13731374@Override1375public int getBegin() {1376return beginning;1377}13781379@Override1380public int getEnd() {1381return ending;1382}1383} // End SiE class138413851386/**1387* Line Effect. Flattened ellipse with lines from the center1388* to the edge. Expand or collapse the ellipse. Fade in or out1389* the lines.1390*/1391static class LnE implements Part {13921393static final int INC = 1;1394static final int DEC = 2;1395static final int R = 4; // rotate1396static final int ZOOM = 8; // zoom1397static final int AC = 32; // AlphaComposite1398static final int RI = R | INC;1399static final int RD = R | DEC;1400static final int ZOOMI = ZOOM | INC;1401static final int ZOOMD = ZOOM | DEC;1402static final int ACI = AC | INC;1403static final int ACD = AC | DEC;1404private int beginning, ending;1405private double rIncr, rotate;1406private double zIncr, zoom;1407private List<Point2D.Double> pts = new ArrayList<Point2D.Double>();1408private float alpha, aIncr;1409private int type;14101411public LnE(int type, int beg, int end) {1412this.type = type;1413this.beginning = beg;1414this.ending = end;1415float range = ending - beginning;1416rIncr = 360.0f / range;1417aIncr = 0.9f / range;1418zIncr = 2.0f / range;1419if ((type & DEC) != 0) {1420rIncr = -rIncr;1421aIncr = -aIncr;1422zIncr = -zIncr;1423}1424}14251426public void generatePts(int w, int h, double sizeF) {1427pts.clear();1428double size = Math.min(w, h) * sizeF;1429Ellipse2D ellipse = new Ellipse2D.Double(w / 2 - size / 2, h / 2 - size1430/ 2, size, size);1431PathIterator pi = ellipse.getPathIterator(null, 0.8);1432while (!pi.isDone()) {1433double[] pt = new double[6];1434switch (pi.currentSegment(pt)) {1435case FlatteningPathIterator.SEG_MOVETO:1436case FlatteningPathIterator.SEG_LINETO:1437pts.add(new Point2D.Double(pt[0], pt[1]));1438}1439pi.next();1440}1441}14421443@Override1444public void reset(int w, int h) {1445if ((type & DEC) != 0) {1446rotate = 360;1447alpha = 1.0f;1448zoom = 2.0;1449} else {1450rotate = alpha = 0;1451zoom = 0;1452}1453if ((type & ZOOM) == 0) {1454generatePts(w, h, 0.5);1455}1456}14571458@Override1459public void step(int w, int h) {1460if ((type & ZOOM) != 0) {1461generatePts(w, h, zoom += zIncr);1462}1463if ((type & RI) != 0 || (type & RI) != 0) {1464rotate += rIncr;1465}1466if ((type & ACI) != 0 || (type & ACD) != 0) {1467alpha += aIncr;1468}1469}14701471@Override1472public void render(int w, int h, Graphics2D g2) {1473Composite saveAC = null;1474if ((type & AC) != 0 && alpha >= 0 && alpha <= 1) {1475saveAC = g2.getComposite();1476g2.setComposite(AlphaComposite.getInstance(1477AlphaComposite.SRC_OVER, alpha));1478}1479AffineTransform saveTx = null;1480if ((type & R) != 0) {1481saveTx = g2.getTransform();1482AffineTransform at = new AffineTransform();1483at.rotate(Math.toRadians(rotate), w / 2, h / 2);1484g2.setTransform(at);1485}1486Point2D p1 = new Point2D.Double(w / 2, h / 2);1487g2.setColor(YELLOW);1488for (Point2D pt : pts) {1489g2.draw(new Line2D.Float(p1, pt));1490}1491if (saveTx != null) {1492g2.setTransform(saveTx);1493}1494if (saveAC != null) {1495g2.setComposite(saveAC);1496}1497}14981499@Override1500public int getBegin() {1501return beginning;1502}15031504@Override1505public int getEnd() {1506return ending;1507}1508} // End LnE class150915101511/**1512* Template for Features & Contributors consisting of translating1513* blue and red rectangles and an image going from transparent to1514* opaque.1515*/1516static class Temp implements Part {15171518static final int NOANIM = 1;1519static final int RECT = 2;1520static final int IMG = 4;1521static final int RNA = RECT | NOANIM;1522static final int INA = IMG | NOANIM;1523private int beginning, ending;1524private float alpha, aIncr;1525private int type;1526private Rectangle rect1, rect2;1527private int x, y, xIncr, yIncr;1528private Image img;15291530public Temp(int type, Image img, int beg, int end) {1531this.type = type;1532this.img = img;1533this.beginning = beg;1534this.ending = end;1535aIncr = 0.9f / (ending - beginning);1536if ((type & NOANIM) != 0) {1537alpha = 1.0f;1538}1539}15401541@Override1542public void reset(int w, int h) {1543rect1 = new Rectangle(8, 20, w - 20, 30);1544rect2 = new Rectangle(20, 8, 30, h - 20);1545if ((type & NOANIM) == 0) {1546alpha = 0.0f;1547xIncr = w / (ending - beginning);1548yIncr = h / (ending - beginning);1549x = w + (int) (xIncr * 1.4);1550y = h + (int) (yIncr * 1.4);1551}1552}15531554@Override1555public void step(int w, int h) {1556if ((type & NOANIM) != 0) {1557return;1558}1559if ((type & RECT) != 0) {1560rect1.setLocation(x -= xIncr, 20);1561rect2.setLocation(20, y -= yIncr);1562}1563if ((type & IMG) != 0) {1564alpha += aIncr;1565}1566}15671568@Override1569public void render(int w, int h, Graphics2D g2) {1570if ((type & RECT) != 0) {1571g2.setColor(myBlue);1572g2.fill(rect1);1573g2.setColor(myRed);1574g2.fill(rect2);1575}1576if ((type & IMG) != 0) {1577Composite saveAC = g2.getComposite();1578if (alpha >= 0 && alpha <= 1) {1579g2.setComposite(AlphaComposite.getInstance(1580AlphaComposite.SRC_OVER, alpha));1581}1582g2.drawImage(img, 30, 30, null);1583g2.setComposite(saveAC);1584}1585}15861587@Override1588public int getBegin() {1589return beginning;1590}15911592@Override1593public int getEnd() {1594return ending;1595}1596} // End Temp class159715981599/**1600* Features of Java2D(TM). Single character advancement effect.1601*/1602static class Features implements Part {16031604static final int GRAPHICS = 0;1605static final int TEXT = 1;1606static final int IMAGES = 2;1607static final int COLOR = 3;1608static final Font font1 = new Font(Font.SERIF, Font.BOLD, 38);1609static final Font font2 = new Font(Font.SERIF, Font.PLAIN, 24);1610private final FontMetrics fm1;1611private final FontMetrics fm2;1612private static final String[][] table = { { "Graphics", "Antialiased rendering",1613"Bezier paths",1614"Transforms", "Compositing", "Stroking parameters" },1615{ "Text", "Extended font support",1616"Advanced text layout", "Dynamic font loading",1617"AttributeSets for font customization" },1618{ "Images", "Flexible image layouts",1619"Extended imaging operations",1620" Convolutions, Lookup Tables",1621"RenderableImage interface" },1622{ "Color", "ICC profile support", "Color conversion",1623"Arbitrary color spaces" } };1624private String[] list;1625private int beginning, ending;1626private int strH;1627private int endIndex, listIndex;1628private List<String> v = new ArrayList<String>();16291630public Features(int type, int beg, int end, Surface surf) {1631list = table[type];1632this.beginning = beg;1633this.ending = end;1634fm1 = surf.getMetrics(font1);1635fm2 = surf.getMetrics(font2);1636}16371638@Override1639public void reset(int w, int h) {1640strH = (fm2.getAscent() + fm2.getDescent());1641endIndex = 1;1642listIndex = 0;1643v.clear();1644v.add(list[listIndex].substring(0, endIndex));1645}16461647@Override1648public void step(int w, int h) {1649if (listIndex < list.length) {1650if (++endIndex > list[listIndex].length()) {1651if (++listIndex < list.length) {1652endIndex = 1;1653v.add(list[listIndex].substring(0, endIndex));1654}1655} else {1656v.set(listIndex, list[listIndex].substring(0, endIndex));1657}1658}1659}16601661@Override1662public void render(int w, int h, Graphics2D g2) {1663g2.setColor(myWhite);1664g2.setFont(font1);1665g2.drawString(v.get(0), 90, 85);1666g2.setFont(font2);1667for (int i = 1, y = 90; i < v.size(); i++) {1668g2.drawString(v.get(i), 120, y += strH);1669}1670}16711672@Override1673public int getBegin() {1674return beginning;1675}16761677@Override1678public int getEnd() {1679return ending;1680}1681} // End Features class168216831684/**1685* Scrolling text of Java2D(TM) contributors.1686*/1687static class Contributors implements Part {16881689private static final String[] members = {1690"Brian Lichtenwalter", "Jeannette Hung",1691"Thanh Nguyen", "Jim Graham", "Jerry Evans",1692"John Raley", "Michael Peirce", "Robert Kim",1693"Jennifer Ball", "Deborah Adair", "Paul Charlton",1694"Dmitry Feld", "Gregory Stone", "Richard Blanchard",1695"Link Perry", "Phil Race", "Vincent Hardy",1696"Parry Kejriwal", "Doug Felt", "Rekha Rangarajan",1697"Paula Patel", "Michael Bundschuh", "Joe Warzecha",1698"Joey Beheler", "Aastha Bhardwaj", "Daniel Rice",1699"Chris Campbell", "Shinsuke Fukuda", "Dmitri Trembovetski",1700"Chet Haase", "Jennifer Godinez", "Nicholas Talian",1701"Raul Vera", "Ankit Patel", "Ilya Bagrak",1702"Praveen Mohan", "Rakesh Menon"1703};1704private static final Font font = new Font(Font.SERIF, Font.PLAIN, 26);1705private final FontMetrics fm;1706private int beginning, ending;1707private int nStrs, strH, index, yh, height;1708private List<String> v = new ArrayList<String>();1709private List<String> cast =1710new ArrayList<String>(members.length + 3);1711private int counter, cntMod;1712private GradientPaint gp;17131714public Contributors(int beg, int end, Surface surf) {1715this.beginning = beg;1716this.ending = end;1717fm = surf.getMetrics(font);1718java.util.Arrays.sort(members);1719cast.add("CONTRIBUTORS");1720cast.add(" ");1721cast.addAll(Arrays.asList(members));1722cast.add(" ");1723cast.add(" ");1724cntMod = (ending - beginning) / cast.size() - 1;1725}17261727@Override1728public void reset(int w, int h) {1729v.clear();1730strH = (fm.getAscent() + fm.getDescent());1731nStrs = (h - 40) / strH + 1;1732height = strH * (nStrs - 1) + 48;1733index = 0;1734gp = new GradientPaint(0, h / 2, WHITE, 0, h + 20, BLACK);1735counter = 0;1736}17371738@Override1739public void step(int w, int h) {1740if (counter++ % cntMod == 0) {1741if (index < cast.size()) {1742v.add(cast.get(index));1743}1744if ((v.size() == nStrs || index >= cast.size()) && !v.1745isEmpty()) {1746v.remove(0);1747}1748++index;1749}1750}17511752@Override1753public void render(int w, int h, Graphics2D g2) {1754g2.setPaint(gp);1755g2.setFont(font);1756double remainder = counter % cntMod;1757double incr = 1.0 - remainder / cntMod;1758incr = incr == 1.0 ? 0 : incr;1759int y = (int) (incr * strH);17601761if (index >= cast.size()) {1762y = yh + y;1763} else {1764y = yh = height - v.size() * strH + y;1765}1766for (String s : v) {1767g2.drawString(s, w / 2 - fm.stringWidth(s) / 2, y += strH);1768}1769}17701771@Override1772public int getBegin() {1773return beginning;1774}17751776@Override1777public int getEnd() {1778return ending;1779}1780} // End Contributors class1781} // End Surface class1782} // End Intro class1783178417851786