1 /*
2  *
3  * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  *   - Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  *
12  *   - Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution.
15  *
16  *   - Neither the name of Oracle nor the names of its
17  *     contributors may be used to endorse or promote products derived
18  *     from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 
34 package java2d.demos.Clipping;
35 
36 
37 import java.awt.*;
38 import java.awt.event.*;
39 import java.awt.geom.*;
40 import java.awt.font.FontRenderContext;
41 import java.awt.font.TextLayout;
42 import javax.swing.*;
43 import java2d.AnimatingControlsSurface;
44 import java2d.CustomControls;
45 import static java.awt.Color.*;
46 
47 
48 /**
49  * Animated intersection clipping of lines, an image and a textured rectangle.
50  */
51 @SuppressWarnings("serial")
52 public class Intersection extends AnimatingControlsSurface {
53 
54     private static final int HEIGHT_DECREASE = 0;
55     private static final int HEIGHT_INCREASE = 1;
56     private static final int  WIDTH_DECREASE = 2;
57     private static final int  WIDTH_INCREASE = 3;
58 
59     private int xx, yy, ww, hh;
60     private int direction = HEIGHT_DECREASE;
61     private int angdeg;
62     private Shape textshape;
63     private double sw, sh;
64     private GeneralPath ovals;
65     private Rectangle2D rectshape;
66     protected boolean doIntersection = true;
67     protected boolean doOvals = true;
68     protected boolean doText;
69     protected boolean threeSixty;
70 
71 
Intersection()72     public Intersection() {
73         setBackground(WHITE);
74         setControls(new Component[] { new DemoControls(this) });
75     }
76 
77 
78     @Override
reset(int w, int h)79     public void reset(int w, int h) {
80         xx = yy = 0;
81         ww = w-1; hh = h;
82         direction = HEIGHT_DECREASE;
83         angdeg = 0;
84         FontRenderContext frc = new FontRenderContext(null, true, false);
85         Font f = new Font(Font.SERIF, Font.BOLD,32);
86         TextLayout tl = new TextLayout("J2D", f, frc);
87         sw = tl.getBounds().getWidth();
88         sh = tl.getBounds().getHeight();
89         int size = Math.min(w, h);
90         double sx = (size-40)/sw;
91         double sy = (size-100)/sh;
92         AffineTransform Tx = AffineTransform.getScaleInstance(sx, sy);
93         textshape = tl.getOutline(Tx);
94         rectshape = textshape.getBounds();
95         sw = rectshape.getWidth();
96         sh = rectshape.getHeight();
97         ovals = new GeneralPath();
98         ovals.append(new Ellipse2D.Double(  10,   10, 20, 20), false);
99         ovals.append(new Ellipse2D.Double(w-30,   10, 20, 20), false);
100         ovals.append(new Ellipse2D.Double(  10, h-30, 20, 20), false);
101         ovals.append(new Ellipse2D.Double(w-30, h-30, 20, 20), false);
102     }
103 
104 
105     @Override
step(int w, int h)106     public void step(int w, int h) {
107         if (direction == HEIGHT_DECREASE) {
108             yy+=2; hh-=4;
109             if (yy >= h/2) {
110                 direction = HEIGHT_INCREASE;
111             }
112         } else if (direction == HEIGHT_INCREASE) {
113             yy-=2; hh+=4;
114             if (yy <= 0) {
115                 direction = WIDTH_DECREASE;
116                 hh = h-1; yy = 0;
117             }
118         }
119         if (direction == WIDTH_DECREASE) {
120             xx+=2; ww-=4;
121             if (xx >= w/2) {
122                 direction = WIDTH_INCREASE;
123             }
124         } else if (direction == WIDTH_INCREASE) {
125             xx-=2; ww+=4;
126             if (xx <= 0) {
127                 direction = HEIGHT_DECREASE;
128                 ww = w-1; xx = 0;
129             }
130         }
131         if ((angdeg += 5) == 360) {
132             angdeg = 0;
133             threeSixty = true;
134         }
135     }
136 
137 
138     @Override
render(int w, int h, Graphics2D g2)139     public void render(int w, int h, Graphics2D g2) {
140 
141         Rectangle rect = new Rectangle(xx, yy, ww, hh);
142 
143         AffineTransform Tx = new AffineTransform();
144         Tx.rotate(Math.toRadians(angdeg),w/2,h/2);
145         Tx.translate(w/2-sw/2, sh+(h-sh)/2);
146 
147         GeneralPath path = new GeneralPath();
148         if (doOvals) {
149             path.append(ovals, false);
150         }
151         if (doText) {
152             path.append(Tx.createTransformedShape(textshape), false);
153         } else {
154             path.append(Tx.createTransformedShape(rectshape), false);
155         }
156 
157         if (doIntersection) {
158             g2.clip(rect);
159             g2.clip(path);
160         }
161 
162         g2.setColor(GREEN);
163         g2.fill(rect);
164 
165         g2.setClip(new Rectangle(0, 0, w, h));
166 
167         g2.setColor(LIGHT_GRAY);
168         g2.draw(rect);
169         g2.setColor(BLACK);
170         g2.draw(path);
171     }
172 
173 
main(String[] argv)174     public static void main(String[] argv) {
175         createDemoFrame(new Intersection());
176     }
177 
178 
179     static final class DemoControls extends CustomControls implements ActionListener {
180 
181         Intersection demo;
182         JToolBar toolbar;
183 
DemoControls(Intersection demo)184         public DemoControls(Intersection demo) {
185             super(demo.name);
186             this.demo = demo;
187             add(toolbar = new JToolBar());
188             toolbar.setFloatable(false);
189             addTool("Intersect", true );
190             addTool("Text",      false);
191             addTool("Ovals",     true );
192         }
193 
194 
addTool(String str, boolean state)195         public void addTool(String str, boolean state) {
196             JToggleButton b = (JToggleButton) toolbar.add(new JToggleButton(str));
197             b.setFocusPainted(false);
198             b.setSelected(state);
199             b.addActionListener(this);
200             int width = b.getPreferredSize().width;
201             Dimension prefSize = new Dimension(width, 21);
202             b.setPreferredSize(prefSize);
203             b.setMaximumSize(  prefSize);
204             b.setMinimumSize(  prefSize);
205         }
206 
207 
208         @Override
actionPerformed(ActionEvent e)209         public void actionPerformed(ActionEvent e) {
210             JToggleButton b = (JToggleButton) e.getSource();
211             if (b.getText().equals("Intersect")) {
212                 demo.doIntersection = b.isSelected();
213             } else if (b.getText().equals("Ovals")) {
214                 demo.doOvals = b.isSelected();
215             } else if (b.getText().equals("Text")) {
216                 demo.doText = b.isSelected();
217             }
218             if (!demo.animating.running()) {
219                 demo.repaint();
220             }
221         }
222 
223         @Override
getPreferredSize()224         public Dimension getPreferredSize() {
225             return new Dimension(200,40);
226         }
227 
228 
229         @Override
230         @SuppressWarnings("SleepWhileHoldingLock")
run()231         public void run() {
232             Thread me = Thread.currentThread();
233             while (thread == me) {
234                 if (demo.threeSixty) {
235                     ((AbstractButton) toolbar.getComponentAtIndex(1)).doClick();
236                     demo.threeSixty = false;
237                 }
238                 try {
239                     Thread.sleep(500);
240                 } catch (InterruptedException e) { return; }
241             }
242             thread = null;
243         }
244     } // End DemoControls
245 } // End Intersection
246