From 302000f3790b507b532a06e4fb8d9fc93ee1344a Mon Sep 17 00:00:00 2001 From: Phil Race Date: Mon, 14 May 2018 08:58:32 -0700 Subject: [PATCH] 8198991: Move Java2D demo to the open repository Reviewed-by: serb, jeff --- make/CompileDemos.gmk | 6 + src/demo/share/jfc/J2Ddemo/README.txt | 96 + src/demo/share/jfc/J2Ddemo/fonts/A.ttf | Bin 0 -> 2348 bytes src/demo/share/jfc/J2Ddemo/images/bld.jpg | Bin 0 -> 19492 bytes src/demo/share/jfc/J2Ddemo/images/bld@2x.jpg | Bin 0 -> 64564 bytes src/demo/share/jfc/J2Ddemo/images/boat.png | Bin 0 -> 60077 bytes src/demo/share/jfc/J2Ddemo/images/boat@2x.png | Bin 0 -> 99870 bytes src/demo/share/jfc/J2Ddemo/images/box.gif | Bin 0 -> 4241 bytes src/demo/share/jfc/J2Ddemo/images/box.png | Bin 0 -> 6791 bytes src/demo/share/jfc/J2Ddemo/images/box@2x.png | Bin 0 -> 14475 bytes src/demo/share/jfc/J2Ddemo/images/boxwave.gif | Bin 0 -> 4690 bytes src/demo/share/jfc/J2Ddemo/images/boxwave.png | Bin 0 -> 7168 bytes .../share/jfc/J2Ddemo/images/boxwave@2x.png | Bin 0 -> 22712 bytes src/demo/share/jfc/J2Ddemo/images/clone.gif | Bin 0 -> 193 bytes .../share/jfc/J2Ddemo/images/clone@2x.gif | Bin 0 -> 356 bytes src/demo/share/jfc/J2Ddemo/images/clouds.jpg | Bin 0 -> 5114 bytes .../share/jfc/J2Ddemo/images/clouds@2x.jpg | Bin 0 -> 9879 bytes src/demo/share/jfc/J2Ddemo/images/duke.gif | Bin 0 -> 1503 bytes src/demo/share/jfc/J2Ddemo/images/duke.png | Bin 0 -> 2124 bytes .../share/jfc/J2Ddemo/images/duke.running.gif | Bin 0 -> 9946 bytes src/demo/share/jfc/J2Ddemo/images/duke@2x.gif | Bin 0 -> 2297 bytes src/demo/share/jfc/J2Ddemo/images/duke@2x.png | Bin 0 -> 4445 bytes .../share/jfc/J2Ddemo/images/dukeplug.gif | Bin 0 -> 2537 bytes .../share/jfc/J2Ddemo/images/dukeplug.png | Bin 0 -> 2671 bytes .../share/jfc/J2Ddemo/images/dukeplug@2x.png | Bin 0 -> 5712 bytes src/demo/share/jfc/J2Ddemo/images/fight.gif | Bin 0 -> 3737 bytes src/demo/share/jfc/J2Ddemo/images/fight.png | Bin 0 -> 9362 bytes .../share/jfc/J2Ddemo/images/fight@2x.png | Bin 0 -> 22331 bytes src/demo/share/jfc/J2Ddemo/images/globe.gif | Bin 0 -> 4057 bytes src/demo/share/jfc/J2Ddemo/images/globe.png | Bin 0 -> 6733 bytes .../share/jfc/J2Ddemo/images/globe@2x.png | Bin 0 -> 14217 bytes .../jfc/J2Ddemo/images/jumptojavastrip.png | Bin 0 -> 13308 bytes src/demo/share/jfc/J2Ddemo/images/loop.gif | Bin 0 -> 246 bytes src/demo/share/jfc/J2Ddemo/images/loop@2x.gif | Bin 0 -> 378 bytes src/demo/share/jfc/J2Ddemo/images/looping.gif | Bin 0 -> 570 bytes .../share/jfc/J2Ddemo/images/looping@2x.gif | Bin 0 -> 1038 bytes src/demo/share/jfc/J2Ddemo/images/magnify.gif | Bin 0 -> 6255 bytes src/demo/share/jfc/J2Ddemo/images/magnify.png | Bin 0 -> 9728 bytes .../share/jfc/J2Ddemo/images/magnify@2x.png | Bin 0 -> 21324 bytes .../share/jfc/J2Ddemo/images/painting.gif | Bin 0 -> 3726 bytes .../share/jfc/J2Ddemo/images/painting.png | Bin 0 -> 9340 bytes .../share/jfc/J2Ddemo/images/painting@2x.png | Bin 0 -> 31537 bytes src/demo/share/jfc/J2Ddemo/images/print.gif | Bin 0 -> 983 bytes .../share/jfc/J2Ddemo/images/print@2x.gif | Bin 0 -> 1251 bytes src/demo/share/jfc/J2Ddemo/images/remove.gif | Bin 0 -> 135 bytes .../share/jfc/J2Ddemo/images/remove@2x.gif | Bin 0 -> 205 bytes src/demo/share/jfc/J2Ddemo/images/snooze.gif | Bin 0 -> 2859 bytes src/demo/share/jfc/J2Ddemo/images/snooze.png | Bin 0 -> 4160 bytes .../share/jfc/J2Ddemo/images/snooze@2x.png | Bin 0 -> 9552 bytes src/demo/share/jfc/J2Ddemo/images/star7.gif | Bin 0 -> 5427 bytes src/demo/share/jfc/J2Ddemo/images/star7.png | Bin 0 -> 6934 bytes .../share/jfc/J2Ddemo/images/star7@2x.png | Bin 0 -> 16605 bytes src/demo/share/jfc/J2Ddemo/images/start.gif | Bin 0 -> 907 bytes src/demo/share/jfc/J2Ddemo/images/start2.gif | Bin 0 -> 945 bytes .../share/jfc/J2Ddemo/images/start2@2x.gif | Bin 0 -> 1147 bytes .../share/jfc/J2Ddemo/images/start@2x.gif | Bin 0 -> 1076 bytes src/demo/share/jfc/J2Ddemo/images/stop.gif | Bin 0 -> 865 bytes src/demo/share/jfc/J2Ddemo/images/stop2.gif | Bin 0 -> 880 bytes .../share/jfc/J2Ddemo/images/stop2@2x.gif | Bin 0 -> 971 bytes src/demo/share/jfc/J2Ddemo/images/stop@2x.gif | Bin 0 -> 944 bytes src/demo/share/jfc/J2Ddemo/images/surfing.gif | Bin 0 -> 9093 bytes src/demo/share/jfc/J2Ddemo/images/surfing.png | Bin 0 -> 17912 bytes .../share/jfc/J2Ddemo/images/surfing@2x.png | Bin 0 -> 37795 bytes .../share/jfc/J2Ddemo/images/thumbsup.gif | Bin 0 -> 2218 bytes .../share/jfc/J2Ddemo/images/thumbsup.png | Bin 0 -> 4400 bytes .../share/jfc/J2Ddemo/images/thumbsup@2x.png | Bin 0 -> 9453 bytes src/demo/share/jfc/J2Ddemo/images/tip.gif | Bin 0 -> 2640 bytes src/demo/share/jfc/J2Ddemo/images/tip.png | Bin 0 -> 3181 bytes src/demo/share/jfc/J2Ddemo/images/tip@2x.png | Bin 0 -> 7314 bytes .../jfc/J2Ddemo/java2d/AnimatingContext.java | 43 + .../java2d/AnimatingControlsSurface.java | 81 + .../jfc/J2Ddemo/java2d/AnimatingSurface.java | 111 + .../jfc/J2Ddemo/java2d/CloningFeature.java | 196 ++ .../jfc/J2Ddemo/java2d/ControlsSurface.java | 82 + .../jfc/J2Ddemo/java2d/CustomControls.java | 133 ++ .../J2Ddemo/java2d/CustomControlsContext.java | 51 + .../share/jfc/J2Ddemo/java2d/DemoFonts.java | 82 + .../share/jfc/J2Ddemo/java2d/DemoGroup.java | 384 ++++ .../share/jfc/J2Ddemo/java2d/DemoImages.java | 105 + .../J2Ddemo/java2d/DemoInstVarsAccessor.java | 27 + .../java2d/DemoInstVarsAccessorImplBase.java | 79 + .../share/jfc/J2Ddemo/java2d/DemoPanel.java | 124 ++ .../jfc/J2Ddemo/java2d/GlobalControls.java | 151 ++ .../share/jfc/J2Ddemo/java2d/GlobalPanel.java | 100 + src/demo/share/jfc/J2Ddemo/java2d/Intro.java | 1784 +++++++++++++++++ .../share/jfc/J2Ddemo/java2d/J2Ddemo.java | 728 +++++++ .../jfc/J2Ddemo/java2d/MemoryMonitor.java | 367 ++++ .../J2Ddemo/java2d/PerformanceMonitor.java | 202 ++ .../share/jfc/J2Ddemo/java2d/RunWindow.java | 444 ++++ .../share/jfc/J2Ddemo/java2d/Surface.java | 504 +++++ .../jfc/J2Ddemo/java2d/TextureChooser.java | 241 +++ src/demo/share/jfc/J2Ddemo/java2d/Tools.java | 496 +++++ .../java2d/demos/Arcs_Curves/Arcs.java | 165 ++ .../java2d/demos/Arcs_Curves/BezierAnim.java | 339 ++++ .../java2d/demos/Arcs_Curves/Curves.java | 142 ++ .../java2d/demos/Arcs_Curves/Ellipses.java | 108 + .../J2Ddemo/java2d/demos/Clipping/Areas.java | 222 ++ .../java2d/demos/Clipping/ClipAnim.java | 302 +++ .../java2d/demos/Clipping/Intersection.java | 245 +++ .../J2Ddemo/java2d/demos/Clipping/Text.java | 246 +++ .../J2Ddemo/java2d/demos/Colors/BullsEye.java | 76 + .../java2d/demos/Colors/ColorConvert.java | 129 ++ .../java2d/demos/Colors/Rotator3D.java | 397 ++++ .../java2d/demos/Composite/ACimages.java | 127 ++ .../java2d/demos/Composite/ACrules.java | 263 +++ .../java2d/demos/Composite/FadeAnim.java | 486 +++++ .../J2Ddemo/java2d/demos/Fonts/AllFonts.java | 181 ++ .../java2d/demos/Fonts/AttributedStr.java | 190 ++ .../java2d/demos/Fonts/Highlighting.java | 135 ++ .../J2Ddemo/java2d/demos/Fonts/Outline.java | 115 ++ .../jfc/J2Ddemo/java2d/demos/Fonts/Tree.java | 129 ++ .../J2Ddemo/java2d/demos/Images/DukeAnim.java | 97 + .../J2Ddemo/java2d/demos/Images/ImageOps.java | 277 +++ .../J2Ddemo/java2d/demos/Images/JPEGFlip.java | 182 ++ .../java2d/demos/Images/WarpImage.java | 134 ++ .../jfc/J2Ddemo/java2d/demos/Lines/Caps.java | 81 + .../jfc/J2Ddemo/java2d/demos/Lines/Dash.java | 134 ++ .../jfc/J2Ddemo/java2d/demos/Lines/Joins.java | 247 +++ .../J2Ddemo/java2d/demos/Lines/LineAnim.java | 164 ++ .../jfc/J2Ddemo/java2d/demos/Mix/Balls.java | 359 ++++ .../java2d/demos/Mix/BezierScroller.java | 389 ++++ .../jfc/J2Ddemo/java2d/demos/Mix/Stars3D.java | 328 +++ .../J2Ddemo/java2d/demos/Paint/GradAnim.java | 318 +++ .../J2Ddemo/java2d/demos/Paint/Gradient.java | 215 ++ .../J2Ddemo/java2d/demos/Paint/Texture.java | 172 ++ .../java2d/demos/Paint/TextureAnim.java | 450 +++++ .../J2Ddemo/java2d/demos/Paths/Append.java | 83 + .../java2d/demos/Paths/CurveQuadTo.java | 72 + .../java2d/demos/Paths/FillStroke.java | 75 + .../java2d/demos/Paths/WindingRule.java | 92 + .../java2d/demos/Transforms/Rotate.java | 170 ++ .../java2d/demos/Transforms/SelectTx.java | 316 +++ .../demos/Transforms/TransformAnim.java | 519 +++++ test/jdk/TEST.ROOT | 2 +- test/jdk/TEST.groups | 6 +- test/jdk/demo/jfc/J2Ddemo/J2DdemoTest.java | 205 ++ test/jdk/demo/jfc/TEST.properties | 2 + 137 files changed, 15701 insertions(+), 2 deletions(-) create mode 100644 src/demo/share/jfc/J2Ddemo/README.txt create mode 100644 src/demo/share/jfc/J2Ddemo/fonts/A.ttf create mode 100644 src/demo/share/jfc/J2Ddemo/images/bld.jpg create mode 100644 src/demo/share/jfc/J2Ddemo/images/bld@2x.jpg create mode 100644 src/demo/share/jfc/J2Ddemo/images/boat.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/boat@2x.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/box.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/box.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/box@2x.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/boxwave.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/boxwave.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/boxwave@2x.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/clone.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/clone@2x.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/clouds.jpg create mode 100644 src/demo/share/jfc/J2Ddemo/images/clouds@2x.jpg create mode 100644 src/demo/share/jfc/J2Ddemo/images/duke.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/duke.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/duke.running.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/duke@2x.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/duke@2x.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/dukeplug.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/dukeplug.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/dukeplug@2x.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/fight.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/fight.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/fight@2x.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/globe.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/globe.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/globe@2x.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/jumptojavastrip.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/loop.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/loop@2x.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/looping.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/looping@2x.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/magnify.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/magnify.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/magnify@2x.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/painting.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/painting.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/painting@2x.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/print.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/print@2x.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/remove.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/remove@2x.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/snooze.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/snooze.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/snooze@2x.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/star7.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/star7.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/star7@2x.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/start.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/start2.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/start2@2x.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/start@2x.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/stop.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/stop2.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/stop2@2x.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/stop@2x.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/surfing.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/surfing.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/surfing@2x.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/thumbsup.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/thumbsup.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/thumbsup@2x.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/tip.gif create mode 100644 src/demo/share/jfc/J2Ddemo/images/tip.png create mode 100644 src/demo/share/jfc/J2Ddemo/images/tip@2x.png create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/AnimatingContext.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/AnimatingControlsSurface.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/AnimatingSurface.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/CloningFeature.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/ControlsSurface.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/CustomControls.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/CustomControlsContext.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/DemoFonts.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/DemoGroup.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/DemoImages.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/DemoInstVarsAccessor.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/DemoInstVarsAccessorImplBase.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/DemoPanel.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/GlobalControls.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/GlobalPanel.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/Intro.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/J2Ddemo.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/MemoryMonitor.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/PerformanceMonitor.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/RunWindow.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/Surface.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/TextureChooser.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/Tools.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/Arcs.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/BezierAnim.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/Curves.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/Ellipses.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/Areas.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/ClipAnim.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/Intersection.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/Text.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Colors/BullsEye.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Colors/ColorConvert.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Colors/Rotator3D.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Composite/ACimages.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Composite/ACrules.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Composite/FadeAnim.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/AllFonts.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/AttributedStr.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/Highlighting.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/Outline.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/Tree.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Images/DukeAnim.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Images/ImageOps.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Images/JPEGFlip.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Images/WarpImage.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/Caps.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/Dash.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/Joins.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/LineAnim.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Mix/Balls.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Mix/BezierScroller.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Mix/Stars3D.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/GradAnim.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/Gradient.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/Texture.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/TextureAnim.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/Append.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/CurveQuadTo.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/FillStroke.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/WindingRule.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Transforms/Rotate.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Transforms/SelectTx.java create mode 100644 src/demo/share/jfc/J2Ddemo/java2d/demos/Transforms/TransformAnim.java create mode 100644 test/jdk/demo/jfc/J2Ddemo/J2DdemoTest.java create mode 100644 test/jdk/demo/jfc/TEST.properties diff --git a/make/CompileDemos.gmk b/make/CompileDemos.gmk index a224c9b9418..5addedcb599 100644 --- a/make/CompileDemos.gmk +++ b/make/CompileDemos.gmk @@ -253,6 +253,12 @@ $(eval $(call SetupBuildDemo, Font2DTest, \ DEMO_SUBDIR := jfc, \ )) +$(eval $(call SetupBuildDemo, J2Ddemo, \ + DEMO_SUBDIR := jfc, \ + MAIN_CLASS := java2d.J2Ddemo, \ + JAR_NAME := J2Ddemo, \ +)) + $(eval $(call SetupBuildDemo, Metalworks, \ DEMO_SUBDIR := jfc, \ )) diff --git a/src/demo/share/jfc/J2Ddemo/README.txt b/src/demo/share/jfc/J2Ddemo/README.txt new file mode 100644 index 00000000000..ca57326ee6b --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/README.txt @@ -0,0 +1,96 @@ +The classes for the Java2D(TM) demo are contained in the J2Ddemo.jar file. +To run the J2D demo: + +% java -jar J2Ddemo.jar + +----------------------------------------------------------------------- +Introduction +----------------------------------------------------------------------- + +This Java2D demo consists of a set of demos housed in one GUI +framework that uses a JTabbedPane. You can access different groups of +demos by clicking the tabs at the top of the pane. There are demo +groups for Arcs_Curves, Clipping, Colors, Composite, Fonts, Images, +Lines, Mix, Paint, Paths and Transforms. On the right-hand side of the +pane, the GUI framework features individual and global controls for +changing graphics attributes. There's also a memory-usage monitor, and +a monitor for tracking the performance, in frames per second, of +animation demos. + + +----------------------------------------------------------------------- +Tips on usage +----------------------------------------------------------------------- + +Click on one of the tabs at the top of the pane to select a demo group. +When you select a group, a set of surfaces is displayed, each of which +contains one of the group's demos. At the bottom of each surface is +a set of tools for controlling the demo. The tools can be displayed +by selecting the Tools checkbox in the Global Controls panel or +by clicking on the slim strip of gray bumps at the bottom of the demo +panel. + +If you click on a demo surface, that demo is laid out by itself. A +new icon button will appear in the demo's tools toolbar one that enables +you to create new instances of that demo's surface. + +To run the demo continuously without user interaction, select the +Run Window item in the Options menu and press the run button in the +new window that's displayed. To do this from the command line: + + java -jar J2Ddemo.jar -runs=10 + +To view all the command line options for customizing demo runs: + + java -jar J2Ddemo.jar -help + +You can run the demos in stand-alone mode by issuing a command like this + + java -cp J2Ddemo.jar java2d.demos.Clipping.ClipAnim + +You can run the demos in groups by issuing a command like this + + java -cp J2Ddemo.jar java2d.DemoGroup Clipping + +To increase or decrease the Memory Monitor sampling rate click on the +Memory Monitor's title border, a panel with a TextField will appear. + +The J2Ddemo Intro (the 'J2D demo' tab) contains a scene table, click in +the gray border and a table will appear. + +Animated demos have a slider to control the animation rate. Bring up +the animated demo toolbar, then click in the gray area of the toolbar +panel, the toolbar goes away and the slider appears. + +Demos that have Custom Controls can have their Custom Control Thread +activated and stopped by clicking in the gray area of the demos Custom +Control panel. + +----------------------------------------------------------------------- +NOTE about demo surfaces +----------------------------------------------------------------------- + +The demo groups are in separate packages with their class files stored +in directories named according to the demo group name. All drawing +demos extend either the Surface, AnimatingSurface, ControlsSurface or +AnimatingControlsSurface classes. Surface is the base class, demos +must implement the Surface's render method. All animated demos extend +either the AnimatingSurface or the AnimatingControlsSurface classes. +Animated demos must implement the reset and step methods. The demos +with gui controls extend either the ControlsSurface or the +AnimatingControlsSurface classes. Demos with controls must implement +the methods in the CustomControlsContext interface. + + +====================================================================== + +Here are some resources for learning about and using the Java2D(TM) + +OpenJDK group page: http://openjdk.java.net/groups/2d/ + +Learning Java 2D: http://www.oracle.com/technetwork/articles/java/java2dpart1-137217.html + +Tutorial : http://download.oracle.com/javase/tutorial/2d/ +Specification: http://download.oracle.com/javase/8/docs/technotes/guides/2d/spec/j2d-bookTOC.html +Java 2D (TM) API White Paper : http://www.oracle.com/technetwork/java/javase/tech/2d-142228.html +2D FAQ: http://www.oracle.com/technetwork/java/index-137037.html diff --git a/src/demo/share/jfc/J2Ddemo/fonts/A.ttf b/src/demo/share/jfc/J2Ddemo/fonts/A.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f80f5c3d569c810493a9fbaf7141a63831733764 GIT binary patch literal 2348 zcmbVO&2JM&6n``O>5tg!+OZ8Ju*6B67Kmdzu@eZ5A>f26!6qam0n%iX7&}rN8^;NW z+5=T7qF*Yg66&Fss;9P53qs;ULRDG`Rh4>aFTHT!*gt^wfH3Zx-EDxNwrbyc=KX$e z-p>4HcXq}=0Kf@tz`=Uzcqo$kYWxcTS;gpybnn3Mz}LUrL%xDMHj~$i@CUsNAl^lO ze`dL?-W<7o8h~3zUU#OL&A%P}K81V@xhFfndS=h!XE^{~0igZ4+5F0tmS7P;`UKlA zS4NH^stYxw-~>G5-UMwH8a6;yvys2kN_zyd8_5G-GYpUZ^(_ z0R<*aOu+%mCgz|Y)=kV~4(pYf07p%0~3&8)Wj4dD43Xo zM)=gkJmy?5u>b)gn^**yoHeo0KL>=jVBbu?ferlzHuM|V&~IQvzkv%oE)mw{@ z)ALk(@U0LYSt!qy=QFb~qG!!v<~+N9D3e{9*Ge#iBnwLz)S&ct$%EQVsgTdi&S@_w zQ#bAz#2#i)LILu+z&YgqDi1R@3Hzt9Iz!=bsH+S9?@*l(f-qho=z^{d;hO|Ng23+O z!|FAz>2N^H`2)GBLwj(Y$5HEU*a}V(C2+E2T)=~vut<_95`xR_!`r0#&f(mljo%H9 zCSlhNfyeqfr5L}?^H>9g9?ZYVskoLTIFV3^EGH~f;yD7Mz;RUId5}b&P{OhGoLmmY z{m|1L>Q*Z3M?&2dB$aLmw~-^cJGe0ABRTC_VrZ<>6~6;=b-i;u>e}gQin;Vq^)!L7tF(X_-gOujyG`qats(Gw%X$A^v$BoDRGDU4xg z3}YBd4@A5ma{C*&qpxtCazD3!8&x{^-RXYbB5xOJ8u@)5-oKC308vcEJ)w$%moB$L zLX{B8#!9KQzG(1bsMVaF0@}0F)7bQy#6Ux^xuZQE5G8~R#e7}{#afRy8i~g`+5-&| zHr9F=^F<^F(eq+auX{W3d41k!EE);Mg3Up1tw##_g1)#Em(T^##c7J~sI}H{({0KA z-j_R^t}QB0M5S)0XMQ}L=?b^o=;+`MDsekCJE9)TT*aOmpXm`_JF_>RFSMVX1LPrFW4L%88ih_kJsHFRWl@0Y z8{jd}rdmW!FpKSzO?n$HLEYBO9kGt>fEZcBeHhOvv|h7CCwfIN$1roer%js>>j@8w zP0{~Oc|0L_JY(@7LeFNP!og}4xe5n#&*mk9h?v6+K_5cFTDAxR2!g;_Mdn4$CSjT= z@pjYK$P!4B%sUJ(I4v^Bc$Z>j-YU4P7O+^X;!8H>ZKB&|1*_F2dhE>GrP>-B*labD z*YrMz9qe|8>~}Kn)K49985L1_m%fLJJ~BMH2NAXb;MvY9!=8Img9mztAi-ve-!qy~ z<2(ℜyHe$X3A=a4KE;YvWT*tD?oL)h8oIhlkqO(__Z&$MRa%9hh`>|BkPR{a1h+ zzaGW4_0-c8?qKZQQFBDRhf}MasAB@-4w~9ff>bwAkBE3W81tZb0w=(VZDVi?+sL1^ CwQRot literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/bld.jpg b/src/demo/share/jfc/J2Ddemo/images/bld.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6dd18fa86b5889b039c28e840ba7163252e87223 GIT binary patch literal 19492 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

!Yh-l5m@H>Za>WD#}| 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

R5^q) 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 literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/bld@2x.jpg b/src/demo/share/jfc/J2Ddemo/images/bld@2x.jpg new file mode 100644 index 0000000000000000000000000000000000000000..44d68b2851118b2004d77532540da98a8324c9c8 GIT binary patch literal 64564 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

HuffpPyKrXoPPJxggQ|Hm2G$c9|G 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%0DqYAOwOkSh;fiElAS4JAiQ|qQ24$_(! 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 ZW6uKqw&9Cgn!0ubx$%}eyFozY{{a+l1oQv^ literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/box.png b/src/demo/share/jfc/J2Ddemo/images/box.png new file mode 100644 index 0000000000000000000000000000000000000000..48d36a4309411cc1ebd83380644329427b1dc9e4 GIT binary patch literal 6791 zcmV;28hGW2P)^@RCwC#oq2E@_jSkL;=Tc%qDURE zCF`=|p{+P_I!=UmVows=F`J}q;+e!$GO@?WOs!0lrkPGlsx$o~O;g$KOmnmos+~;K zG)^qXb`u}5!Pu#z%c76bEsKK;n(pyMO=?*w63#uHO#} zfSSR!tzHjqhpYW_=xQjLy@uOC1nR57tZr5I;I3V~*;RvCy&w3; zcxX}!4Cd1*fUt??ACNLNb%DZm3GSJ^&bF-@xCq2r8Zucl>_P1)|1q#(?FS55VBdV%6pRNuKl%`xiaOGzTjGcWoWiGROCD%%&$WmGq zGuvt?Q*>3XN^-A0Wf@YSK3ufX>&DbTz2cNw4dxQMSCvAjo-EaOU5phNBoEhME|Ytu zcAa*9a;ep+ao-iUv_w~>s#LjGn%0_cyKW&?>66!76@n!9s%oMaSdg`B*1DlZnb`tV zPy@aim3dg3y{;5Uve9PY99XXGwIs~^27E`QG~laEnR$z{mMeQLW#Rl5 zUuO;G{8ZTuinTnHSuS;RU_R=s#1U8s424yRgz+;L7+4OND5J^(P=Tmmp;4~9&EoE+T2dy2|fW#XMo2I zQYqk5X=)t-j~gV@aB^e}et7A9I2BUEBiCE1=c`%8x2h`g37Io!2-JGh*7l&u~(1kLI2G59!+r$_O^p2s~w!mZV8hEF#&!Cs7m zrz25_WwY${OhzMH2Q(F*W^#Tp36xuTmlxmXk7_X0s#L9gCHE@1I&!IPs7SqDFM~Yt@aIsCHvva+ z(}W<+Mggc^CnypGCCU&H9w+VzqOcc^&G;Cf-2uZmfG#3bY4FfW_oR4RGE%D%-K-*B zx8Qq!7J-h|ng%&ldW*HtC}UNwHh=0fpMqT*n{jC3#~~%6BC)tcr)Oe&cALQKMR!X| zWo}mhU3ddHv~eRswX6Pap-j0zzjjrc2$k9a%FAGtnJbkbl6?&mojbO)in*Ku27_u8 zAjfZ0f%GW;wlV~0`?WQgAb;Vfq$=e)&*^~2_T45qJYnN! zg$=V;9^)CyVp)$ZT=Wf|X|B264{a-jDkbmXM#YAdG6f$kUb~TojRH8B;FQ!T< zgOyeJ!CM7L2#Z(5JU*Re%hOOX@Ibtw5jn z!F3H&tSf!R+!vihDQ2}g?C|MrUPbbvsUv5k4b_P?rJ&M`u+igZv$+8v!Ik&s0|0EN~ZQyv2* zKm;lw#JvhAJ&qJCw)J=kXhx}2N$tD{nTH*UQ&p^izuHq{m88s0ZQrw$wPJ0_6qZg4 ztvLcEw&qxyE+Hy2kz%)*VpEbr>G7gVCWtDPib_>NML-)B-Jep8e2uI1uH@xsDyh*f zk763#vHVr!>S8@JD=18C2++CaSR#}a>P_VdCs!%EWGS`^3YE4zrDk&=dFi+eqncAQ zHAbPMZ{5HY(|Aw0suVL0rZTAu!yzy}tCxGRtgaL=GnmX>O72vKm{uH%n?k9)_;><& zaW<<;c8Zylv?<~$#m#T5CpW7~G9-h%;BkN<}QWV56Q*iCMQ11y>LJKH^~)C z2~jEsRB+olsIpRVe<7O#n4V*vbG2Npt^!o)Rc3w43oCVWbim=mhvCebGfaJ7c<3Sd zc^4uvL75aESu7MlsX;2XWKsssr&5aJw5ZT@uC$TVD`vd}w3pAh*}wSw=b^j18+<-r zQCC|kOJB=wR+YZrbML+Ina_Qefz;ZbJ-g-OQ{k`xLY(p74f*$Bwbvl!>o~ ztK}*{nY2)gxgnR!1#i9ccG1TU4GzNoyFMb{e&N0RH-$-(ttl zO@`p1x_a1Yx5?#*I+KN56JE+_r8!I~Yn9@nGG>a+g^SrV{DUr+#qPWFP7DE`E9-;N zpd%FzqBmg)+xr*5WYqgCCZo?~w{-p6|M>AO@%~IU+Z&E0{N0Z};IC>oJ0BOTv*HR79LEQ@Gk;-2V%ohF(y2 zd;SRrS-I|2Yumjy$j3MCxef07;@4R_P_0fiT;&2a$x=ATGTGTagzKMi{2LvGK!T8HBu%iRI;!AI(dn5(f7AI1e_2fff_Hrg;RQns-fvzx?oGs#Y?UHw8!?ItYaS8Eq+)r+ zJ!Lcs7IP9S!6&>C77f_))*oh?X#dAU~S_k3s?(g|Nq(<*;rbP$@iY-in6HmR-?RH`eW(lpQa zW6gO8As(5torfShU+O*G6Bv)MMy(L{xFv(9wTth*rAjuI+r?EP%<_@t_=n{7kt&^GK}17VEEd) zQl;{G6cPT&6dW@IKOk35#iAQ16=FQOD;D)Ap7i_>i zWw|Dk;h9%Yp8v+(ckDX0D423x^Z_pg+atgJzq8#VV-t@@B2!Cp(V~E&>qGH!vE7yG zaIfjhKARCyd-!5f`^p>!HY0>vob0f6fX>TN@6*2 zakX;&ukcu&UeA-7EMKMbu0M`n8u4AaavhAsdH*7jvpk<3SNT6K%R?+%l%iY6dn#*1UE7sg>Wpc z`fiB?hf~lf28ZJm&k^sQ%k9#!%Wmunj-f&+ z%?{u`uf~jxS6vo66&K0|1}_+acrt}GpaLGJ2E((fm`Lq8!G-b)psd>?E)Jva4x5z| zr{ARKm2$iEoXFISFOdwKdF8~pJeAHH=4+=ec&?95^i0KPIw+WDX-y6O#SQgN*x2BL zy}PzDl}<*d*(j!M;QBCR60wShDZv{efCw)-ohYd`_O%F_hvaiAl7I?8azG`uY2hqn zAYkU}!LWAtx!=G2pi-stauN?T|f|p?|IlOVfo6r`Wnvs>Fjz#&dQ0+cBjVoO~x2t>}?TrR~*yFT4 zdGDQjy18=II4~USiB8XS&=*lT1+;QtN`F{-oEcqn3l_;6#A4aww5}MukqN1$7q9tL9BRpv%oPS&av+pWj*1Ngy1 zl1r<_gz$8JtJ&0B@3#BVz4n!r&7vB;m#>ZWgrjjErvn+{a=^@uSmA~lOP*#C?0n!7 zys^osT%=Fq?Hn)#xB|d_@GL--f!vNY8>rLP6e zOJPct76MxIHRb?XyznoqQnS$r27?Yuoh+m?voMoNvpP05J#(P@(Fcw!YS!fFizm9@ z9}0HSdQ2TxnO81FPXWI>aSl$N?PoA|Zf${&-o67zwE&%^_p+-J-6*?~B`?(tY+wi_ zfk;#Qta53fcnwy1$Tc4?ysif7+@*++FjD9s*O|#?5MCBS(J8iSogPFNS+rnM*xFnV z7p@NfcA@8oQ^d%2OwWB-KkiRwv%W+k<(Z|Q8>|pzULOm=Pk(cQHSBNM*2>)O8-16V z+x@~P?tm7&o$oT|j+3QSx)`@hNgaci$q3g7!Vn<9)8W4v*uN7%3thC4thwU13ieDOqz!KG}LnglBiGlMSZB~;@p$Ir=pKmMWJu&KEYe)i%C`8oIO z+YKMR?IvN3=>pyEyke~eC;>7eymUIt;GrlOJi72Axl{s&*(igkXN$FXIf63%FDJ}G zaD$@AN73ZF7HtL1hpi~OdDG^>O#oo7tsm{dU(O$0;owT@sm;+c{ zm|FYxQ@=cnndCug^;G|7Zo`gz>&np3Q!HsrQ zMC9GeL#zi&&F33h8)5sFCfJ6m*tV%rST;Dz&u?VmhwZyK2*3E>AQFYu@7@atBvq~eNn1!=s!-%Oq!KCaELjfFn?KIqs z$v*E|S6B+yrhsL8KURy>GsE6`p_n zT~t822lE}ocy2ttb@zzA*x zk5uNgTft$oKy!l!A)3`+!KmQhn^^L%^pSe#1hh1|7$|a=q&jM9zxnR_@H)b!^U+i< z)QJ<3DM5`e_p15L=rXld@3Mi%X~QfsBLb9w<~CC48*iP5tsBu>v@~FiHw|MGVaQ^= zN6K^IfFytfn;=T-nSiUVpBG*B3sewTC!V0zCO3miO$h=U!35&e*#XQ3(`AizN-W4# z7qYGBY6nIp@*qkZsf}hC2;g`q3T}koh?%bo0XpfI7IgFf^3%G6sWmo3g4th7qX3s+ z(!wWNKNF56gu=RjQB$CpZ9}&`5)6s(^a_X^+k0Ggre0b#?nD*p6srl>lCAm`x~L|z zHkwem9u}JjZU~`L-4=?`53LD5JyGwrmsD*%0;5ua;L&j%KHh`y+~|e{aBB}<#lg%2 zBi3v>PJl}Z3qhrNwv_F@v5hSrqu3`b>#cUDxdvcr&1lfi36jiVGYh|2vW`s$HLJm_ zSq)~*YA|b7gIUXFYqsJL3_7sctznPb;jh80GNV}+yWJ8tnv8zC-P*fhLxX=?y{)gN z%qlPwU5EmeXEB@nc)VorYA{y_p2J}an@uLa%kAj(c$~`uuLg4&j4lCVwORUYHcOwI z!E>z$yc*0Uf`{Pxaqmaf^)@tk{Nm+zsxzCtb>|lU*T3}1{m0K-@V#?>fL(ln7Adbu zcr@W|v-VTW^VB(e8yo8?0-n~E>Uy)jcg|k*jRZpb$3rpSrT!6!#uID}DJNgmShJ8? zy6h%E?zq@vgkJ?b&6rA%Cr}e03D@dCDuMSS@BsSo$p%v%jv+ z)!WomnedhcW+Axmo)h3sgr|I021X$kpJB`LD-ouZE_vo4cqV^Cox8WWxxOmktq9CQ zaNj%E?;8z<_D@EpeD7ZyW0x7D^|7k~lU5#Jyz55=`WqYEQmN2i?crcmCIC-g4Rj1# zAKf3EjQK*5srJFq2?m$0Qnef~-7W{Xo%Vh#)cvh3jlEbltOaOtTU_lbru9S8lCnH4x@6z)4sq&xSd>bbA!9D psow3sVM|MIeck$mr?vkVU;z68v7F7U;1U1;002ovPDHLkV1m|t4|xCp literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/box@2x.png b/src/demo/share/jfc/J2Ddemo/images/box@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..087edfb1fb62e68b96fe536dba2477260a612d26 GIT binary patch literal 14475 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 literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/boxwave.png b/src/demo/share/jfc/J2Ddemo/images/boxwave.png new file mode 100644 index 0000000000000000000000000000000000000000..5cf6e834095cfdbad412280098ca789914a14b9f GIT binary patch literal 7168 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 D9e2^% literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/clone.gif b/src/demo/share/jfc/J2Ddemo/images/clone.gif new file mode 100644 index 0000000000000000000000000000000000000000..c0f7db8a602eb34dbd2fb4e3b86b7b8e421e2f5b GIT binary patch literal 193 zcmZ?wbhEHb6k!l%*v!E2|Ns9p|IeHO#a28Njo3_$unkc9w> zKUo+V7`Pd9Ktdoh7+CTOPI|81`(xHwUqjChNry--2PT$N967ErD_Vjw@;h5R1GEot zbxzS@t!YW=Hq!Yja6u!<(vYLWT0ul2CC*>t=(hzsxz0T-yxApIAewSI@qiouyXK12 fxZ{t%im*4;wKP<>)U`D>_4Ia0PM9bm$Y2cs9>Pfp literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/clone@2x.gif b/src/demo/share/jfc/J2Ddemo/images/clone@2x.gif new file mode 100644 index 0000000000000000000000000000000000000000..3d273b1722a810faccb563e1fef7195e00fc629d GIT binary patch literal 356 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 SNn1kX5o`~Q+NH&hrv3+5-3G1z literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/clouds@2x.jpg b/src/demo/share/jfc/J2Ddemo/images/clouds@2x.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ccf21f661641227e8f5f01613c6fec2fc210b3ae GIT binary patch literal 9879 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 literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/duke.gif b/src/demo/share/jfc/J2Ddemo/images/duke.gif new file mode 100644 index 0000000000000000000000000000000000000000..b7179557f012b1c68c7383ec9d668887eab8c7d9 GIT binary patch literal 1503 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 literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/duke@2x.gif b/src/demo/share/jfc/J2Ddemo/images/duke@2x.gif new file mode 100644 index 0000000000000000000000000000000000000000..a936603c3e6f7df00c360d298042dc3e418a32bb GIT binary patch literal 2297 zcmX|AeLR%;7XNKnleS9{in=2r2F><(8HrC4smW_ZhV;T?u+gY?)uk;{OuA7l=0OOt z<|bLmmL$0$JyT;tUXz!+B`-CL?yi0IJpQ=nkNJGgbI$pm@ArFtvwM#-$L2^R5}|p7 zC^|@rA}9){D2$>IoslF(5)_G3Bu0^lE)pa~5EOw^1V#~v?!`$8Cny}JaE!tcJ&KVO zMo<_|VHkxWK%x*yA%a3Ug)j<10@wfzSTGFTh~7g7L6SI0VkC*^wU7}6N#G=bkp!Yy zKoKWM94B#%#1TyjdNG2;a1z5v3;{OGAO*by!U=>C2;_kuKoh3H4$u!I zKq0UOFdz*qp%r+*V!#Gyz(TZhbQy98495{|B+kYN~(A@CLC0t+bO2*VNh2u_0m zzzf>JXiy7Qf*(K=roj&21cE^!um&(74U<3%c)()7253Z|i0+0m4xO76==B2C9y-P;Zt}l5Sm(P=na2)}8bS<&v>6Pxwl-5uO^w0eu-OX>3u3XD&*yVsjLnA6@Z4eD|3mMK z;#Ua$flTQy^nU^|C^WxZ*X3@0y^x`963~42W<#Qy{@xsyih^fXRHp-bVm@wYOkp}s zRW@BO+ z1&zL!^sD&&30qY(2ZL{y#SETXVIm*!)=6m3cbx0}d^6d0YPV_(%w#XC)Ey)nh||=wf^+T zaUHRu^?_d4^u5n3IRnhBF{}P3`s*Cy4f#ISmlM>Jtuu~3lot1I_bq!M$Yt06Y*i!iTAq0MH-#ognUbK-r;CA|A`X_GvOCy;c0x8Gc9=)S^Fto!oy z%SQ@B5)&&A$B(0yPHzeYUM`OxdT!UN3z#VOOpFse_AyGdsIZ;?)3WpEu?DGg>w&n_ zCta?rdDX009T&CRCy(lBj|nw=w(@Oucwu$kf;?`j_n}^3R!HBwviY|%lc{Q9Xr_i) z;Pijft`2)P4JGFZc#%~Nx|yf$oSHq+;M#VlN&jIUBRluR{$%%bL4&TeFvVWCcF4%i zvL{!N=56Kl{nNRbT~MAMIFhf=c)>i%r=cj;T4w*221sST6Q2Jfc{R18T~zt*axdl#GhI+8M7i>ly-N=UBS`{DZAfbp2Q3grV#n zYQ`&V^vTM^A=bMi6ltKrOpXfL_)Ch)Rc*WVhMsop;DXukvCOs@kEGU!BfQw7>Ny^2 zSCT5pV`EP>Z;Dj^9Va~8(!DjKH(!t>ui*xtSXO84?{+14)r(J)oz~xONbn09E|hLm zdYbW_$F(@FmQHJ;%QNFtQ?t@Q{r`-pKXLfYIBimA!-_Kv`|hM%b8>KJ+SyoZCA>;= z;wo>Zp1OD&?z?KMc=`K@v6ho|sVs||A!e=Zxn;VtfSP+Did(u;JquEkA}d<-gqO)1 z`Nr$(HAXB=zpOs0ckRdFyG@*XVJRUkQNGTzFBcmtvi=p57Aw8DJnK|fZP5LZoK|kA zrBZ`i&x6YC6AC4shMW%jXho6leDk4l{ETzYIF@sASoCeJuhu15!?mHb(1TW6lTE!! z^u{if^crOCE9i3L*bckOy=};v6Giz}tZyvW7ufdHM~ieW6c4s_a=U&aPyHnvx3utA zO*PTbe^C1K`)L1X;<>V*^G`)zPcOVKINKJy=x^*~s=sINoz!&q+Fr9QgREzPvZAWz zen;&2*KcW-U37os?DV`fUF=t!yCHU8!d?~ioJmjrpjxiY&ENKfDRCtpUp!15kF7pF gIA!59xaQz!n10ckP3FSWle-?SKKOi@5fj<|4R+;dlmGw# literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/duke@2x.png b/src/demo/share/jfc/J2Ddemo/images/duke@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6f87deade5f237c929bf18fbdef9904ba1f72570 GIT binary patch literal 4445 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 literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/dukeplug.gif b/src/demo/share/jfc/J2Ddemo/images/dukeplug.gif new file mode 100644 index 0000000000000000000000000000000000000000..adadb3e75bee1c8a0d53b033303ec41529bd2aef GIT binary patch literal 2537 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 U)zYBCAN*CnNe(bc7!0udzewrFYybcN literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/fight.png b/src/demo/share/jfc/J2Ddemo/images/fight.png new file mode 100644 index 0000000000000000000000000000000000000000..39bfa78691e1a460211c54e690ffdddc2597aa37 GIT binary patch literal 9362 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 G*!w^99l&k? literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/globe.png b/src/demo/share/jfc/J2Ddemo/images/globe.png new file mode 100644 index 0000000000000000000000000000000000000000..ee07523907dfffac68e19615e39a0430f3f60ba0 GIT binary patch literal 6733 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 literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/globe@2x.png b/src/demo/share/jfc/J2Ddemo/images/globe@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5f807740fec3fcb3172fe6c882b6221f17362088 GIT binary patch literal 14217 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 literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/jumptojavastrip.png b/src/demo/share/jfc/J2Ddemo/images/jumptojavastrip.png new file mode 100644 index 0000000000000000000000000000000000000000..76a1e8f586830824ff1f45c8185891a843f531e7 GIT binary patch literal 13308 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 literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/magnify.png b/src/demo/share/jfc/J2Ddemo/images/magnify.png new file mode 100644 index 0000000000000000000000000000000000000000..5fb28743e5ac6449f109875428b9f74d91c93f6f GIT binary patch literal 9728 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 O0000;F9HeuiYQ8 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 U{O;ZS1ONa407*qoM6N<$f_WVHn*aa+ literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/painting.gif b/src/demo/share/jfc/J2Ddemo/images/painting.gif new file mode 100644 index 0000000000000000000000000000000000000000..8415e41c0ef744dfbd001f87acac4b22e19ae166 GIT binary patch literal 3726 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߬W-@t9z}y;fO~ z5Qg+9M|c6XqLU~TF{vA-frm~bhU-UnE{1hW7eGo%DzsuIboydzq-Bn1)k`bQ8mX^w ztjsn%#;cS7hHZ!`*hnA?Wep9~on{aE{N%}npj0NJl40iCAN;dtO;*9(OHJT*^)vM% zV}X8F8ejZXLQxJ^mz$hv4|PaoBLz$wp~^A1{_Uez!lLsT|cUIu&H?}sJ?#{+_Y=~ez64Br%0XFXB*nU*wq&*Q7GkO zIb)RSRSu%r&s3WlX-9S}CUKJiDu!TL1;G0H;#)4E3^FS#T~hW)hRn=N%uF?4GWEbu ze)3-oFol8uqgXI_vN5Fa$6DkPDcHC64#4rx+Q8Jq-9#w~o>1LPWh2cZcLsq&aK<+v zTxAb$Sq5{jn*rV-1%r$F6&tbbtq&S|RfI|qA_(jQ)T=uR*C=%L&;?1ryS$&TmAO%o zqE$cwTc-O+^LeAuh%VcJa8(Wsd6=7|z&j}^K8bv0W;*K@qG~=_ad9!a%r3Co?W~ct zwzk6DxiewQmfJCWpfO}_Od#X|Y3%STthLuEt6F)gegrHts28J|QX~0x1_;ri`@090 zYO}M|x{{I-wFmEzmR1w%`uP;)^-sr5;2azZ25o%|=XZy=JVI`&KSV*5h740-G!wJg z6q!+fIoW}3kM`y0k33l*6%zp_s943#H{WY881`5YGBv4~#bSekg50>N*w(EZp|c7L_`Y**Z-U#xMU@nT;b*z$`Tq7P4}n3zOBQ=0%|#>%FoG#g1kIPQ>lET z6+#)sEd*gkdOBofWI#fKG9 z3+$yeFS^jV*=oqnk{^^eB`Xt(voau)##yDO!MRQ|1N5k=bC~kcyhu_$s;z|r&4MaM zFiT1ndOWsjY}*kqH9^+i-VW2JPi1jxJZ#>)8Svb5KVzNT6n{}0cGXW_fNoZJ?ni~r z53w&T;Wq*v$n#ijw1M^qYzx41O{E6Dy*WfSHughyuAFH;>pDrygHe3kxajL zx)t6y(;e!qdWfNF&u3_LVt3YfsU`5P#=CP;L1Dm58g}v~6~KL~mcWW>Q=m8lgJX<| zyj1sbyTD8Fh7-5gj$Ueq{l;dfYwrNNBpwsit_Y@lGo}Vq){Pj4u~hHi!KZd0T)RA; zLGXCo41y_BO5*8E*!i!ld>Y<=|A>4by|V(QP0NNQOV*$Qslx7$3b{t(d1$)S3f=u_ zKES9h7hDB5gMZ0L4s z#5Ffk6>?8vxQdG=pQlo;=fRlTS+jC|M zR9?6U=S1-hl|$qTx^xUBsOnev8xdefj~r2>DpY1g}g!6n2*1l3f$u!396#6bFox9Xs5r4|&_k4KGHE%Z@TkKo{P zau9KVaZqvFz{fU6A3SjW0-O`YU^E0M~*B z!ljYUPaOBA906Qfyl{2uoSYp+lO};jJqz01YG`Zks&_d0mx$mJ>SGT{${I#K?urF2 zofs}*=(1omszDrc{q(E1K-tno98{=Y1epS%V~t?L*D7e_C_Rr&L8`}^f`d@fG7}PE z_w?y7CnY7|GsS8dqVQTSJhm9?KPdGyT&V-Te>O6q9(7>~PB8f=T>BJtqAfBC{%_`=+oT#TjU z00M-GLB_+y{?7-K(hn1e!4l~`ZZk2idkkH0CJ&X6sY*>|ltsXh>U-|_nI6GnkWoCQ zP$aN^%5&#Ff%E52u~No00obvlN3|-Is;;o8NS%r4{>LAG3N%@ zoF&I{z~R(Oyu8wiDU;wn?ILmL&4PDoUcBhkgungc0KGz#KK#SIfqxVuWDjKeOCOnm zwJ%>?PU1SXe5bs>3!|c%L8eeBE%bh&&(LBq!zZ5{gSNI7gw8W&P@HLLguNdgVy(*- z)BFWX&^p*(jZdmQLqlZ_r(5G5$b<}4#&%RK^$?!;!-o$;eSJOEaP-yH)#1tv8VDSE zQ$JejMQ%}CL4R=h4J?~e&;UOI%7c&ja)g2bq+sO<7^LTh*lU1)tsgvT1Ajx?qDqIC z>~?5H^&v1wJ*6XO?T&z1;AGpS<(cn%XSe>@XTMjkR3^|0LRzYe3C(0`gYNEbC@d_( zHfdCVYV2%>Er~KIz?Z&`q#hybtG|=bYb0CGDiZnAz0=}g;b%qIX5>4UcTci04&x@ zrj!m8*eJl~vd9EMVz?mR<@VLS#6dm<^}uhr$I{^636EKN;H80npGy=ky(t*2jwp%? zEg0wrtx4?J^AA-B)^=K|N(>t7Rlti}P*4Qf+1W9J^@8CIc=z;4=#z27srWgA9)Djf z!F8YRZ(!Ym8>0CL!!QN=$oQmY&@)uq>vX9tjsfU#^h1}OS_d?o=>eC~ZLwOd6;D0& zRHSR7YGt~H;-X&C09qxw!#2&F##Bk+A;rSjMmfmGRlvDMazn!7K|YhDLMu}=52tA4 zmVC+%4?1iPXt(r2TaO(sne8Z_7mfIVOQL`)ZpM$8C>K}lrDXx}#hpt_M$+BK zpc&-qTrRh-#sxk_;#G?jj9x>9TDR~%4};7rfaVdv61h@rOBD$L7fQ}#N*E#MPu_d) z&y8EQ{FLIdQfvlsY(|Y@GLxwj!<3GwhhVdq`tx(X$29U{`Lg9Od-m)AxR_T!rKIP5 z?)2i>NY@c#ViIsR-aP$inXS)RZb8-R?j_aggHD8uKr>l;!GVG3$)}z-!sW4mC6{Ct z9|^d)%X8G6Dk-_~Pc*fRpimGbLJdp^=6MzK@?d#+D80Ozaf&8D=HGI08~^?=CXC7u z#fW8e(}Y_@_^!LEDC;(C+<4QjRjU^5SiE?)4>D>raIw9;3vzR_AT3Qbq7yrFM&NWd zQY{+VLoSlt91edk04)2un8F0|(wO#|F3GzRvjIgLe{K8l_UfAY;i68w99C$WkIY z7IDB%@C!F5fpxLrVmt)FLd!ZS4_|zu%I)#=*aw`uy6g_M$?8Ct*bA-X7JF>a+-(Ju z%|URDv{QPYBy*(E59%o0W0^P;r7SJnEFsR-xn+WPiHj5hdf|DeTjVZ9istr6Vl*!M z^eI{dCUaA4ir{U+EGhPrg0H^%-sanG`@swZ>me#@C=?2xn%PhkT#*fDhUKD(yH=Z( zsa8{S6N8Ha{5iAd!1ar+hxzm84|AJQTz62enYq0Rv&0+>=qu1A>N~6sLo0%Xa9I#E z13p*LRQ-M|^AyPih-VsUL1v117~3Qbn8O+M88T3)Z!w^M(cksMw*5S4{Fc4W#m8hW z0k%P(l5ty)FFvE~G0$Lt8U!;LZgmvqI;eQp-cMk>-`n;eeDoo=(8nda1LmfuV^Ge=UW0t> zMdb;lf8>M^o3S`baDl$8Qh;obbDM&qNnkU0{VsC;f(5Yo&O2BUnrel^RII;Gy39Z* zH@QRf-7BP_#fA+JQ20?=SEsK**yvYJ@ZRvSiM`}L!x`1K>P{Yoo<4^!783$`I>)4F zq-^3CEQ;&B&j;8TnE+W8_@}-#@OPylOdZWyyO2l!QhX0%Xzs@~47~oD{ z`0p2?yu5rETx6?Oukt;vGn=`1$|(%F2`r9E8++c#yH3GPvaQ?aF2ObEFJbUX_D8Q9 zgxP^vSy^z)m%ilh!q8~gvDVhsVi4W~H8nMG^UXI0xXGlXBrVmu`0spzS9y)7I89)M zEokFD9#ZiAr!-tWQX5hXM}S;rFt{cM_DBS+6-V6{8D|quQ8Vza-~{guPVj&0FtgDm zB_{ev`Z_8@R#xz}NW~Yo72!D0ZVDXRC5^j$k6r#DIZjEy&ky7A$7BAu?EIh`{;2R@ z%<^x2E9mjj4MDKg)z!gM|MgVBb22Vd_*t2Hh;Y=&x^?#&QN8p8S*Yn~QtK4;H4;=# z{Qd($I@puZ1LUc~mO>2T-v__kivSzIKM&F%%`hb=9s$}Aa%XgLzs|cSvZveH!QR&| zQZc7Li|iLE*MN9Xq09F=alr2j`kfqHHf%pe*C2qVi=}JW46*U{LkvdVEo{dVUKWje6dT1tXHK7iS6+UZgADJ?dz{ViKvp)~ z&Vp3TB3Tlt;KzLlnWU&(AyoYbxooi&x6cf@;Lk8L?6asvYjnf>6ej_&EhS3KGYlmde6CYAIl!|xcn&@zPLJKxWtfA>4KEP#xI1@if8>LM=xt+%kacy z;su#Q6JPlOg?8@{oX6K4^UC)zQZbd_qHQcj!M^?ve_)R(9H6iOW1yI(@*!MCQf8`H z&_G}Eyb48Rkd5G%KA4?8ecV`H{zR2*`2@zN>4L>8(HbettFQfUKz1p%V|e!&+%DMd z?1$a10od&xfR_ecvT%{&5LmRoSmBb^?O4o{lM}L_8i}o3Sys=fAeTw@_72J}qYy7U zd$yh?s01ygD8{LR)qtpb==jGcBhJu58L8M_beV7dC zz~DXKyvbPX$dLo6Cf-VJw$dOf*bwC8q=7;azspT-@zkj!^rH@jZQGtHz0v^d5$a*2 z6r>oVVP{UCW*7OR4?mJs7lJDuN)^g(zwImRID{leSY9ATz|=!SG^uw`EkNc)Mb64f zV?VSNt95m?Gvz|aC|;a_fCVk5B#uM4wBllGyj4RQOK~u*zHHx@K3fEsCXzvj;cUf< zjg}8S_@7db$5Y2Gvcf^u)n$h6Zt7K_6|B=`=W&Lz_VyMqnVK=KfZ(ok@X*C0P` z@z<4Lq?AIS&zlxTHXt*=)~>y?{?MW4OA)R*VI?1G1X_E08{4W>so2t3220CQ(GNjT zEZzx+4}YO)xY)D zvj~}|2AfuZj2eyPwcBk7P!9zDzlV)m6JA4)xn)1S0$g-#o5LyB6`^34({+uNQ9X=q zB%6Od*&E`y|66XkpZ$KpYp*?7j?mEZofJO7%x2)4`ct8mwvf@#8JRadpq`~k6j-e@#T z05*ylEb`)F?w~v#)plUt|Fg{9INsKbuM!wTJ1rHPg5Tub>mP>NQuX2 zb?Hbx-#7u-D92!<6X%@vjm3|2Jic@wwJ<)Pioi4@Xq1$80U*@rWBuoi#`-YFr{=Rur9_3;;#u8Iok2pNJS_ks z?{+^Ov6@NT;{;&i$tcG9=YRaCP+%E&sPysrOddFzfnANT5oncS&-gdyUyA5v zxtfctWXdb`z)7*z-?T0mTy&92@nV(66D}Fp^!!BGozj@<-n+NRsZ%%?Sr1p4U2%X3 z3PJ8D3|M2P1o&B1z^&3~kwSJUMD|M0NwQnR1Yq$uOPH7>K(!=O?Zt7+n1dyOjMQg_ zScM3(Z4Z1WXlFJhBof;{0odqVn4mFLal6|QlmV4}NT!z-DF2dn-{4}SUT qKmB^iR`3^P3A#O3GhAfgz>h^UxEvF3|LV~jl-O*HnNXkv-c#10x26{IOmI&3e~d;8A0@4cBf zv-4(WW-Gb}?(fY`eeb?||M!2+Jq2J?MrDAczNU5>w%XC27?q(C`Dho6$^d~^4IVzk z_M6e(7?q(C*=QGx$^d|unFp_#*do~ScI?@08||4<8D(Ijav;c)*k*_p#bu*iGAg4C zY*a?P)K%BqEtAQvP8dr)kw|3B&b@o=qdhb#gDJ|(;%Z#lr>Ev|7z{JSzA$9GhnZWFc%p zuh+K=kFR5UcG|QbZy5!!QTf40eNF9u@Ni59W9J5BVSo660aqy=euJQOA+KU9N7!6T z1hWT-nIV{YM*(b9zPB=_y5?cIOtvIL2GJQt7Pf2e9@qE1f7Y&jc{Tx;PNzKrk7_tD zHpvLg0>qX*9xt)7-%g)?M#m_Cjmq~6ysD~yESJk)%yLp*hb-)_?`z+zS@ZWIJltnA z>P{ozibR;2c;KmHG6>?q=X83W!sD$oXP((P3Sgu1eE_d<2wv;)p;mhE%ODboNWI(< z4u|V@?c4jkVqpke8a!Nyz;z4t&4CJBeE`|j2xR_|dak3M_@mMncoidfeV7Wo2)OKy zl-?5b9ZSDY{jz%X-)0$&`meD44lm#EeE~1-eu9#&39s!^Y}@f#uO4M!qjDgEmllEN zU3@q{74z!s>1F^{Q&9;Dh2%VLM;0~)S(xWQ@0TyXeCd{)9OKmp+=d^*9Kw6-v)P>F zdhyfQv(Nr|6u?I1fROr{TH2kuLW-#qcv=(boG3(GN?pfJBca$(1I?T$UW?>T^h zi|l{zBX}K**Q@>^jRm~dbpKokWcT9nb_BA(D1eR1NM>IbA^Um+xZSj*;_-T+wWB?1 z`y%#5ER29nLfVjp)guc#;Jm`W_~OO7++5QK_^=wUcf^}sWO5nEvC)xkM>rgTNSKac zZYk*p8^gn9tJQJwoH^&L9R;va8HwPv5W(x;_)sVHo z!Y)A;_QU}OUPmB!J&nLsJ<`uru8@O5DTA(k4rt!e108$qVDEH8QMDP0YjU7&W-%yL z3J8Vz1!NHfGADxAZxF=(I0|4taQW|@=T7r_{ToiX`IYc+pG$33b-h9^r!b)^>ERoJ zeF$EDfA7tyG+5Xs1hA$9<=%Y$`ST~|=jS|!;AI-oz@?Of65Hlan_=xcyP#v24Z;Xg z;Se#e2*?yN25x$@8fGjW15=N#1*IB+ESNoz;XU^B^w`L;`HX`PJ})#1U_T)F*YD0a zNu^Rft(FB>Ji4NJ*ubl@N`(MKM*G843|eSIwbAL8)&l!rVc}3H zblUFy`(7XE_vo|Fo;$g)F!woBzeX&0$q|?o$f&k{)(op&`wlEEP6+rz47^CS=d}As zoQsP_s{&Jj9;OqJ9aY0IvS4;=C#tFBa{dnbYom+iPEva@CyQh!>udbeMusIy5e7@3QVc#GN zn>@n7s}{lQ69liyY(B40D%tfTT61=%L72G&JZ;-847m1e=mftnh(N>_Vs%M@`6Hc9TZ3J%aJf7TxNLSO*c~pAg@d!NeEO@ehKYThkHGUdq%hjMk#)6o zb*2Qb3|QEy$im(jiTCN#PoK>%D$4r`!K*Ht&#MqTwyydL?A={ZF}@Kh8X6$r^QF~q z>CRdLnlInj4r|`t2>~wwSA-euYig?*aA~w!&WJCIH9;&r7TEOd7N$DNb$5 z!ODY|%jI5o$D5mHJ3N8FFo4$-1h4<$LrGPMjQ0CmThe9|N@QWxsae~5W?HrZ$^ed`0AZs zK=W1$0%Hh-E^eIA2>JQB2qbbz^`BnbvUw}Cw{=9%LoQb^!@owaf*Hq-f!QZD0LZd~ z2K;_odwcgy^XFgi@Q|p`qtG(=^5PB0pHNwx_dEkHT=JYwH&|^BY)%GZ4u>-k2?l>P zOyHG=;PqN6@FHn#Z_8-n(e9+fnbJFd68`o{Bkf)xcrC~4JR-}%b%7e$kwTfB<371X5P0qVwi|*X@FL00HTME9CH{^Q z)mds@pBJ`n`Hq2?(O`ha@ncydx<$r*x7`O{yuO`%f3|{smxFzHCoTkc4#oW%O({Ld z^89tjEv+ohyZ1c6g4f^iAgL!E8Y%Z`#fqnn#|d~NKz3n4mW~cs`SL3e^!wwkne1RL zo1FpMx1anEs+%Ulv_*?x%+yH;LjH^vhOWJK242iomC&s&mkZU$oao=Ero)Ey-+<5S z!=GbTc5#mMP-r37_SoN7m*)RLqtQ~jV2*haa3T8=>|WuZ|IxeN+3_cbHw%R5r_@wdQnu8ElB+$1 z30Zo;?a40shht$Wa~V#?b2won+^e_Vdh)u`(xT_^p*}mimj>Q@;u-LJyiENfdl!KP zfk=oq-Rqhw(f4GW~SYz{xCDPCuPaaZE?Wqc6-2KcYx35 zV<6`D2VnffaZp}S3My1}WxS&+*~-L5C51KuZEgFIwW<2U#I)t*Max#KcydrP@+wAQ zX5i)VWk`5E2hqWXBSwlHuk+*tq!J6p9Chn7l~?SM|&p&IYG?i z0hreb7E31-7gwaRWAPvPjI&NV?a1z@pMGQYD1aRR^4L`ip{gYBt>XNgvr%o- z(aLKVsf>1N_;)1W|L^@D>^={{Ysd@0)>KqhE0xNZ@nMnVN{@t)b{zX_aHh{|)f!N# zBvGBGfxQ&_HWq+?>_M~gs{&DED8$D&@{dt z)j1;=^g7V%wO}ylAU`h$N{aItuo384EH(%r=l1iu)7l}w9(CNG4~c@WsVP*_-+ zb^r1pw%|uUTD10=Xa2Q)RD~ST;I#;9O7h;+>kY@K)EXVB5O%v8I6p5Z&%8)&^u6=P z4|ktu_Xc~00lZ`gUVp`hV^Y13z$-XFT5Y$@nrao7>qQBnFAWL~;# zz>BVljPn2a>*LH|&jQ-bMi@V~7IZodV_d|Bs5zW&*t4${zT2@EcI?{Ec4>854N*|= zpql-~zy6)}@8%X8;JBsJV9Me$7T*{VX_P(P7I3-U+_~B847|o6c2wAxAW+^g7AV%99XSr|fCo zzhMZ$OI1}>_GBay%2lbd11}O{Ue@+@_P1K2f^iKs2wWQ2v2!1EbXsDQILsN)V}b8B zE*_Ept{rRFXY~6zlLjU%DuiH83$%Wv0P7C?P7Rlv?VAnXf?OtN{XVg2JY&Df)Kdm> zR(l-F*5(1IM7POo&Kr>a4uwJm)zxJWBZwWgXwlCGEZSt0fei$BU3oSH9}dl$j$yx{_`>Wa!A!&!WW+B#O?DE8}1OLBv-vhAs+s#pM7*|)#)WyB~TA;b56FjJv35^Ws1Qc9& zPXuU;h(X0;x5MVmYbAZSlBi}-QC$U9<4T}vK@i5D7W*#0&(G{(ob5}S6ujtnXp!2v zb64E+hSK=oC@Lx)us+BBu0s%e_r3T2I;ujB6#2{Lhd0)hBY5cy6V+<9ED#7Xup%F? z=x(E(F|YR?{Ae$MSJ&`>S4Fv6r6OawWM)+#uGn3CZm)qBAJ4)hCnT~kJjY2x(HF12 z`lt#g)Ai)nsmxFZA(f91@Adm0gk9@5AP@zZs@OEXj`?A^+#XaF+Zf{#d%^c*2q$ps z>}-Lap7hhuE95GeFkuGNHjDwKF&GE1QYpR(xRfd-{*DE{{bn7za8T0Oze zVFE9tIO>;iK<7(NOtO1*b_`D3UV1D{gXj2vL(w0#wUwunIZ&NpNy0 zThHz{*}NuAY=FExGh=e!ZQmPJ4KopyPRsh5b%r<|R) zl8?>6Vs10m5!RzwFj~rK3 z^t@K5FD4_c4^;%aEf&{k=bcoMdA?GxY-qUI$CAVz?@|khAI_2Lkx| zu!Z3{o?KmCQM0$DdCy>;2eN=`7-(c*`%)s>b?(~-Z~o~o(7k^@Qwd9p^AS9%n30}< zVjF@Nb4<=cjK!R-$>FeM^f_W#DwP^soxRx>xlFXSw6o0^J1(l^=t@3mbf4*SiQuF$ zW1omNLi6$p2kRCn>*^}6`R{)p`E>E(CGU+gupyQQFP(o?V|6hPUTX0A{K&X?wb9NS z?j25YQvKlJkN2NvaR-O3&K?57kvLc{ffQ+>du&z~s67;7v)fX$Ftz&9!TkMKUitGp zJWM6ThGOr%+cs$V@Zi)ARw9Uc^5z*ga1i+j@yAR01 z3=Iv{554{NpUX!9YzXB~OXmMyQ(f6_5xhzmczOMdZCQDHm%zYKZT#TRAMZQY;tsSA zBY2hLIZ{xqvZ9zVFJiClT^87}dw*8yH-V21)z6$t&RA|X=Vx_YHIs{a<@6HR zRwxjPGOnbH2i|-Is?$ZHG?NB{8FV`1ppFFu>v7}8)joK4vn8C5y8FRNexC>xgt1(l{=ASUdXO5YEz)gB%JxjG6gP+#9P zDE6-;Ahx)%v3A)gfDNMDdBH*O$Dbei(xis+Yc+aas2yjDE=zvlCL z+`+ctJZIF!uEYr>={QJ!LLFV5EYxSHh3sH`u&}ETfO7}>cgKwzb2O2Qbl8_1@9~Nk zUxMvxzGk_+WW0Mr6*47C-AwFe)0UmEzqy^Ml;X)wE)t|xk~3>E5F?e5g18OEc`*L? z!$6mB=5ll4cjV?~XLnMn@Hn6)*l?o!ijYF7?3-CwJ33%JGB3&`AqFR{R?Qd-xl45S*dUz57(TYX8Vd4r znEJVS>n;|=FQ{sislrf{2PKooq1spiYNMV}AnJ$GQnIOOv+Pq;0c*@~`b`JJs`tNu z)~!zPJAt)CA$3uQnyM~00y(t+YQj%MHKjrYjg3>Gq@-d<*q2ChCr+$;20?7ni6>q$ z3SbaR53{pBU-J9&XBJJUE__IDF#SlY(<^9IbrJKjIivB7Y_}1?3xa`_kABvA?y!Sb zSvj#Us-PpuV2Ckv_4EvizgN0KIrVdqg$RMiNkHy$yq5d+wYCh1e*4l(4^l;;>1+b0 zp+0W<^mFhN^GcY=G7g8LUiGp#n^PFZ)RaScSz$C)jZ&2Ni{4*%#B2s!D!rDekHmV2 z%~7y5F`xb|42T3JdT5-B0F<+tY6r!I8Hq1KuH>3b8Dbe&%gU;ure-X&ebKoO_1M70 zr3pdoZhW}>KvyBBVLK1oiO@&9UV@OJno@UAt-AO4Mvt?~M|8*evkE7TDSq2vG@Yu~ z>y^a3oVe;njr9a#HX$%O@bO~|yaFx5-FX^~hU{LF4xuvq*Vfg+94&`aXo5K0DLwwF zcEAM#^?MU0G@OmUsz}q(9h$dpOUgn*e9rhp;HB#+D=lR9G5Qg~2Ilt#qH1H!{25R< zwgxn2BghmAmcKp_@I!HNIZT-{hxv5%S12)IMO7{6bJU>F1(97vK$8P;O>IKpRR}SlAF{XC1DE4MFU(*I$32;Xq|zW!PT9MxmrsvYo7=#J%mvdhOK=W{SU}ahPi8%N!lmsul4l>&NQ`nz|QtS=~X-~Tv|0)Zr+{#^$i^0An+B9YA{gvVu~bSm%$PnOcJJN>9UU#; z^Lj*J909%F2o>cOP*hY7I-P<2wv^}o5Q|~TlyQ$Eh%G$jl&iuA8i3u7ZJxwyl=t?0 zY!tXf;V>^IdHqKc*F)PnwMFe+PL|t? zb{pm4z+I28YP$!)t8)Z^SBX}mc@zhsMhd)KE_YuE28UE=_tWaILtc)gwp)+abTS_Q z*`MEe{`vcBaBfaYSA9$+Jr)~Flf!+NJnD5{itLM6nHU5}RTus?mlZScB6K5`GjZY+ z=IO4{=-BRNB6z4&N-&uW@b0^x!T*RjDqwi>2S9}mYKJ0I1)GB!TNKt|t1 zAwUfcO;BCkfMDmtd++2Kx|RW$nx!~WN8g_bcxlx#(5hsN&4=)Fv;pf2gdsct_=kNq zA3=;XuxAf606QxcGV_htStD@y+aDFZUeU+3&}+Bwonn`I)9=omap=^sWiJ?v<|-ZU zEgl0e&P9T;F9a}oIC%FHtJ;3w=?vILLg(Q`e+UO*nIxmYRlBpNYb30)abmUGS@j~h zGz(kaUjUmlsqr|R7)oLv3PpMhEG|o_NLt&wpt`Dz0SvLOP>5r*xw)oZed`v*8R`r3 zK%i#RrX7snl#A!0WDcW=pCjkkojaT1p@&|8RjW2KHyw}YyS8rK1uIvshG(CB6An3K zIxJguHmacoaXG!{dkLfjW+(WUQ9sK?DsHBt)5zh&^)C2uqZ>T_Fcg>+Fr`)lM@%+= zUL!*wi$Fhzm>lob-T(N3yc@u=(Ii5}iP*+t%%Spqbn!L~5oy(b!KB4wl$jsnT=A zxUzB#f?WY`C{L~>ty;AnF24Bx;9vh*0j;f_ap1-5aLD=y)OPON4==y`UpVWmYvI#R z*CJpkd)eiL3>fr#!p4H|T&AK#@c;K$4tREj4L0ua!L}AZtlsX0m;dL08=vchk2bhL zjVd}Zw0>@47SEV5;g4yd-3S`XnS|Tq^9)SrCQ7E1j$!BgWKZ65*0gJ8HdZ`pG;z#} zrGQ58vc!c3aq*4vQ1G6ozGxpg;8j{yhwSTqNZ~SJb2^62Wg;E1+3l%bR^avhF5B;Z z>ZyB3PdbEFBzXp-eeA56F!z*`AmH&qn9sB-^k;Xs6?X4!WnTHo7#lGh0=lm5SX`rw z2am$S@;=$m7hi0IJ$qWx3JNDRm4Iyd@_S*&4rw!Nwv0X@kBI#aMPJomYHtz)zK?in+hX5%+#GhtsOYK;aC`O(QR?$~*dTg&-H z1>9Z;di~6oi_|r7pSoOL_8v0g)7bfT^9~kfCWzO{Wj!^U`}WTz6*5z4Y3YQUZ+?gw z{Rcx7h(vFEiJFKjjGz<&e=vk&i*`{%5DbTydfaIb!iL>m#?XF)K(-QrEQDQT*2_`7 zl%vX>5i`@yn$>jUfn)>A6ch-2DgDZ;Jb=Byt+ah!@1fZCTz7IK==Azq<~CJdr8Agv zwHhs3@rZees|GQHz0(DXaPYpTzv{TH-4U>k7@b?IU4oNHx~dTVYwzl0enul*dTcf@ z>J3sTqrhvW!F*As-|O@F777d`6X#532sfFad}1RQiVGlwOectJ%!5GW?&!gz9XzNa z5};94q2`tjC@RQ>{mtFb(#j<>6#pK9pTN%gl2cAu2w#2m4Se|Fml<8_=bvwYPd-@# z2OTuVN8h% z8p^0?*pXP7#~(@K-uch?``_<=;LJ0ZuagAU5j2J;@!*n)6!6#Z0XAB~m!vZ`uRCSJ z%hMW)o*GwE_A|Y~Y$ovHQb6+=RCzZE`rF~~&~D@X&#mqpQQ(D)WQrB+oN&^rOgMoN zyowsfz}Tbbfi};?*gM(2l3jzVvnR@n`x4Rwh(#&0sNVhAXX{a&9N6ql8U+6L*0~w* zWTHl$3Jf|muXb{FGExAnsCw@24#4`|K6v&cJN)A_2eXs) zC8&lkc~p$?Ds&}=Y@dRLpHB_iFu7A@Zwd+pCdb1l!`fYbaxMFmWhE7FZR19#byIu*V2m8 zQbW4m_t(GvehhxfMBtUJ36T1db`9(5Ccw05^I+D@!=RylB9s(YqRMMx>Z8J>g`%c< z2nPa^@D$>mhr{9Y)Om`zoI7`F#^*~${kPx#ctG#V+MQl#w{pJ3d8XvCnnL%II=Q>m znxGAEU`D%`bnJG7;I+>ku(dfYhidu32T#4~K(K+4+yR{D{HYm!j!JR9fK9SCl~yH( zYfhOAhfE%$Hk)&}M0BLvTb=Nak2k^E?d{<7_?fE#r6kGM$u@U519u>JSw>O^Rg{$0 z;H0`uYVjc(OGj51sxdw|5QY50%5*xZO@{(hGnet>q)(YMXIcYiZ0Dv}wi_ArxtLEC zvJg}&Y2zUj;+n_fg7(4+@F9b5+wdJkC;(icU|>d31~Ns=QPt(LGasUR) zv1Tf7zPS=EyzrC(yC+|4i!CZfUGfbE3ZL>L``omf=Vtg>@(W8EJEujey8N`MaOjjVU^1FOrB*{2 z)yBVl^bNf6`FGIT?F5%EK6Iqn3Y9p9$i{RtwpAkpyg;YZQLJOJ)O#pxu-)l^16AC} zd}-%Y$`*##{&VbyJDS`3&Q^p2e=-Lg90TLr5)@g3m;gdbrHVC9Rg^J6qBJ-rV=k<# zTnS!W6y2Q`2;p_m?xU-thXrp7z?7cI;IP9Ef;;bgGUIdIx^?$}-49|-pKpozq2(HT zGcXk*QisjOm=_uH)7dMb&4B-H^1%6r=|HaNbJx{y=%F(x6!4aj4qzk{5KaDC%Xl!$ zM0zc4HAQ;3^w^0oYeEee3A|J)99TiP^|_DX({J~K&6S*~;5Z}I^k|+DUWV=cVOJe> zx-)SS9i3{D4OUg5p%O0Djtz_!fU6&YMQwHB$UYzMQ0C5v}VCG>vsOA8M`Y|oCi z064tis6Ur7AyWl8@a}B2Kx>Z^Jl=q01Vb`$;`gpvw;ATop3&z{IW9(*Kl|+M_x#*Li<#YGihHs;|ZlY`geMn>h022iIG zva5A;>;|)04>M*oWPBbK6(z{@C~uvI_kYX&n(~Ya2!tXakidN%wrJRt2SKYHnO86r zj@x;q-z4TZX-o-gT!xN_l%@k+UFjt+_ISLP4W|kz<5e-C@*Is&a(mbe((Vs5BgqIr zK3;zTF0(|RvS4BnoIZanOlqhEts#oa;bY}}~z9cUwxOk=2275uGi-aB1`h2_Mt}LlxMXQTav4Q zC5v<6^)KDfVGTh`w*&kLSdCQ$pw%do0;Ec%fC<$_QF|FVyl&dlnKU#?#(*j93@Njo zeDcw9j*QHh&T?ols}&iRi~8|m#7Uo{cXrf)Y7V>HD!+Z z15s$OyFDH-8Vph_?J(?{+SZQt-F@4u1Ves=IV>v_gX_Odt`b}^S$%Yx3Jir_>uaHT z=9&M%Yp;F5%pHDz=Bd!8O`E`gUnY|?z;?NUI2V-IG6ym8)jE8V0YdgI@b))3(Bd#M z)=oNrAe}P|7Bm&XPmXMYx=I2sJ-dl+wfqg^Sc9--8Ua=j-2y=hXXa+w3 zr9Z*b-+Z$Z)xYfPbdDKQ$-ql!WFPl>IWkrbsUamJOpBYRM*;TPzI?wb2@o)VTa#GE^z4>QLr3 zG3vs~>PDDQn-2$-YzK`Z#O##ac25HHj6iK^Zj@!IQFT;^4Eu#(z`PS`nty+ zyLrY?0$43%mfJoVs1aAK;g3nd>*PbmK^=mZR>!4)cA?rxCC{up`*J&7uyOBz_@vr~ z2)u}W+zY)^WJgs;%A-Xa6W?d)NnJzIh<&s)1q+gk85p$yWeyFGY+GS%ZNG|D!SVdVS zHtp|$J>Bm9{v0Xmw+@NwXfT|LH})8**QtJAx5WbAcky^VEUr`9-W0x!z+OVUoB=-~ zQYXW4X>LZM%$(WOug~9q|I;k4SEtiPoozWg954{``!mmfPava5&8EDf4i?Txp7^&o zPakD>U8n-LTb!u%bb&VzWH!yN1hrTp<9zc>rpyYlyIh`=hZ4ZlgYl&rr3@}RW-OdC zAHl1*2yd1EUT${tIPl`~czN)-k2ZI)?cfZgP1I-uf_%Zw#P-=>cUWn0u?h#wy^tbY zhz$1!LYkZbp}Y=9Di&6UVEMH9tL5^3vvfFC5%c1~ zYkQjw_F24{{KU(^6$ud<+3;=xt~%17i^*WTjaR*sirekRf#HH5iqN%^@m)%#z=>JsUs6rA0ql^)hh;O6{<=3A#Z+hRh6`c;KY8Lqb+U<65I-RUhIN5veeFC@M`XEb5 zP5Hax!79vbVSzyA_CV^xmY(DcR`?AEE)XuB%c3fz!{G~Xc<@GUZ@0sHTP>L+Q=xPH z6>#y7LZfO(LsEIDw5YfdC*&2W22hu!=X>SzmCnlVNS!x-HuhVu*x90@{8jPb6^Z7F zPs}qvl7!T)OD;J*<$H)}5xXK&0;$*pT$IT}Xaov7cI<^)Zuujd4}zDx5RpLc94=RO zO!VuW$yIu#Le45R5m?1*465L*BT=*|uYyuZ~7J?@MU zp3ZgHYCM{Z#(Qvr8KhP?i_JD@K40X!M8;oX7fHz%f}jB(2*$R*>GvtlFFb@GN?9s$ z&62hf753YuZJix)LHCzj^6T}t-S!KIkWxq7Xu+ezfg@FwoHc7A9CT0EQzl=2xgLK1`-kCiH1F81w&XQ4o4XvSCWfIq zO&1WYk~{Zwq7#zHqM-sXl6SFDT3BNWds9?HN_g!ZZ05rz6yAB{w2Gh17+=luiZk#E z@mW-P)+Hn%^m{$9YKH~ZH9HZ!GNQ@%^5;4%f-K@V1h3PLdh)wz+zkQk+_{AN;xDvN0}pNB2oIDKydI}6o^r{P<3V%qmr|n7ZgsQ$5!xxbZ@@D6){r z4?cLkYA91mlhMW^(E_5@Yu^6+$T5`*r&a!P^4O{(lL)*Bu(*@ z&&5w(d+o&@1gf(H;NpOcvjb6InoPzK$-?LyOG}GbG2*prx5T|>G#ZgXW)}ClY14Ob z*kQBr9%*<03$U7&1ZcUrnE@E(^4ixO26sRSp@Gl}E zrx%Tb$POSa8ra z2wuu~5Q_zO3q_1aqD-DV7S^oU1g))6Vu>1vIb#4LAf%W~Duhdwx(U1}KGW~_044a8 zXHavlpW(OD|d!W?l0;AdwN_hlqJ}rWog1JYevnDhZb%FsuTTxNV(h+4Ur~+>q z(E#?-g|$C9W@h!B22=iIa}EbyG$E+q1_xYZ^Kycd4E8v|-{0H~U+>4qnS&QqG`bD4 zO`P6ODJd+#wQrlNs7S)9ar1EfZ=HP%Q;G+IxDj~q2Yy!}C()Tkk(`Xo= z=@A^LI?_O<`AHF8WYTK1pCSv3mgw8PyE$<6)fbfF1fDIhFAl^wAR_}fv9L@g@KB1u zphFNF2dh_aV)ZD6`|8P}&gagZdtve7dH8vXkt6`~F#yZUE6m6aX4J|-6K)4^?}QSg z8$rwoRXKL3&9Q=75rS@y9(*BXN+1h{<#0&VK4k0>sIPCzw*U8xSOEL!qS~Jg;~ z(VRafCnuLp1~NJl+al1i+g!|OPkvwIR`9_V1g~aSroLW+P`J+S;kwrHlG0moG94oY zUX)tKp23Pssv@a~dDw48RO{F_I`r+lNS@N90(gT#mT|y`OxH~|E_|L|qhp9?YI1-+ zRWD*@#K@@8q+_1&{j`(O=S>EaWa2#hjdF|4`keT=En9Z2oj-r(FA%iki7pl4aFFff zna!pVIS*(9rM$cdCQWK!)wgN<)A=UzUZ?&pC@5g6e6mJaS<1=^p}M+=0azg5#pZ$h z{1Rq!OZ%K6q=3s2P}{-pbAnp#1B1#31v(cL8Qf4|a)MqRfKHbI$4qh{BOkD-rETm! zG&E%GxZ64+0qo)i@U8ZSovKKtVi(5l2p)Y zeLXXZ3=jJ%MfOEyqcjr6X=v;0Oq($g<0;I~r`=4pqZmo4l7$&qIedPwdwo!3)I$Zb zwHf85P@k6rlZy*saeXZ`;NvoUtv<&LCY740on82TCuJMu!*Y}oE2vP`o~f4_R9o?} zuOH!0?E8={kcuiH)oPXMAE-uliCCEP>Z{L>IGvs&V(crPg%JaxNj?(YQ^;geU0n(j zC)UG;4cnlz(-NmnnoK5k?le#6T4-l7StADD-EDz|3um$bY638y&xN2?lkrX@)dw({ z^6>Zbz+^7KdxGOap#fRQ4Q92C#W4~6(1GT>KM)@9o@ z>JewXyy%G9b5EQz<{rH%uas^Mu?I3VlDcT+)kabw$<9IG^`A{$u(R8nEqKu&r}P}d zw(~f4Ox=qJQfEuCFY@`K6wB!dF)owQz`#N(8v;G&LEv%w{ZN5`)L2>sGb+kpd~pHf zX|-TbD1in1Et+FmzWl;<2wHUlc+uh@JSG*Uy1I%@ zsFCVpr`Ky)!P{GJeH6a=W*4%pJX9s!Q8q>ZMNX|L`woHX?|;7?-%IKvXBV3}b3Q(w zxe7;&jy41c90?HVNJ$%Qwr;Rm+QDJ#0B6t$-Ci^7wB#X>>2U0+U`(zBW>+*bb(0c6 zPMdZ}wp|jEjUeEn!_6nntzV)u<(8UFX4ctWuK-?rrEI&C#X5HMIN|-RU9h7o>(zWE zaA`R{8m?VQobrWhPVkH#z84VwOmfm<8yM#z8T_Pw|hKbb$b|yZ9_0y zhd}meXE*F3cZU=}MqoiD)CiazSr*b#)C<*O8GZI-Q2Gu-9K-0Z%>k22+7Em3!`4imWRK!Nv(WIYr3q zre?hpD~r0^$eEf*f78O`c2k|zF6e0A%Ye)kG=V3iK_-T3uGS4YRgkHom6i4VQ6Wc0 zW$p_OuYpCAOMW+{zVt@DInPYsr6A_z^&^_|t`f}0i)#*tyZem|o%%hNei??Tc;5ZP zdEGb(AIFK(C^axTy1V*xT19mUiVKQT8Mcu<`5}OybmWAwaK({_!kM$D!ZDK?p`ol8 ziV?h23I(%$kvd3?>|E5sG`Y#%L4H$Y|00K0W+&rpWlB6plTrn>_}f#E%}q2LVHT?V zWvJdYd%Vz!16d{VD-(k$F>7w8k^{4h)hhgbv$RWv5y5S3kJYj{-iW<_$B8E%R^W1Z z=EN8(2VgQ;gs}&oFY{fwp;jj;Wpra>H8RE$*tf48dU`VR4V*P=EHWPr%g;Z4{50l9 z(_axsIgrVK+#*Q5G@5cjr_Y6;uLsm&E3$kqGu(&yEV+%1Q&9EQ9=HJZlLa+!)RdCj zlp4czxp@UDD!#$xulMrcB{-?Nnd^is=k%C@6vA;&Lb{sqA-p?_mS5 zGiRFNn8}5|Rq1oCFDfclQNdYKCm49y`7El;=7r7a26;H};A`tUZ{FPQ-YsZGz!e5r zn&l}h2QJWj$fcsRltPBCk$RnS!CO)o?n(VBE-C`O1bEp|eVbcf1HV4uNH`tU#j^Zd z4!C4IP*G`QTqro;A|T_Lmn;TcvP8h*MkB}9genM0a5zw7*!U8z<*aZk6 z6@y+IARfrLjS^yHMr30~qnXvK=r8*l79;*mH{GN=c6!-$exLV7dCxYLI_v?3O2e|K zGK0MUUdX&0PLD?s4&3?r`p$d4ZR?dohB7n0lf@}e;SegzHRSn)sbH(wXres-2T8qW ze_N~M4jmckOA3pb`jiM>tSBsk*VzY6g`X{$1Jmki8C?$x42v}xM4fUX5MxlpM98Sk z8|cZP&mIT)7UGTj(Z|8)Yuxj}B#*hHHWUG;-v@7XcEcU}_k#<6OPR>T2$1l5+d4Zk z+MO&dDwd3oMCq|R9p#sH0|UZoKilSG&8d$8pB|5FaBM;tOwZyK5!{$eNl4 zC@d^x{#V1~>ztMlKxi~7=F>%WA$xkP(A5 z(3MSCQaom|s-S8dgd81U?QBKn<&H8h^0bG5Z*MplxC+7RQ3S7K`UUAdnO5)Ki;c>Z zw+u&zSC*C?iv#D{RO~BNz;=FaJ~Lh?8+_!`b?N*$ux!zx&{$ClJ^~;G&$!6X2UlDf zK4wkMwJ4woyGfDc_AY^aMQfDBwQ#~Q{xQWcD)HfDofb+_CHoASn2(a}m^6HjfY;JSCiQpy0-)W|k7u=LIPJt}q zWILk@NvnpVvy1Wz$l34(h}FhS9D!`-F(?r-L`>QzV5a1rLp>Zg^5DM|vR@VMmYvO=uj`{C?$;Qw$M!X)nI$qT6TBnR7kT@H&d7H<`^Wh}LGc zK%31AZS9@VwQ~bF?9ATv^ed}dZ`{!A{Hnv5G8j0*gA!$u_%{z^$&yBW2wZie7y0)O ziy-@2j05O8sn@AUhg8TAO;A!Dl}RS5%kPKNr#8X$$1DJ&PQ#`2;F%W3z!V&q5erkw zMF1v`HzLFt=ONCn6$7epa^}SYRTQ)mKn{3Y6HTfnWLd>>1*}Mtq>z4=9C2wEI+$kI z5wopG8}m!C&t5`6OlsL~ZSCHe-<8yTaC z<@}HmOa34M?7Hi&8;`8(E|15v6bF*th;*Mk>?!PlavJU2xf6En*bZ%0Tygh*y&qM^ zn_m8^<^J{i9edLJ2{Pob;TvUhNLJzDW^Av*5M@g+9Ft;S6tFF|vKQp#GX|D8 zUHr&E4y~((-yXXVa#3Xnap@sM0H%lmnDCg`7&GGY)~7giQN*J7-NjxiVjQ~?089KC ziTCiwa45n+Oos1W;o){C6Gg37A)u${b;iy(F^ zm$gEyP6D4NO~Kb0bum{9@)x6U8l6r*3S!?^0K0bi^2Q~XUit)5?-L9L1IuGX;6($i zy}ccF?AQT&_UwU{mKI9*|IXiEd+XY7o9%yJyU*^<@>=eMUHu+mr9#VE)!(@Po^dm8T4@9Nk>C{aRJ+rkVTF4avr4QQQMcmzGO-s;AD{0W)%Y= zNDe}A?@7YG`Z_ZIu`oQp^4*hi3s z1(JhU8+3MBH_V?uai0KUoGJ-?g=@~!oXd-*WNNF!VPmcq^q8vkD3z)ayHhy|VA(LQ zYp-p*?6S+A@cDf645Ts=^UBF#J2}nG%?!Nu?%j(Np6$48{l`CEId9FDU29rxS%(Hq z1+Hp#QY?k!$r6V|3iAtO$SAUAUquCl%($IQ-TL(r^I*}qI`Glti5lkR$shA7W%T(- zGLXp=vcjNe*JR_4DVC z-=|h9CVIX8LOF9Uk&EgpDuDAu;n*0tS&+L0r&dOQoUli77*c(*`W=g%&bc%BM!3~LFW{M_8>c%5@ou`elm52@M)U2oNq{Hf+uSHLMv8cs3^?En}&lcy@%ME6blQ5L$q7{UaIf-@WTxhQuHhW(5_1_J?aj- z-8)ZUU*byFu_kAWPFGh4OX)=Mf4RB&e36RC_oiYxW$INU^YjJ$uzvS;*wNMucD&w7 zTv+Q%E1)}4M4*F&9n9XiMwMsJF&N=hw+p%x zD>vh7d1f=TrU78|UMEhfyd25GABzj~^2@s{Jt^I1KKOunTzrB6wRFjn#aGyD?n}5E zz(*iwtlcJnls3<6cDK+&lf8tcAE-GQqhlfy=&Kkge`I}R7!{JC% zFdUv3;ytfrVGZ1H&5g&}UADtWWn`g2*a2N#U9fA{F4(_+KLfAs?rutn>r*O~mmzq4 zJP>`4?NEu=nul{x;G~&=hf}0pr_?f1?2GyGByrND$$BEHjZ;es!9y+=#1MGUqI83@ zDB$qLOG7fjRu2sB!o1aD)I2vJD7Mzq;(QW4B-*{>p0g z@UAa1QG@7_)Jp1VGV)VUI320tH084+8(AncG95>itj2+gxvw};74EQFpwn&z2cCbI z!^R#rcXuIZb;6#`c2FS`qt9rN=~|o)=(Jhj+r7JB^Zq?Bd+bCwYU)hTs;@3YyejHiy^Q(`a69|Ute1YH?Djn`&#X=RZuH|FX__CQ$kXHcypr0A&3B1Ve zMTUCB!RO;#umiSo{m8E0!|=r;-IJMNg54^^V~}bl?WqMQYyOw-iHed^78NRw)CVm zv)+Gyy;Cli--oBL>9Wg?{|U0Ov$>s4ImqS7R7zlWG6tp&2U9C)$C4KEJe&`t-g27* z!w+OEK2f8E4rKpZ_V0$B?X3t%cCg_2T5%z8;lgUg#}<67lq*@r5@Uj^3IQ24+C=$c z+a~y~Wgl#B-3K%48)4prDeRtm2dM;LRsgo_##0tue%*;nL!t1gZS7W8K8frv9zOyY zvIvhafO>KZw0YWKe%)elSv^tkB72v`Vxf*(_0Bu*+>KxN>V^#)2I@KvPVw5F;Tj|b zd3nV+X;QE+FL+ag%@`#zgfs3jLfKZm%bO4ORj;w(E3nf5e zGTxI}2w-XZ0>1k$#r(s6kzuVt5L<`+dXCNJnJU=8;*YUx9>VUW0A!RYf{grR4<@_j za03~c9^PNSngP$Q_7>RJ-N~XFm>S8aK%#3f>$o&coKtL&E9Syy;T6j6QPblh!BMz#&XY*xc~m|iyy93J;zUB)hD2H-XAiW^RPxTC|~=*J83B6#@(@bYsEi~!7q z6LL@2DroPqLVaigG`BP}dzTfN2C}ZF5WF5(k21g)a%hUzI))Fx@|Q`mFS_|XeN-7T zNR*m7y0(%F`5_#TMS6o)h?p1t9pv>!QY{q`4#ed0gjmS1h;>Dxs$@iL7ZX|pM0T+- z&#MwW_7fPH_;J)u*BjXU*p5`HlL8p^Lnm~n)#on0Dz#K99DMD^kcBhzfBv(&6Z`ir zeE9L@m!EttK0Xf_S*}bbRx9NRs-+CL0!nhQ*=#%`b1@JT%qzoXA6vbB3q1SLf1uUc z!wmFVWQQ`DIq*8ugU(O?9fUdL*P>UpyUm$=Xk797X)UM0`cS}oo1kIz@YhCMsr z2xNAPXUrL_oysj~0odi&pQO6t`jhVIXty;|J|7=b8IgUV3gZ?4j2;t!;n9y1XU+b# zc=0lDb~@?e0@w+EK$Y=s#4g7mTu6P2*R~H2c;%_^x|c}3PCI6)*cYje$<#;6y|uWy zl4VCFAd<<&poM>j`MAa)+3;l|UoSbg`zQ}50GMD4_(1UE1 z)W}5pDpzh!#(Xx-e8dc8`xQ(Yf{M<@FlrHYn;lx(TEOXavd_`3CDpJam9iO`-RyA_ zAV+T;j7!;<7JyxOtMm?(#B-pv4!Pp@Y zFexG&I}7suUqUINusmv8iUXK1Z_f&ez>I-dqJcjV%*3AeB9@gb@LLpS)C<_~i4r`g zV(ObDSvF|mq+8V2hH4w_-b$!w)p&2_A%MM~?Y({T%~gc6|3tNNHQvjAFI{@d#WtIB zw%EO*H!Bl>P0oPKhLhfh^MtaZQbIyO?HvlWvd3wMogJ;c!qNytNxdy9Dgw%iY&0QL z#C{a3ysWYm&ys0TAqRB^at0l2-MTfJNrd`Aqf!HDYaMnQi;3dMtv|$yTd#cKl9djFAa{bG9QH8wZr~ z#^a&dltGp~VkjJ8J1N@<8x!$^g;c}Z+FDkUj~)vyAb|w6UM?iU6aimhK_PVHbwFEN zTQ9b^d-pb|&dblLcx}o_UzE4DPXJqb!%5e*x7+Gyr;+V8`Z>Fon^zeb>+%ciD~R;n z2TmMl9#7Eq(Yqfl-SqXw&F}-0!u7ylTMM>DT-yGK!kOR!0a)W|4U@#BFmKOc2lj! za8f2F{7v2OaB#7eR4JTFs0|hq>q?Suj#OAGikr+QQ8-W9h@b=vw6mHFz{m!cT$@la z5F20s+w{mIFS{fs{rOiM-L&M!lm61yX4R9e%ga>8fQWeo7>E(;a1K?Yn@KM-Hr z*!kYByM_=m_NK6dm0@cgI`uKPm{xd6gB&u0beuA!W^6IVMDpQ4OdI5P8p-KCn%7Ig z8N66Nayjpv&k`4k)XgaUg18+-&f7j7tQbQIaw?^mk;NJLh=2m$P)6aYqG z^4QR+j|CUv4VTn+EOvXpzCS1c1%(jdn2;$2+ZU;mWbcx5XeQ@0ln7&A5vF2BLttc( z0ALWaM}kix>e6%4?Bx@>V7o=bf=5-tpdBMn#n z=G1AvVCclwmL4-#!8yPT^-6OrxLGS zFjN4Rmy@eS@VY#uak-zK$x*fw;g%mVy33+qq~MvDh*gnoOfCSNoI{8>8(26YRxu=U zY~_I^DC|)3s-vJ%2IK8wkx&XpSh0;P>Vgr82eXJY1IuOt5Zk2;wi2J!;$m|=0@#ZK zI0UFd)^8J^T)Fb=nOn%77t{xYZX*VuEwGY29k&sn{y!_ zS(sf^V#34w&(ZIRL6w--{^tD*u;?|x&4L~a8%-1rNAFkgSvrP7ZoTyp7C)`L=YdN~ z0uWl}h2Zh+9X5SSi-qklCSzVM9>APp=7r6H;N_M_f<8rLxnsqy2VGz8A8NDHr`R6G zmJB@R0atRfs6w&52)2j9_$82 z2z=&_Yl64ed>&s*!$uz{-s`Tk&@08WUdscZo0=6O%WIB18Lxi^4_ zdGQz|6a2rzoZ1*+Y9!}*FB28+h-Y9T;1a2I;=J||!6z(|=w1=x*;tsXMkE5S=q5l^ zMU-kWV55NaO%j<5vQ5=OYNSrO^7O%ZIXN{Jo2|d$W;%X>Of+LW&5z5dJonsNI}t$s zfH&d8%P&9sLIkEu5Xh9tfQ;qZ!v6Gl{HRK525g)XARRe%7JRy8Ba3;As*3yevP6;u zV8qDCSTBr23Nb1zEronk$qVuem@}&YY{a@qyP)@P*tlUR=K8;*8w8Ks`){HJuTb-c z!)5+pXnG(R8h`Xf^QYn@s0hhI6@iGn!jI$1tCX2Mfd~Rt#Nm>K!7U4K^eQ47dsgiH zo9m1HD`0qqbhBUbBOuWOUdykJWSjV4aMZ^fGTxsot1}1i%%v4-_vO%c@p{StnOa!q0Za7iBg;Nur`+x_pUN(cLpZ*sezEmjW zU*gT!uypC!KeyQ&(-Yk-1R!&}{h-%tU?9y%wZ&y{{LF*l`IYaoOcW#(uPk0bh3E$g zeInLXURDkottJ{`B!Cz7FEKNhYiQE$6%^#Y6$LQy3okzO9_`jqd)wm=s{FxVH3C|d zFBqy0kQY7z8#z%1LZL0>ksl0&*9OAjjjmPuV1x*{0sn%3oCsnRZuID2ff!DNGw{Z$ zrCzu9ky(@|c|}D9G&D4@wq?_1_-^agUhmsUgM@aA*hV8kmK-rk!2u4hItqsSXw_{2 z$k@n~L(B)$BxsdPluYC8W=x*Jd~A{!Q20S3zl7RMX&GL<#e;egiI}?-1b4ig(8w* zxDRuzi#OoMb|AwdBbcxSDHD0dLqeLJNW4K`0HPqD-zp>kS~yw|HwsFUM*T!P8^SQQ ze?vH__sH}aGvLf~&w=gRx3g5_)EtiVLu$zW^wDsW25|H;;8%G zz*UP+d)_?$_&>iuCiC;9OV7H+VsZXl3|=zcQQ6}O4k&<;P-^HO&z%nsz4InZi6dsI z0(jMpsbk?nf{TT~xX2%jTq>xBr^oGKb})K=u#Nc0zFxWSzGowS0@wjA1Y)=GD-zWqAM2L;%ZllZV*$Ll9r%lU6AzoA*(sW9YAceWevA|FX+2J4J3BhTX17Jt z=?E(4V9Q;1J@rf+5rFTv&;Z-a+bE6|Jx>PsprE0a#RcE2CCA^R9d)w!ABKEiw2M?{8uMNEB^iQ*(dte?qZ zs$>#7Sk&zyvG9lBN)d?%sYpoV=o!h%pg!C(HKEJ{Gszu`Nn??nZ1cXFHA_ zdF1c7@XD@Sy7ZjM2x4`GAR$+&;k0=R;oFvH;sA_PMq*w<05-=0J+N!f zE@*FSXMd~J>Y<*`8}GjRsc(Kr045kyH}eL50vfTK!$mxZ{fXbmNY~I3Eq}vrL!Tk_ z#={mYfaNz_597v;&FG}ba5@n|kC;Z>4a0%+Zf7?%QlXEi;a(mqA}j1b%H$#dgV+w2 z3?vy?q!$BAU}8z!B_iPj6*4i*C=`wZvxxY;JeW~|l1Gs(CL4@nvEOQu2_zF@uGAJS zTEvXX)K@E4t^~?@LXW@r;*02eDgHEt8aWHu!xQ{ur5#D~BBhT18aNl7#0BnLY}X__ zM`P%o{tnhh9{HP3p-?P2^UUK`lUXXJPRhaW4})Gmu#WDZ7`O^XLV_X+`KrM(TM$d;BYy)0w!5@gYlNA?0RlJ|Og;L3{fUWR*_oX;>IkL^AR3@nn& zg+icT5eYRioFwe0m#airB721>06ZKIT4E-qLN)SDWM5nG#}na&K<*^8ovAPJ1~2U%+D#w1d|zbx?Bghi=6H@cA*!@r><&J8$LK`Gr-Z(E--NiySM+zm% z6ud~x1H;t1?!W)JmlB^;zz<8vSn^+Nv|U1xzBQtLAiab}e~4En{33PpDr~<7ZfA25 z4|p><1F(6fMxES8rxMk`n|||uS)VL1hUcGqu2+m%hd%&^noUp^&Crlg=8Oh;VwO}f zn~KE8IYO^I_@ZnRp@g`|Uf>mpfmK2dv1DuuM5-ojMsy)~-6Rh|GWW;4ygaz~kN0O~ zTOpsN`Sa()Nhh7e?2c7cRm{;+D&Uy>oE*vB0IIMp<{$6mflN#ZsVEH@-n$2KpdwIg zoHVJC&|4APm86|Q`GDHNNZPDD@ZS2bdNDBS|LB-Q@UmwS2A7XxcpBad+9Vh=rm;Wl z>)De}UiQyk_YHn{LMc=zw1@@=p$pXt6h`$Sz&Rh@3tU(T@GC3*JuMkErc9Mma{P%W z^y@^YPMgL+Fi|u(p&w~!MF0qK4y4pV{E=@FaSI5~2jkuodoGypnILP)-Y>j|Ik1XY z7YA0Mn9)88UI~AT>}XWj_Rq)^lX;Pn&FZ3`UYym6A7^RD)&HoYj)L27zn!sRsibr zil8;Npnx6wX)g;s@W2ayPP*{G4_CHf`yH=Rl6v`1en0}hqEaR8-$Ihuw&iok2|hkCrAK!&Uxo0%@Xh#4zMq6c2I^ypc3K%DHId|lK@V^7&rxjQIHaYR&Q{N zeJ6WQ97x3gje9Hxv_$X<$N!BWqQ~|sg4Zk9G`&o65oY(g_-8*G&>Md8$tNdOA%(uC z>PLOZk3^66@yvYNU=7f`JoCd`9m<$r*kI%dQzQXy%BM#8y~xjtHcM<-#Jp>9@u}lk zoL+D0Pe1(Y_S^ruaTLIk3xO8-hMmI?$h&yMEm5oAq_pH4jFR5ZB}`$c~b+tON!Y=;QSS7MIBIKn!TX7^p>eBgNnq48#t>M%s`6CY-SrHQesHoLQXvBdTg%_=D>X7iGPr}!y&%wgPG_s z@gC5wF8SP%|6MSYnIkdPZkR-=sd?r_H8QhhUk^R>(yygn90f3u&7B{Rq%zXdpVAqT zQy-HLcmlN_pK->37+Z^ri`jQ2x(3iUufbLFk@j{_QBh$5d_oE8V=r(D_6D~=D1oU3 zc_2(wBZJ9-l4o5}po@Z4C@zN>2VNmqh2Zr&c^KT#dsCD)J{BLlnE8GUhAcSzaLGl7 z%mHcMvs+={g1{x^zWbi^;_3WH%)+8sxCc-|NlLuY@3pnJL1%X-S1dWru}tbB`Sewq zOfb2mgzYesfws7~B3t(L=54n9hu>*E8S1h}d`9LKO zGCflNC%d}fwH}KI#DXboTk$roIJL4Ddy}w#C908v$`}kMQ7z+DMq zb&FKx>gpQ!&2N7@XgBt_6HiF0GBLwBRjE#Gt07(fue|ADNF*o6{FFG&4#&a<_BRTV z9fgyiBCCw0P^JZ5^m+0lQ)3@CA@e${rUo>8`W>@5A6s5l=k~}WFQ?oE8wIe`^0Bn~ zXpmgV$Bk=bAwmN-zzPfD(j`lh+QQU08E?at@-?fKftXy1WyOJ7Z;(s=cMP-`lMAIX z=<|RT3@50OAyDAo8a%#*;B}iKxyuAy8!ZagT(_LXgbtR_eW|Ifm1NEaUCP1}v zdhAr|Q%xYpv4^q@|Im*a&JhYTBB`X(m#A>`PS>b7*La_60YI z0DfJ{=HrK~yeu?ZRpEs)!{GYd$LGL@fMAW)B08m>JsDMApTzZy0K)VJPW_Q78NrKd+-UD{W?Y{nca>vyEz+7smGNTn{++jk(#MIbHy0ASeAwMqccogT@1-w4Cz8f{u9+C8)iDPN& z;eB+mveF)R4yqs5Cumm=vm4ODd*t2VE5;p9ch2!y4L?hKAI~(1JA#OaNQ#NMuGwRD zK0anTe?IHXd+%-BDgk!wg5@E2nv*$UtF)*PWfM|0K}3n@n3z_%kO2b+(!xcHXu3@^vB zAv?@W3b_0@Wz^coyEalS?PGX#RB3V!vvK;288rXtr`zm-4j(Z>Y{se;zY3ExCF*`p zo7$%envOW&WiK~-U*XQR)71=~=wAJ3{KY)F$mLR`Y*1T*h_(zXKc%jPG2nyz{KV{{ zh3iDEqLr2N_pp98ARv&!!@E(pZjscdPqbKoZnM=k1J))gD=VhUm-Alv$3OO0N`SdX zuyh2m#HNIWhK>ym3jS?N%oBGAoMUrybLq`x%f#YZ=Rs#wu|P~)aRofU$L?i_jSCE< z7_M+poKWE~|8HpwFNY^TDf=_pY#K|88U;F3KJ(@GzKRBx&fq%56?QXgUR$vjCI59& zxeu7ah;;DSoH;aS-dw$Pimjm0m}vBvF|=d5dVpSjzG?u2x91n_QTaM{3`;91DXY77 zyNLx$z`ef{)}b?XWs}cx?lgt?nuYVMxnl>VD%k4Ay)Xt>T3uDQQ@5X=KVM^K*1AGC z52xZ?1gbEZO9;K*9Mjs&}6hHWPoVZnxLa?-svE zJypWvxKrX2;)SW2lbubME?sJ1PNI7Ib0x3lim-<(Su*#GXDl^T&R{9yuG^36Qv})F6!lDf zbPD^XAAWu&w?=8jv+3HkJNdBIE*7Kl$uX8?Gu5xD1=O&^HeeMN)`>cG>cZMqPu8|# zMC#I|yQrI1Yx4t8!lKB_%YpXwn|>%3&Y>mwD+-sj zPV=g*Ga&&wGs6w%D+07w!z$wUxeTtO{Jo}dPapgHFse&&n$kA+3#r*wEZr8$aZY+$i z=FYFUxRA}ctCtx8UeNrJBiVsv_@%L zKGfI8OyLZ$KAZM9Pp~Ds-%pJe{=oydDT^TNq{wX zj36WwyQJQzYF}~>H0jn!ZGKHRjU7vI@$t0$jW=lfw(XRjmR1*R&KYDTWqd49`K*9@ z%REl|sD`k|k;PVD4F@^T&M6;OkWBy!|BbzL{YB+5Q8yhW-Vu);*D~(rn`!FLrn(#+ zr!8d4)Tycf6XRfkL3Fve7!$cz#Az*?Y9|!ZJxd;#bt?&9x&TtwY;xd;n{@yj?KrA(9m|fzP)?)(8i=BN;#ZN z8R_YDQ2_L|d{+~-?$4(gy&ZaG4ANt9^bNy?i3q9>KKzhsWR3QeeOz7-{QMW1Q7H2A z&%aYyRrR?=Cc~-hF!0_=yw6qG<#XH1sp&4hIoKk`EtNZydh9@JQZmglm1_g=J;;+;jU! ztcCr`QRixF8$ztK)WY`^D0cETD#YxYf0(JHq=u{URPA8d#Fc5bQ5|1s3-v~uJ-cPky_!v}{2=!0JI}pFy-RAg(aP zf+#rHU${h|Q)*9;Im))Yyo@ef$P@6wOs4{`|J}PcI_a1l4&0clC-Uuo!!J0_yhK}8fG&JvVWRFT>2w^SEVlvqt zn>zKDPgtY5q24E}J^^ArJ|@<*tHr7Z01P0*gazQ?Sou)@efL5O3FD%bl@(%LV}5=v z6%^!&-||;Bz+rfO|J`>#KEd$1rj4Z~z+4dSh40b|sf)3ogv3NyNFFTkrPBf!*>|5Z zlsy0ZA5Sn09-1=cruAiI<<~p3uiDy%+8BdQKm&2@OG`@xz=DH=gv$>g=I3XhnKqfs zissf3W?FD_-X%%-M7*x4sTLmmSFTjE##JQ7xC#sN#d++LL?*=o@cUu^{u2-V`On)@ zueB^Bz+4c9*WFsj;6Bk7TdGTGJ&B9gWz+;CUh{$l%TjH&`Lica9<#o@ydGkX@i1p? z44lDMZ1zn$%Ejl<$`FGsFfd3l>C6huOv1bqaPVy$jnyQU3)$B>+JS`$1dF9cKnvPd zaq%UFWie}C-Hdz*u zhs%)bt`oCk8m=UfTnEC-D=P|(cHIjXE>DFfHfd7gI@Yp=J1_B31De?L*vGyx2uw>1 zsyk+u0|NX7%y1kbaqN%_6cBO%2s{L+YHF&)Ypjz5yeca(##Jo-*Q6}?_VWv%y67f~ z9>DP0cJN^4B6q=yNP6NoDY4N5qF4hvrKL)LwR1Z~MMcYk@^Be><1o#QTYb&G(=$$; z++@^iU%K?kf#b)=y}>5rWCmGKy?aGNkU9Lu8iLJkdP1|ZFUGDnMeVV?tPR#a*2ByZ zRMDmcs&Fi2s@MD+?-^Wq{NmHYhcg$hT=`|GJMUfEK24jCn&DO9xGCY~J>y_Hbs);f z*S>J!iW9qb9h&y_*N0wb)9^UVLp2QyzG4kc%vvWi)1+)-YgQbb?PFw!_0>4R{Q=40 z2n~&^F}&>NqHiU`>kxzMSx&!pH@u_?>6&Pce_`2<6z`Cj0lHCiM;QJ37cF`l*^-xE zp8FYtY0lWOH;!dZYH(#`)m7tSSHIW#tl?Oi15l0MH+&6q)UT3XA5Ts`wT0iVVsM>n zt^1Y$(~;nyAS@pmr8WLFYRqU^NM0fcu&5)~d&+(M?sxAdbN1*02c9CUM?(^}|$F*7GS!V~Xn@#05A*>rr6;WBB| zs3FmuM=+$iatgu%1Lv`@dNWfUZqCQB-jX3@;nx@W#f6lVQyKhzC%^t+#fmLuZFPSV zV0vanzy8m0_PW|JjDLN-XSXaQFA;d+Uq5(=7{FGOy!`yI%BspTPrk<&U;OV#hEgI! zCxKy<7#BCFBfk&k_sD&fTy>0$U)S)<5`JI9|681znst$1r}42voDMEu{&_}w+>M~ZZ#(2%~7y)dfVS+&r7d?;QnAM!eBBBIDpSwa$E9wXf2 z-lladGBT2S_UtJO$;$-cfpjE9mXHLPCyAzKBch#3@jmen&<&<7r<*0fJWArV4vdVC zlcnQ@GFU%$|6o}{5?~%7fdK(wq~W}XY4#g#xIq?@H$L~kK)u5?vVaDrK zV^~-i4T_DGh2({z-tf3q^=O0x>!3k{WFbkBA^~Phu~@B|YlPsb-8np5 z7LpVx5@3cE%~ASc!-vb#ks?I`%+S(L>ww%oO^Or=Fr$m6oBiM+(ivNd6bUeciobo^ zVAWkZ5JIPkr6y85Tr{Gw)*Y55Bmrh<>EF9gg4QwYW*pw7i!3BB7Hs^gBUfYzNq`wz ztX8Y$B1i1NEycSfJuOY|aHcFF2{5CJW)QMEr31J2jVWg#aweDyIYPG5!3kV3Ht`QMGiE=<0=*7i?nPoPcy|Xd+>NW>C1||V! z=!V;0>)7BSL%a@B*vPe}riQ92E6K{hx>9ZT63EC%r_$0=&HqI}$JkiAKb$Wst$y6- z{Tc88TToCCG+B==mx~uKY92G0OfuS`1el>ka|uznhcDn3psK23SXD8&swwUGamq+f zr?YwI=|KVkDAwdrKU!@QAmIpS~NAVk#U~2i3cE4&A_T)?F!&JxPLz#I&_#0A3P{P zg~4io3R)91C==%`ani+ke&q8VKXy#~=DO8u$YQmK@j`$sfq{noGZ6$5AcKYmbKHnh zU0tmQTHEQfx#wgPkpS~ZfHkqi#4u7(UQT74va_;;X0>z2P5~|WH#y8bfU85tj&Auq z01(O7VKxTYvvR(Mg9i@KzP)?N!rEW=9z9q)OQ4CjPNK=T-A17yp%fAtVkpfF<)tG9 zvUx~=8C`m59T;+*amT=*VO6rGm7kwan>Hj-Qc{vIg)kuP@9!`2unu8udQE^DejCXF zv>n^F(HC2`2u*DI%$YP}#&o)I_;3md32ACKpf=N5b>s)xJS4!3E}H598kx~d#Imw7 zVZv?rSN=hi})G7L4{Rgyh!v-;SgPFgMojSSmr}UgQuW6bQ z<~YW|kkS|$M~@z*RV&}2Igih4SCC!4T%>pSTiHB}DKbQeA~F5?YuXSev$NXu+5oBY zvT`w|^v=qa!r?MN(YCH(e9o$X3fe`r;G@-w*TtNU>ipj@P91&CW;j9nE1D}h!T=?2 z_65Q345n~IL1O0ymN5$00+i%(9RtWPdpc~y2wJdkA;l%ci!erQA!A347UPH- zGKK-RU$ztpFhk0~sOWCocvNdI%(Ju;KeijV-g$c^T_`9J<3}x+wS#wRC7`7M>l;p+ zIepKtYL#neuyr8&zM25qEqu)bI0uD-T&-^~m7$USYR+7G^696j6Pw4aITH*&x!9Ni zT8p`DTy|kxUgff-7*FIFn7!xMj6#t(YE+wD2O2KC;6M5JV*#!L1{XB0pyp{IR}?L) znj2mc=bs_97O)zNqQz}i5`fm1vj;g%W0(z8V5aK~1`RVbG?dn@T|+x}Y^Qhryh^Nw zXe}@Q@AmD}i$rlz!b<|o=wj7_N*e%FXk2^u?xlsleVz)~l!3+t$4?gp<98Jbv^H?Q z38}51)dbLBqP~j6FvIxSgAB5V6p-nX8Sp-H<_z64VQMj(F0&E1Kb3{rmIV4&itgRAYQk=|1c+Rg|vxeSzYbArMsyU5OjBW8b-sAk`>@%ke zJ-ICS`Z4pnBC1c{4>(`z8Phug>(pMNfZ28cDo#MYF;!a_QK{=C*CfsM=h z8(C{5z@#WzS87U%(7KR|r9Q3=Oaol!xiPKae0`ROgR8M9_cMz@HjyC)IQJ%vl@Tbf zEt|#sfLkE;)z+uX1=M-?g#f{0Um$dNx z?P7?2ub^P^R$XYKdTm zdFKvYMs1WeSOUxwL~|LDR+#A~PiV6Vt?P|t%V^e&8I+x!O@2*l3b>APZoHp!is6R* z6dLqT@qzGtFX1wnO?F3IO^E&Rwb#YM@RmHMtzUd0W`VU8=i1$}X-E^&6HL59Ek{Pg zwSo!Q#FkrELGM&%CjI8w=jvP|Tv68eci;~32shqC@~H@jeZnRs7roDVeyduDFdtu7 z_yYCr+n2^qn9!`}wEe4XdgEV*`S;Jtryw;jPiQFLgJY@%#0}zy@4t8XTo|a|yy-KV ze%IY}^vDrcyvLzBoMm{uz}Inugx6Ki=3_+@tJeAsAolp2xng2OZ$lDixpe80a9`1p z_hjiyfO(Q=dR%|G^-GtuE-VIq?9ul~kNde-TjyEx^`;%@?Cr*l?wd95LhWnU<7bQ*vdG+#YU z4BFS<*RR+6xt;ubxw6zHz&u8{acBYzkxzeq|NUZI3$VhLWXRF$16+6AaVIT&eu1l6 z*A@P)|Kk*W>U7SRvgBPCF0Z+q0b({iP3(dH`ni~)R9nZ2&z^hw8NFS&`O(;<`RE}c z!|6ClOuzmYIP0oWt3~BURD=#4I*7=q*q+R>(W?vLUeM?Y_&oEuA$}xFyJZsHw_hli z^>%)ls8@gStY$y_Fg@|qlXc;Epp~sy{wI2OCBQtfVT5tR0B8of%QA&Bz>Q)FH;SdQgxels4v;xIoF+P*L#%xz%F^{5kz-&^ z!jLIt*vulG_+ZTtw3WisiEiHS|fc`#0sD95m~YlV4mJE zum|8wPK8Z13>~ct09?XpB%g1OEY;TQa5%e_>@G02Yd97DcfRuMrAQOf^ChNVe}tJ{ z&S|1jPNpUrfFu2l)9=|7IU`H4O`jM1=;pVeQ--Ge9zU-~WhqL4d1J#E&)JilX6StF zYqBr=P2z@-BTKE_p4D`v)9LSG-4>b`KeH9G^d!K33JnCC-#YIgo6VI!Tb7LBp3}pe oEmlCL*XaOWGUBQS%l`{704@14xye}U`2YX_07*qoM6N<$f|LCV;s5{u literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/print.gif b/src/demo/share/jfc/J2Ddemo/images/print.gif new file mode 100644 index 0000000000000000000000000000000000000000..11f8f776154195880ab956841c41e62ecc0cfde9 GIT binary patch literal 983 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 RzP=LSza-Bm>uCTI{sVD$(Oduk literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/snooze.png b/src/demo/share/jfc/J2Ddemo/images/snooze.png new file mode 100644 index 0000000000000000000000000000000000000000..98a081a5fb8072f81e05f01437fe0ccafc0badc3 GIT binary patch literal 4160 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 KMNUMnLSTZ6zut5J literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/snooze@2x.png b/src/demo/share/jfc/J2Ddemo/images/snooze@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ec50b59b6647dd2a96c79d36e92c212bae851cd5 GIT binary patch literal 9552 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 literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/star7.png b/src/demo/share/jfc/J2Ddemo/images/star7.png new file mode 100644 index 0000000000000000000000000000000000000000..c0bf06df26f9d81bea369f429eeb2769cd7ff176 GIT binary patch literal 6934 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 literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/star7@2x.png b/src/demo/share/jfc/J2Ddemo/images/star7@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cf0fdc4411f213b17848525356e2117e6a28b7cf GIT binary patch literal 16605 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 G(fA*tU!|r1 literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/start2.gif b/src/demo/share/jfc/J2Ddemo/images/start2.gif new file mode 100644 index 0000000000000000000000000000000000000000..4abae4fb929a8e65f2a42d961d74b286bd083650 GIT binary patch literal 945 zcmW+#Nl2Dq5S}2&j26rUQ6!-v#b_CFNuQMw``-NJNK<2#TRY zNs@;m#6uc}v>74;(n8sxE*>-^BBbS~!`n08dmCov+2;GURaO+2G~`e^{UHkeECdZf zLf{a{E3;r4OoDMR@}^o)4Jtu7DEX{d5Dg+hI0*SFTVM?=fjKY%DUb!yKoW=pp#V0Z zfrVvElk@mfGcjW`a#~cXreeyb&tI*hU=i z4-s$()c}KNsKh9AfEd_-1{Qg8-bRhbBIH5BA81iA3lnmMU8q1)h=q_Nl12c~g>eK8 zw}=vXKqj^k2QQQ#S8pYv9h#WdnB-(Eh>2Tl(8lMBMgz(@AR1_yVL{v{yOSG3LMzoWt zlBj}cGu57}O*~8_dJ;>T7NoT-TpUkb*0w0?Y+7ztM$z!frbh?MUgVXJ6l@(?Q#H1} zdTc{%yl~fe;lB5!4WG6g`BHIwvg*`y&FSfy&hLA4wteVt_r%0Re}6wd{oLf-IWS5E zuEGBaO1Vm5e)jghyU)8)mgest?dyJdDfL!E*JxYjP|M`%Rj*zjyR)e^b7O|xuQ@Q> z@pbTGdh*(e;f~)kZ_1~xWLLMYZG3xs-gtdUTVY;vSKf`Op_AV}biNzh(HrZTdUm-n ze|OH)d$Ez^Z144~vIjpdH2?Zob9ms)&$07abvNTh?MDY5$CKlA#ZOMm&V2s2ZaJ0y E2dqoLKmY&$ literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/start2@2x.gif b/src/demo/share/jfc/J2Ddemo/images/start2@2x.gif new file mode 100644 index 0000000000000000000000000000000000000000..64a5810e68f3f8ce1f77b538c38835761fe5cb41 GIT binary patch literal 1147 zcmW+#drZ}J6hCe{y?;1eHya6a7?*jc(8FVLuUw+lOp-ZN)O>&s)KjVXm?fHte?TLb zx0;pni>4{7&EfSmKzUr$Ttf048yj3rFASN8k7+bO1hj9T@9+E9Jv--oUgvk`eE5OS zza~Il8Xz+EX=9WzVhkHYw$j>YWwaR0Mw4wSZIm)fjAEn6&WbjojEE67LUxt4VP#kh zvta^~A#F$*5<_eV1+W1PEG%Q1ERTIkYtfpuCQFM-DXl~+){3kOG(~9~Y5yHJ59 zi(*zxa1T+KRV0d75$quk$iz0{fPaX9L#PHAL_;M;p##Lg1~jn9CTH8I@mPdxknjgu zRLsJJTwxa~&=g`J`cdZNvdhFbs!K4KRqtCS*Yeh=C1gvL~|B zXrsm>Tns_NA81iA*^k5K>fGBlofF!aovYYcCup0xlbv04;;=_>99kqtw7rR=!vZ_d z_#AL0ga=Qca&2_QY>A1_kN0l%F4(gmcrh4`gd_JNq4S~6?#{@q$hh5O6AL^k``!*5 zm?fw3Jcr{vKg3O~h?`OK+SZo5z#rc9+T?7VKD++)xs7j?M1xsPGqRg~i<*6_T4xvE z*}l9rurB(3$-}R=-Ob$lWbv871NiR2J9%*A2%`Te3BSqyCuoeJ7p}OBv%g*`9OIsv z({T3q)#C99bB|=4JMrhYF}xw#aIUoe`;ir2xJOSftxWs7Y1gz*n{!;dy34n%_-kRF z-<>&hrA5AzdBrJ%|2Dd|ukasBpK$Qel=72Jhq|g07jHQ6pswtB-{bwW`a2euebn1^ zJAcc^Gf(D@E(lLtlJw43Pp=(}$B&4J;Xq4_nLQ_^ei4?lk3&I$|%3xj*obYI p@&0?O6Wm2FP5QiJQb*B`lizEP@4xen=in!u`@Fw5tbCVJ{|6$RJ4FBh literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/start@2x.gif b/src/demo/share/jfc/J2Ddemo/images/start@2x.gif new file mode 100644 index 0000000000000000000000000000000000000000..139e233d5a8fdc9c52f7434232b42aab6869e9e5 GIT binary patch literal 1076 zcmW+#YfR2z6hCcleQ+Ba zORiG2YOIP?wo0yP)EZ-rSi{zkn-#TUtcVr1LT;7Svau|d*)jpil3FsB#1dOV0c=16 z3(J@$$K#$+6;)OxM~liBHKK;qkW+!C7!^@r6>_35%SKt0S(%^_t4c;mlvoL@Pz^AM zhDyjn55&L*G_bHt&XB9|#27Y)oIlW_5;4L?$k~MoG+7L@VS;;z!mJ@N#D-uGc|az% z5eNK31RO#&z#tkbF$x_Z1~#C9MJ_qlMvccJn?@To9^qmL68=DoiphN(E?4i~ zuIZi7#q3?h&3Zw*)V=K7suzblg6Gg7d7|A-JRJ_$gU088DX%hfib+4HnC4LtXPc!XniEprvvT zw{W#xRM0dJvoPTvQOt%sWFhR42Qt|v4*Vkmho}Y&(Wqn;9T0;JG+657x=qb9cXg2X zgO${6R})>W`yy9ry0$IAO;;uF|t3=uUlP*Q+CrKEiO=NJDhrWawz%0nO*Yl?V?{ zP@NopSewlMoKE>1DgWDB`#U=${nAD=_CKM?OMRbPeSP`m>eFQT>D!N+=Rb}X7yNeb t+vBa{mFYo#{c~`2y!zt7Y`posd-`bS{oVS~`OW7i53euw&wN+g{{T=LX9EBL literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/stop2.gif b/src/demo/share/jfc/J2Ddemo/images/stop2.gif new file mode 100644 index 0000000000000000000000000000000000000000..06fb70dbf39f23488c762713d3894fdf4f235a6a GIT binary patch literal 880 zcmchWJ!_R=42Ex^!?AP_6j3Q+>C|J-6a>Y^$<~7O54d#6R2M-9*A5PX!`Y&OU!apv zRM1uYphLh_a8q3T10o3V%JU<9wvgoh%KL6yxqSY@&S@RfZ>joaRaAMERjI4Y%Bb{8 zt5i25E26?HtU^8OSsvwHZsqD#%d#l*GAk2Er7T6sOID%)8)&dtW?IeDFETyTGS#$H z5gDFg8EO?YJ<>hh($%7vwMg?cOA{JdO-0I6mVy=4fFT-{$f5@^*g%8Dvf5DBJddyl zwLfU7+`}zgZ5I_Z&BH8AxJMMTArDyyd*p#kwuuA(h`=GL0Yfw@8AS)gU;_=7I=OCB z^UPfxB>teKGIJBTViy%OUFIT3k|qFjF;399B}(!@Cfme;CJf^c)qo+IO=O`1Vz7Z$ zpQxv4Q}e{d2oitLQknYW=v>FWyE#tSF^{YC>w zu#W}BH^TK25tT~JN_EVrpo?BT7}U-Q1l%f~vqhD+2!zll7axvRUl zvpYp)=B94q#%>f%HCJ^NS9YbC6?0J+abXvVRW@gJ7H4)QAUT&tI*hU=i4-s$( z)c}KNsKh9AfEd_-1{Otf(MFBOA{0TwA81iA3lnmMU8q1)h=q_Nl12c~g>eK8w}=vX zKqj^k2QCx;Voq0y z*%Wl7p0bP86h|B(ISiyEI&PA51aN}J=YT6AJa_`ttxMy%ow?<-rIAdP~Lrh zak{0yS~~OP=f}GT&NY=@%ss8&>&S+u%TxQ;9)2C$Ds1F8PR;bx_OzePZ+@EXd$4tN zWT4ttJvz7e{%`-q@_gs(JGqIm3ze5$^&|D=SEH5L(e;kg-R<*(S@HAQ<%!C(A8#f% chw4pBhridZ=MN3pQub?Qs(5m{xskg60jNizdH?_b literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/stop@2x.gif b/src/demo/share/jfc/J2Ddemo/images/stop@2x.gif new file mode 100644 index 0000000000000000000000000000000000000000..470b8a62516bc8f49a3cf89e2c7bf2d2d6f2334f GIT binary patch literal 944 zcmchW&uhqW7{?#lVJ=#^h$&J_Y<@k2#zkVAQj3*?r6mt>CZ`=xa@Y=7d17I-vYIxR z9k`$gJx(rup5#Zal(;-z&-ah;xjjA4^ZxaGzx#UkZr?G~E*vdV zo?#i9A=UIq_jF6wbg5a3G*7cMO_N&HNcB`p)l>l~B~m=aQZ$7EY@oqnnQ1AWdLCgB z8X-kXP`o4_Yc!Qz2LEqJpN0nvf$&69BpxCurOfC3zr|ZQ?)^hH;2$z!1$Q zvd{rB*g#92sHSOC^Ms2LB>teKQmK!la&7Ki&E|v^b90rNZGx`Uo9t?}iKC9tI4q<_ zbls%UQNRr}p95DSJUl@)dgg4)!j|VS{S(qUB6Ew{duDDw zxzM^~?U5HVcb;8pTitiFXLe%#{JYJkKEBxW`RVA&ZNo7+eedPfj@hB*mmePQ9qSyN zxOji#-SBm%uRQk6CwAZ1dGzm|)-7vZ-|8M&yzB6_Z~YU!*=#PC8y_Dp6bi*+aZOE4V`F1$YwPgv@bvWb^78U@Yb%pLsGw50 zD3l+O5RZfM{g}OMdIXs`!DWiM>{d2)m`jhR5~uleA)6{@lZG3`^EKQGE_q%|ui=u0 zh2&l_yOmF#7E_mNsKa7vZah7gORN!dYlNh=UMi6QWl~WSjbzybnaxD;xj5N8dwGIP zB|~NN^xj62Y@WQfES?^wE>BaZhsndOq}CeZ#4vYlIliWXEY2m>RFHCo#OVpYiD7bM zqj-6_cX_#SdRja^&9A7S3x(v|Tr!(Yz~KO4E-9W*jNlTd=PPn6NXu)(@q8woN#gSV zF+%W*C$i(I^UKrB2r@l_?@l+_4K!~Tu3;AR|o5-f) zm}C^41f>!IGJ#u>8zB}F{pe6CiSVzp=>P!-_)!5W380fnd@g~@2IAR-_y~Su4V4=~ zWcv}AbX0r{}ig}?TydP&24P_ zry@H(UfkQu6^r?ejS;!IY@v`_QQ^nu6G$Xxd_0Lxr*pY%v6vbWLFegn84&i$?*V*izD*^QanJc5au!oBr)!vL2z6skq;2rC?Xk0@FS3NQ6xH! zz$cP($y6Z<7Y{`N06_Qw0Rcb+VEzvS|DOp8R0h0&YP;4JcO*g8%mVsqOS)1~26VA& zU1?7S&f3{#-~4-Dx1dKJXcx zj#;Uz^1OuPn;rBcQLXbCK2usfM{{e%rS_{+QxOH0ReijMKyK)wU{H8$aW zO~wc<-o1W@#C?lBY@cRd1}V_w(ldq&Mcgzw3DBTdZBKNqwz<;fWvh?{5{{ zJ2FrtI6r6Jun-z>|K`Dr!Q0k%hKgQOhgNZiK;xKzeg%u`%WovBGp~JPB)l?JuyrPI zJMO=rk<`~eo&FS91`g!EtbaeKam#PZF*_Oi2d2JgZ@d15e#fo#CjM9LxUB;6>W9Pk zoAe_F^!zNnAOBI4c&-5^d+ipg3{*JCt&>9so608;2f(8l$!z+@%!aX&)Jl>5Y?{%PwBU3zcvo=71KYJ(t49mqgNHkd*AS#QogUa# zx4&#&UU~k}rD|ZZf|u>Dsb+Mm=!Yyj;F{Kh?D?AJ&#;W^cN)gv`bjBa3ngj!uDdNv zh7FM%iE9=Wl;0kR(@C-nx?q|E-oDbDxqr zu(|J}iv`en+t|Z&@b_lAMOnz#468w;W4}Qs3LH^lQr=f1+L?%qVwP1Cw2HqWMAeC1whnk>S>iKiz^7OY;J z$#%0cvFQIeR{lKU@v~E`my(BGw+7G_nHDWJ_o`{Lu7nKRY&glSKnJdWqB|i?*J$aL z6|vHObB1A}{#bgqKmvYZZnh@-blUu~RgB;bfBDIg0fAv@RI$}9@a;jJE1O*jtfY0q z`y}M{NQ2YQJs;~ZZUjM8%HOPjVcK4-;a$iEYyz0}hn<9`JU>KJ-O96Z82=r#_)EeITa(%>c z`NPkl`_w-Dq`&YugQ)JhM}v9zF=%c1Bcn_VV+E{w)J0-S>yS5d1u0sMWRCwa0JUr! zhy3+Sn))MwhfEd@q7u^P;zr^=AcB6Dp5EzWc=2ql2x9nMy>0p23DrW>6C=i4r`ELD z*%|+!0Y>w!?jN=M3(-^0WcU&i6_bdf{NAVck)@bv1XexO+@+J|DNt*b*ZiB)t9(i- zX9yMXSTP9*CeKb`XO-#Pf`TGdl&Ibe2sws{s(ma)t*MoZ>Q`wd;4;|u*)NwSx=Qeh zZhh4KLeBZvB)v!Tsm?!VxEw|juBjL@)$t{}usi{Gfa0voq3F#@AH$}h5CbV%HLrM_ zy14{OdH6N2R#;&kN)k{Yi7K4F3X9V)#huVZj(}mrvKWOqy$a9obFbXYCc}IN>4hUg zW2!!?<$~*fS0)4GAeE%dxmRGb`#`S^eq}IHzx+y^8;|@VJS*JZ$*7*-9(0_P?z!Hn zW)~!H(4a3Pd^TLvxQ_3&V6rpVkv*zLb&MNdnR^7{4+cviHyDiI!rXVI>O0+F!M+{B zLjlRy2426#d58S#v^o1CkvzOQl#g_$~MWnZ#O!fJ*-vDkA|^ZGhIJHKnFlh@JTJHKzV;!&Yx{s{inaRHvA{|F z9rJZPaVfcFeeV)H-rm&6zS3b9?hXWi89a#ZJ!~NFmX>lDLhf&nO4H9uy}#>Y1wXSc zosq?qgVe$(;F~W6=c8x!#znxj?`GNIgPA@FXS9cu-}_)fKY3bceXOWdL$Vl0>?mJ* zOtzAQj=%L)BcT$D&J={m|o`OEjQs`dHj{5-r7P+6EDO6qz8ji zyjiun+;hVnLw0kwcOPj}@8);?Cl05K9VpGtFAb;)GrrW%u?q0Y@Uy+4>hi1GD%t_z z^YQczoyD4}*vG;9qC&O?yoalge^mzxU*KGSI(6{sU>+i>niAf`QzM}Ht=S!)nzRG& z@;A(&4;p(m;GACmO^4c94fy3v@=eU5goycBgUe6kGYYdZet!hpZ#-Ui<$wCA7s7&N zEG=aPYpWc@VSBTni*V=k!mL_vt3=nqpM2s1FRdxFFK93#8AhDzck8C29Z#m|wI8wV z-gGBQwEIvR(lc#P=|e=uh^Ed*j`hB82^gbnIVE3-q^wX*&itPr{mm0DaAs+O{>D4p zPff-jKF0QMz(6;QIxc-tx|HME?V&dY^PS_I-C=+I=j43z$EOq&Bh*Dr{uQ|T72A^||G=Na+jg+^ zR9_03`Ob_w_Z>5wWc%L)luKXp>S)I+>>8G!JNn3ZrGzU8qv`b>JZ?YYpcN~VIvV{> z6%v0xg;7Nc8e$69m=#nqH{t^IrO@5MB~aX}B-lA$4rWOt8sPJdwdmRIl+qa|i*n@~ z7O=4Y7$?q75>!fRI{os0DW5Im<6Zxrbg%`hCs}E$R|I9;hjb`zUwQBN|4z}K%|S{^y#AtZsH0yRBbrMrB&`7z{f zg6f?~`?oH8e~!H+su%5TU1}t6c8|Ty$7QsB4804@JXy*%@NfMr=Qt$y@$Z_%2X5zt z{XM%OP@g=s+x235JWO0(+D|#^_85$W9Jyy{`WNw^(bCzkeJRGtb@H-JxSXfgB!)rN zEZQFa49s2oEp8&v5mI<3YrM4CRJqv|qDg6 zxP&EC&!|Td_P2^)${ZNi39V{%c5NOF=AgR@5`Zd{gu)wjL3q!oJ&?ei>ai_6geMkz z9fe$mU?oy!1wm`=tD$FoBqHmqPN7Dd3tG9@7%Bx+MgV==#H64^wgWcZ;XFeg+s!&~ zoddnjL-@r)$Fcj$>ac4w-rx!K;FD^Hwjhxr!%vA^uoVEI0KFstj0a3oE;yDLH+w3b z@l`S~MHwydTO{ymp56x+EWzoVp*+$H3qM3Sa9vi63|?SvV`>ev)ciXRkSYz$#}Q3I z7!X4VfdY+cl(|-anN}YWH41{kkN=};UGdgaDnLaXHZC! zRb7)+ELj!Vk0Jy`2^!FB-)=pOE2E~*?*~J9(kdOW0!>;eSH`Bdp-(i4hVVc;L!a#6Isl) zSc8Qq=#*2ze3qild(G7>tq~FO8VX-MeyH(_3Y=vYt_omBlo>?-Rfftk2egh-dB`MH|v`=yC1lU zwNf*UMqI8pO+zV;BtnHu*b@{|DcXr)4FM`&v?B6IHKW$CA0I%Ab8+oO+OpyRT{hamQ;F{av zW4n7pQtF{e(ygo{({c$7^6+4um6CzZ%CDM;mF^oZnD{3#XzfyV()$9h*&4zb3?}RcM_h% zFHxHHx*cw3zy%Uoya=jOPdg{AE0H3IehQ&d`F)Z`n>DZrUQWeZ2_;)GRKo*v61nKd za=TFq$9W+b7b@kQqtEFWTfV!16|3n9d)VThSnlZK664ljtJeanwI1QQ9TK!}mfELMvoRZFI!^uBcRqAKxwJ z2=Mv^lDo!$|Dco%a%Rri_LY-YH^(~fEJ|2iPjV^ z;1z;7@_xngc_EOZfXDXIC#B~7ezo%9BiAi3?l1VT9|L`N#O|k2aW-DN>yU9xk9H@& z+LptEf8XeNWu*VE_F(5(mz=g;^6Sg;GVoV%#!xgIof8U|Ki_I5*;I+ zo~-w{u)rU{?+Fawqt^fQuetj({9eydq`GnP4~$x|gh>Qp)?Ov(6^`_SK$u3=Sx?Vd z#biXYS{VTEWQ=G=k8E$$(5k_pB_r}xnp^r*6=co4XSWPnScoDNvJ3^=WQ$xr0*eks zbd5aK>dV^hG`w>at$A$(Y^&a8rJI7zA#WPHO*z!M0xOcjeC5<|TNr=JwLUjqE|8u# z)j@yP;G;s(zh0p|l%DSW#1}!~?~m*as6*Jm;Gs>I)*Z0+L5M3I*og(6O#W6bi(bcmvLLlmF9rVLXXsnj$wAs--ro5|ed@P&0DZ zrpuxXG(IN}#J)-tXbwyw42=j&g479)(*J6e@ATX`P2#I$P3T4ekiY0NTN0src&2Hd zi8$m2Y|@;krdJQL7=(NX6#W5`4c2s}uAd_LaC0fC?T^$jBT+DKAJe zu^bJBHk9HY!8asN75}2YHZjoQ#qC;LH3R44t zK2=CjkPzKj8e61QW;?lO7(2ft_#{!9-L9NGoVhGXmv7XJk4ITdqvcU=bEf) z-2t_%FNh+EZdeEQa>s!Z!b$^SN>vIVR_0?JR2GXqe<%tbj6*skoUX2og(j+ z8bwFdnNBPCFg~H?&eE~U+{DXT?I(>Rvy5Ml;Jq#L4$Z3kV4XlWs4Md(<%$9L2<%!( z9t1!ZvJjsYFU*NyPaMrn$=^4Ie;5o4!-FPYg zsVvHTjHI?2c4?lJqo{|>lt-4b;IrVAk2NVeGr!7OvFG=iExb~0BmHJBs;o+sKLMz< zzpykwB6Z+H{%-p1QsZNJq_vm;!PgX2Y|-3u{N3c}TNe?*Dcwe4W7bBW8n2Sz@O~qr zC&@AS=Qjb46huz?gj7J{tXW-r<(88lUW^7_SN;*aG;qTtsQv4@9qprTXTwUN=V#&Blk&%#HOHIIxKui?3bptSc8p4CpRu1D!`wZZ#$Q5zLK-CEOI>E z=;jb<`?K3|);Gcqceu(8c%P|a9PIJhpp^gk*ae!*B z-%$IgyE(-U5LJt|1>zSzJEC@_%iF8=+(TN^Yz#u3R_!C6wu+-?7S)UC_dE;yQoe>3 z+VdZT7BWiFJc_;?ZjP|18;qhFU!{d5Uby*^)2~#p7^<<`3>Gz@;$m1w>t{K@oQB+k zJdHI1%abqTLf^TyjUBD7Xb1rY4XOgtOM7zPq!}_34&}#0GoXs~+4Pz-4l)IYaKLJg zI?a2KjB~e0pnxr`<(~{#cI46q2mIX7twXl{ms+nxm&o7nk47K6@$Y$a0tZVWY{Dh~ z4oJ({W2?!q3xr|6ljZ)t9L-PaUvhGou1{3B;!He~b~)%Q-1x>`>LLxxw2A}vc{s#W z?29%@l7Ify`Q(#9>(O#Sp+BdtdVC~0T`p_eX)WWz5Hrog6fo^aD3J2ApQBa#mn^}B z7l%hA1{qXV`MUXsrf4F|Jk-0=fhwA35-PwMclcfF#LdezLJ!6Z72bpOJuC=S^_ZzJGk_Y(#%RUQbgnFv`U_7R2ZjCkXze+NH^Ml@+_b|5n!PkM zIh?-q-}Sr4N~-hyj~>|X3H|FyIVN~HLBnlWjA(3QrFA4@1J1vcFO(E$lCv3COyto{ zA8X~Zo-((FiuP-f?`Jt{UkKp#5gxqz`WO?WH^|-FX@2kN?)SoczmQJ5p=YZJ%G*k= zwDUX#5%2kgaZ|cyK%SbPH1Tu;6ab}ZkeUusF`a#f+7dftLi+>e3CmBOC?waV(*S)m zAJ=Wh%C_x!P#&6@@$%=~i)uGho~my2pwV$$kyXOd`I|WJ%ae_zp5ONF_zX`rzR%Gj@Z`3h#Jn@KX4oW^GR(UP&2fsv$*Nl>r?z^E41%AOfU{NJe3eR-8mmg%FyqnLA6 z+h1%wHtFHS0tZ}jqq!!yUfz4)u=`p>_3jtRgSNWpJIf7W?(XOu=T`~JmFrZ57X_?5 zm~>t8WdQQ7SOmP2!WC?LM39kz1|z9Vud48<>06v<*@5xW53?UC;%>h{b8$kEWOG5pQd&5_>8b_e^j3ypK`rI_*wHWBGNr4G$qJzco-Qph{w)3A0D zAcqlYrwkfEh@6hS7yS5I+70-wpO5uyejQ}SY_3dMh>SZC(KnTUiJitxTmkBrxCwn#KOyC7#4`yuUX_H1Rhj)it_E&rXJ1I!TGu~QIo zF^+?m-&71jMO%qJ*$Ix_Xg(U}@q51`ZuZeU=vY|YgYnUa8cm12yM1>VCQLm1emmFZ z3H`{xewlu-R}#+B>^m=YyJ06PL&kB_FCr@rZ%r(UDOAw^%<%U<8w9gouU5H@fM_+~ zTg)hH) zVq=K;;{&Y=Nng&ZMSZZ_-PwR&wHAE;T@tl==5cNUt@y;Jw|W{6v6oD>(WJ#Cm%BNb zCY*vL?$#SFK-D@wV`Py6odsQk?JxT+E^S<5g_&D!7!ZW<%~U-VXTA~&kkfqK zl#bfXxie6Yv_zEHN*;b257)&X1^23g6ix9y+IUdv%c0}?h6Lmd$+osj9#eJ&`EL~F z8*4pF?g?G9rB|(O+tEcUMQT&i0@QIGo;#FU<%90b)8Daem}Te6#+{jjG}Y-Oo3j1~ zqu~-UXGeG&zZEOmrF9g}J9tTBlH_zG9YgH_e6vDA`!8L)(TuhjRSz)s*3fgCK0$2d zwrg)3?*8|*tnJOtS0zikEFgrBnQc2_PBfpa>UxnCphz=^JKVfZL6xH+rVtQxyGQ}W z7y&7BiZ{eQjZbltQC=(mdi~Jemx^0jneTEu6z%fjxsmSOvsRi#Z+a@vzQ1t(<990c zKgjf5L-^>Af%#uQo9K|lttHa>tAAD}rxR9QDlMt6l<7PQOtUq|gV+4;Ll0Obohz{% z+XHQ$i*J)<*e_n)xpb>-DTz;!%E>oWHYD-`9?I=R@qepAh72rr7DD#1Fd^&m&VWKB zf*f85SPtxBa1$`D2`DLWZn71$sBmt?3R`8-ZU8p2m6QG2=1zHdsR~lDk!^ZYNA;e+5%dOek_K_TEB+&>Dwu;%M1tgra zP2K!UaWNRQo}-R|-CkkCwiUT2U*z`L_w0<6Z09BIV#tvu z!JDkW2Cg)#7?A(FgiVx9?$2plW#r8^{d1ANEk&vdeHe4hU$QNygkh&4&!p> zUGE8g5(mRSX;?rLb#Wo+J&`U6+OB;sozFafY;x8mDpyQfce(a}k2iD`i2F7yK~kU7 zf?+6mr%9LekA0_pH)i~P3~jE^`R1B~>2zD@5CuHBSPb#tBxl*VUH-kz2_+8-aT6n9 zFdpC$>*kXtUyP)ec=1;@(#!1W<=PDtRDZF##Ft~^AuSP$={IlFZv{Nz0l@bE1N4@o A5&!@I literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/surfing.png b/src/demo/share/jfc/J2Ddemo/images/surfing.png new file mode 100644 index 0000000000000000000000000000000000000000..27836008836646d9b25328347123b7d24faa66ca GIT binary patch literal 17912 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

dAHsyj9pLXU(_Yv( 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 JPDHLkV1jXN`WFBI literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/surfing@2x.png b/src/demo/share/jfc/J2Ddemo/images/surfing@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7f83823cc8bc047479db3e18a6e163dbbbf797c4 GIT binary patch literal 37795 zcmXVX2Q*yW_x2sVlOQ?~G6Z3wccLYF1W|(#y^9tljNXFiqxar|5TcD9j7~%sHF_AL z^WFFN|IRXFF?XG_&vSM=&)yUHO5+775j_zA0Hn$<6e0hq)|mYaQ+F z2U2HCCvvJ0h$L0#*VF_LU&}=!sN$hqtb`OQ5v+N$)LNbQ6cuq8e&j}A$HpQ)QETy# zL=pYMUuVsa4K9d?8oc`LTVVgQ^=xzawqZtks}hq{KZ=hcAW3;Cpe2MLDU)Nqw-Vgn z)AxIwS2mD{-36c^sJCEsyJ3R>=l+tC+>cQB?EvJ%BrySiQqMra7{l+#cjVHHA&3wN z$~|6Gl>k8n$oj;}6$7$L5JVOdstx4g0A@q)%-4WdPXRNIfXzt&k#(Nt3jvIhSg9eo z@xVh$%LoO)MgpiDeG{b!=)(XiE7cw`;MY?CrmSc668Q2BK#fok*8v1108A?)^a+6D z3z+?2WBUMvqybb)$9j@S+|?9YTp&_ub&}2OVv2!A1W#S@_4Ig|IY*RfxT%EUSnzaN z-Y)MnI{rXG@)ZntD7o>};BGNDA4bTkM@EEW8_7(c?sVYYJu)|6yWJSAaFGRo-|qh7 zw>*6H^au$&gyU`g;{zNU6XINtvuLY2a@htTcY96`$Qi*0 z^*-KOcbTH}ZX7QBC9ls;SK3$E1Nq+uzQ8$O=|Z2V6)}z`5Qdm9Y{tE~{ziOv%{2L_ zN7=ktpNncu>%MEOLi#5Rf6=2zxr8UZk08^5a0NxrElM1|5N3l z(050zo&msdi*x4`CjmCXCiwTL*WIDa&5PW}0K!T+!4&{Z6xexn2J2<|2>?JLH<0Vg zbB2>nS{@W0V<+xHC-JqJaEKgxPnR5p9FYZr@x9rT${;z;u;DLETxNVzvP^;~Et{}J z7c$;1-6k?A7xGIuL3Sr+Yak)c^B)A1aMrm9ht*RfMs~q_bA%#<*dbb79FG!9 zRlh>N-@E9cHRpd8uK$vU?dSbCNBin_WP0Y{2a}nv6O2IbtdjlC`~xMX4~c| z%Mg4?&z3kaXJKE5FP6mfko!mIde(aPy1+WaI_t3!QI@%^YvH-}D(CA#I~BSOiVeXH zJWC}1bKQdU*NdfjI`@R)4CSiw8ei9Fg_lwadZddD2R~3&Evm{-o}{;-u{pD?`Q!fm z-eNMdM(UW}#L)JOKdFDPPrOJ-!>EJ%Bdj^;GHCH>t?9gIYmjQibd%9^{W>s_XS>L) zH1afOU45=bEHWUr8`vm_H=|NN1b{M&9>`675SJoR@-eDkaFnTzD_-C3>hSake{;iCyjG2t(Z)S!c40#$$ z8=EYZ>(&j64GtPxok9)842tx14d2!)Rb^E@{@GI1QgW}PStC)SBKxOx_m`u_fyT0L zbYC`p;mub!IyQcUTbt8Zf9tL8K1gg!{P_K2%#9R2Y4|Kz1(P9@zuVXMRN`;Mm(oWv z4`e>}o}_H^S?iBdjQ$c>Yor`{(qo&YoiX{sn#Q`>Ef^CK9jO{L#G5M3o59ex_@ixI z#r@Rv?Qfrn)2xj8jIRCC`I-aa1KWe}g&eeC&Xa5d0k^U4AMz_&8{;y>Ims~lBpa?3VDq$$h$2o zTq>j}EM-_f(-fm;<~K^gCT9`O`ewFnK-q`%K8xJn;8d1EeSjpLVG>OKj3@vTDM?7ad-JR8j+9A%$d)kxJAGsLqWq$G(lWH}w$~~88y|Br{(yb`=Sp0Ir$mi%#eZ}RIcK== z>#QyHtU87x2gOn*!Ix?!7YMv&QI^Y-Q!iNopaOc5}w1uRvWfeWm7Nb@ZR@<9PPqU54Qp!^| zQ^}l2XXn0>F2DJ@fBH{xo-cKnbG{|GQNFpLL$ayWvSeUnSVBgpQ0GMFQb+h;VzB`} zbM7>Lz~I~ZPjGK~-l+BLMtY!qUKgUPK5aE^d8K?+eyw|tS2$#>8NyX

h(#Hz@U* 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˅NzIeI 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 literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/thumbsup.gif b/src/demo/share/jfc/J2Ddemo/images/thumbsup.gif new file mode 100644 index 0000000000000000000000000000000000000000..f701f847bd9177428ae18f28b8db3cac7479131c GIT binary patch literal 2218 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 aEFsB$q>_DquI%^4c@GN4!VUBQ?>_;>{im=1 literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/thumbsup.png b/src/demo/share/jfc/J2Ddemo/images/thumbsup.png new file mode 100644 index 0000000000000000000000000000000000000000..a0d87963345f00bd1ef9a1296e6e359ec395b1c2 GIT binary patch literal 4400 zcmV-05zp?4P)P#racL{;N~A@qYNsvjLoZ2MD)oY7hlf&HDRv$xeMpE? zc!EkC5t=J%2#)0QOzqnIJYA~UHwJ2ig~*<65tz#f=Za{;#-3#mz4wCyq96R|lS{77VaCR4 zYJ<8O@Pp#e5=>tD7*eT}>vN?uX=qusN@wHRQ0M|-=-4t7D{lj`ACws7ij7hbR5gY1 zKozsFTh0gF_(3z1syJbmb9!N@B!{sdl0_xUdA41*g&G3{Y976@A)rh?SK}$*62|SFgy8*}Vu&fHIC_q-sM$gWA#2p>E&4 zeOinUlqvx69o`emnbbSAEt@)^v7v!)#!2$Ot%5(N$~)TH+Muzq5eR@VH#Y}UQ&Y09 z>{NUXV2|hvu{P?Yw1y+~fj~fPd`J=C5qvDqxshTlimz{L7k70MAY&D{T~wSiGJr{P zy$GI-bq0MN%nXP=$__wm?3K+c|~I=cO~~2tiGzfV2YKzF{4}d=k`!BwU=HffxUK9{xP>5zG;Q@jQ6G=Ef#d z#`APT7&PuFBZz%g6&VCDZvTh~GB{l4Qx*=3K1q}_Y{(7m>p)Qyoq5kb@&J7I%bl=& z(|UmVASl5)Pyz~#y%iSoDJuB~7Xt8V0@@cst#HqpH8A)_>Y_rQ*= zn?Y%;2ZemE0T`g!lLnv)3jRG?luYh(3+V{=w6;PEIqYw&vG6yrf5`HUY+Ox16xbgk zARaHnE&t9k03(uFS62s_Ovd&Ebv|QZl=VzKrQnG@Hr{n4XX6aK^TzEk-1`VLu4p0v zHel;(Al8#xQV>97oyI)iz|nO^Tc-)2D7mD8Zf$6U4kZ9F<`XeRnO~UCk6g)5uV`-8 z)sA$y>hFk!#ez#B>1nljEtZQfXB{!(aPMX-ao!pZ60+KEAp&m!pyB z)hyjG@n@x&Z5a=N!z6!VVuJccT(`8eP+v*X4|JAC$ns#oM=T7B|0&BLUe{;%(bTEoONlZX=+C zkztl%B>cq0Lsl#dwd4ToBGKnfZELk4g)CYmn$;pv5_ytL9@KOuC!x5gnzX94s>K2v zRr8nHHt72f`&C{K|P8S&K4TbX~$XkZcW zAeEv3s@E1konO#^#JQ&_a!e*8`9$U`Nwle|{IkmNRN?-HCK~X_zbodflCONC1b;Xn zY>!C{9VQ@RopvWr>Lmbs`G#NeM1w4eV|gg0yySJ$nh6;5*GqawZj=?gAjlCO-Vr>*8-s^U}qVQ@m-c*q@o2o;FOw zmwXP5&U7C|8dOF0(JD-eR%56ioY!QO%Bd)++(**m)7sw>X3~z3(E!x|XHuKdfV@!v zQ7-H8oUw#wH^hg3hFyYhYKy_dFbK~Pu3EV=m)s_kdD2xUFyY2kD>Wa;8HkBIGK-}d zdfTHcQnqp6I3rUzAXAK)$WR?n##9GGRoK~thf^cy*B!h@B`WyAVbQPo5yS|);M*8z zVL?6&y$y4ir{mRGJf#e6TK%OCj{AHIoApnV8gAOabNl`7umt zar<00V+dr-j20o<^3-L}fgj|u*jui~4wji=ee7mrz|avNXX_|WCt8Kn!DNORO=>r7 z+z6K@KjI|}Le~_HDk*@3ZAvghK~w`q5UG!2piq#KEQ(E~a)72JAX6HU=hUp>y3CAU zuMojLQ2<2lHW0wFJ{nLC5c%M(ocN9~;6_ZGa~HBz4B@dsR+EH28jV6%R~KC)i0_>} z3;XZAPh;ZcY3k<`l>u0vp+OE-X6T~JDdf@+1TrNAIY~CM!2y+koFnT|(1641d2{3x z#9}cR9UZ0XgivL}Lb-4cc9J^4)QP7C3BQ3T0~li$8n;POJJ*In10?d(|8DTPqwv_{ zkLMkH^DVc~#+)U||NB?3YJp0Y14u4E$N^MxDF)B~P!`h+Owl*8phydL7@$cF(3i3) zy)*3Hw+|wb2wnR7wMY3!Mn>TD>C<$L*Ca~nr_-0uv-=xk9e9{26MqjtCpegb=+=}n zNa%S9Ku1!+-Zeu(+_Gg0#NPO;<*`p4_$Ivm+H3Ulk*(Lm12{Iw>!auo8Hh3yRi5By zGR7c>`$jg_s70|Um>{3Orlf$^Nk+*vZ6?=dWeDU8zkMG5bMBlTn2k?P$Z8a2YUL)C zaAl>Y7;@R@phEx+&&7Y`;fL)j0pG~Q051^#sN&!*rV+RZX@!_#=->17V?L=53TtUc zQUj1Na+a|1X(g=#_z<}!I{;}U)7=eE9(d9as7ZNcHv{lUr2s4kh+(NzBj3Lu0*N_hN?Q{k2h=p2V>1R(zJK)7 zpE$aayNTqAW>Ts{@D5ipXDb!NJ(6@dwJy=;73%S5KNcGGm6;iMc5+f@ALz?GTNb1O z00WN$DHH-`Q9>aJuPV7H^!eYvK!J2(cpTn?4q|g2h`mr@D`&;#-C|_85DP`HfBo!l z^zA>ADDlAfhcI#FYL0dKqA?Q$Y1J5+%td-UIqXp=f^G3lNKqP6vdljH`3GiAt>uBh?=g zAZKUuD?FdCZ-7lo06H+h;FF`sGDpCCJ8MkjMG%mIPGsFuTE6%t7#|;}pV>@xN6*_Y z784_o|NgTv#>%)GDZRUhUeEKlU2p7$;bTK&Ic5O!?Nrk7d9V|Gr@yaYbnKLk<0nqA zdhn_Q0nv*WHn?VDh?UEFzfCmQ{uEix{UUQ4o`4vT5^v7R^N@Q%PB#>o&?D4D3teR)^vBNB2 z8WJlR7Cp9RY_ZfOV3EuZvEZgGFEy9yi8aea6E;S@29f82@7N^tC4*S2{%|qb7?5(o zVtWqy(=}i*@Y&SZWEH_JTNy!&768yL2RtGKLI=$%HsZ9zTJ?v10MYKDkeCp?nx!Md z64;$=AB}G7gTaIt)GRZxav)k2F$WnaJl!}geLn{IBNu#H9?Gk7{pKwXE|s8Wu`DQn zg^cT#7${3<$ON!L7PZQwmaV)Xa#j@@oiC=8blXyr(u=tQxYJHvkv!26ATBJllt3Ie zf;i?!5M?kbZDS~zK#7PRC)kwZnbza;^Sb9V0Dx3{R7ZZ=X1 zUXJX$u_HoGc@$jEt1NYD1cHEbSr9y@z&SbRNqWu`B~P5H7A6jZyJrf@Qh&w989FvZ z0W2^PibvQNz`Vl5UtF+9_-tSjPIh{3@F<sTM3=DBM3uoluhacfD#`-@SPl8}5O7?;{KxGy@Pp!~cD| zvs3_003BifL!04AUIgZ=k3Lq=2cv38*E_c4K*R<>3B$!CJ>cN=I(S1xsbJFI5~Y`4 zo1H)A55amJnR*JMUF3!hfX_0>4Z#|6rx)N!03;YIhebb$jI;t0BW9GBoK)iuf&EQ zkQqYAN)RpMBw7V2#KZmoVJ&i-j0bECZhH)PJl$P;PxYM>Gfl!Ep%3h5y?6a!WY<)=MUu=D;^_OjF)BU6r|q9*fHdKY#*H#VnnjevEhDp zQyRDqOyMFJvOdmyyd7Ag&W z!uQ^PU;8=8iW(zUBp{M`m^MO+(a|${klCzAc|`&uSui%l${8h7p%fJ(q+a&!nKH2= z0gY{Y=}N#Q7J2#6vcdDyGE=S52FUd@%0N2tDeW8%kL8cb7!1wvv)0wS5*FgT<1%MdUgpb2Di?`c1?NWLNgvDf^<;i&yW znPKGBBl=3LNIoL@h3FUl<;_`BMn+}JmM(?Ci!af=WDWBb%XGDf5qs7zL?(<9gg#ku z4_z$+V$b@8Sjg?Qq9QCitTPfy_m=$xxisU1v5rlc}7v{R< z7s_m4RT1R@Dmk&oDU5a#%W z&8uEB!~DW9OV}dv6-&%d+>$~7?(>k|I72?nj!|O7WScfs5q2GEJBHG@hZ+*+`2^|3 z^f?aJ!(p-`0kN}ehyzzScrk6@r}=UW8U5O@?}v|`jMqqC9}eU7E7L4W+M zH^DHBSbc9~XU*m{X=8dJ;si6nDFSST z7&l4kX2nJQ{jg;5Vr2k>$d}uu)AG7)2j8z5~(tT5CtV5 zk|d4Hd@PYl3oA|s1TXR9aFQFLwyM1jL9X=~$X1sRM|;Q4Bua zNe~hcqp^Kylca9*m`Ls+AQBL}&4vZgw30}&Bo)o07(5MoE4C_Gju8;!W&6`ANk#Kf z4Bl(3I7L8=4;zkxCYOZEo02X`MLT;g^_{_6nKf|&#^79@fY@CS;sw~PlX7vcB@JRe z_RHv{b{f`_sH0F{(eFM^Lw)7V7$~CYv_d}|AWo=GaJM?Kb;7Xrbkn7SIz~xyw>Jb% zTfXjMc7E2cUvJ*xj?VM*^YG3)?^sgyHj#Dv2}W&$umGBzA^L@B1R)x(Rm9*Ew(6Hy zj-QwDUKj`K)~$mjOP1K6GtUnL-t6qG?BxXx^z9ZHi4ofe;!%}vfCCl#&!pK>+}Gx) zAD_=+y;G-7*#K<8aFQA!AF+K9j_NMfJ00xM-7WKx;4dWbXXX5W5Ls|wV8CR(3&Hvf z6}f*&(zFc_=5zrG9H3$4471s+>5riV?CIB@85J%Z zUcY9o>gnAOLU_N!=4)F4l%fjh*(&G>h;7(@(6q{LcfSe*-oT2Lu#|yKvmn=D2v8YF z@%!MU@ZJaSo3~;6tT^ecU7a&042hX5_!G4Cw|0V!z)A$f;A~g`%}N6d&;-dD;y^~9 zD>typ22@y#x?=fq^FTAxDGZch?L3UX6+aWdyM`6_Cgk#JSIvZMQx*^@SQ8A0%FuR@ z01W~Kr5yrA!77oMRqYc7AaUZ@ym6CKy+Sfl85rgD-69cvM4pZaYTGT@PCaW{2O(ap zZ>XL>dFpN7(hotmX7y^gc>M-g%KQyQ%fiUaV#-yF$tqRmUoI@P#fm707s;6%b@FSc z&y=TQd}+1qE@k$?2OqTa_Z|QtwL{W0m~SXGlxKbeG&pE6>>oseUcF%*3@lj;SFKwM zs}{5O8wMCP1716I8s_Hb;rO}tVD>%#l|1+zF4=IA`Q6*ufePzS6*)yqo{pzgl3HmD zKgL+JJU>70n3PDGw#J4<(5y8)c6`RyAVwLwdeti5fA^DDeh6;7d?Va=*&qYqTBIK^ zss_8Q0#unVTCLw2cw4EO|3CY|JiPYKyYQzIZ^M7jo`BcR`0F5!%!XhLT9SwIR5Q73 zXYzC^hL^U$*|23B92_)3I5#&JM5azcJ&#x>Ao>R(&Xz}2vnKX)dAD5ll!Aj7U*anY zdSiYQ3=e$-K6%v@u!^yt*=~`s9-}@6G{XcV0?xo&4n7AM*Hv!G3$Pq2ZcXb5>k(_f@ujej;&HVH1D zJp=D+9CrjEGGSkz`gCv1t%jf6bsK!;Q=fp1>({Um&0gD=tsmJ;9h7X4V?d`7)X6yg z3x?5*UGr}U_5X%&Yrs`2mcthZFNHz&yccEq|zc&V7FxBDLkhwjY5uae{;g2!8 zyu(4*5U(X3Z3b*C8=?|7f3`;@NzD|1Mv__})TJem0iV17UbykYn*sX!Aj1Z7W)Z*T z2R?2def1;L$AOy7Hg5Tm$z~+?h1*Ql1or1Iz6hQjx(>GI)G-Q=T2eWaCab~JbwS>Q zauh3TLb4n&qBk4nd4NXBhUiDBd;|pFMhz1VEL{SR{^K1my!B&sa3Ki$`Z*JF(3t>2 z7Ob-&2q}(?;buakiT%L#Ee-aX#{aGRIFvra*m!__?*A}U!BvETCkd4ID%PEME- zQA|F$nC&3-4G6fP7gty0*d!JPD-saBgAbUlxLGyebUxIj7hSBBXjfmd0mh5}09S9i zq|SmC@cR1%Aab_j42FkOj2f;br~(LU&;-QB|7-ky&A$Iv%a*~`<;!8}>>ON>?8AY1 zPRup>4NTP7XIqs#ir`jU_R1I!`o=2ry+e|wC6cDzY*T^iY*kyZYh{F!oP7 zVdL7>4M{10&nZpoOlix~EP}QnH8a_U4{0+d-p@Af+dd}ZS9p#2fN=kY6)WJ;%P)rk zg^b3ui{HGbM}w(iOuB;SV=~kZQbJ#E%9iOR;&-t0|7B08|wCf*q{h*46uv!y<0y8 z1Iv~;nJLqVikblI=j>ycx`bqd>rHw}+_<9zby9y3{X`AZIR~OXmC^0~ryVUU zKv14Mc@mXY(+Up)qTG~uLoYUz1v3U$t%NV%bbTYb2}Yx0Mu>D8LS)mxsu`??!CRx| zN=pFWVc2kfo^@ZiY5X1G3)$}x9+2epF{N?u$^q$bT|MBhR@P&Q)o_=CHdtOZ)rG%1 z1g;*q1VlL-?he9+s=@i?8;4*3<*EoC!)QLt`cYo4hP9##yjHYQf7}q$4(|7Y>@!_p z1Vg;*0<8h#tvLofuA$Chsx&`RLyBu+qVfeo$p zfl_}#F)#-QR>F=eKg1aiY#YJw z9c&Eh`$CTL&ZTl+5nFlqF^>|tZpqUew6F+RCNtZxgCtG8O*t@h`#q=z<$WLjr~ncX zL^a`7U_xHFZJ;b&;J5bbifV%y9U!iMrbF5qK0qq6a}!gW{AoV^_lxDFTuYbwTSJQx zR?YITLYLa}W3^P!zl)4E!kzOi{QhJMa(I-0sF$Th)y45@F|Vp3`Q&9ACBQQzOvo8e zWI|Jx3acp)qyivq5Z7vw&#%elucOkY*}pVI?aCiVUvb-_#ZndEx3z~y(5BeoOFgQP z#M2yD2cXeUrp)i-fvf7T=dT$TK#BJ;0=fq3>4<4XUZbJ2?wJr zNP{38Sk!M0?hKcrMlA~&6D*l}eozQ_ni$B|>Ir@`PYBLHj>VkTT0{gS2cgK44!{W# zR>hcxj5S?lbA`S|aA=`9Opkd*KRHF*v_`W|@g5mVL}cg_?o)u!>bxDa(N&p)_yC{K z^Zf5kc?E?Chz&L@fMPc%kAQ=+lx_Q_O9htV`8^Xf8M9Kxa>wkYOIS6-o-?e984HPa z{iw^A6c2$J4FRx*i-nu(P7O74LgW6G3g$yr^aDgx6q@$@m{S~j{a7jLo;E7Ku*~IU znCXlXKYT@HNt*g#Lyx@xmC?hk8`jxCF$5+P{XL7>?A7#^40TA;ihbX(R^GdP#;O~H zR&=%I^id6se3gQ*lR$v`c^jif!T~&7T{Ac&Wu6;CCRynAu&RS3_v2Qb>2}lMKdjT*wnNv(NG=WHDLeXce zHoCmkWI-JveNt2BCT$Sb?E1X+fXLS=YWB&8e9K zf(xEVM1WX$GHi}(B-D`!GaQ7FbuMi(T!h#ZM5#&Sr|2`fiUi!zR3{sH-LHirO+_$j zSTW4aO=W)JIK*%tj-&&zz-K$_WM2pJ^0Xn9Z>LH}-F=EvrMR~DVJzbIIK@kqZ zOvVBuIM)=qOVA8MA}?!BdCGg8I(){e>$Org}JO|!3kW{Y+(k+@51i^hnK~I{4USLD3bc}&8<5+2L)K}2k{vp`?X&Uv| zt`vh91$E0$J8&b&Q+FVzstVvpd`J$=BN8A6X|9WMAM=Weh-(<~bO@TaMz9k0KtK!z zzG3df`vqQ^pY%igcAEPM1(|=Sva>C)p)9KU+T6K%iowQ^1wJtSLX&OGHW@};l4dha zEA9<9uDaj&v>Mr)e#ezxycZLX+swBUCa6SzU>lB$i@H~!8` zAWz{0Z8wkpw+4vq$kPdM)(gibSC}LqqNd*m-c|8s4!)8U^)dnbC%*X-xXQK*7vduue z>E@g5^Mr?aqRVBNoSZa)iMM4<7xa+jX#tvxx%Wc6w}P`RE}PK2-~mDlfa4(me$T3v z1G_h@TPH=<4O_Ruop;}54=lg-;ry1S$F{B-fS-Tl8b@1vyLFTdF#!R5NJ83aXnB$9d<>`$Kx6yjVlm~pxJW}8hM}49Bn3h4y%Gc z&-~_DxaQhxTmHFceW~(rGNh4ms>hVGEnOFQ#|^YH)MgZ5(n6n@R<90 znp>SEC?gPyqVIhkARGx9gn1PRH!+DB1cYdxzU9->$A5M5ZRg@%dlf~cvEpLEI$Vo_ z7lZ-mMo<3^>in&0vHRbC+O*elUuKM4pWDGrNS_h;lm8ZRc4+0f7s?BBm1jvhS< z6B83qEEcte;0pI4&lOaW|9`&(gxeuu)@>jTX#z7Ph^7KUsX2?gf-9L%-*Sue@&9B% zY%E=Jt+;oA$#8?PA^=Z#js1C*=2iTTWm2NVbhBMmQKwpKtaW^Xf$*h_Jc&QDt3B0+ z(tm7h41V{A-z#6UY>BoN#~45MxMBgZPE*7ch&sRU;fPM?J*|Stk72+DgBNa_y>Nkn z@ubj;#toi|W8I+$G-JVezxh2C0e}@3Gd9ajrN3x1Wg~EN1Zwc}teg$Mx@V6vK-H?D z0@!ajSsJS8WGN1ab_bV=Q6D*R66WSFICk-EFrZADR-9m4 zs7M}nF{vAXB5PKKt-Pz%W)Skgj>Uv?%+Gv~v7xL_8Ty9BUE#(+WD}SgI#Y<8bxgZ-c1c*C{g-U%2{c7hwAB6t_7{1D`;)b~`$ z)0(phRmHje_Z*X^_hlI)DkSOmfA|9vjA7c}D*S67^3<}#q$%PGM3sMdD5Ad?i7a&w zRGGc>{`;`+_-uo{+^i=6&>>GN;;Q{>lO%1tM-19j8~}6x(~+WR4TN{>+!@+=a-Vw@ zxP34p0x;2=*>oF-y4umuS7}ErOGTNb8m!NpJqyp2%MG9{Slzs<@~EjTP2G}J@Fy2I zuom1w8wE2uuh6AqvmHVX<(g%^aw@p#pK-0d?q0Z_(_O>(schs<1IMF~RuEkAqok0y7G_e_((_{Xk;vyz6+xOVZ_@fp!KydF|y zom`KI#kqTg`<-&W3qb+|VH--kU;XA;__qhY3r{hI^kYZZ;5(w|6mWyp5Sg>&90TAH zqt=#Biy-Wz6jjMn+4;dV1|AHMB}iaVcU*kLJjgpOHz~yk{`QV;_=l>11g197_fqA} z{2H>JdDQTz1_mLjf`|Bb>NW`L6T(f(=T0q$p+4Nok7y;BN5Wfvvy~lpa$d_=os+b1DfG zhe7xF6F0+g<~NQ#HU__a?zxtH$RLc2zx#Hk1iCc=c-cn2CKP?@R@@8<*2v9jbsm)6 zLUG0!5Jy3=@ED_laR8&+5R}g|K)(9QtLBRTc7ch58bODWFOI)gX5V9e^!Q_ssh+;R z1N$hZ0*J^$FMzs)&97k-m{OZSRJO#xHV>T+&j&RGBt{YuoM`p?uSh|MziHE^jmq_r zNidv4#h#*9pYV-Zu0?xQ(@n*$5S39W#;x?b`f^2sfn)`%AF;h*40K|f7wv9u+j7)FW zTzid|3zRw_=398ZwfpL6ep}=Nexk+CiIffbYKy#Fmfk|6JP|;=HcGc8cGe$IPFk|H z7}58_Dx9a=0OYV*^4vtDJlWC|?YcBFVkxHIZK4ecLjGa8SuvkRARdhAceA3fL5czj zstX(Sk|(n8>{>MtQ|Tj)Lw#*mIi_GlX7nAA)s?jo8z#$ilP15;sRAO}DAd;hVp-V; z2j*0aWGniNhkg2_1@aHm;wRqZHA$z&+(qBkR@X8qkmG}VGlaBV-*+m@M7 zk|oD_Dc>7(859Cw7}P86J7GUT)*0Zh5G8RwVk?7RtV4~JPG79) z2u=PWv0~C0(MsO$hM4DXbQ_jjOJ!|ovs49ZvK~Kll(XM{NI()*0nQ+P{(6{i3VjH+Z*SrITsoTZ9f0_I(QnYBzxCPjl-DWu<_Y$QxZmP8<0;1~_*^H=*|)-WtDdvFt# zwI$wgyMd70nnX#{u+6I;uml~YFSEw8ZrW+A0S4?hU6cT5fB>y$q^9A+A+nV zU;<(o014SgR7OmxHAeDHv0*9NGy&0{6@0uVjFU;N6MNInr0K`>ckyqRqXc{}u%WnN zX&M(l_lhiy8i<=az=n`!{}4fj$IQ%eJB+Uh=QsU+YoEdTzVz3a_mgy9G_n+}L_iG3 zM{FC2y3_@3U!AnsA3^rwA73;FpkKgw4dNFSvKNF)TCqCd8-EYMh+XdRHcsaaC#4R!HmL_9){&}~RZWE?O_h1dxcZ34XJ%mRu`&4V zbI&o!ITMTT^gR16czo}{@0wu5t<7)Wxii)S_w{3?R7FiQ5q`F{o70d)l5P)UMq|=+ z6cme@|F3j3RHvAd1&n5wG9IFjkOpOf8+Om_=Cs`CXVaR;mZU> zvZw%v%=R=&_pk#I?DI-c5BEJc1(80rrg z0mVV|Fb7{O1{D7u*mYqq17#6}jbFXk@pHF+79L_!HSBbU?%bv=b&*xUu2o-{fS7W_Kn12DFjx^F z=z;_L;kdA0i_-Oa&XAtlFpNL;7|gNrgn^teCcIusT@Vm`&dmSHX8acYz%rMg2RiNh zMZu5^j2Pq@1CIvOR=%`dFnTDCLj=SgV?hL9i!wAd0Ca)TY@f*hISd{ z9f+kCFQhLPyzkyGwX!I6JnaBmE9OF|NO0= zZKW>M3}&!_InoONbW2rsYzL3cWN}h!HO2GGC!f+ieUN~dARyw!Zv~8)l*fFS&wz}% zi7F1nH0HBf1muWLrs6fgDjdIH#AvC8MN4Tu-$@6evgYu&K4j5xUar+bT4IvR&~fsl zZQC9e7;!@MIQOZwOp?F+6`S*zY?ki9h)MmaKm1;r+z*f!EO8c`BHT%@14dDC0jM&X zir3-sCw`%U_`G4={m_lSSHAM zPKqyhfe~|z?mjs_SaXW|q{N6Z9sr}z{+8o9UvQFO79JSU5Qvy(#EB9?h*4^fNcZ-% ztC2JS(Nh)$Fudru5eo*o9!01p{X@GJX=g*U#3%GQSVltp$h|xwN+1k&J;uYn9=&kh zvMIUvlObGuWI@ae9w0b{0>&^JgzfE>6j3HkKgLfjq{K?>cz{w8k@<`h;B&FD%f@-0 z5(tRN^%?g-eQ~R509ZX?4pK0tBiCaezb1YSi{|(C(s|0Hd=TU%U@Z4~MNF5jMFAS^ zICSp81HG89&Cn1b>jFa}D2Ln%rI#nj{}*5Y^-^=>fxJoc00000NkvXXu0mjfxed`U literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/tip.gif b/src/demo/share/jfc/J2Ddemo/images/tip.gif new file mode 100644 index 0000000000000000000000000000000000000000..4601ab274b6e929f052378d8ceaec73ba0305fa3 GIT binary patch literal 2640 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 TYE6cQ00000NkvXXu0mjfS1R{W literal 0 HcmV?d00001 diff --git a/src/demo/share/jfc/J2Ddemo/images/tip@2x.png b/src/demo/share/jfc/J2Ddemo/images/tip@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e40d8d10a6acb9968bd3a9da812c148e4f5bee8b GIT binary patch literal 7314 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
C ztr7>|fD4vg2s!$J5r~(0_-(L8j%1_|-*V|aF+sa0O8wpr2}m1_^1#bjb4T1ZOu%~k z?YBifa~47#B@Q!W<7vlY(hi|CG0IP3BbhO?kfSb%EQ*nMuA|W^5rRu+#qYxzJ7VU} zk|j$z>&-f6{c;HFIl56Ty1Kg9=FOXHvfOw>Ad#)c1HTW7$@zhjIxMF!KRoFSp)yT+RV+PRx@K zH)++Of=ov12Xwr|>H&o41EV0e#R=n>s)^ZWepLy@Y_}-(4b)boF|lZmJE8rm4Gm>d zW~0Md%c%8*hMcT=t zwIl(~_=sv1eLOB{j$fd27sIm9v59hEiK{39Eg@P#yQ1VS(a#&E0-#BAs&$;6kYNQ_07WOyWKJ-8Tw!@3-} zLI6%p3#yL@6(mO#Cca{6geqrB<7j6m_&Z|*zq`+^!zgBE``u4a`x0;U5r+=5a7+#B z4&nshHVAIUvnVNB@z^kw=r^ey79Y*lGoiB(fl8tn{;G0i*v^nIT)Ug&#B=f!4mW=* z5!%v%^w=?~QiZ(e1b1uj1%WnjIl>t5dM|a2v|Xp*phXZv)m4n}MTy8&liH8|L_+`( ztlb<11ZGu4`6{X6kDC>oqW%c2xcZo-7M-8^nR0)@rZ%u&j$su}Uti3;^@>YY-{(k7GiIT_>ULttBhYWn8&8!Gi!@m7*TC7z^}8%JePG5v%m5tfu3uTwf&VRp-TQ zdQV3Y%Q%CbMB!5O*3$84HOf2&>p@~TAzP_G@M-3eb*AWs+h~WA=0l5IWma60B}P?J zPJRNqO<*cxG-!0NmRKsv3G7sCHB3sayM=AshVtA<4-EBz`_*Cz7A@`N0z+7QBoB$&oWS2I&FSFPcuB?NWL;4Y*WTcDbFp);+0fwbXG)D2kl)KvK(=8hw-s z(vGZimB@h0*%|y|bwD&zJYyq01hHNED4}X+CFaD=^6fk*7Suk*w+F#_CN;qfln7fr z_?{lMt)T8CL;-G}dgY`BJqZbs($l?TAaombAt82=4n8R_esci>%uuPwq_ cache = + new ConcurrentHashMap(names.length); + static { + for (String name : names) { + cache.put(name, getFont(name)); + } + } + + public static void newDemoFonts() { + } + + + public static Font getFont(String name) { + Font font = null; + if (cache != null) { + if ((font = cache.get(name)) != null) { + return font; + } + } + String fName = "/fonts/" + name; + try { + InputStream is = DemoFonts.class.getResourceAsStream(fName); + font = Font.createFont(Font.TRUETYPE_FONT, is); + } catch (Exception ex) { + Logger.getLogger(DemoFonts.class.getName()).log(Level.SEVERE, + fName + " not loaded. Using serif font.", ex); + font = new Font(Font.SERIF, Font.PLAIN, 24); + } + return font; + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/DemoGroup.java b/src/demo/share/jfc/J2Ddemo/java2d/DemoGroup.java new file mode 100644 index 00000000000..d7aa0ce3863 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/DemoGroup.java @@ -0,0 +1,384 @@ +/* + * + * Copyright (c) 2007, 2011, 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 java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.Image; +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 javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.JToggleButton; +import javax.swing.border.BevelBorder; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.SoftBevelBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + + +/** + * DemoGroup handles multiple demos inside of a panel. Demos are loaded + * from the demos[][] string as listed in J2Ddemo.java. + * Demo groups can be loaded individually, for example : + * java DemoGroup Fonts + * Loads all the demos found in the demos/Fonts directory. + */ +@SuppressWarnings("serial") +public class DemoGroup extends JPanel + implements ChangeListener, ActionListener { + private final DemoInstVarsAccessor demoInstVars; + public int columns = 2; + private static final Font font = new Font(Font.SERIF, Font.PLAIN, 10); + private final EmptyBorder emptyB = new EmptyBorder(5, 5, 5, 5); + private final BevelBorder bevelB = new BevelBorder(BevelBorder.LOWERED); + private String groupName; + public JPanel clonePanels[]; + public JTabbedPane tabbedPane; + + public DemoGroup(String name, DemoInstVarsAccessor demoInstVars) { + + groupName = name; + this.demoInstVars = demoInstVars; + + setLayout(new BorderLayout()); + + JPanel p = new JPanel(new GridLayout(0, 2)); + p.setBorder(new CompoundBorder(emptyB, bevelB)); + + // Find the named demo group in J2Ddemo.demos[]. + int ind = -1; + while (!name.equals(J2Ddemo.demos[++ind][0])) { + } + String[] demos = J2Ddemo.demos[ind]; + + // If there are an odd number of demos, use GridBagLayout. + // Note that we don't use the first entry. + int numDemos = demos.length - 1; + if (numDemos % 2 == 1) { + p.setLayout(new GridBagLayout()); + } + + MouseAdapter mouseListener = new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + DemoGroup.this.mouseClicked(e.getComponent()); + } + }; + + // For each demo in the group, prepare a DemoPanel. + for (int i = 1; i <= numDemos; i++) { + DemoPanel dp = + new DemoPanel("java2d.demos." + name + "." + demos[i], demoInstVars); + dp.setDemoBorder(p); + if (dp.surface != null) { + dp.surface.addMouseListener(mouseListener); + dp.surface.setMonitor(demoInstVars.getPerformanceMonitor() != null); + } + if (p.getLayout() instanceof GridBagLayout) { + int x = p.getComponentCount() % 2; + int y = p.getComponentCount() / 2; + int w = (i == numDemos) ? 2 : 1; + J2Ddemo.addToGridBag(p, dp, x, y, w, 1, 1, 1); + } else { + p.add(dp); + } + } + + add(p); + } + + public void mouseClicked(Component component) { + String className = component.toString(); + + if (tabbedPane == null) { + shutDown(getPanel()); + JPanel p = new JPanel(new BorderLayout()); + p.setBorder(new CompoundBorder(emptyB, bevelB)); + + tabbedPane = new JTabbedPane(); + tabbedPane.setFont(font); + + JPanel tmpP = (JPanel) getComponent(0); + tabbedPane.addTab(groupName, tmpP); + + clonePanels = new JPanel[tmpP.getComponentCount()]; + for (int i = 0; i < clonePanels.length; i++) { + clonePanels[i] = new JPanel(new BorderLayout()); + DemoPanel dp = (DemoPanel) tmpP.getComponent(i); + DemoPanel c = new DemoPanel(dp.className, demoInstVars); + c.setDemoBorder(clonePanels[i]); + if (c.surface != null) { + c.surface.setMonitor(demoInstVars.getPerformanceMonitor() != null); + Image cloneImg = DemoImages.getImage("clone.gif", this); + c.tools.cloneB = c.tools.addTool(cloneImg, + "Clone the Surface", this); + Dimension d = c.tools.toolbar.getPreferredSize(); + c.tools.toolbar.setPreferredSize( + new Dimension(d.width + 27, d.height)); + if (demoInstVars.getBackgroundColor() != null) { + c.surface.setBackground(demoInstVars.getBackgroundColor()); + } + } + clonePanels[i].add(c); + String s = dp.className.substring(dp.className.indexOf('.') + 1); + tabbedPane.addTab(s, clonePanels[i]); + } + p.add(tabbedPane); + remove(tmpP); + add(p); + + tabbedPane.addChangeListener(this); + revalidate(); + } + + className = className.substring(0, className.indexOf('[')); + + for (int i = 0; i < tabbedPane.getTabCount(); i++) { + String s1 = className.substring(className.indexOf('.') + 1); + if (tabbedPane.getTitleAt(i).equals(s1)) { + tabbedPane.setSelectedIndex(i); + break; + } + } + + revalidate(); + } + + @Override + public void actionPerformed(ActionEvent e) { + JButton b = (JButton) e.getSource(); + if (b.getToolTipText().startsWith("Clone")) { + cloneDemo(); + } else { + removeClone(b.getParent().getParent().getParent().getParent()); + } + } + private int index; + + @Override + public void stateChanged(ChangeEvent e) { + shutDown((JPanel) tabbedPane.getComponentAt(index)); + index = tabbedPane.getSelectedIndex(); + setup(false); + } + + public JPanel getPanel() { + if (tabbedPane != null) { + return (JPanel) tabbedPane.getSelectedComponent(); + } else { + return (JPanel) getComponent(0); + } + } + + public void setup(boolean issueRepaint) { + + JPanel p = getPanel(); + + // Let PerformanceMonitor know which demos are running + if (demoInstVars.getPerformanceMonitor() != null) { + demoInstVars.getPerformanceMonitor().surf.setPanel(p); + demoInstVars.getPerformanceMonitor().surf.setSurfaceState(); + } + + GlobalControls c = demoInstVars.getControls(); + // .. tools check against global controls settings .. + // .. & start demo & custom control thread if need be .. + for (int i = 0; i < p.getComponentCount(); i++) { + DemoPanel dp = (DemoPanel) p.getComponent(i); + if (dp.surface != null && c != null) { + Tools t = dp.tools; + t.setVisible(isValid()); + t.issueRepaint = issueRepaint; + JToggleButton b[] = { t.toggleB, t.aliasB, t.renderB, + t.textureB, t.compositeB }; + JCheckBox cb[] = { c.toolBarCB, c.aliasCB, c.renderCB, + c.textureCB, c.compositeCB }; + for (int j = 0; j < b.length; j++) { + if (c.obj != null && c.obj.equals(cb[j])) { + if (b[j].isSelected() != cb[j].isSelected()) { + b[j].doClick(); + } + } else if (c.obj == null) { + if (b[j].isSelected() != cb[j].isSelected()) { + b[j].doClick(); + } + } + } + t.setVisible(true); + if (c.screenCombo.getSelectedIndex() + != t.screenCombo.getSelectedIndex()) { + t.screenCombo.setSelectedIndex(c.screenCombo. + getSelectedIndex()); + } + if (demoInstVars.getVerboseCB().isSelected()) { + dp.surface.verbose(c); + } + dp.surface.setSleepAmount(c.slider.getValue()); + if (demoInstVars.getBackgroundColor() != null) { + dp.surface.setBackground(demoInstVars.getBackgroundColor()); + } + t.issueRepaint = true; + } + dp.start(); + } + revalidate(); + } + + public void shutDown(JPanel p) { + for (int i = 0; i < p.getComponentCount(); i++) { + ((DemoPanel) p.getComponent(i)).stop(); + } + System.gc(); + } + + public void cloneDemo() { + JPanel panel = clonePanels[tabbedPane.getSelectedIndex() - 1]; + if (panel.getComponentCount() == 1) { + panel.invalidate(); + panel.setLayout(new GridLayout(0, columns, 5, 5)); + panel.revalidate(); + } + DemoPanel original = (DemoPanel) getPanel().getComponent(0); + DemoPanel clone = new DemoPanel(original.className, demoInstVars); + if (columns == 2) { + clone.setDemoBorder(panel); + } + Image removeImg = DemoImages.getImage("remove.gif", this); + clone.tools.cloneB = + clone.tools.addTool(removeImg, "Remove the Surface", this); + Dimension d = clone.tools.toolbar.getPreferredSize(); + clone.tools.toolbar.setPreferredSize( + new Dimension(d.width + 27, d.height)); + if (demoInstVars.getBackgroundColor() != null) { + clone.surface.setBackground(demoInstVars.getBackgroundColor()); + } + if (demoInstVars.getControls() != null) { + if (clone.tools.isExpanded + != demoInstVars.getControls().toolBarCB.isSelected()) { + clone.tools.toggleB.doClick(); + } + } + clone.start(); + clone.surface.setMonitor(demoInstVars.getPerformanceMonitor() != null); + panel.add(clone); + panel.repaint(); + panel.revalidate(); + } + + public void removeClone(Component theClone) { + JPanel panel = clonePanels[tabbedPane.getSelectedIndex() - 1]; + if (panel.getComponentCount() == 2) { + Component cmp = panel.getComponent(0); + panel.removeAll(); + panel.setLayout(new BorderLayout()); + panel.revalidate(); + panel.add(cmp); + } else { + panel.remove(theClone); + int cmpCount = panel.getComponentCount(); + for (int j = 1; j < cmpCount; j++) { + int top = (j + 1 >= 3) ? 0 : 5; + int left = ((j + 1) % 2) == 0 ? 0 : 5; + EmptyBorder eb = new EmptyBorder(top, left, 5, 5); + SoftBevelBorder sbb = new SoftBevelBorder(BevelBorder.RAISED); + JPanel p = (JPanel) panel.getComponent(j); + p.setBorder(new CompoundBorder(eb, sbb)); + } + } + panel.repaint(); + panel.revalidate(); + } + + public static void main(String args[]) { + class DemoInstVarsAccessorImpl extends DemoInstVarsAccessorImplBase { + private volatile JCheckBoxMenuItem ccthreadCB; + + public void setCcthreadCB(JCheckBoxMenuItem ccthreadCB) { + this.ccthreadCB = ccthreadCB; + } + + @Override + public JCheckBoxMenuItem getCcthreadCB() { + return ccthreadCB; + } + } + DemoInstVarsAccessorImpl demoInstVars = new DemoInstVarsAccessorImpl(); + final DemoGroup group = new DemoGroup(args[0], demoInstVars); + JFrame f = new JFrame("Java2D(TM) Demo - DemoGroup"); + f.addWindowListener(new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + System.exit(0); + } + + @Override + public void windowDeiconified(WindowEvent e) { + group.setup(false); + } + + @Override + public void windowIconified(WindowEvent e) { + group.shutDown(group.getPanel()); + } + }); + f.getContentPane().add("Center", group); + f.pack(); + int FRAME_WIDTH = 620; + int FRAME_HEIGHT = 530; + f.setSize(FRAME_WIDTH, FRAME_HEIGHT); + f.setLocationRelativeTo(null); // centers f on screen + f.setVisible(true); + for (String arg : args) { + if (arg.startsWith("-ccthread")) { + demoInstVars.setCcthreadCB(new JCheckBoxMenuItem("CCThread", true)); + } + } + group.setup(false); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/DemoImages.java b/src/demo/share/jfc/J2Ddemo/java2d/DemoImages.java new file mode 100644 index 00000000000..0583e4b7f7f --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/DemoImages.java @@ -0,0 +1,105 @@ +/* + * + * Copyright (c) 2007, 2011, 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 java.awt.Component; +import java.awt.Image; +import java.awt.MediaTracker; +import java.net.URL; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + + +/** + * A collection of all the demo images found in the images directory. + * Certain classes are preloaded; the rest are loaded lazily. + */ +@SuppressWarnings("serial") +public class DemoImages extends Component { + + private static final String[] names = { + "bld.jpg", "boat.png", "box.png", + "boxwave.png", "clouds.jpg", "duke.gif", "duke.running.gif", + "dukeplug.png", "fight.png", "globe.png", + "jumptojavastrip.png", "magnify.png", "painting.png", + "remove.gif", "snooze.png", "star7.gif", "surfing.png", + "thumbsup.png", "tip.png", "duke.png", "print.gif", + "loop.gif", "looping.gif", "start.gif", "start2.gif", + "stop.gif", "stop2.gif", "clone.gif" + }; + private static final Map cache = + new ConcurrentHashMap(names.length); + + private DemoImages() { + } + + public static void newDemoImages() { + DemoImages demoImages = new DemoImages(); + for (String name : names) { + cache.put(name, getImage(name, demoImages)); + } + } + + + /* + * Gets the named image using the toolkit of the specified component. + * Note that this has to work even before we have had a chance to + * instantiate DemoImages and preload the cache. + */ + public static Image getImage(String name, Component cmp) { + Image img = null; + if (cache != null) { + if ((img = cache.get(name)) != null) { + return img; + } + } + + ClassLoader cl = cmp.getClass().getClassLoader(); + URL fileLoc = cl.getResource("images/" + name); + img = cmp.getToolkit().getImage(fileLoc); + + MediaTracker tracker = new MediaTracker(cmp); + tracker.addImage(img, 0); + try { + tracker.waitForID(0); + if (tracker.isErrorAny()) { + System.out.println("Error loading image " + name); + } + } catch (Exception ex) { + Logger.getLogger(DemoImages.class.getName()).log(Level.SEVERE, null, ex); + } + return img; + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/DemoInstVarsAccessor.java b/src/demo/share/jfc/J2Ddemo/java2d/DemoInstVarsAccessor.java new file mode 100644 index 00000000000..2f85591266e --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/DemoInstVarsAccessor.java @@ -0,0 +1,27 @@ +package java2d; + +import java.awt.Color; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JTabbedPane; + +/** + * The interface provides access to instance variables of 'J2Ddemo' object, which + * were static variables of 'J2Ddemo' class read/written from various parts of the + * demo classes. The interface is a part of the fix which changed static variables + * for instance variables in certain demo classes. + */ +public interface DemoInstVarsAccessor { + public GlobalControls getControls(); + public MemoryMonitor getMemoryMonitor(); + public PerformanceMonitor getPerformanceMonitor(); + public JTabbedPane getTabbedPane(); + public DemoGroup[] getGroup(); + public void setGroupColumns(int columns); + public JCheckBoxMenuItem getVerboseCB(); + public JCheckBoxMenuItem getCcthreadCB(); + public JCheckBoxMenuItem getPrintCB(); + public Color getBackgroundColor(); + public JCheckBoxMenuItem getMemoryCB(); + public JCheckBoxMenuItem getPerfCB(); + public Intro getIntro(); +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/DemoInstVarsAccessorImplBase.java b/src/demo/share/jfc/J2Ddemo/java2d/DemoInstVarsAccessorImplBase.java new file mode 100644 index 00000000000..eb318ed7f43 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/DemoInstVarsAccessorImplBase.java @@ -0,0 +1,79 @@ +package java2d; + +import java.awt.Color; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JTabbedPane; + +/** + * The implementation of 'DemoInstVarsAccessor' interface with empty methods. + * It is used, when some parts of the demo are executed as standalone applications + * not creating 'J2Ddemo' instances, for example in 'TextureChooser.main', + * 'DemoGroup.main', 'Surface.createDemoFrame'. + */ +public class DemoInstVarsAccessorImplBase implements DemoInstVarsAccessor { + private JCheckBoxMenuItem printCB = new JCheckBoxMenuItem("Default Printer"); + + @Override + public GlobalControls getControls() { + return null; + } + + @Override + public MemoryMonitor getMemoryMonitor() { + return null; + } + + @Override + public PerformanceMonitor getPerformanceMonitor() { + return null; + } + + @Override + public JTabbedPane getTabbedPane() { + return null; + } + + @Override + public DemoGroup[] getGroup() { + return null; + } + + @Override + public void setGroupColumns(int columns) { + } + + @Override + public JCheckBoxMenuItem getVerboseCB() { + return null; + } + + @Override + public JCheckBoxMenuItem getCcthreadCB() { + return null; + } + + @Override + public JCheckBoxMenuItem getPrintCB() { + return printCB; + } + + @Override + public Color getBackgroundColor() { + return null; + } + + @Override + public JCheckBoxMenuItem getMemoryCB() { + return null; + } + + @Override + public JCheckBoxMenuItem getPerfCB() { + return null; + } + + @Override + public Intro getIntro() { + return null; + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/DemoPanel.java b/src/demo/share/jfc/J2Ddemo/java2d/DemoPanel.java new file mode 100644 index 00000000000..bae121834a7 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/DemoPanel.java @@ -0,0 +1,124 @@ +/* + * + * Copyright (c) 2007, 2011, 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 java2d.CustomControlsContext.State.START; +import static java2d.CustomControlsContext.State.STOP; +import java.awt.BorderLayout; +import java.awt.Component; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JPanel; +import javax.swing.border.BevelBorder; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.SoftBevelBorder; + + +/** + * The panel for the Surface, Custom Controls & Tools. + * Other component types welcome. + */ +@SuppressWarnings("serial") +public class DemoPanel extends JPanel { + private final DemoInstVarsAccessor demoInstVars; + public Surface surface; + public CustomControlsContext ccc; + public Tools tools; + public String className; + + public DemoPanel(Object obj, DemoInstVarsAccessor demoInstVars) { + this.demoInstVars = demoInstVars; + + setLayout(new BorderLayout()); + try { + if (obj instanceof String) { + className = (String) obj; + obj = Class.forName(className).newInstance(); + } + if (obj instanceof Component) { + add((Component) obj); + } + if (obj instanceof Surface) { + add("South", tools = new Tools(surface = (Surface) obj, demoInstVars)); + } + if (obj instanceof CustomControlsContext) { + ccc = (CustomControlsContext) obj; + Component cmps[] = ccc.getControls(); + String cons[] = ccc.getConstraints(); + for (int i = 0; i < cmps.length; i++) { + add(cmps[i], cons[i]); + } + } + } catch (Exception e) { + Logger.getLogger(DemoPanel.class.getName()).log(Level.SEVERE, null, + e); + } + } + + public void start() { + if (surface != null) { + surface.startClock(); + } + if (tools != null && surface != null) { + if (tools.startStopB != null && tools.startStopB.isSelected()) { + surface.animating.start(); + } + } + if (ccc != null + && demoInstVars.getCcthreadCB() != null + && demoInstVars.getCcthreadCB().isSelected()) { + ccc.handleThread(START); + } + } + + public void stop() { + if (surface != null) { + if (surface.animating != null) { + surface.animating.stop(); + } + surface.bimg = null; + } + if (ccc != null) { + ccc.handleThread(STOP); + } + } + + public void setDemoBorder(JPanel p) { + int top = (p.getComponentCount() + 1 >= 3) ? 0 : 5; + int left = ((p.getComponentCount() + 1) % 2) == 0 ? 0 : 5; + EmptyBorder eb = new EmptyBorder(top, left, 5, 5); + SoftBevelBorder sbb = new SoftBevelBorder(BevelBorder.RAISED); + setBorder(new CompoundBorder(eb, sbb)); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/GlobalControls.java b/src/demo/share/jfc/J2Ddemo/java2d/GlobalControls.java new file mode 100644 index 00000000000..6432e3e65d7 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/GlobalControls.java @@ -0,0 +1,151 @@ +/* + * + * Copyright (c) 2007, 2011, 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 java.awt.Dimension; +import java.awt.Font; +import java.awt.GridBagLayout; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.SwingConstants; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + + +/** + * Global Controls panel for changing graphic attributes of + * the demo surface. + */ +@SuppressWarnings("serial") +public class GlobalControls extends JPanel implements ItemListener, + ChangeListener { + private final DemoInstVarsAccessor demoInstVars; + public static final String[] screenNames = { + "Auto Screen", "On Screen", "Off Screen", + "INT_xRGB", "INT_ARGB", "INT_ARGB_PRE", "INT_BGR", + "3BYTE_BGR", "4BYTE_ABGR", "4BYTE_ABGR_PRE", "USHORT_565_RGB", + "USHORT_x555_RGB", "BYTE_GRAY", "USHORT_GRAY", + "BYTE_BINARY", "BYTE_INDEXED", "BYTE_BINARY 2 bit", "BYTE_BINARY 4 bit", + "INT_RGBx", "USHORT_555x_RGB" }; + public final JComboBox screenCombo; + public TextureChooser texturechooser; + public JCheckBox aliasCB, renderCB, toolBarCB; + public JCheckBox compositeCB, textureCB; + public JSlider slider; + public Object obj; + private Font font = new Font(Font.SERIF, Font.PLAIN, 12); + + @SuppressWarnings("LeakingThisInConstructor") + public GlobalControls(DemoInstVarsAccessor demoInstVars) { + this.demoInstVars = demoInstVars; + + setLayout(new GridBagLayout()); + setBorder(new TitledBorder(new EtchedBorder(), "Global Controls")); + + aliasCB = createCheckBox("Anti-Aliasing", true, 0); + renderCB = createCheckBox("Rendering Quality", false, 1); + textureCB = createCheckBox("Texture", false, 2); + compositeCB = createCheckBox("AlphaComposite", false, 3); + + screenCombo = new JComboBox(); + screenCombo.setPreferredSize(new Dimension(120, 18)); + screenCombo.setLightWeightPopupEnabled(true); + screenCombo.setFont(font); + for (int i = 0; i < screenNames.length; i++) { + screenCombo.addItem(screenNames[i]); + } + screenCombo.addItemListener(this); + J2Ddemo.addToGridBag(this, screenCombo, 0, 4, 1, 1, 0.0, 0.0); + + toolBarCB = createCheckBox("Tools", false, 5); + + slider = new JSlider(SwingConstants.HORIZONTAL, 0, 200, 30); + slider.addChangeListener(this); + TitledBorder tb = new TitledBorder(new EtchedBorder()); + tb.setTitleFont(font); + tb.setTitle("Anim delay = 30 ms"); + slider.setBorder(tb); + slider.setMinimumSize(new Dimension(80, 46)); + J2Ddemo.addToGridBag(this, slider, 0, 6, 1, 1, 1.0, 1.0); + + texturechooser = new TextureChooser(0, demoInstVars); + J2Ddemo.addToGridBag(this, texturechooser, 0, 7, 1, 1, 1.0, 1.0); + } + + private JCheckBox createCheckBox(String s, boolean b, int y) { + JCheckBox cb = new JCheckBox(s, b); + cb.setFont(font); + cb.setHorizontalAlignment(SwingConstants.LEFT); + cb.addItemListener(this); + J2Ddemo.addToGridBag(this, cb, 0, y, 1, 1, 1.0, 1.0); + return cb; + } + + @Override + public void stateChanged(ChangeEvent e) { + int value = slider.getValue(); + TitledBorder tb = (TitledBorder) slider.getBorder(); + tb.setTitle("Anim delay = " + String.valueOf(value) + " ms"); + int index = demoInstVars.getTabbedPane().getSelectedIndex() - 1; + DemoGroup dg = demoInstVars.getGroup()[index]; + JPanel p = dg.getPanel(); + for (int i = 0; i < p.getComponentCount(); i++) { + DemoPanel dp = (DemoPanel) p.getComponent(i); + if (dp.tools != null && dp.tools.slider != null) { + dp.tools.slider.setValue(value); + } + } + slider.repaint(); + } + + @Override + public void itemStateChanged(ItemEvent e) { + if (demoInstVars.getTabbedPane().getSelectedIndex() != 0) { + obj = e.getSource(); + int index = demoInstVars.getTabbedPane().getSelectedIndex() - 1; + demoInstVars.getGroup()[index].setup(true); + obj = null; + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(135, 260); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/GlobalPanel.java b/src/demo/share/jfc/J2Ddemo/java2d/GlobalPanel.java new file mode 100644 index 00000000000..2f9754938d0 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/GlobalPanel.java @@ -0,0 +1,100 @@ +/* + * + * Copyright (c) 2007, 2011, 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 java.awt.BorderLayout; +import java.awt.GridBagLayout; +import javax.swing.JPanel; +import javax.swing.border.BevelBorder; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + + +/** + * Panel that holds the Demo groups, Controls and Monitors for each tab. + * It's a special "always visible" panel for the Controls, MemoryMonitor & + * PerformanceMonitor. + */ +@SuppressWarnings("serial") +public class GlobalPanel extends JPanel implements ChangeListener { + private final DemoInstVarsAccessor demoInstVars; + private JPanel p; + private int index; + + public GlobalPanel(DemoInstVarsAccessor demoInstVars) { + this.demoInstVars = demoInstVars; + + setLayout(new BorderLayout()); + p = new JPanel(new GridBagLayout()); + EmptyBorder eb = new EmptyBorder(5, 0, 5, 5); + BevelBorder bb = new BevelBorder(BevelBorder.LOWERED); + p.setBorder(new CompoundBorder(eb, bb)); + J2Ddemo.addToGridBag(p, demoInstVars.getControls(), 0, 0, 1, 1, 0, 0); + J2Ddemo.addToGridBag(p, demoInstVars.getMemoryMonitor(), 0, 1, 1, 1, 0, 0); + J2Ddemo.addToGridBag(p, demoInstVars.getPerformanceMonitor(), 0, 2, 1, 1, 0, 0); + add(demoInstVars.getIntro()); + } + + @Override + public void stateChanged(ChangeEvent e) { + + demoInstVars.getGroup()[index].shutDown(demoInstVars.getGroup()[index].getPanel()); + if (demoInstVars.getTabbedPane().getSelectedIndex() == 0) { + demoInstVars.getMemoryMonitor().surf.stop(); + demoInstVars.getPerformanceMonitor().surf.stop(); + removeAll(); + add(demoInstVars.getIntro()); + demoInstVars.getIntro().start(); + } else { + if (getComponentCount() == 1) { + demoInstVars.getIntro().stop(); + remove(demoInstVars.getIntro()); + add(p, BorderLayout.EAST); + if (demoInstVars.getMemoryCB().getState()) { + demoInstVars.getMemoryMonitor().surf.start(); + } + if (demoInstVars.getPerfCB().getState()) { + demoInstVars.getPerformanceMonitor().surf.start(); + } + } else { + remove(demoInstVars.getGroup()[index]); + } + index = demoInstVars.getTabbedPane().getSelectedIndex() - 1; + add(demoInstVars.getGroup()[index]); + demoInstVars.getGroup()[index].setup(false); + } + revalidate(); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/Intro.java b/src/demo/share/jfc/J2Ddemo/java2d/Intro.java new file mode 100644 index 00000000000..9cf2aabf485 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/Intro.java @@ -0,0 +1,1784 @@ +/* + * + * Copyright (c) 2007, 2011, 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 { + + 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 parts = new ArrayList(); + 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 parts; + public int index; + public int length; + + public Scene(List 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 rect = new ArrayList(); + private List grad = new ArrayList(); + 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 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(width); + ylist = new ArrayList(height); + list = new ArrayList(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 subs = new ArrayList(20); + private List pts = new ArrayList(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 pts = new ArrayList(); + 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 v = new ArrayList(); + + 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 v = new ArrayList(); + private List cast = + new ArrayList(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); + java.util.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 + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/J2Ddemo.java b/src/demo/share/jfc/J2Ddemo/java2d/J2Ddemo.java new file mode 100644 index 00000000000..06d0e5ee30d --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/J2Ddemo.java @@ -0,0 +1,728 @@ +/* + * + * Copyright (c) 2007, 2011, 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 java2d.CustomControlsContext.State.START; +import static java2d.CustomControlsContext.State.STOP; +import static java2d.DemoImages.newDemoImages; +import static java2d.DemoFonts.newDemoFonts; +import static java2d.RunWindow.RunWindowSettings; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.RenderingHints; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +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 javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.Icon; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JColorChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JProgressBar; +import javax.swing.JSeparator; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.border.EtchedBorder; + + +/** + * A demo that shows Java 2D(TM) API features. + */ +@SuppressWarnings("serial") +public class J2Ddemo extends JPanel implements ItemListener, ActionListener, DemoInstVarsAccessor { + private final GlobalControls controls; + private final MemoryMonitor memorymonitor; + private final PerformanceMonitor performancemonitor; + private final JTabbedPane tabbedPane; + private final DemoGroup[] group; + private JCheckBoxMenuItem verboseCB; + private JCheckBoxMenuItem ccthreadCB; + private JCheckBoxMenuItem printCB = new JCheckBoxMenuItem("Default Printer"); + private Color backgroundColor; + private JCheckBoxMenuItem memoryCB, perfCB; + private final Intro intro; + public static final String[][] demos = { + { "Arcs_Curves", "Arcs", "BezierAnim", "Curves", "Ellipses" }, + { "Clipping", "Areas", "ClipAnim", "Intersection", "Text" }, + { "Colors", "BullsEye", "ColorConvert", "Rotator3D" }, + { "Composite", "ACimages", "ACrules", "FadeAnim" }, + { "Fonts", "AttributedStr", "Highlighting", "Outline", "Tree" }, + { "Images", "DukeAnim", "ImageOps", "JPEGFlip", "WarpImage" }, + { "Lines", "Caps", "Dash", "Joins", "LineAnim" }, + { "Mix", "Balls", "BezierScroller", "Stars3D" }, + { "Paint", "GradAnim", "Gradient", "Texture", "TextureAnim" }, + { "Paths", "Append", "CurveQuadTo", "FillStroke", "WindingRule" }, + { "Transforms", "Rotate", "SelectTx", "TransformAnim" } + }; + private final boolean demoIsInApplet; + private JCheckBoxMenuItem controlsCB; + private JMenuItem runMI, cloneMI, fileMI, backgMI; +// private JMenuItem ccthreadMI, verboseMI; + private RunWindow runwindow; + private RunWindowSettings runWndSetts; + private CloningFeature cloningfeature; + private JFrame rf, cf; +// private GlobalPanel gp; + + /** + * Construct the J2D Demo. + */ + public J2Ddemo(boolean demoIsInApplet, DemoProgress progress, RunWindowSettings runWndSetts) { + this.demoIsInApplet = demoIsInApplet; + this.runWndSetts = runWndSetts; + + setLayout(new BorderLayout()); + setBorder(new EtchedBorder()); + + add(createMenuBar(), BorderLayout.NORTH); + + // hard coding 14 = 11 demo dirs + images + fonts + Intro + progress.setMaximum(13); + progress.setText("Loading images"); + newDemoImages(); + progress.setValue(progress.getValue() + 1); + progress.setText("Loading fonts"); + newDemoFonts(); + progress.setValue(progress.getValue() + 1); + progress.setText("Loading Intro"); + intro = new Intro(); + progress.setValue(progress.getValue() + 1); + UIManager.put("Button.margin", new Insets(0, 0, 0, 0)); + + controls = new GlobalControls(this); + memorymonitor = new MemoryMonitor(); + performancemonitor = new PerformanceMonitor(); + + GlobalPanel gp = new GlobalPanel(this); + + tabbedPane = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.WRAP_TAB_LAYOUT); + tabbedPane.setFont(new Font(Font.SERIF, Font.PLAIN, 12)); + tabbedPane.addTab("", new J2DIcon(this), gp); + tabbedPane.addChangeListener(gp); + + group = new DemoGroup[demos.length]; + for (int i = 0; i < demos.length; i++) { + progress.setText("Loading demos." + demos[i][0]); + group[i] = new DemoGroup(demos[i][0], this); + tabbedPane.addTab(demos[i][0], null); + progress.setValue(progress.getValue() + 1); + } + + add(tabbedPane, BorderLayout.CENTER); + } + + private JMenuBar createMenuBar() { + + JPopupMenu.setDefaultLightWeightPopupEnabled(false); + JMenuBar menuBar = new JMenuBar(); + + if (!demoIsInApplet) { + JMenu file = menuBar.add(new JMenu("File")); + fileMI = file.add(new JMenuItem("Exit")); + fileMI.addActionListener(this); + } + + JMenu options = menuBar.add(new JMenu("Options")); + + controlsCB = (JCheckBoxMenuItem) options.add( + new JCheckBoxMenuItem("Global Controls", true)); + controlsCB.addItemListener(this); + + memoryCB = (JCheckBoxMenuItem) options.add( + new JCheckBoxMenuItem("Memory Monitor", true)); + memoryCB.addItemListener(this); + + perfCB = (JCheckBoxMenuItem) options.add( + new JCheckBoxMenuItem("Performance Monitor", true)); + perfCB.addItemListener(this); + + options.add(new JSeparator()); + + ccthreadCB = (JCheckBoxMenuItem) options.add( + new JCheckBoxMenuItem("Custom Controls Thread")); + ccthreadCB.addItemListener(this); + + printCB = (JCheckBoxMenuItem) options.add(printCB); + + verboseCB = (JCheckBoxMenuItem) options.add( + new JCheckBoxMenuItem("Verbose")); + + options.add(new JSeparator()); + + backgMI = options.add(new JMenuItem("Background Color")); + backgMI.addActionListener(this); + + runMI = options.add(new JMenuItem("Run Window")); + runMI.addActionListener(this); + + cloneMI = options.add(new JMenuItem("Cloning Feature")); + cloneMI.addActionListener(this); + + return menuBar; + } + + public void createRunWindow() { + if (rf != null) { + rf.toFront(); + return; + } + runwindow = new RunWindow(this, runWndSetts); + WindowListener l = new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + runwindow.stop(); + rf.dispose(); + } + + @Override + public void windowClosed(WindowEvent e) { + rf = null; + } + }; + rf = new JFrame("Run"); + rf.addWindowListener(l); + rf.getContentPane().add("Center", runwindow); + rf.pack(); + if (!demoIsInApplet) { + rf.setSize(new Dimension(200, 125)); + } else { + rf.setSize(new Dimension(200, 150)); + } + rf.setVisible(true); + } + + public void startRunWindow() { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + runwindow.doRunAction(); + } + }); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource().equals(fileMI)) { + System.exit(0); + } else if (e.getSource().equals(runMI)) { + createRunWindow(); + } else if (e.getSource().equals(cloneMI)) { + if (cloningfeature == null) { + cloningfeature = new CloningFeature(this); + WindowListener l = new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + cloningfeature.stop(); + cf.dispose(); + } + + @Override + public void windowClosed(WindowEvent e) { + cloningfeature = null; + } + }; + cf = new JFrame("Cloning Demo"); + cf.addWindowListener(l); + cf.getContentPane().add("Center", cloningfeature); + cf.pack(); + cf.setSize(new Dimension(320, 330)); + cf.setVisible(true); + } else { + cf.toFront(); + } + } else if (e.getSource().equals(backgMI)) { + backgroundColor = + JColorChooser.showDialog(this, "Background Color", + Color.white); + for (int i = 1; i < tabbedPane.getTabCount(); i++) { + JPanel p = group[i - 1].getPanel(); + for (int j = 0; j < p.getComponentCount(); j++) { + DemoPanel dp = (DemoPanel) p.getComponent(j); + if (dp.surface != null) { + dp.surface.setBackground(backgroundColor); + } + } + } + } + } + + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getSource().equals(controlsCB)) { + boolean newVisibility = !controls.isVisible(); + controls.setVisible(newVisibility); + for (Component cmp : controls.texturechooser.getComponents()) { + cmp.setVisible(newVisibility); + } + } else if (e.getSource().equals(memoryCB)) { + if (memorymonitor.isVisible()) { + memorymonitor.setVisible(false); + memorymonitor.surf.setVisible(false); + memorymonitor.surf.stop(); + } else { + memorymonitor.setVisible(true); + memorymonitor.surf.setVisible(true); + memorymonitor.surf.start(); + } + } else if (e.getSource().equals(perfCB)) { + if (performancemonitor.isVisible()) { + performancemonitor.setVisible(false); + performancemonitor.surf.setVisible(false); + performancemonitor.surf.stop(); + } else { + performancemonitor.setVisible(true); + performancemonitor.surf.setVisible(true); + performancemonitor.surf.start(); + } + } else if (e.getSource().equals(ccthreadCB)) { + CustomControlsContext.State state = + ccthreadCB.isSelected() ? START : STOP; + if (tabbedPane.getSelectedIndex() != 0) { + JPanel p = group[tabbedPane.getSelectedIndex() - 1].getPanel(); + for (int i = 0; i < p.getComponentCount(); i++) { + DemoPanel dp = (DemoPanel) p.getComponent(i); + if (dp.ccc != null) { + dp.ccc.handleThread(state); + } + } + } + } + revalidate(); + } + + public void start() { + if (tabbedPane.getSelectedIndex() == 0) { + intro.start(); + } else { + group[tabbedPane.getSelectedIndex() - 1].setup(false); + if (memorymonitor.surf.thread == null && memoryCB.getState()) { + memorymonitor.surf.start(); + } + if (performancemonitor.surf.thread == null && perfCB.getState()) { + performancemonitor.surf.start(); + } + } + } + + public void stop() { + if (tabbedPane.getSelectedIndex() == 0) { + intro.stop(); + } else { + memorymonitor.surf.stop(); + performancemonitor.surf.stop(); + int i = tabbedPane.getSelectedIndex() - 1; + group[i].shutDown(group[i].getPanel()); + } + } + + /** + * Start of 'DemoInstVarsAccessor' implementation. + */ + @Override + public GlobalControls getControls() { + return controls; + } + + @Override + public MemoryMonitor getMemoryMonitor() { + return memorymonitor; + } + + @Override + public PerformanceMonitor getPerformanceMonitor() { + return performancemonitor; + } + + @Override + public JTabbedPane getTabbedPane() { + return tabbedPane; + } + + @Override + public DemoGroup[] getGroup() { + return group; + } + + @Override + public void setGroupColumns(int columns) { + for (DemoGroup dg : group) { + if (dg != null) { + dg.columns = columns; + } + } + } + + @Override + public JCheckBoxMenuItem getVerboseCB() { + return verboseCB; + } + + @Override + public JCheckBoxMenuItem getCcthreadCB() { + return ccthreadCB; + } + + @Override + public JCheckBoxMenuItem getPrintCB() { + return printCB; + } + + @Override + public Color getBackgroundColor() { + return backgroundColor; + } + + @Override + public JCheckBoxMenuItem getMemoryCB() { + return memoryCB; + } + + @Override + public JCheckBoxMenuItem getPerfCB() { + return perfCB; + } + + @Override + public Intro getIntro() { + return intro; + } + /** + * End of 'DemoInstVarsAccessor' implementation. + */ + + static void addToGridBag(JPanel panel, Component comp, + int x, int y, int w, int h, double weightx, double weighty) { + + GridBagLayout gbl = (GridBagLayout) panel.getLayout(); + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.gridx = x; + c.gridy = y; + c.gridwidth = w; + c.gridheight = h; + c.weightx = weightx; + c.weighty = weighty; + panel.add(comp); + gbl.setConstraints(comp, c); + } + + + /** + * The Icon for the Intro tab. + */ + static class J2DIcon implements Icon { + private final DemoInstVarsAccessor demoInstVars; + private static final Color myBlue = new Color(94, 105, 176); + private static final Color myBlack = new Color(20, 20, 20); + private static final Font font = new Font(Font.SERIF, Font.BOLD, 12); + private FontRenderContext frc = new FontRenderContext(null, true, true); + private TextLayout tl = new TextLayout("J2D demo", font, frc); + + public J2DIcon(DemoInstVarsAccessor demoInstVars) { + this.demoInstVars = demoInstVars; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2.setFont(font); + if (demoInstVars.getTabbedPane().getSelectedIndex() == 0) { + g2.setColor(myBlue); + } else { + g2.setColor(myBlack); + } + tl.draw(g2, x, y + (float)(tl.getBounds().getHeight())); + } + + @Override + public int getIconWidth() { + return (int)(tl.getAdvance())+5; + } + + @Override + public int getIconHeight() { + return (int)(tl.getBounds().getHeight()); + } + } + + /** + * This class eliminates the need in presence of static 'JLabel', 'JProgressBar' + * variables in 'J2Ddemo' class. It is a part of the fix which changed static + * variables for instance variables in certain demo classes. + */ + public static class DemoProgress { + private final JLabel progressLabel; + private final JProgressBar progressBar; + + public DemoProgress(JLabel progressLabel, JProgressBar progressBar) { + if (progressLabel == null) { + throw new IllegalArgumentException("null was transferred as 'progressLabel' argument"); + } + if (progressBar == null) { + throw new IllegalArgumentException("null was transferred as 'progressBar' argument"); + } + + this.progressLabel = progressLabel; + this.progressBar = progressBar; + } + + public void setText(String text) { + progressLabel.setText(text); + } + + public void setMaximum(int n) { + progressBar.setMaximum(n); + } + + public int getValue() { + return progressBar.getValue(); + } + + public void setValue(int n) { + progressBar.setValue(n); + } + } + + private static void initFrame(String[] args, RunWindowSettings runWndSetts) { + final J2Ddemo[] demoOneInstArr = new J2Ddemo[1]; + + JFrame frame = new JFrame("Java 2D(TM) Demo"); + frame.getAccessibleContext().setAccessibleDescription( + "A sample application to demonstrate Java2D(TM) features"); + int FRAME_WIDTH = 400, FRAME_HEIGHT = 200; + frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + frame.setLocation(d.width / 2 - FRAME_WIDTH / 2, d.height / 2 - FRAME_HEIGHT + / 2); + frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + frame.addWindowListener(new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + System.exit(0); + } + + @Override + public void windowDeiconified(WindowEvent e) { + J2Ddemo demo = demoOneInstArr[0]; + if (demo != null) { + demo.start(); + } + } + + @Override + public void windowIconified(WindowEvent e) { + J2Ddemo demo = demoOneInstArr[0]; + if (demo != null) { + demo.stop(); + } + } + }); + JOptionPane.setRootFrame(frame); + + JPanel progressPanel = new JPanel() { + + @Override + public Insets getInsets() { + return new Insets(40, 30, 20, 30); + } + }; + progressPanel.setLayout(new BoxLayout(progressPanel, BoxLayout.Y_AXIS)); + frame.getContentPane().add(progressPanel, BorderLayout.CENTER); + + Dimension labelSize = new Dimension(400, 20); + JLabel progressLabel = new JLabel("Loading, please wait..."); + progressLabel.setAlignmentX(CENTER_ALIGNMENT); + progressLabel.setMaximumSize(labelSize); + progressLabel.setPreferredSize(labelSize); + progressPanel.add(progressLabel); + progressPanel.add(Box.createRigidArea(new Dimension(1, 20))); + + JProgressBar progressBar = new JProgressBar(); + progressBar.setStringPainted(true); + progressLabel.setLabelFor(progressBar); + progressBar.setAlignmentX(CENTER_ALIGNMENT); + progressBar.setMinimum(0); + progressBar.setValue(0); + progressBar.getAccessibleContext().setAccessibleName( + "J2D demo loading progress"); + progressPanel.add(progressBar); + DemoProgress demoProgress = new DemoProgress(progressLabel, progressBar); + + frame.setVisible(true); + + J2Ddemo demo = new J2Ddemo(false, demoProgress, runWndSetts); + demoOneInstArr[0] = demo; + + frame.getContentPane().removeAll(); + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(demo, BorderLayout.CENTER); + FRAME_WIDTH = 850; + FRAME_HEIGHT = 600; + frame.setLocation(d.width / 2 - FRAME_WIDTH / 2, d.height / 2 - FRAME_HEIGHT + / 2); + frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); + frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + String s = arg.substring(arg.indexOf('=') + 1); + if (arg.startsWith("-runs=")) { + runWndSetts.setNumRuns(Integer.parseInt(s)); + runWndSetts.setExit(true); + demo.createRunWindow(); + } else if (arg.startsWith("-screen=")) { + demo.getControls().screenCombo.setSelectedIndex(Integer.parseInt(s)); + } else if (arg.startsWith("-antialias=")) { + demo.controls.aliasCB.setSelected(s.endsWith("true")); + } else if (arg.startsWith("-rendering=")) { + demo.controls.renderCB.setSelected(s.endsWith("true")); + } else if (arg.startsWith("-texture=")) { + demo.controls.textureCB.setSelected(s.endsWith("true")); + } else if (arg.startsWith("-composite=")) { + demo.controls.compositeCB.setSelected(s.endsWith("true")); + } else if (arg.startsWith("-verbose")) { + demo.verboseCB.setSelected(true); + } else if (arg.startsWith("-print")) { + demo.printCB.setSelected(true); + runWndSetts.setPrintCBIsSelected(true); + } else if (arg.startsWith("-columns=")) { + demo.setGroupColumns(Integer.parseInt(s)); + } else if (arg.startsWith("-buffers=")) { + // usage -buffers=3,10 + runWndSetts.setBuffersFlag(true); + int i1 = arg.indexOf('=') + 1; + int i2 = arg.indexOf(','); + String s1 = arg.substring(i1, i2); + runWndSetts.setBufBeg(Integer.parseInt(s1)); + s1 = arg.substring(i2 + 1, arg.length()); + runWndSetts.setBufEnd(Integer.parseInt(s1)); + } else if (arg.startsWith("-ccthread")) { + demo.ccthreadCB.setSelected(true); + } else if (arg.startsWith("-zoom")) { + runWndSetts.setZoomCBSelected(true); + } else if (arg.startsWith("-maxscreen")) { + frame.setLocation(0, 0); + frame.setSize(d.width, d.height); + } + } + + frame.validate(); + frame.repaint(); + frame.getFocusTraversalPolicy().getDefaultComponent(frame).requestFocus(); + demo.start(); + + if (runWndSetts.getExit()) { + demo.startRunWindow(); + } + + } + + public static void main(final String args[]) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + RunWindowSettings runWndSetts = new RunWindowSettings(); + for (int i = 0; i < args.length; i++) { + if (args[i].startsWith("-h") || args[i].startsWith("-help")) { + String s = "\njava -jar J2Ddemo.jar -runs=5 -delay=5 -screen=5 " + + "-antialias=true -rendering=true -texture=true " + + "-composite=true -verbose -print -columns=3 " + + "-buffers=5,10 -ccthread -zoom -maxscreen \n"; + System.out.println(s); + s = + " -runs=5 Number of runs to execute\n" + + " -delay=5 Sleep amount between tabs\n" + + " -antialias= true or false for antialiasing\n" + + " -rendering= true or false for quality or speed\n" + + " -texture= true or false for texturing\n" + + " -composite= true or false for compositing\n" + + " -verbose output Surface graphic states \n" + + " -print during run print the Surface, " + + "use the Default Printer\n" + + " -columns=3 # of columns to use in clone layout \n" + + " -screen=3 demos all use this screen type \n" + + " -buffers=5,10 during run - clone to see screens " + + "five through ten\n" + + " -ccthread Invoke the Custom Controls Thread \n" + + " -zoom mouseClick on surface for zoom in \n" + + " -maxscreen take up the entire monitor screen \n"; + System.out.println(s); + s = + "Examples : \n" + " Print all of the demos : \n" + + " java -jar J2Ddemo.jar -runs=1 -delay=60 -print \n" + + " Run zoomed in with custom control thread \n" + + " java -jar J2Ddemo.jar -runs=10 -zoom -ccthread\n"; + System.out.println(s); + System.exit(0); + } else if (args[i].startsWith("-delay=")) { + String s = args[i].substring(args[i].indexOf('=') + 1); + runWndSetts.setDelay(Integer.parseInt(s)); + } + } + + initFrame(args, runWndSetts); + } + }); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/MemoryMonitor.java b/src/demo/share/jfc/J2Ddemo/java2d/MemoryMonitor.java new file mode 100644 index 00000000000..95a773d76f1 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/MemoryMonitor.java @@ -0,0 +1,367 @@ +/* + * + * Copyright (c) 2007, 2011, 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.GREEN; +import static java.awt.Color.YELLOW; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +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.geom.Line2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.util.Date; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; + + +/** + * Tracks Memory allocated & used, displayed in graph form. + */ +@SuppressWarnings("serial") +public class MemoryMonitor extends JPanel { + + private final JCheckBox dateStampCB = new JCheckBox("Output Date Stamp"); + public Surface surf; + JPanel controls; + boolean doControls; + JTextField tf; + + public MemoryMonitor() { + setLayout(new BorderLayout()); + setBorder(new TitledBorder(new EtchedBorder(), "Memory Monitor")); + add(surf = new Surface()); + controls = new JPanel(); + controls.setPreferredSize(new Dimension(135, 80)); + Font font = new Font(Font.SERIF, Font.PLAIN, 10); + JLabel label = new JLabel("Sample Rate"); + label.setFont(font); + label.setForeground(BLACK); + controls.add(label); + tf = new JTextField("1000"); + tf.setPreferredSize(new Dimension(45, 20)); + controls.add(tf); + controls.add(label = new JLabel("ms")); + label.setFont(font); + label.setForeground(BLACK); + controls.add(dateStampCB); + dateStampCB.setFont(font); + addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + removeAll(); + if ((doControls = !doControls)) { + surf.stop(); + add(controls); + } else { + try { + surf.sleepAmount = Long.parseLong(tf.getText().trim()); + } catch (Exception ex) { + } + surf.start(); + add(surf); + } + revalidate(); + repaint(); + } + }); + } + + + public class Surface extends JPanel implements Runnable { + + public Thread thread; + public long sleepAmount = 1000; + private int w, h; + private BufferedImage bimg; + private Graphics2D big; + private Font font = new Font(Font.SERIF, Font.PLAIN, 11); + private Runtime r = Runtime.getRuntime(); + private int columnInc; + private int pts[]; + private int ptNum; + private int ascent, descent; + private Rectangle graphOutlineRect = new Rectangle(); + private Rectangle2D mfRect = new Rectangle2D.Float(); + private Rectangle2D muRect = new Rectangle2D.Float(); + private Line2D graphLine = new Line2D.Float(); + private Color graphColor = new Color(46, 139, 87); + private Color mfColor = new Color(0, 100, 0); + private String usedStr; + + public Surface() { + setBackground(BLACK); + addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + if (thread == null) { + start(); + } else { + stop(); + } + } + }); + } + + @Override + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + @Override + public Dimension getMaximumSize() { + return getPreferredSize(); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(135, 80); + } + + @Override + public void paint(Graphics g) { + + if (big == null) { + return; + } + + big.setBackground(getBackground()); + big.clearRect(0, 0, w, h); + + float freeMemory = r.freeMemory(); + float totalMemory = r.totalMemory(); + + // .. Draw allocated and used strings .. + big.setColor(GREEN); + big.drawString(String.valueOf((int) totalMemory / 1024) + + "K allocated", 4.0f, ascent + 0.5f); + usedStr = String.valueOf(((int) (totalMemory - freeMemory)) / 1024) + + "K used"; + big.drawString(usedStr, 4, h - descent); + + // Calculate remaining size + float ssH = ascent + descent; + float remainingHeight = (h - (ssH * 2) - 0.5f); + float blockHeight = remainingHeight / 10; + float blockWidth = 20.0f; + + // .. Memory Free .. + big.setColor(mfColor); + int MemUsage = (int) ((freeMemory / totalMemory) * 10); + int i = 0; + for (; i < MemUsage; i++) { + mfRect.setRect(5, ssH + i * blockHeight, + blockWidth, blockHeight - 1); + big.fill(mfRect); + } + + // .. Memory Used .. + big.setColor(GREEN); + for (; i < 10; i++) { + muRect.setRect(5, ssH + i * blockHeight, + blockWidth, blockHeight - 1); + big.fill(muRect); + } + + // .. Draw History Graph .. + big.setColor(graphColor); + int graphX = 30; + int graphY = (int) ssH; + int graphW = w - graphX - 5; + int graphH = (int) remainingHeight; + graphOutlineRect.setRect(graphX, graphY, graphW, graphH); + big.draw(graphOutlineRect); + + int graphRow = graphH / 10; + + // .. Draw row .. + for (int j = graphY; j <= graphH + graphY; j += graphRow) { + graphLine.setLine(graphX, j, graphX + graphW, j); + big.draw(graphLine); + } + + // .. Draw animated column movement .. + int graphColumn = graphW / 15; + + if (columnInc == 0) { + columnInc = graphColumn; + } + + for (int j = graphX + columnInc; j < graphW + graphX; j += + graphColumn) { + graphLine.setLine(j, graphY, j, graphY + graphH); + big.draw(graphLine); + } + + --columnInc; + + if (pts == null) { + pts = new int[graphW]; + ptNum = 0; + } else if (pts.length != graphW) { + int tmp[] = null; + if (ptNum < graphW) { + tmp = new int[ptNum]; + System.arraycopy(pts, 0, tmp, 0, tmp.length); + } else { + tmp = new int[graphW]; + System.arraycopy(pts, pts.length - tmp.length, tmp, 0, + tmp.length); + ptNum = tmp.length - 2; + } + pts = new int[graphW]; + System.arraycopy(tmp, 0, pts, 0, tmp.length); + } else { + big.setColor(YELLOW); + pts[ptNum] = + (int) (graphY + graphH * (freeMemory / totalMemory)); + for (int j = graphX + graphW - ptNum, k = 0; k < ptNum; k++, j++) { + if (k != 0) { + if (pts[k] != pts[k - 1]) { + big.drawLine(j - 1, pts[k - 1], j, pts[k]); + } else { + big.fillRect(j, pts[k], 1, 1); + } + } + } + if (ptNum + 2 == pts.length) { + // throw out oldest point + for (int j = 1; j < ptNum; j++) { + pts[j - 1] = pts[j]; + } + --ptNum; + } else { + ptNum++; + } + } + g.drawImage(bimg, 0, 0, this); + } + + public void start() { + thread = new Thread(this); + thread.setPriority(Thread.MIN_PRIORITY); + thread.setName("MemoryMonitor"); + thread.start(); + } + + public synchronized void stop() { + thread = null; + notify(); + } + + @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; + } + } + + while (thread == me && isShowing()) { + Dimension d = getSize(); + if (d.width != w || d.height != h) { + w = d.width; + h = d.height; + bimg = (BufferedImage) createImage(w, h); + big = bimg.createGraphics(); + big.setFont(font); + FontMetrics fm = big.getFontMetrics(font); + ascent = fm.getAscent(); + descent = fm.getDescent(); + } + repaint(); + try { + Thread.sleep(sleepAmount); + } catch (InterruptedException e) { + break; + } + if (dateStampCB.isSelected()) { + System.out.println(new Date().toString() + " " + usedStr); + } + } + thread = null; + } + } + + public static void main(String s[]) { + final MemoryMonitor demo = new MemoryMonitor(); + WindowListener l = new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + System.exit(0); + } + + @Override + public void windowDeiconified(WindowEvent e) { + demo.surf.start(); + } + + @Override + public void windowIconified(WindowEvent e) { + demo.surf.stop(); + } + }; + JFrame f = new JFrame("J2D Demo - MemoryMonitor"); + f.addWindowListener(l); + f.getContentPane().add("Center", demo); + f.pack(); + f.setSize(new Dimension(200, 200)); + f.setVisible(true); + demo.surf.start(); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/PerformanceMonitor.java b/src/demo/share/jfc/J2Ddemo/java2d/PerformanceMonitor.java new file mode 100644 index 00000000000..388dab4226f --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/PerformanceMonitor.java @@ -0,0 +1,202 @@ +/* + * + * Copyright (c) 2007, 2011, 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 java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import javax.swing.JPanel; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; + + +/** + * Displays the time for a Surface to paint. Displays the number + * of frames per second on animated demos. Up to four surfaces fit + * in the display area. + */ +@SuppressWarnings("serial") +public class PerformanceMonitor extends JPanel { + + Surface surf; + + public PerformanceMonitor() { + setLayout(new BorderLayout()); + setBorder(new TitledBorder(new EtchedBorder(), "Performance")); + add(surf = new Surface()); + } + + + public class Surface extends JPanel implements Runnable { + + public Thread thread; + private BufferedImage bimg; + private Font font = new Font(Font.SERIF, Font.PLAIN, 12); + private JPanel panel; + + public Surface() { + setBackground(Color.black); + addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + if (thread == null) { + start(); + } else { + stop(); + } + } + }); + } + + @Override + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + @Override + public Dimension getMaximumSize() { + return getPreferredSize(); + } + + @Override + public Dimension getPreferredSize() { + int textH = getFontMetrics(font).getHeight(); + return new Dimension(135, 2 + textH * 4); + } + + @Override + public void paint(Graphics g) { + if (bimg != null) { + g.drawImage(bimg, 0, 0, this); + } + } + + public void start() { + thread = new Thread(this); + thread.setPriority(Thread.MIN_PRIORITY); + thread.setName("PerformanceMonitor"); + thread.start(); + } + + public synchronized void stop() { + thread = null; + setSurfaceState(); + notify(); + } + + public void setSurfaceState() { + if (panel != null) { + for (Component comp : panel.getComponents()) { + if (((DemoPanel) comp).surface != null) { + ((DemoPanel) comp).surface.setMonitor(thread != null); + } + } + } + } + + public void setPanel(JPanel panel) { + this.panel = panel; + } + + @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; + } + } + + Dimension d = new Dimension(0, 0); + Graphics2D big = null; + FontMetrics fm = null; + int ascent = 0; + int descent = 0; + + while (thread == me && isShowing()) { + + if (getWidth() != d.width || getHeight() != d.height) { + d = getSize(); + bimg = (BufferedImage) createImage(d.width, d.height); + big = bimg.createGraphics(); + big.setFont(font); + fm = big.getFontMetrics(); + ascent = fm.getAscent(); + descent = fm.getDescent(); + setSurfaceState(); + } + + big.setBackground(getBackground()); + big.clearRect(0, 0, d.width, d.height); + if (panel == null) { + continue; + } + big.setColor(Color.green); + int ssH = 1; + for (Component comp : panel.getComponents()) { + if (((DemoPanel) comp).surface != null) { + String pStr = ((DemoPanel) comp).surface.perfStr; + if (pStr != null) { + ssH += ascent; + big.drawString(pStr, 4, ssH + 1); + ssH += descent; + } + } + } + repaint(); + + try { + Thread.sleep(999); + } catch (InterruptedException e) { + break; + } + } + thread = null; + } + } // End Surface +} // End PeformanceMonitor + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/RunWindow.java b/src/demo/share/jfc/J2Ddemo/java2d/RunWindow.java new file mode 100644 index 00000000000..7ac88261277 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/RunWindow.java @@ -0,0 +1,444 @@ +/* + * + * Copyright (c) 2007, 2011, 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.GREEN; +import static java.awt.Color.RED; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Date; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.JTextField; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.border.BevelBorder; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; + + +/** + * A separate window for running the J2Ddemo. Go from tab to tab or demo to + * demo. + */ +@SuppressWarnings("serial") +public class RunWindow extends JPanel implements Runnable, ActionListener { + private final DemoInstVarsAccessor demoInstVars; + private final JButton runB; + private int delay = 10; + private int numRuns = 20; + private boolean exit; + private final JCheckBox zoomCB = new JCheckBox("Zoom"); + private final JCheckBox printCB = new JCheckBox("Print"); + private boolean buffersFlag; + private int bufBeg, bufEnd; + private JTextField delayTextField, runsTextField; + private Thread thread; + private JProgressBar pb; + + @SuppressWarnings("LeakingThisInConstructor") + public RunWindow(DemoInstVarsAccessor demoInstVars, RunWindowSettings runWndSetts) { + this.demoInstVars = demoInstVars; + + delay = runWndSetts.getDelay(); + numRuns = runWndSetts.getNumRuns(); + exit = runWndSetts.getExit(); + zoomCB.setSelected(runWndSetts.isZoomCBSelected()); + printCB.setSelected(runWndSetts.isPrintCBSelected()); + buffersFlag = runWndSetts.getBuffersFlag(); + bufBeg = runWndSetts.getBufBeg(); + bufEnd = runWndSetts.getBufEnd(); + + setLayout(new GridBagLayout()); + EmptyBorder eb = new EmptyBorder(5, 5, 5, 5); + setBorder(new CompoundBorder(eb, new BevelBorder(BevelBorder.LOWERED))); + + Font font = new Font(Font.SERIF, Font.PLAIN, 10); + + runB = new JButton("Run"); + runB.setBackground(GREEN); + runB.addActionListener(this); + runB.setMinimumSize(new Dimension(70, 30)); + J2Ddemo.addToGridBag(this, runB, 0, 0, 1, 1, 0.0, 0.0); + + pb = new JProgressBar(); + pb.setPreferredSize(new Dimension(100, 30)); + pb.setMinimum(0); + J2Ddemo.addToGridBag(this, pb, 1, 0, 2, 1, 1.0, 0.0); + + JPanel p1 = new JPanel(new GridLayout(2, 2)); + JPanel p2 = new JPanel(); + JLabel l = new JLabel("Runs:"); + l.setFont(font); + l.setForeground(BLACK); + p2.add(l); + p2.add(runsTextField = new JTextField(String.valueOf(numRuns))); + runsTextField.setPreferredSize(new Dimension(30, 20)); + runsTextField.addActionListener(this); + p1.add(p2); + p2 = new JPanel(); + l = new JLabel("Delay:"); + l.setFont(font); + l.setForeground(BLACK); + p2.add(l); + p2.add(delayTextField = new JTextField(String.valueOf(delay))); + delayTextField.setPreferredSize(new Dimension(30, 20)); + delayTextField.addActionListener(this); + p1.add(p2); + + zoomCB.setHorizontalAlignment(SwingConstants.CENTER); + zoomCB.setFont(font); + printCB.setFont(font); + p1.add(zoomCB); + p1.add(printCB); + printCB.addActionListener(this); + J2Ddemo.addToGridBag(this, p1, 0, 1, 3, 1, 1.0, 1.0); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource().equals(printCB)) { + demoInstVars.getPrintCB().setSelected(printCB.isSelected()); + } else if (e.getSource().equals(delayTextField)) { + delay = Integer.parseInt(delayTextField.getText().trim()); + } else if (e.getSource().equals(runsTextField)) { + numRuns = Integer.parseInt(runsTextField.getText().trim()); + } else if ("Run".equals(e.getActionCommand())) { + doRunAction(); + } else if ("Stop".equals(e.getActionCommand())) { + stop(); + } + } + + public void doRunAction() { + runB.setText("Stop"); + runB.setBackground(RED); + start(); + } + + public void start() { + thread = new Thread(this); + thread.setPriority(Thread.NORM_PRIORITY + 1); + thread.setName("RunWindow"); + thread.start(); + } + + public synchronized void stop() { + if (thread != null) { + thread.interrupt(); + } + thread = null; + notifyAll(); + } + + @SuppressWarnings("SleepWhileHoldingLock") + public void sleepPerTab() { + for (int j = 0; j < delay + 1 && thread != null; j++) { + for (int k = 0; k < 10 && thread != null; k++) { + try { + Thread.sleep(100); + } catch (Exception e) { + } + } + Runnable pbUpdateRunnable = new Runnable() { + + @Override + public void run() { + pb.setValue(pb.getValue() + 1); + } + }; + SwingUtilities.invokeLater(pbUpdateRunnable); + } + } + + private void printDemo(final DemoGroup dg) { + Runnable printDemoRunnable = new Runnable() { + + @Override + public void run() { + if (!demoInstVars.getControls().toolBarCB.isSelected()) { + demoInstVars.getControls().toolBarCB.setSelected(true); + dg.invalidate(); + } + for (Component comp : dg.getPanel().getComponents()) { + DemoPanel dp = (DemoPanel) comp; + if (dp.tools != null) { + if (dp.surface.animating != null) { + if (dp.surface.animating.running()) { + dp.tools.startStopB.doClick(); + } + } + dp.tools.printB.doClick(); + } + } + } + }; + invokeAndWait(printDemoRunnable); + } + private DemoGroup dg = null; + private DemoPanel dp = null; + + @Override + public void run() { + + System.out.println("\nJ2D Demo RunWindow : " + numRuns + " Runs, " + + delay + " second delay between tabs\n" + "java version: " + System. + getProperty("java.version") + "\n" + System.getProperty( + "os.name") + " " + System.getProperty("os.version") + "\n"); + Runtime r = Runtime.getRuntime(); + + for (int runNum = 0; runNum < numRuns && thread != null; runNum++) { + + Date d = new Date(); + System.out.print("#" + runNum + " " + d.toString() + ", "); + r.gc(); + float freeMemory = r.freeMemory(); + float totalMemory = r.totalMemory(); + System.out.println(((totalMemory - freeMemory) / 1024) + "K used"); + + for (int i = 0; i < demoInstVars.getTabbedPane().getTabCount() && thread + != null; i++) { + + final int mainTabIndex = i; + Runnable initDemoRunnable = new Runnable() { + + @Override + public void run() { + pb.setValue(0); + pb.setMaximum(delay); + if (mainTabIndex != 0) { + dg = demoInstVars.getGroup()[mainTabIndex - 1]; + dg.invalidate(); + } + demoInstVars.getTabbedPane().setSelectedIndex(mainTabIndex); + } + }; + invokeAndWait(initDemoRunnable); + + if (i != 0 && (zoomCB.isSelected() || buffersFlag)) { + dp = (DemoPanel) dg.getPanel().getComponent(0); + if (dg.tabbedPane == null && dp.surface != null) { + Runnable mouseClickedRunnable = new Runnable() { + + @Override + public void run() { + dg.mouseClicked(dp.surface); + } + }; + invokeAndWait(mouseClickedRunnable); + } + for (int j = 1; j < dg.tabbedPane.getTabCount() && thread + != null; j++) { + + final int subTabIndex = j; + + Runnable initPanelRunnable = new Runnable() { + + @Override + public void run() { + pb.setValue(0); + pb.setMaximum(delay); + dg.tabbedPane.setSelectedIndex(subTabIndex); + } + }; + invokeAndWait(initPanelRunnable); + + final JPanel p = dg.getPanel(); + if (buffersFlag && p.getComponentCount() == 1) { + dp = (DemoPanel) p.getComponent(0); + if (dp.surface.animating != null) { + dp.surface.animating.stop(); + } + for (int k = bufBeg; k <= bufEnd && thread != null; + k++) { + + final int cloneIndex = k; + Runnable cloneRunnable = new Runnable() { + + @Override + public void run() { + dp.tools.cloneB.doClick(); + int n = p.getComponentCount(); + DemoPanel clone = (DemoPanel) p. + getComponent(n - 1); + if (clone.surface.animating != null) { + clone.surface.animating.stop(); + } + clone.tools.issueRepaint = true; + clone.tools.screenCombo.setSelectedIndex( + cloneIndex); + clone.tools.issueRepaint = false; + } + }; + invokeAndWait(cloneRunnable); + } + } + if (printCB.isSelected()) { + printDemo(dg); + } + sleepPerTab(); + } + } else if (i != 0 && printCB.isSelected()) { + printDemo(dg); + sleepPerTab(); + } else { + sleepPerTab(); + } + } + if (runNum + 1 == numRuns) { + System.out.println("Finished."); + if (exit && thread != null) { + System.out.println("System.exit(0)."); + System.exit(0); + } + } + } + Runnable resetRunnable = new Runnable() { + + @Override + public void run() { + runB.setText("Run"); + runB.setBackground(GREEN); + pb.setValue(0); + } + }; + invokeAndWait(resetRunnable); + + thread = null; + dg = null; + dp = null; + } + + private static void invokeAndWait(Runnable run) { + try { + SwingUtilities.invokeAndWait(run); + } catch (Exception e) { + Logger.getLogger(RunWindow.class.getName()).log(Level.SEVERE, + "ERROR in invokeAndWait", e); + } + } + + /** + * This class contains initial values for instance variables of 'RunWindow' class, + * and its instance is used in creation of 'RunWindow' object. Values parsed from + * certain command line options of the demo or from the demo applet parameters are + * set to the fields of this class instance. It is a part of the fix which changed + * static variables for instance variables in certain demo classes. + * + * This class is not thread safe, its instances must be accessed only from EDT. + */ + public static class RunWindowSettings { + private int delay = 10; + private int numRuns = 20; + private boolean exit; + private boolean zoomCBIsSelected; + private boolean printCBIsSelected; + private boolean buffersFlag; + private int bufBeg, bufEnd; + + public int getDelay() { + return delay; + } + + public void setDelay(int delay) { + this.delay = delay; + } + + public int getNumRuns() { + return numRuns; + } + + public void setNumRuns(int numRuns) { + this.numRuns = numRuns; + } + + public boolean getExit() { + return exit; + } + + public void setExit(boolean exit) { + this.exit = exit; + } + + public boolean isZoomCBSelected() { + return zoomCBIsSelected; + } + + public void setZoomCBSelected(boolean b) { + zoomCBIsSelected = b; + } + + public boolean isPrintCBSelected() { + return printCBIsSelected; + } + + public void setPrintCBIsSelected(boolean b) { + printCBIsSelected = b; + } + + public boolean getBuffersFlag() { + return buffersFlag; + } + + public void setBuffersFlag(boolean buffersFlag) { + this.buffersFlag = buffersFlag; + } + + public int getBufBeg() { + return bufBeg; + } + + public void setBufBeg(int bufBeg) { + this.bufBeg = bufBeg; + } + + public int getBufEnd() { + return bufEnd; + } + + public void setBufEnd(int bufEnd) { + this.bufEnd = bufEnd; + } + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/Surface.java b/src/demo/share/jfc/J2Ddemo/java2d/Surface.java new file mode 100644 index 00000000000..4d690d3a04a --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/Surface.java @@ -0,0 +1,504 @@ +/* + * + * Copyright (c) 2007, 2011, 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.RenderingHints.KEY_ANTIALIASING; +import static java.awt.RenderingHints.KEY_RENDERING; +import static java.awt.RenderingHints.VALUE_ANTIALIAS_OFF; +import static java.awt.RenderingHints.VALUE_ANTIALIAS_ON; +import static java.awt.RenderingHints.VALUE_RENDER_QUALITY; +import static java.awt.RenderingHints.VALUE_RENDER_SPEED; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Toolkit; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.image.BufferedImage; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferInt; +import java.awt.image.DataBufferUShort; +import java.awt.image.DirectColorModel; +import java.awt.image.IndexColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JPanel; +import javax.swing.RepaintManager; + + +/** + * Surface is the base class for the 2d rendering demos. Demos must + * implement the render() method. Subclasses for Surface are + * AnimatingSurface, ControlsSurface and AnimatingControlsSurface. + */ +@SuppressWarnings("serial") +public abstract class Surface extends JPanel implements Printable { + + public Object AntiAlias = VALUE_ANTIALIAS_ON; + public Object Rendering = VALUE_RENDER_SPEED; + public AlphaComposite composite; + public Paint texture; + public String perfStr; // PerformanceMonitor + public BufferedImage bimg; + public int imageType; + public String name; + public boolean clearSurface = true; + // Demos using animated gif's that implement ImageObserver set dontThread. + public boolean dontThread; + public AnimatingSurface animating; + protected long sleepAmount = 50; + private long orig, start, frame; + private Toolkit toolkit; + private boolean perfMonitor, outputPerf; + private int biw, bih; + private boolean clearOnce; + private boolean toBeInitialized = true; + + public Surface() { + setDoubleBuffered(this instanceof AnimatingSurface); + toolkit = getToolkit(); + name = this.getClass().getSimpleName(); + setImageType(0); + + // To launch an individual demo with the performance str output : + // java -Dj2ddemo.perf= -cp J2Ddemo.jar demos.Clipping.ClipAnim + try { + if (System.getProperty("j2ddemo.perf") != null) { + perfMonitor = outputPerf = true; + } + } catch (Exception ex) { + } + if (this instanceof AnimatingSurface) { + animating = (AnimatingSurface) this; + } + } + + protected Image getImage(String name) { + return DemoImages.getImage(name, this); + } + + protected Font getFont(String name) { + return DemoFonts.getFont(name); + } + + public int getImageType() { + return imageType; + } + + public final void setImageType(int imgType) { + if (imgType == 0) { + imageType = 1; + } else { + imageType = imgType; + } + bimg = null; + } + + public void setAntiAlias(boolean aa) { + AntiAlias = aa ? VALUE_ANTIALIAS_ON : VALUE_ANTIALIAS_OFF; + } + + public void setRendering(boolean rd) { + Rendering = rd ? VALUE_RENDER_QUALITY : VALUE_RENDER_SPEED; + } + + public void setTexture(Object obj) { + if (obj instanceof GradientPaint) { + texture = new GradientPaint(0, 0, Color.white, + getSize().width * 2, 0, Color.green); + } else { + texture = (Paint) obj; + } + } + + public void setComposite(boolean cp) { + composite = cp + ? AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f) + : null; + } + + public void setMonitor(boolean pm) { + perfMonitor = pm; + } + + public void setSleepAmount(long amount) { + sleepAmount = amount; + } + + public long getSleepAmount() { + return sleepAmount; + } + + public BufferedImage createBufferedImage(Graphics2D g2, + int w, + int h, + int imgType) { + BufferedImage bi = null; + if (imgType == 0) { + bi = g2.getDeviceConfiguration(). + createCompatibleImage(w, h); + } else if (imgType > 0 && imgType < 14) { + bi = new BufferedImage(w, h, imgType); + } else if (imgType == 14) { + bi = createBinaryImage(w, h, 2); + } else if (imgType == 15) { + bi = createBinaryImage(w, h, 4); + } else if (imgType == 16) { + bi = createSGISurface(w, h, 32); + } else if (imgType == 17) { + bi = createSGISurface(w, h, 16); + } + return bi; + } + // Lookup tables for BYTE_BINARY 1, 2 and 4 bits. + private static final byte[] lut1Arr = new byte[] { 0, (byte) 255 }; + private static final byte[] lut2Arr = new byte[] { 0, (byte) 85, (byte) 170, (byte) 255 }; + private static final byte[] lut4Arr = new byte[] { 0, (byte) 17, (byte) 34, (byte) 51, + (byte) 68, (byte) 85, (byte) 102, (byte) 119, + (byte) 136, (byte) 153, (byte) 170, (byte) 187, + (byte) 204, (byte) 221, (byte) 238, (byte) 255 }; + + private BufferedImage createBinaryImage(int w, int h, int pixelBits) { + int bytesPerRow = w * pixelBits / 8; + if (w * pixelBits % 8 != 0) { + bytesPerRow++; + } + byte[] imageData = new byte[h * bytesPerRow]; + IndexColorModel cm = null; + switch (pixelBits) { + case 1: + cm = new IndexColorModel(pixelBits, lut1Arr.length, + lut1Arr, lut1Arr, lut1Arr); + break; + case 2: + cm = new IndexColorModel(pixelBits, lut2Arr.length, + lut2Arr, lut2Arr, lut2Arr); + break; + case 4: + cm = new IndexColorModel(pixelBits, lut4Arr.length, + lut4Arr, lut4Arr, lut4Arr); + break; + default: + Logger.getLogger(Surface.class.getName()).log(Level.SEVERE, + null, new Exception("Invalid # of bit per pixel")); + } + + DataBuffer db = new DataBufferByte(imageData, imageData.length); + WritableRaster r = Raster.createPackedRaster(db, w, h, pixelBits, null); + return new BufferedImage(cm, r, false, null); + } + + private BufferedImage createSGISurface(int w, int h, int pixelBits) { + int rMask32 = 0xFF000000; + int rMask16 = 0xF800; + int gMask32 = 0x00FF0000; + int gMask16 = 0x07C0; + int bMask32 = 0x0000FF00; + int bMask16 = 0x003E; + + DirectColorModel dcm = null; + DataBuffer db = null; + WritableRaster wr = null; + switch (pixelBits) { + case 16: + short[] imageDataUShort = new short[w * h]; + dcm = new DirectColorModel(16, rMask16, gMask16, bMask16); + db = new DataBufferUShort(imageDataUShort, + imageDataUShort.length); + wr = Raster.createPackedRaster(db, w, h, w, + new int[] { rMask16, gMask16, bMask16 }, + null); + break; + case 32: + int[] imageDataInt = new int[w * h]; + dcm = new DirectColorModel(32, rMask32, gMask32, bMask32); + db = new DataBufferInt(imageDataInt, imageDataInt.length); + wr = Raster.createPackedRaster(db, w, h, w, + new int[] { rMask32, gMask32, bMask32 }, + null); + break; + default: + Logger.getLogger(Surface.class.getName()).log(Level.SEVERE, + null, new Exception("Invalid # of bit per pixel")); + } + + return new BufferedImage(dcm, wr, false, null); + } + + public Graphics2D createGraphics2D(int width, + int height, + BufferedImage bi, + Graphics g) { + + Graphics2D g2 = null; + + if (bi != null) { + g2 = bi.createGraphics(); + } else { + g2 = (Graphics2D) g; + } + + g2.setBackground(getBackground()); + g2.setRenderingHint(KEY_ANTIALIASING, AntiAlias); + g2.setRenderingHint(KEY_RENDERING, Rendering); + + if (clearSurface || clearOnce) { + g2.clearRect(0, 0, width, height); + clearOnce = false; + } + + if (texture != null) { + // set composite to opaque for texture fills + g2.setComposite(AlphaComposite.SrcOver); + g2.setPaint(texture); + g2.fillRect(0, 0, width, height); + } + + if (composite != null) { + g2.setComposite(composite); + } + + return g2; + } + + // ...demos that extend Surface must implement this routine... + public abstract void render(int w, int h, Graphics2D g2); + + /** + * It's possible to turn off double-buffering for just the repaint + * calls invoked directly on the non double buffered component. + * This can be done by overriding paintImmediately() (which is called + * as a result of repaint) and getting the current RepaintManager and + * turning off double buffering in the RepaintManager before calling + * super.paintImmediately(g). + */ + @Override + public void paintImmediately(int x, int y, int w, int h) { + RepaintManager repaintManager = null; + boolean save = true; + if (!isDoubleBuffered()) { + repaintManager = RepaintManager.currentManager(this); + save = repaintManager.isDoubleBufferingEnabled(); + repaintManager.setDoubleBufferingEnabled(false); + } + super.paintImmediately(x, y, w, h); + + if (repaintManager != null) { + repaintManager.setDoubleBufferingEnabled(save); + } + } + + @Override + public void paint(Graphics g) { + + super.paint(g); + + Dimension d = getSize(); + + if (biw != d.width || bih != d.height) { + toBeInitialized = true; + biw = d.width; + bih = d.height; + } + + if (imageType == 1) { + bimg = null; + } else if (bimg == null || toBeInitialized) { + bimg = createBufferedImage((Graphics2D) g, + d.width, d.height, imageType - 2); + clearOnce = true; + } + + if (toBeInitialized) { + if (animating != null) { + animating.reset(d.width, d.height); + } + toBeInitialized = false; + startClock(); + } + + if (animating != null && animating.running()) { + animating.step(d.width, d.height); + } + Graphics2D g2 = createGraphics2D(d.width, d.height, bimg, g); + render(d.width, d.height, g2); + g2.dispose(); + + if (bimg != null) { + g.drawImage(bimg, 0, 0, null); + toolkit.sync(); + } + + if (perfMonitor) { + LogPerformance(); + } + } + + @Override + public int print(Graphics g, PageFormat pf, int pi) throws PrinterException { + if (pi >= 1) { + return Printable.NO_SUCH_PAGE; + } + + Graphics2D g2d = (Graphics2D) g; + g2d.translate(pf.getImageableX(), pf.getImageableY()); + g2d.translate(pf.getImageableWidth() / 2, + pf.getImageableHeight() / 2); + + Dimension d = getSize(); + + double scale = Math.min(pf.getImageableWidth() / d.width, + pf.getImageableHeight() / d.height); + if (scale < 1.0) { + g2d.scale(scale, scale); + } + + g2d.translate(-d.width / 2.0, -d.height / 2.0); + + if (bimg == null) { + Graphics2D g2 = createGraphics2D(d.width, d.height, null, g2d); + render(d.width, d.height, g2); + g2.dispose(); + } else { + g2d.drawImage(bimg, 0, 0, this); + } + + return Printable.PAGE_EXISTS; + } + + public void startClock() { + orig = System.currentTimeMillis(); + start = orig; + frame = 0; + } + private static final int REPORTFRAMES = 30; + + private void LogPerformance() { + if ((frame % REPORTFRAMES) == 0) { + long end = System.currentTimeMillis(); + long rel = (end - start); + if (frame == 0) { + perfStr = name + " " + rel + " ms"; + if (animating == null || !animating.running()) { + frame = -1; + } + } else { + String s1 = Float.toString((REPORTFRAMES / (rel / 1000.0f))); + s1 = (s1.length() < 4) ? s1.substring(0, s1.length()) : s1. + substring(0, 4); + perfStr = name + " " + s1 + " fps"; + } + if (outputPerf) { + System.out.println(perfStr); + } + start = end; + } + ++frame; + } + + // System.out graphics state information. + public void verbose(GlobalControls controls) { + String str = " " + name + " "; + if (animating != null && animating.running()) { + str = str.concat(" Running"); + } else if (this instanceof AnimatingSurface) { + str = str.concat(" Stopped"); + } + + if (controls != null) { + str = str.concat(" " + controls.screenCombo.getSelectedItem()); + } + + str.concat((AntiAlias == VALUE_ANTIALIAS_ON) ? " ANTIALIAS_ON " + : " ANTIALIAS_OFF "); + str.concat((Rendering == VALUE_RENDER_QUALITY) ? "RENDER_QUALITY " + : "RENDER_SPEED "); + + if (texture != null) { + str = str.concat("Texture "); + } + + if (composite != null) { + str = str.concat("Composite=" + composite.getAlpha() + " "); + } + + Runtime r = Runtime.getRuntime(); + r.gc(); + float freeMemory = r.freeMemory(); + float totalMemory = r.totalMemory(); + str = str.concat(((totalMemory - freeMemory) / 1024) + "K used"); + System.out.println(str); + } + + public static void createDemoFrame(Surface surface) { + final DemoPanel dp = new DemoPanel(surface, new DemoInstVarsAccessorImplBase()); + Frame f = new Frame("J2D Demo - " + surface.name); + f.addWindowListener(new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + System.exit(0); + } + + @Override + public void windowDeiconified(WindowEvent e) { + dp.start(); + } + + @Override + public void windowIconified(WindowEvent e) { + dp.stop(); + } + }); + f.add("Center", dp); + f.pack(); + f.setSize(new Dimension(500, 300)); + f.setVisible(true); + if (surface.animating != null) { + surface.animating.start(); + } + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/TextureChooser.java b/src/demo/share/jfc/J2Ddemo/java2d/TextureChooser.java new file mode 100644 index 00000000000..0247a576a7f --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/TextureChooser.java @@ -0,0 +1,241 @@ +/* + * + * Copyright (c) 2007, 2011, 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.GRAY; +import static java.awt.Color.GREEN; +import static java.awt.Color.LIGHT_GRAY; +import static java.awt.Color.WHITE; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.TexturePaint; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; +import java.awt.geom.Ellipse2D; +import java.awt.image.BufferedImage; +import javax.swing.JPanel; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; + + +/** + * Four types of Paint displayed: Geometry, Text & Image Textures and + * a Gradient Paint. Paints can be selected with the Mouse. + */ +@SuppressWarnings("serial") +public final class TextureChooser extends JPanel { + private final DemoInstVarsAccessor demoInstVars; + public Object texture = getGeomTexture(); + public int num; + + public TextureChooser(int num, DemoInstVarsAccessor demoInstVars) { + this.num = num; + this.demoInstVars = demoInstVars; + + setLayout(new GridLayout(0, 2, 5, 5)); + setBorder(new TitledBorder(new EtchedBorder(), "Texture Chooser")); + + add(new Surface(getGeomTexture(), this, 0)); + add(new Surface(getImageTexture(), this, 1)); + add(new Surface(getTextTexture(), this, 2)); + add(new Surface(getGradientPaint(), this, 3)); + } + + public static TexturePaint getGeomTexture() { + BufferedImage bi = new BufferedImage(5, 5, BufferedImage.TYPE_INT_RGB); + Graphics2D tG2 = bi.createGraphics(); + tG2.setBackground(WHITE); + tG2.clearRect(0, 0, 5, 5); + tG2.setColor(new Color(211, 211, 211, 200)); + tG2.fill(new Ellipse2D.Float(0, 0, 5, 5)); + Rectangle r = new Rectangle(0, 0, 5, 5); + return new TexturePaint(bi, r); + } + + public TexturePaint getImageTexture() { + Image img = DemoImages.getImage("globe.png", this); + int sw = img.getWidth(this); + int sh = img.getHeight(this); + int iw = sw/5; + int ih = sh/5; + BufferedImage bi = + new BufferedImage(iw, ih, BufferedImage.TYPE_INT_ARGB); + Graphics2D tG2 = bi.createGraphics(); + tG2.drawImage(img, 0, 0, iw, ih, 0, 0, sw, sh, this); + Rectangle r = new Rectangle(0, 0, iw, ih); + return new TexturePaint(bi, r); + } + + public TexturePaint getTextTexture() { + Font f = new Font(Font.SERIF, Font.BOLD, 10); + TextLayout tl = new TextLayout("OpenJDK", f, new FontRenderContext(null, + false, false)); + int sw = (int) tl.getBounds().getWidth(); + int sh = (int) (tl.getAscent() + tl.getDescent()); + BufferedImage bi = new BufferedImage(sw, sh, BufferedImage.TYPE_INT_RGB); + Graphics2D tG2 = bi.createGraphics(); + tG2.setBackground(WHITE); + tG2.clearRect(0, 0, sw, sh); + tG2.setColor(LIGHT_GRAY); + tl.draw(tG2, 0, tl.getAscent()); + Rectangle r = new Rectangle(0, 0, sw, sh); + return new TexturePaint(bi, r); + } + + public GradientPaint getGradientPaint() { + return new GradientPaint(0, 0, WHITE, 80, 0, GREEN); + } + + + public class Surface extends JPanel { + + public boolean clickedFrame; + private int num; + private TextureChooser tc; + private boolean enterExitFrame = false; + private Object t; + + public Surface(final Object t, final TextureChooser tc, int num) { + setBackground(WHITE); + this.t = t; + this.tc = tc; + this.clickedFrame = (num == tc.num); + this.num = num; + if (num == tc.num) { + tc.texture = t; + } + addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + tc.texture = t; + clickedFrame = true; + + for (Component comp : tc.getComponents()) { + if (comp instanceof Surface) { + Surface surf = (Surface) comp; + if (!surf.equals(Surface.this) && surf.clickedFrame) { + surf.clickedFrame = false; + surf.repaint(); + } + } + } + + // ABP + if (demoInstVars.getControls().textureCB.isSelected()) { + demoInstVars.getControls().textureCB.doClick(); + demoInstVars.getControls().textureCB.doClick(); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + enterExitFrame = true; + repaint(); + } + + @Override + public void mouseExited(MouseEvent e) { + enterExitFrame = false; + repaint(); + } + }); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2 = (Graphics2D) g; + int w = getSize().width; + int h = getSize().height; + if (t instanceof TexturePaint) { + g2.setPaint((TexturePaint) t); + } else { + g2.setPaint((GradientPaint) t); + } + g2.fill(new Rectangle(0, 0, w, h)); + if (clickedFrame || enterExitFrame) { + g2.setColor(GRAY); + BasicStroke bs = new BasicStroke(3, BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER); + g2.setStroke(bs); + g2.drawRect(0, 0, w - 1, h - 1); + tc.num = num; + } + } + + @Override + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + @Override + public Dimension getMaximumSize() { + return getPreferredSize(); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(30, 30); + } + } + + public static void main(String s[]) { + Frame f = new Frame("J2D Demo - TextureChooser"); + f.addWindowListener(new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + f.add("Center", new TextureChooser(0, new DemoInstVarsAccessorImplBase())); + f.pack(); + f.setSize(new Dimension(400, 400)); + f.setVisible(true); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/Tools.java b/src/demo/share/jfc/J2Ddemo/java2d/Tools.java new file mode 100644 index 00000000000..8f4dff776e5 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/Tools.java @@ -0,0 +1,496 @@ +/* + * + * Copyright (c) 2007, 2011, 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.GREEN; +import static java.awt.Color.LIGHT_GRAY; +import static java.awt.Color.WHITE; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Insets; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.print.PrinterJob; +import java.text.DecimalFormat; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; +import javax.swing.SwingConstants; +import javax.swing.border.EtchedBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + + +/** + * Tools to control individual demo graphic attributes. Also, control for + * start & stop on animated demos; control for cloning the demo; control for + * printing the demo. Expand and collapse the Tools panel with ToggleIcon. + */ +@SuppressWarnings("serial") +public final class Tools extends JPanel implements ActionListener, + ChangeListener, Runnable { + private final DemoInstVarsAccessor demoInstVars; + private ImageIcon stopIcon, startIcon; + private Font font = new Font(Font.SERIF, Font.PLAIN, 10); + private Color roColor = new Color(187, 213, 238); + private Surface surface; + private Thread thread; + private JPanel toolbarPanel; + private JPanel sliderPanel; + private JLabel label; + private ToggleIcon bumpyIcon, rolloverIcon; + private DecimalFormat decimalFormat = new DecimalFormat("000"); + protected boolean focus; + public JToggleButton toggleB; + public JButton printB; + public JComboBox screenCombo; + public JToggleButton renderB, aliasB; + public JToggleButton textureB, compositeB; + public JButton startStopB; + public JButton cloneB; + public boolean issueRepaint = true; + public JToolBar toolbar; + public JSlider slider; + public boolean doSlider; + public boolean isExpanded; + + @SuppressWarnings("LeakingThisInConstructor") + public Tools(Surface surface, DemoInstVarsAccessor demoInstVars) { + this.surface = surface; + this.demoInstVars = demoInstVars; + + setLayout(new BorderLayout()); + + stopIcon = new ImageIcon(DemoImages.getImage("stop.gif", this)); + startIcon = new ImageIcon(DemoImages.getImage("start.gif", this)); + bumpyIcon = new ToggleIcon(this, LIGHT_GRAY); + rolloverIcon = new ToggleIcon(this, roColor); + toggleB = new JToggleButton(bumpyIcon); + toggleB.addMouseListener(new MouseAdapter() { + + @Override + public void mouseEntered(MouseEvent e) { + focus = true; + bumpyIcon.start(); + } + + @Override + public void mouseExited(MouseEvent e) { + focus = false; + bumpyIcon.stop(); + } + }); + isExpanded = false; + toggleB.addActionListener(this); + toggleB.setMargin(new Insets(0, 0, -4, 0)); + toggleB.setBorderPainted(false); + toggleB.setFocusPainted(false); + toggleB.setContentAreaFilled(false); + toggleB.setRolloverIcon(rolloverIcon); + add("North", toggleB); + + toolbar = new JToolBar(); + toolbar.setPreferredSize(new Dimension(5*25, 26)); + toolbar.setFloatable(false); + + String s = surface.AntiAlias == RenderingHints.VALUE_ANTIALIAS_ON + ? "On" : "Off"; + aliasB = addTool("A", "Antialiasing " + s, this); + + s = surface.Rendering == RenderingHints.VALUE_RENDER_SPEED + ? "Speed" : "Quality"; + renderB = addTool("R", "Rendering " + s, this); + + s = surface.texture != null ? "On" : "Off"; + textureB = addTool("T", "Texture " + s, this); + + s = surface.composite != null ? "On" : "Off"; + compositeB = addTool("C", "Composite " + s, this); + + Image printBImg = DemoImages.getImage("print.gif", this); + printB = addTool(printBImg, "Print the Surface", this); + + if (surface instanceof AnimatingSurface) { + Image stopImg = DemoImages.getImage("stop.gif", this); + startStopB = addTool(stopImg, "Stop Animation", this); + toolbar.setPreferredSize(new Dimension(6*25, 26)); + } + + screenCombo = new JComboBox(); + screenCombo.setPreferredSize(new Dimension(100, 18)); + screenCombo.setFont(font); + for (String name : GlobalControls.screenNames) { + screenCombo.addItem(name); + } + screenCombo.addActionListener(this); + toolbarPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0)); + toolbarPanel.setLocation(0, 6); + toolbarPanel.setVisible(false); + toolbarPanel.add(toolbar); + toolbarPanel.add(screenCombo); + toolbarPanel.setBorder(new EtchedBorder()); + add(toolbarPanel); + + setPreferredSize(new Dimension(200, 8)); + + if (surface instanceof AnimatingSurface) { + sliderPanel = new JPanel(new BorderLayout()); + label = new JLabel(" Sleep = 030 ms"); + label.setForeground(BLACK); + sliderPanel.add(label, BorderLayout.WEST); + slider = new JSlider(SwingConstants.HORIZONTAL, 0, 200, 30); + slider.addChangeListener(this); + sliderPanel.setBorder(new EtchedBorder()); + sliderPanel.add(slider); + + addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + if (toolbarPanel.isVisible()) { + invalidate(); + if ((doSlider = !doSlider)) { + remove(toolbarPanel); + add(sliderPanel); + } else { + remove(sliderPanel); + add(toolbarPanel); + } + validate(); + repaint(); + } + } + }); + } + } + + public JButton addTool(Image img, + String toolTip, + ActionListener al) { + JButton b = new JButton(new ImageIcon(img)) { + + Dimension prefSize = new Dimension(25, 22); + + @Override + public Dimension getPreferredSize() { + return prefSize; + } + + @Override + public Dimension getMaximumSize() { + return prefSize; + } + + @Override + public Dimension getMinimumSize() { + return prefSize; + } + }; + toolbar.add(b); + b.setFocusPainted(false); + b.setSelected(true); + b.setToolTipText(toolTip); + b.addActionListener(al); + return b; + } + + public JToggleButton addTool(String name, + String toolTip, + ActionListener al) { + JToggleButton b = new JToggleButton(name) { + + Dimension prefSize = new Dimension(25, 22); + + @Override + public Dimension getPreferredSize() { + return prefSize; + } + + @Override + public Dimension getMaximumSize() { + return prefSize; + } + + @Override + public Dimension getMinimumSize() { + return prefSize; + } + }; + toolbar.add(b); + b.setFocusPainted(false); + if (toolTip.equals("Rendering Quality") || toolTip.equals( + "Antialiasing On") || toolTip.equals("Texture On") || toolTip. + equals("Composite On")) { + b.setSelected(true); + } else { + b.setSelected(false); + } + b.setToolTipText(toolTip); + b.addActionListener(al); + return b; + } + + @Override + public void actionPerformed(ActionEvent e) { + Object obj = e.getSource(); + if (obj instanceof JButton) { + JButton b = (JButton) obj; + b.setSelected(!b.isSelected()); + if (b.getIcon() == null) { + b.setBackground(b.isSelected() ? GREEN : LIGHT_GRAY); + } + } + if (obj.equals(toggleB)) { + isExpanded = !isExpanded; + if (isExpanded) { + setPreferredSize(new Dimension(200, 38)); + } else { + setPreferredSize(new Dimension(200, 6)); + } + toolbarPanel.setVisible(isExpanded); + if (sliderPanel != null) { + sliderPanel.setVisible(isExpanded); + } + getParent().validate(); + toggleB.getModel().setRollover(false); + return; + } + if (obj.equals(printB)) { + start(); + return; + } + + if (obj.equals(startStopB)) { + if (startStopB.getToolTipText().equals("Stop Animation")) { + startStopB.setIcon(startIcon); + startStopB.setToolTipText("Start Animation"); + surface.animating.stop(); + } else { + startStopB.setIcon(stopIcon); + startStopB.setToolTipText("Stop Animation"); + surface.animating.start(); + } + } else if (obj.equals(aliasB)) { + if (aliasB.getToolTipText().equals("Antialiasing On")) { + aliasB.setToolTipText("Antialiasing Off"); + } else { + aliasB.setToolTipText("Antialiasing On"); + } + surface.setAntiAlias(aliasB.isSelected()); + } else if (obj.equals(renderB)) { + if (renderB.getToolTipText().equals("Rendering Quality")) { + renderB.setToolTipText("Rendering Speed"); + } else { + renderB.setToolTipText("Rendering Quality"); + } + surface.setRendering(renderB.isSelected()); + } else if (obj.equals(textureB)) { + if (textureB.getToolTipText().equals("Texture On")) { + textureB.setToolTipText("Texture Off"); + surface.setTexture(null); + surface.clearSurface = true; + } else { + textureB.setToolTipText("Texture On"); + surface.setTexture(demoInstVars.getControls().texturechooser.texture); + } + } else if (obj.equals(compositeB)) { + if (compositeB.getToolTipText().equals("Composite On")) { + compositeB.setToolTipText("Composite Off"); + } else { + compositeB.setToolTipText("Composite On"); + } + surface.setComposite(compositeB.isSelected()); + } else if (obj.equals(screenCombo)) { + surface.setImageType(screenCombo.getSelectedIndex()); + } + + if (issueRepaint && surface.animating != null) { + if (surface.getSleepAmount() != 0) { + if (surface.animating.running()) { + surface.animating.doRepaint(); + } + } + } else if (issueRepaint) { + surface.repaint(); + } + } + + @Override + public void stateChanged(ChangeEvent e) { + int value = slider.getValue(); + label.setText(" Sleep = " + decimalFormat.format(value) + " ms"); + label.repaint(); + surface.setSleepAmount(value); + } + + public void start() { + thread = new Thread(this); + thread.setPriority(Thread.MAX_PRIORITY); + thread.setName("Printing " + surface.name); + thread.start(); + } + + public synchronized void stop() { + thread = null; + notifyAll(); + } + + @Override + public void run() { + boolean stopped = false; + if (surface.animating != null && surface.animating.running()) { + stopped = true; + startStopB.doClick(); + } + + try { + PrinterJob printJob = PrinterJob.getPrinterJob(); + printJob.setPrintable(surface); + boolean pDialogState = true; + PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); + + if (!demoInstVars.getPrintCB().isSelected()) { + pDialogState = printJob.printDialog(aset); + } + if (pDialogState) { + printJob.print(aset); + } + } catch (java.security.AccessControlException ace) { + String errmsg = "Applet access control exception; to allow " + + "access to printer, set\n" + + "permission for \"queuePrintJob\" in " + + "RuntimePermission."; + JOptionPane.showMessageDialog(this, errmsg, "Printer Access Error", + JOptionPane.ERROR_MESSAGE); + } catch (Exception ex) { + Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, + null, ex); + } + + if (stopped) { + startStopB.doClick(); + } + thread = null; + } + + + /** + * Expand and Collapse the Tools Panel with this bumpy button. + */ + static class ToggleIcon implements Icon, Runnable { + + private Color shadowColor = new Color(102, 102, 153); + private Color fillColor; + private Tools tools; + private Thread thread; + + public ToggleIcon(Tools tools, Color fillColor) { + this.tools = tools; + this.fillColor = fillColor; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + int w = getIconWidth(); + int h = getIconHeight(); + g.setColor(fillColor); + g.fillRect(0, 0, w, h); + for (; x < w - 2; x += 4) { + g.setColor(WHITE); + g.fillRect(x, 1, 1, 1); + g.fillRect(x + 2, 3, 1, 1); + g.setColor(shadowColor); + g.fillRect(x + 1, 2, 1, 1); + g.fillRect(x + 3, 4, 1, 1); + } + } + + @Override + public int getIconWidth() { + return tools.getSize().width; + } + + @Override + public int getIconHeight() { + return 6; + } + + public void start() { + thread = new Thread(this); + thread.setPriority(Thread.MIN_PRIORITY); + thread.setName("ToggleIcon"); + thread.start(); + } + + public synchronized void stop() { + if (thread != null) { + thread.interrupt(); + } + thread = null; + } + + @Override + public void run() { + try { + Thread.sleep(400); + } catch (InterruptedException e) { + } + if (tools.focus && thread != null) { + tools.toggleB.doClick(); + } + thread = null; + } + } +} // End Tools class + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/Arcs.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/Arcs.java new file mode 100644 index 00000000000..697496bee10 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/Arcs.java @@ -0,0 +1,165 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Arcs_Curves; + + +import java.awt.*; +import java.awt.geom.Arc2D; +import java.awt.geom.AffineTransform; +import java2d.AnimatingSurface; +import static java.awt.Color.*; + + +/** + * Arc2D Open, Chord & Pie arcs; Animated Pie Arc. + */ +@SuppressWarnings("serial") +public class Arcs extends AnimatingSurface { + + private static String types[] = { "Arc2D.OPEN", "Arc2D.CHORD", "Arc2D.PIE" }; + private static final int CLOSE = 0; + private static final int OPEN = 1; + private static final int FORWARD = 0; + private static final int BACKWARD = 1; + private static final int DOWN = 2; + private static final int UP = 3; + private int aw, ah; // animated arc width & height + private int x, y; + private int angleStart = 45; + private int angleExtent = 270; + private int mouth = CLOSE; + private int direction = FORWARD; + + public Arcs() { + setBackground(WHITE); + } + + @Override + public void reset(int w, int h) { + x = 0; + y = 0; + aw = w / 12; + ah = h / 12; + } + + @Override + public void step(int w, int h) { + // Compute direction + if (x + aw >= w - 5 && direction == FORWARD) { + direction = DOWN; + } + if (y + ah >= h - 5 && direction == DOWN) { + direction = BACKWARD; + } + if (x - aw <= 5 && direction == BACKWARD) { + direction = UP; + } + if (y - ah <= 5 && direction == UP) { + direction = FORWARD; + } + + // compute angle start & extent + if (mouth == CLOSE) { + angleStart -= 5; + angleExtent += 10; + } + if (mouth == OPEN) { + angleStart += 5; + angleExtent -= 10; + } + if (direction == FORWARD) { + x += 5; + y = 0; + } + if (direction == DOWN) { + x = w; + y += 5; + } + if (direction == BACKWARD) { + x -= 5; + y = h; + } + if (direction == UP) { + x = 0; + y -= 5; + } + if (angleStart == 0) { + mouth = OPEN; + } + if (angleStart > 45) { + mouth = CLOSE; + } + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + // Draw Arcs + g2.setStroke(new BasicStroke(5.0f)); + for (int i = 0; i < types.length; i++) { + Arc2D arc = new Arc2D.Float(i); + arc.setFrame((i + 1) * w * .2, (i + 1) * h * .2, w * .17, h * .17); + arc.setAngleStart(45); + arc.setAngleExtent(270); + g2.setColor(BLUE); + g2.draw(arc); + g2.setColor(GRAY); + g2.fill(arc); + g2.setColor(BLACK); + g2.drawString(types[i], (int) ((i + 1) * w * .2), (int) ((i + 1) * h + * .2 - 3)); + } + + // Draw Animated Pie Arc + Arc2D pieArc = new Arc2D.Float(Arc2D.PIE); + pieArc.setFrame(0, 0, aw, ah); + pieArc.setAngleStart(angleStart); + pieArc.setAngleExtent(angleExtent); + AffineTransform at = AffineTransform.getTranslateInstance(x, y); + switch (direction) { + case DOWN: + at.rotate(Math.toRadians(90)); + break; + case BACKWARD: + at.rotate(Math.toRadians(180)); + break; + case UP: + at.rotate(Math.toRadians(270)); + } + g2.setColor(BLUE); + g2.fill(at.createTransformedShape(pieArc)); + } + + public static void main(String argv[]) { + createDemoFrame(new Arcs()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/BezierAnim.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/BezierAnim.java new file mode 100644 index 00000000000..14321f6dae2 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/BezierAnim.java @@ -0,0 +1,339 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Arcs_Curves; + + +import static java.awt.Color.BLUE; +import static java.awt.Color.GRAY; +import static java.awt.Color.GREEN; +import static java.awt.Color.RED; +import static java.awt.Color.WHITE; +import static java.awt.Color.YELLOW; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.TexturePaint; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.geom.GeneralPath; +import java.awt.geom.Path2D; +import java.awt.image.BufferedImage; +import java2d.AnimatingControlsSurface; +import java2d.CustomControls; +import javax.swing.Icon; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; + + +/** + * Animated Bezier Curve with controls for different draw & fill paints. + */ +@SuppressWarnings("serial") +public class BezierAnim extends AnimatingControlsSurface { + + private static final int NUMPTS = 6; + protected BasicStroke solid = new BasicStroke(10.0f, + BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND); + protected BasicStroke dashed = new BasicStroke(10.0f, + BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 10, new float[] { 5 }, + 0); + private float animpts[] = new float[NUMPTS * 2]; + private float deltas[] = new float[NUMPTS * 2]; + protected Paint fillPaint, drawPaint; + protected boolean doFill = true; + protected boolean doDraw = true; + protected GradientPaint gradient; + protected BasicStroke stroke; + + public BezierAnim() { + setBackground(WHITE); + gradient = new GradientPaint(0, 0, RED, 200, 200, YELLOW); + fillPaint = gradient; + drawPaint = BLUE; + stroke = solid; + setControls(new Component[] { new DemoControls(this) }); + } + + public void animate(float[] pts, float[] deltas, int index, int limit) { + float newpt = pts[index] + deltas[index]; + if (newpt <= 0) { + newpt = -newpt; + deltas[index] = (float) (Math.random() * 4.0 + 2.0); + } else if (newpt >= limit) { + newpt = 2.0f * limit - newpt; + deltas[index] = -(float) (Math.random() * 4.0 + 2.0); + } + pts[index] = newpt; + } + + @Override + public void reset(int w, int h) { + for (int i = 0; i < animpts.length; i += 2) { + animpts[i + 0] = (float) (Math.random() * w); + animpts[i + 1] = (float) (Math.random() * h); + deltas[i + 0] = (float) (Math.random() * 6.0 + 4.0); + deltas[i + 1] = (float) (Math.random() * 6.0 + 4.0); + if (animpts[i + 0] > w / 2.0f) { + deltas[i + 0] = -deltas[i + 0]; + } + if (animpts[i + 1] > h / 2.0f) { + deltas[i + 1] = -deltas[i + 1]; + } + } + gradient = new GradientPaint(0, 0, RED, w * .7f, h * .7f, YELLOW); + } + + @Override + public void step(int w, int h) { + for (int i = 0; i < animpts.length; i += 2) { + animate(animpts, deltas, i + 0, w); + animate(animpts, deltas, i + 1, h); + } + } + + @Override + public void render(int w, int h, Graphics2D g2) { + float[] ctrlpts = animpts; + int len = ctrlpts.length; + float prevx = ctrlpts[len - 2]; + float prevy = ctrlpts[len - 1]; + float curx = ctrlpts[0]; + float cury = ctrlpts[1]; + float midx = (curx + prevx) / 2.0f; + float midy = (cury + prevy) / 2.0f; + GeneralPath gp = new GeneralPath(Path2D.WIND_NON_ZERO); + gp.moveTo(midx, midy); + for (int i = 2; i <= ctrlpts.length; i += 2) { + float x1 = (midx + curx) / 2.0f; + float y1 = (midy + cury) / 2.0f; + prevx = curx; + prevy = cury; + if (i < ctrlpts.length) { + curx = ctrlpts[i + 0]; + cury = ctrlpts[i + 1]; + } else { + curx = ctrlpts[0]; + cury = ctrlpts[1]; + } + midx = (curx + prevx) / 2.0f; + midy = (cury + prevy) / 2.0f; + float x2 = (prevx + midx) / 2.0f; + float y2 = (prevy + midy) / 2.0f; + gp.curveTo(x1, y1, x2, y2, midx, midy); + } + gp.closePath(); + if (doDraw) { + g2.setPaint(drawPaint); + g2.setStroke(stroke); + g2.draw(gp); + } + if (doFill) { + if (fillPaint instanceof GradientPaint) { + fillPaint = gradient; + } + g2.setPaint(fillPaint); + g2.fill(gp); + } + } + + public static void main(String argv[]) { + createDemoFrame(new BezierAnim()); + } + + + static class DemoControls extends CustomControls implements ActionListener { + + static final TexturePaint tp1, tp2; + + static { + BufferedImage bi = new BufferedImage(2, 1, + BufferedImage.TYPE_INT_RGB); + bi.setRGB(0, 0, 0xff00ff00); + bi.setRGB(1, 0, 0xffff0000); + tp1 = new TexturePaint(bi, new Rectangle(0, 0, 2, 1)); + bi = new BufferedImage(2, 1, BufferedImage.TYPE_INT_RGB); + bi.setRGB(0, 0, 0xff0000ff); + bi.setRGB(1, 0, 0xffff0000); + tp2 = new TexturePaint(bi, new Rectangle(0, 0, 2, 1)); + } + BezierAnim demo; + static Paint drawPaints[] = { new Color(0, 0, 0, 0), BLUE, new Color(0, + 0, 255, 126), + BLUE, tp2 }; + static String drawName[] = { "No Draw", "Blue", "Blue w/ Alpha", + "Blue Dash", "Texture" }; + static Paint fillPaints[] = { new Color(0, 0, 0, 0), GREEN, new Color(0, + 255, 0, 126), + tp1, new GradientPaint(0, 0, RED, 30, 30, YELLOW) }; + String fillName[] = { "No Fill", "Green", "Green w/ Alpha", "Texture", + "Gradient" }; + JMenu fillMenu, drawMenu; + JMenuItem fillMI[] = new JMenuItem[fillPaints.length]; + JMenuItem drawMI[] = new JMenuItem[drawPaints.length]; + PaintedIcon fillIcons[] = new PaintedIcon[fillPaints.length]; + PaintedIcon drawIcons[] = new PaintedIcon[drawPaints.length]; + Font font = new Font(Font.SERIF, Font.PLAIN, 10); + + @SuppressWarnings("LeakingThisInConstructor") + public DemoControls(BezierAnim demo) { + super(demo.name); + this.demo = demo; + + JMenuBar drawMenuBar = new JMenuBar(); + add(drawMenuBar); + + JMenuBar fillMenuBar = new JMenuBar(); + add(fillMenuBar); + + drawMenu = drawMenuBar.add(new JMenu("Draw Choice")); + drawMenu.setFont(font); + + for (int i = 0; i < drawPaints.length; i++) { + drawIcons[i] = new PaintedIcon(drawPaints[i]); + drawMI[i] = drawMenu.add(new JMenuItem(drawName[i])); + drawMI[i].setFont(font); + drawMI[i].setIcon(drawIcons[i]); + drawMI[i].addActionListener(this); + } + drawMenu.setIcon(drawIcons[1]); + + fillMenu = fillMenuBar.add(new JMenu("Fill Choice")); + fillMenu.setFont(font); + for (int i = 0; i < fillPaints.length; i++) { + fillIcons[i] = new PaintedIcon(fillPaints[i]); + fillMI[i] = fillMenu.add(new JMenuItem(fillName[i])); + fillMI[i].setFont(font); + fillMI[i].setIcon(fillIcons[i]); + fillMI[i].addActionListener(this); + } + fillMenu.setIcon(fillIcons[fillPaints.length - 1]); + } + + @Override + public void actionPerformed(ActionEvent e) { + Object obj = e.getSource(); + for (int i = 0; i < fillPaints.length; i++) { + if (obj.equals(fillMI[i])) { + demo.doFill = true; + demo.fillPaint = fillPaints[i]; + fillMenu.setIcon(fillIcons[i]); + break; + } + } + for (int i = 0; i < drawPaints.length; i++) { + if (obj.equals(drawMI[i])) { + demo.doDraw = true; + demo.drawPaint = drawPaints[i]; + if (((JMenuItem) obj).getText().endsWith("Dash")) { + demo.stroke = demo.dashed; + } else { + demo.stroke = demo.solid; + } + drawMenu.setIcon(drawIcons[i]); + break; + } + } + if (obj.equals(fillMI[0])) { + demo.doFill = false; + } else if (obj.equals(drawMI[0])) { + demo.doDraw = false; + } + if (!demo.animating.running()) { + demo.repaint(); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 36); + } + + @Override + @SuppressWarnings("SleepWhileHoldingLock") + public void run() { + Thread me = Thread.currentThread(); + while (thread == me) { + for (JMenuItem dmi : drawMI) { + dmi.doClick(); + for (JMenuItem fmi : fillMI) { + fmi.doClick(); + try { + Thread.sleep(3000 + (long) (Math.random() * 3000)); + } catch (InterruptedException e) { + break; + } + } + } + } + thread = null; + } + + + static class PaintedIcon implements Icon { + + Paint paint; + + public PaintedIcon(Paint p) { + this.paint = p; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + Graphics2D g2 = (Graphics2D) g; + g2.setPaint(paint); + g2.fillRect(x, y, getIconWidth(), getIconHeight()); + g2.setColor(GRAY); + g2.draw3DRect(x, y, getIconWidth() - 1, getIconHeight() - 1, + true); + } + + @Override + public int getIconWidth() { + return 12; + } + + @Override + public int getIconHeight() { + return 12; + } + } // End PaintedIcon class + } // End DemoControls class +} // End BezierAnim class + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/Curves.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/Curves.java new file mode 100644 index 00000000000..f5d486c5d8f --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/Curves.java @@ -0,0 +1,142 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Arcs_Curves; + + +import java.awt.*; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.QuadCurve2D; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.PathIterator; +import java.awt.geom.FlatteningPathIterator; +import java.awt.font.TextLayout; +import java.awt.font.FontRenderContext; +import java2d.Surface; +import static java.awt.Color.*; +import static java.awt.geom.PathIterator.*; + + +/** + * CubicCurve2D & QuadCurve2D curves includes FlattenPathIterator example. + */ +@SuppressWarnings("serial") +public class Curves extends Surface { + + private static Color colors[] = { BLUE, GREEN, RED }; + + public Curves() { + setBackground(WHITE); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + g2.setColor(BLACK); + FontRenderContext frc = g2.getFontRenderContext(); + TextLayout tl = new TextLayout("QuadCurve2D", g2.getFont(), frc); + float xx = (float) (w * .5 - tl.getBounds().getWidth() / 2); + tl.draw(g2, xx, tl.getAscent()); + + tl = new TextLayout("CubicCurve2D", g2.getFont(), frc); + xx = (float) (w * .5 - tl.getBounds().getWidth() / 2); + tl.draw(g2, xx, h * .5f); + g2.setStroke(new BasicStroke(5.0f)); + + float yy = 20; + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 3; j++) { + Shape shape = null; + + if (i == 0) { + shape = new QuadCurve2D.Float(w * .1f, yy, w * .5f, 50, w + * .9f, yy); + } else { + shape = new CubicCurve2D.Float(w * .1f, yy, w * .4f, yy - 15, + w * .6f, yy + 15, w * .9f, yy); + } + g2.setColor(colors[j]); + if (j != 2) { + g2.draw(shape); + } + + if (j == 1) { + g2.setColor(LIGHT_GRAY); + PathIterator f = shape.getPathIterator(null); + while (!f.isDone()) { + float[] pts = new float[6]; + switch (f.currentSegment(pts)) { + case SEG_MOVETO: + case SEG_LINETO: + g2.fill(new Rectangle2D.Float(pts[0], pts[1], 5, + 5)); + break; + case SEG_CUBICTO: + case SEG_QUADTO: + g2.fill(new Rectangle2D.Float(pts[0], pts[1], 5, + 5)); + if (pts[2] != 0) { + g2.fill(new Rectangle2D.Float(pts[2], pts[3], + 5, 5)); + } + if (pts[4] != 0) { + g2.fill(new Rectangle2D.Float(pts[4], pts[5], + 5, 5)); + } + } + f.next(); + } + } else if (j == 2) { + PathIterator p = shape.getPathIterator(null); + FlatteningPathIterator f = + new FlatteningPathIterator(p, 0.1); + while (!f.isDone()) { + float[] pts = new float[6]; + switch (f.currentSegment(pts)) { + case SEG_MOVETO: + case SEG_LINETO: + g2.fill(new Ellipse2D.Float(pts[0], pts[1], 3, 3)); + } + f.next(); + } + } + yy += h / 6; + } + yy = h / 2 + 15; + } + } + + public static void main(String argv[]) { + createDemoFrame(new Curves()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/Ellipses.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/Ellipses.java new file mode 100644 index 00000000000..3d122a0820b --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Arcs_Curves/Ellipses.java @@ -0,0 +1,108 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Arcs_Curves; + + +import java.awt.*; +import java.awt.geom.Ellipse2D; +import java2d.AnimatingSurface; +import static java.awt.Color.*; + + +/** + * Ellipse2D 25 animated expanding ellipses. + */ +@SuppressWarnings("serial") +public final class Ellipses extends AnimatingSurface { + + private static Color colors[] = { + BLUE, CYAN, GREEN, MAGENTA, ORANGE, PINK, RED, + YELLOW, LIGHT_GRAY, WHITE }; + private Ellipse2D.Float[] ellipses; + private double esize[]; + private float estroke[]; + private double maxSize; + + public Ellipses() { + setBackground(BLACK); + ellipses = new Ellipse2D.Float[25]; + esize = new double[ellipses.length]; + estroke = new float[ellipses.length]; + for (int i = 0; i < ellipses.length; i++) { + ellipses[i] = new Ellipse2D.Float(); + getRandomXY(i, 20 * Math.random(), 200, 200); + } + } + + public void getRandomXY(int i, double size, int w, int h) { + esize[i] = size; + estroke[i] = 1.0f; + double x = Math.random() * (w - (maxSize / 2)); + double y = Math.random() * (h - (maxSize / 2)); + ellipses[i].setFrame(x, y, size, size); + } + + @Override + public void reset(int w, int h) { + maxSize = w / 10; + for (int i = 0; i < ellipses.length; i++) { + getRandomXY(i, maxSize * Math.random(), w, h); + } + } + + @Override + public void step(int w, int h) { + for (int i = 0; i < ellipses.length; i++) { + estroke[i] += 0.025f; + esize[i]++; + if (esize[i] > maxSize) { + getRandomXY(i, 1, w, h); + } else { + ellipses[i].setFrame(ellipses[i].getX(), ellipses[i].getY(), + esize[i], esize[i]); + } + } + } + + @Override + public void render(int w, int h, Graphics2D g2) { + for (int i = 0; i < ellipses.length; i++) { + g2.setColor(colors[i % colors.length]); + g2.setStroke(new BasicStroke(estroke[i])); + g2.draw(ellipses[i]); + } + } + + public static void main(String argv[]) { + createDemoFrame(new Ellipses()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/Areas.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/Areas.java new file mode 100644 index 00000000000..d01f3dfb781 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/Areas.java @@ -0,0 +1,222 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Clipping; + + +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.Area; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import javax.swing.*; +import java2d.ControlsSurface; +import java2d.CustomControls; +import static java.awt.Color.*; + + +/** + * The Areas class demonstrates the CAG (Constructive Area Geometry) + * operations: Add(union), Subtract, Intersect, and ExclusiveOR. + */ +@SuppressWarnings("serial") +public class Areas extends ControlsSurface { + + protected String areaType = "nop"; + + public Areas() { + setBackground(WHITE); + setControls(new Component[] { new DemoControls(this) }); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + GeneralPath p1 = new GeneralPath(); + p1.moveTo(w * .25f, 0.0f); + p1.lineTo(w * .75f, h * .5f); + p1.lineTo(w * .25f, h); + p1.lineTo(0.0f, h * .5f); + p1.closePath(); + + GeneralPath p2 = new GeneralPath(); + p2.moveTo(w * .75f, 0.0f); + p2.lineTo(w, h * .5f); + p2.lineTo(w * .75f, h); + p2.lineTo(w * .25f, h * .5f); + p2.closePath(); + + + Area area = new Area(p1); + g2.setColor(YELLOW); + if (areaType.equals("nop")) { + g2.fill(p1); + g2.fill(p2); + g2.setColor(RED); + g2.draw(p1); + g2.draw(p2); + return; + } else if (areaType.equals("add")) { + area.add(new Area(p2)); + } else if (areaType.equals("sub")) { + area.subtract(new Area(p2)); + } else if (areaType.equals("xor")) { + area.exclusiveOr(new Area(p2)); + } else if (areaType.equals("int")) { + area.intersect(new Area(p2)); + } else if (areaType.equals("pear")) { + + double sx = w / 100; + double sy = h / 140; + g2.scale(sx, sy); + double x = w / sx / 2; + double y = h / sy / 2; + + // Creates the first leaf by filling the intersection of two Area + // objects created from an ellipse. + Ellipse2D leaf = new Ellipse2D.Double(x - 16, y - 29, 15.0, 15.0); + Area leaf1 = new Area(leaf); + leaf.setFrame(x - 14, y - 47, 30.0, 30.0); + Area leaf2 = new Area(leaf); + leaf1.intersect(leaf2); + g2.setColor(GREEN); + g2.fill(leaf1); + + // Creates the second leaf. + leaf.setFrame(x + 1, y - 29, 15.0, 15.0); + leaf1 = new Area(leaf); + leaf2.intersect(leaf1); + g2.fill(leaf2); + + // Creates the stem by filling the Area resulting from the + // subtraction of two Area objects created from an ellipse. + Ellipse2D stem = new Ellipse2D.Double(x, y - 42, 40.0, 40.0); + Area st1 = new Area(stem); + stem.setFrame(x + 3, y - 47, 50.0, 50.0); + st1.subtract(new Area(stem)); + g2.setColor(BLACK); + g2.fill(st1); + + // Creates the pear itself by filling the Area resulting from the + // union of two Area objects created by two different ellipses. + Ellipse2D circle = new Ellipse2D.Double(x - 25, y, 50.0, 50.0); + Ellipse2D oval = new Ellipse2D.Double(x - 19, y - 20, 40.0, 70.0); + Area circ = new Area(circle); + circ.add(new Area(oval)); + + g2.setColor(YELLOW); + g2.fill(circ); + return; + } + + g2.fill(area); + g2.setColor(RED); + g2.draw(area); + } + + public static void main(String argv[]) { + createDemoFrame(new Areas()); + } + + + static final class DemoControls extends CustomControls implements + ActionListener { + + Areas demo; + JToolBar toolbar; + JComboBox combo; + + public DemoControls(Areas demo) { + super(demo.name); + this.demo = demo; + add(toolbar = new JToolBar()); + toolbar.setFloatable(false); + addTool("nop", "no area operation", true); + addTool("add", "add", false); + addTool("sub", "subtract", false); + addTool("xor", "exclusiveOr", false); + addTool("int", "intersection", false); + addTool("pear", "pear", false); + } + + public void addTool(String str, String tooltip, boolean state) { + JToggleButton b = + (JToggleButton) toolbar.add(new JToggleButton(str)); + b.setFocusPainted(false); + b.setToolTipText(tooltip); + b.setSelected(state); + b.addActionListener(this); + int width = b.getPreferredSize().width; + Dimension prefSize = new Dimension(width, 21); + b.setPreferredSize(prefSize); + b.setMaximumSize(prefSize); + b.setMinimumSize(prefSize); + } + + @Override + public void actionPerformed(ActionEvent e) { + for (Component comp : toolbar.getComponents()) { + ((JToggleButton) comp).setSelected(false); + } + JToggleButton b = (JToggleButton) e.getSource(); + b.setSelected(true); + demo.areaType = b.getText(); + demo.repaint(); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 40); + } + + @Override + @SuppressWarnings("SleepWhileHoldingLock") + public void run() { + try { + Thread.sleep(1111); + } catch (Exception e) { + return; + } + Thread me = Thread.currentThread(); + while (thread == me) { + for (Component comp : toolbar.getComponents()) { + ((AbstractButton) comp).doClick(); + try { + Thread.sleep(4444); + } catch (InterruptedException e) { + return; + } + } + } + thread = null; + } + } // End DemoControls +} // End Areas + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/ClipAnim.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/ClipAnim.java new file mode 100644 index 00000000000..1a9f43d53d0 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/ClipAnim.java @@ -0,0 +1,302 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Clipping; + + +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.*; +import java.awt.image.BufferedImage; +import javax.swing.*; +import java2d.AnimatingControlsSurface; +import java2d.CustomControls; +import static java.lang.Math.random; +import static java.awt.Color.*; + + +/** + * Animated clipping of an image & composited shapes. + */ +@SuppressWarnings("serial") +public class ClipAnim extends AnimatingControlsSurface { + + private static Image dimg, cimg; + static TexturePaint texturePaint; + + static { + BufferedImage bi = new BufferedImage(5, 5, BufferedImage.TYPE_INT_RGB); + Graphics2D big = bi.createGraphics(); + big.setBackground(YELLOW); + big.clearRect(0, 0, 5, 5); + big.setColor(RED); + big.fillRect(0, 0, 3, 3); + texturePaint = new TexturePaint(bi, new Rectangle(0, 0, 5, 5)); + } + private AnimVal animval[] = new AnimVal[3]; + protected boolean doObjects = true; + private Font originalFont = new Font(Font.SERIF, Font.PLAIN, 12); + private Font font; + private GradientPaint gradient; + private int strX, strY; + private int dukeX, dukeY, dukeWidth, dukeHeight; + + public ClipAnim() { + cimg = getImage("clouds.jpg"); + dimg = getImage("duke.png"); + setBackground(WHITE); + animval[0] = new AnimVal(true); + animval[1] = new AnimVal(false); + animval[2] = new AnimVal(false); + setControls(new Component[] { new DemoControls(this) }); + } + + @Override + public void reset(int w, int h) { + for (AnimVal a : animval) { + a.reset(w, h); + } + gradient = new GradientPaint(0, h / 2, RED, w * .4f, h * .9f, YELLOW); + double scale = 0.4; + dukeHeight = (int) (scale * h); + dukeWidth = (int) (dimg.getWidth(this) * scale * h / dimg.getHeight(this)); + dukeX = (int) (w * .25 - dukeWidth / 2); + dukeY = (int) (h * .25 - dukeHeight / 2); + FontMetrics fm = getFontMetrics(originalFont); + double sw = fm.stringWidth("CLIPPING"); + double sh = fm.getAscent() + fm.getDescent(); + double sx = (w / 2 - 30) / sw; + double sy = (h / 2 - 30) / sh; + AffineTransform Tx = AffineTransform.getScaleInstance(sx, sy); + font = originalFont.deriveFont(Tx); + fm = getFontMetrics(font); + strX = (int) (w * .75 - fm.stringWidth("CLIPPING") / 2); + strY = (int) (h * .72 + fm.getAscent() / 2); + } + + @Override + public void step(int w, int h) { + for (AnimVal a : animval) { + if (a.isSelected) { + a.step(w, h); + } + } + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + GeneralPath p1 = new GeneralPath(); + GeneralPath p2 = new GeneralPath(); + + for (AnimVal a : animval) { + if (a.isSelected) { + double x = a.x; + double y = a.y; + double ew = a.ew; + double eh = a.eh; + p1.append(new Ellipse2D.Double(x, y, ew, eh), false); + p2.append(new Rectangle2D.Double(x + 5, y + 5, ew - 10, eh - 10), + false); + } + } + if (animval[0].isSelected || animval[1].isSelected + || animval[2].isSelected) { + g2.setClip(p1); + g2.clip(p2); + } + + if (doObjects) { + int w2 = w / 2; + int h2 = h / 2; + g2.drawImage(cimg, 0, 0, w2, h2, null); + g2.drawImage(dimg, dukeX, dukeY, dukeWidth, dukeHeight, null); + + g2.setPaint(texturePaint); + g2.fillRect(w2, 0, w2, h2); + + g2.setPaint(gradient); + g2.fillRect(0, h2, w2, h2); + + g2.setColor(LIGHT_GRAY); + g2.fillRect(w2, h2, w2, h2); + g2.setColor(RED); + g2.drawOval(w2, h2, w2 - 1, h2 - 1); + g2.setFont(font); + g2.drawString("CLIPPING", strX, strY); + } else { + g2.setColor(LIGHT_GRAY); + g2.fillRect(0, 0, w, h); + } + } + + public static void main(String argv[]) { + createDemoFrame(new ClipAnim()); + } + + + public class AnimVal { + + double ix = 5.0; + double iy = 3.0; + double iw = 5.0; + double ih = 3.0; + double x, y; + double ew, eh; // ellipse width & height + boolean isSelected; + + public AnimVal(boolean isSelected) { + this.isSelected = isSelected; + } + + public void step(int w, int h) { + x += ix; + y += iy; + ew += iw; + eh += ih; + + if (ew > w / 2) { + ew = w / 2; + iw = random() * -w / 16 - 1; + } + if (ew < w / 8) { + ew = w / 8; + iw = random() * w / 16 + 1; + } + if (eh > h / 2) { + eh = h / 2; + ih = random() * -h / 16 - 1; + } + if (eh < h / 8) { + eh = h / 8; + ih = random() * h / 16 + 1; + } + + if ((x + ew) > w) { + x = (w - ew) - 1; + ix = random() * -w / 32 - 1; + } + if ((y + eh) > h) { + y = (h - eh) - 2; + iy = random() * -h / 32 - 1; + } + if (x < 0) { + x = 2; + ix = random() * w / 32 + 1; + } + if (y < 0) { + y = 2; + iy = random() * h / 32 + 1; + } + } + + public void reset(int w, int h) { + x = random() * w; + y = random() * h; + ew = (random() * w) / 2; + eh = (random() * h) / 2; + } + } + + + static final class DemoControls extends CustomControls implements + ActionListener { + + ClipAnim demo; + JToolBar toolbar; + + public DemoControls(ClipAnim demo) { + super(demo.name); + this.demo = demo; + add(toolbar = new JToolBar()); + toolbar.setFloatable(false); + addTool("Objects", true); + addTool("Clip1", true); + addTool("Clip2", false); + addTool("Clip3", false); + } + + public void addTool(String str, boolean state) { + JToggleButton b = + (JToggleButton) toolbar.add(new JToggleButton(str)); + b.setFocusPainted(false); + b.setSelected(state); + b.addActionListener(this); + int width = b.getPreferredSize().width; + Dimension prefSize = new Dimension(width, 21); + b.setPreferredSize(prefSize); + b.setMaximumSize(prefSize); + b.setMinimumSize(prefSize); + } + + @Override + public void actionPerformed(ActionEvent e) { + JToggleButton b = (JToggleButton) e.getSource(); + if (b.getText().equals("Objects")) { + demo.doObjects = b.isSelected(); + } else if (b.getText().equals("Clip1")) { + demo.animval[0].isSelected = b.isSelected(); + } else if (b.getText().equals("Clip2")) { + demo.animval[1].isSelected = b.isSelected(); + } else if (b.getText().equals("Clip3")) { + demo.animval[2].isSelected = b.isSelected(); + } + if (!demo.animating.running()) { + demo.repaint(); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 40); + } + + @Override + public void run() { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + return; + } + ((AbstractButton) toolbar.getComponentAtIndex(2)).doClick(); + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + return; + } + if (getSize().width > 400) { + ((AbstractButton) toolbar.getComponentAtIndex(3)).doClick(); + } + thread = null; + } + } // End DemoControls +} // End ClipAnim + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/Intersection.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/Intersection.java new file mode 100644 index 00000000000..936c8fbfbb1 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/Intersection.java @@ -0,0 +1,245 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Clipping; + + +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.*; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; +import javax.swing.*; +import java2d.AnimatingControlsSurface; +import java2d.CustomControls; +import static java.awt.Color.*; + + +/** + * Animated intersection clipping of lines, an image and a textured rectangle. + */ +@SuppressWarnings("serial") +public class Intersection extends AnimatingControlsSurface { + + private static final int HEIGHT_DECREASE = 0; + private static final int HEIGHT_INCREASE = 1; + private static final int WIDTH_DECREASE = 2; + private static final int WIDTH_INCREASE = 3; + + private int xx, yy, ww, hh; + private int direction = HEIGHT_DECREASE; + private int angdeg; + private Shape textshape; + private double sw, sh; + private GeneralPath ovals; + private Rectangle2D rectshape; + protected boolean doIntersection = true; + protected boolean doOvals = true; + protected boolean doText; + protected boolean threeSixty; + + + public Intersection() { + setBackground(WHITE); + setControls(new Component[] { new DemoControls(this) }); + } + + + @Override + public void reset(int w, int h) { + xx = yy = 0; + ww = w-1; hh = h; + direction = HEIGHT_DECREASE; + angdeg = 0; + FontRenderContext frc = new FontRenderContext(null, true, false); + Font f = new Font(Font.SERIF, Font.BOLD,32); + TextLayout tl = new TextLayout("J2D", f, frc); + sw = tl.getBounds().getWidth(); + sh = tl.getBounds().getHeight(); + int size = Math.min(w, h); + double sx = (size-40)/sw; + double sy = (size-100)/sh; + AffineTransform Tx = AffineTransform.getScaleInstance(sx, sy); + textshape = tl.getOutline(Tx); + rectshape = textshape.getBounds(); + sw = rectshape.getWidth(); + sh = rectshape.getHeight(); + ovals = new GeneralPath(); + ovals.append(new Ellipse2D.Double( 10, 10, 20, 20), false); + ovals.append(new Ellipse2D.Double(w-30, 10, 20, 20), false); + ovals.append(new Ellipse2D.Double( 10, h-30, 20, 20), false); + ovals.append(new Ellipse2D.Double(w-30, h-30, 20, 20), false); + } + + + @Override + public void step(int w, int h) { + if (direction == HEIGHT_DECREASE) { + yy+=2; hh-=4; + if (yy >= h/2) { + direction = HEIGHT_INCREASE; + } + } else if (direction == HEIGHT_INCREASE) { + yy-=2; hh+=4; + if (yy <= 0) { + direction = WIDTH_DECREASE; + hh = h-1; yy = 0; + } + } + if (direction == WIDTH_DECREASE) { + xx+=2; ww-=4; + if (xx >= w/2) { + direction = WIDTH_INCREASE; + } + } else if (direction == WIDTH_INCREASE) { + xx-=2; ww+=4; + if (xx <= 0) { + direction = HEIGHT_DECREASE; + ww = w-1; xx = 0; + } + } + if ((angdeg += 5) == 360) { + angdeg = 0; + threeSixty = true; + } + } + + + @Override + public void render(int w, int h, Graphics2D g2) { + + Rectangle rect = new Rectangle(xx, yy, ww, hh); + + AffineTransform Tx = new AffineTransform(); + Tx.rotate(Math.toRadians(angdeg),w/2,h/2); + Tx.translate(w/2-sw/2, sh+(h-sh)/2); + + GeneralPath path = new GeneralPath(); + if (doOvals) { + path.append(ovals, false); + } + if (doText) { + path.append(Tx.createTransformedShape(textshape), false); + } else { + path.append(Tx.createTransformedShape(rectshape), false); + } + + if (doIntersection) { + g2.clip(rect); + g2.clip(path); + } + + g2.setColor(GREEN); + g2.fill(rect); + + g2.setClip(new Rectangle(0, 0, w, h)); + + g2.setColor(LIGHT_GRAY); + g2.draw(rect); + g2.setColor(BLACK); + g2.draw(path); + } + + + public static void main(String argv[]) { + createDemoFrame(new Intersection()); + } + + + static final class DemoControls extends CustomControls implements ActionListener { + + Intersection demo; + JToolBar toolbar; + + public DemoControls(Intersection demo) { + super(demo.name); + this.demo = demo; + add(toolbar = new JToolBar()); + toolbar.setFloatable(false); + addTool("Intersect", true ); + addTool("Text", false); + addTool("Ovals", true ); + } + + + public void addTool(String str, boolean state) { + JToggleButton b = (JToggleButton) toolbar.add(new JToggleButton(str)); + b.setFocusPainted(false); + b.setSelected(state); + b.addActionListener(this); + int width = b.getPreferredSize().width; + Dimension prefSize = new Dimension(width, 21); + b.setPreferredSize(prefSize); + b.setMaximumSize( prefSize); + b.setMinimumSize( prefSize); + } + + + @Override + public void actionPerformed(ActionEvent e) { + JToggleButton b = (JToggleButton) e.getSource(); + if (b.getText().equals("Intersect")) { + demo.doIntersection = b.isSelected(); + } else if (b.getText().equals("Ovals")) { + demo.doOvals = b.isSelected(); + } else if (b.getText().equals("Text")) { + demo.doText = b.isSelected(); + } + if (!demo.animating.running()) { + demo.repaint(); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200,40); + } + + + @Override + @SuppressWarnings("SleepWhileHoldingLock") + public void run() { + Thread me = Thread.currentThread(); + while (thread == me) { + if (demo.threeSixty) { + ((AbstractButton) toolbar.getComponentAtIndex(1)).doClick(); + demo.threeSixty = false; + } + try { + Thread.sleep(500); + } catch (InterruptedException e) { return; } + } + thread = null; + } + } // End DemoControls +} // End Intersection diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/Text.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/Text.java new file mode 100644 index 00000000000..441b914fb49 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Clipping/Text.java @@ -0,0 +1,246 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Clipping; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.BLUE; +import static java.awt.Color.CYAN; +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.BasicStroke; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.TexturePaint; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.awt.geom.Line2D; +import java.awt.image.BufferedImage; +import java2d.ControlsSurface; +import java2d.CustomControls; +import javax.swing.AbstractButton; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; + + +/** + * Clipping an image, lines, text, texture and gradient with text. + */ +@SuppressWarnings("serial") +public class Text extends ControlsSurface { + + /** + * + */ + static Image img; + static TexturePaint texturePaint; + + static { + BufferedImage bi = new BufferedImage(5, 5, BufferedImage.TYPE_INT_RGB); + Graphics2D big = bi.createGraphics(); + big.setBackground(YELLOW); + big.clearRect(0, 0, 5, 5); + big.setColor(RED); + big.fillRect(0, 0, 3, 3); + texturePaint = new TexturePaint(bi, new Rectangle(0, 0, 5, 5)); + } + private String clipType = "Lines"; + protected boolean doClip = true; + + public Text() { + setBackground(WHITE); + img = getImage("clouds.jpg"); + setControls(new Component[] { new DemoControls(this) }); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + FontRenderContext frc = g2.getFontRenderContext(); + Font f = new Font(Font.SANS_SERIF, Font.BOLD, 32); + String s = "JDK"; + TextLayout tl = new TextLayout(s, f, frc); + double sw = tl.getBounds().getWidth(); + double sh = tl.getBounds().getHeight(); + double sx = (w - 40) / sw; + double sy = (h - 40) / sh; + AffineTransform Tx = AffineTransform.getScaleInstance(sx, sy); + Shape shape = tl.getOutline(Tx); + sw = shape.getBounds().getWidth(); + sh = shape.getBounds().getHeight(); + Tx = + AffineTransform.getTranslateInstance(w / 2 - sw / 2, h / 2 + sh + / 2); + shape = Tx.createTransformedShape(shape); + Rectangle r = shape.getBounds(); + + if (doClip) { + g2.clip(shape); + } + + if (clipType.equals("Lines")) { + g2.setColor(BLACK); + g2.fill(r); + g2.setColor(YELLOW); + g2.setStroke(new BasicStroke(1.5f)); + for (int j = r.y; j < r.y + r.height; j = j + 3) { + Line2D line = new Line2D.Float(r.x, j, + (r.x + r.width), j); + g2.draw(line); + } + } else if (clipType.equals("Image")) { + g2.drawImage(img, r.x, r.y, r.width, r.height, null); + } else if (clipType.equals("TP")) { + g2.setPaint(texturePaint); + g2.fill(r); + } else if (clipType.equals("GP")) { + g2.setPaint(new GradientPaint(0, 0, BLUE, w, h, YELLOW)); + g2.fill(r); + } else if (clipType.equals("Text")) { + g2.setColor(BLACK); + g2.fill(shape.getBounds()); + g2.setColor(CYAN); + f = new Font(Font.SERIF, Font.BOLD, 10); + tl = new TextLayout("OpenJDK", f, frc); + sw = tl.getBounds().getWidth(); + + int x = r.x; + int y = (int) (r.y + tl.getAscent()); + sh = r.y + r.height; + while (y < sh) { + tl.draw(g2, x, y); + if ((x += (int) sw) > (r.x + r.width)) { + x = r.x; + y += (int) tl.getAscent(); + } + } + } + g2.setClip(new Rectangle(0, 0, w, h)); + + g2.setColor(GRAY); + g2.draw(shape); + } + + public static void main(String s[]) { + createDemoFrame(new Text()); + } + + + @SuppressWarnings("serial") + static final class DemoControls extends CustomControls implements + ActionListener { + + Text demo; + JToolBar toolbar; + + public DemoControls(Text demo) { + super(demo.name); + this.demo = demo; + add(toolbar = new JToolBar()); + toolbar.setFloatable(false); + addTool("Clip", true); + addTool("Lines", true); + addTool("Image", false); + addTool("TP", false); + addTool("GP", false); + addTool("Text", false); + } + + public void addTool(String str, boolean state) { + JToggleButton b = + (JToggleButton) toolbar.add(new JToggleButton(str)); + b.setFocusPainted(false); + b.setSelected(state); + b.addActionListener(this); + int width = b.getPreferredSize().width; + Dimension prefSize = new Dimension(width, 21); + b.setPreferredSize(prefSize); + b.setMaximumSize(prefSize); + b.setMinimumSize(prefSize); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource().equals(toolbar.getComponentAtIndex(0))) { + JToggleButton b = (JToggleButton) e.getSource(); + demo.doClip = b.isSelected(); + } else { + for (Component comp : toolbar.getComponents()) { + ((JToggleButton) comp).setSelected(false); + } + JToggleButton b = (JToggleButton) e.getSource(); + b.setSelected(true); + demo.clipType = b.getText(); + } + demo.repaint(); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 40); + } + + @Override + @SuppressWarnings("SleepWhileHoldingLock") + public void run() { + try { + Thread.sleep(1111); + } catch (Exception e) { + return; + } + Thread me = Thread.currentThread(); + while (thread == me) { + for (int i = 1; i < toolbar.getComponentCount() - 1; i++) { + ((AbstractButton) toolbar.getComponentAtIndex(i)).doClick(); + try { + Thread.sleep(4444); + } catch (InterruptedException e) { + return; + } + } + } + thread = null; + } + } // End DemoControls +} // End Text + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Colors/BullsEye.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Colors/BullsEye.java new file mode 100644 index 00000000000..dcfcb600a7d --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Colors/BullsEye.java @@ -0,0 +1,76 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Colors; + + +import static java.awt.Color.RED; +import static java.awt.Color.WHITE; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.Ellipse2D; +import java2d.Surface; + + +/** + * Creating colors with an alpha value. + */ +@SuppressWarnings("serial") +public class BullsEye extends Surface { + + public BullsEye() { + setBackground(WHITE); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + Color reds[] = { RED.darker(), RED }; + for (int N = 0; N < 18; N++) { + float i = (N + 2) / 2.0f; + float x = (5 + i * (w / 2 / 10)); + float y = (5 + i * (h / 2 / 10)); + float ew = (w - 10) - (i * w / 10); + float eh = (h - 10) - (i * h / 10); + float alpha = (N == 0) ? 0.1f : 1.0f / (19.0f - N); + if (N >= 16) { + g2.setColor(reds[N - 16]); + } else { + g2.setColor(new Color(0f, 0f, 0f, alpha)); + } + g2.fill(new Ellipse2D.Float(x, y, ew, eh)); + } + } + + public static void main(String s[]) { + createDemoFrame(new BullsEye()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Colors/ColorConvert.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Colors/ColorConvert.java new file mode 100644 index 00000000000..5b7575d27e7 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Colors/ColorConvert.java @@ -0,0 +1,129 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Colors; + + +import static java.awt.Color.black; +import static java.awt.Color.blue; +import static java.awt.Color.cyan; +import static java.awt.Color.green; +import static java.awt.Color.magenta; +import static java.awt.Color.orange; +import static java.awt.Color.pink; +import static java.awt.Color.red; +import static java.awt.Color.white; +import static java.awt.Color.yellow; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.color.ColorSpace; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.ColorConvertOp; +import java2d.Surface; + + +/** + * ColorConvertOp a ColorSpace.TYPE_RGB BufferedImage to a ColorSpace.CS_GRAY + * BufferedImage. + */ +@SuppressWarnings("serial") +public class ColorConvert extends Surface { + + private static Image img; + private static Color colors[] = { red, pink, orange, + yellow, green, magenta, cyan, blue }; + + public ColorConvert() { + setBackground(white); + img = getImage("clouds.jpg"); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + int iw = img.getWidth(this); + int ih = img.getHeight(this); + FontRenderContext frc = g2.getFontRenderContext(); + Font font = g2.getFont(); + g2.setColor(black); + TextLayout tl = new TextLayout("ColorConvertOp RGB->GRAY", font, frc); + tl.draw(g2, (float) (w / 2 - tl.getBounds().getWidth() / 2), + tl.getAscent() + tl.getLeading()); + + BufferedImage srcImg = + new BufferedImage(iw, ih, BufferedImage.TYPE_INT_RGB); + Graphics2D srcG = srcImg.createGraphics(); + RenderingHints rhs = g2.getRenderingHints(); + srcG.setRenderingHints(rhs); + srcG.drawImage(img, 0, 0, null); + + String s = "OpenJDK"; + Font f = new Font(Font.SERIF, Font.BOLD, iw / 6); + tl = new TextLayout(s, f, frc); + Rectangle2D tlb = tl.getBounds(); + char[] chars = s.toCharArray(); + float charWidth = 0.0f; + int rw = iw / chars.length; + int rh = ih / chars.length; + for (int i = 0; i < chars.length; i++) { + tl = new TextLayout(String.valueOf(chars[i]), f, frc); + Shape shape = tl.getOutline(null); + srcG.setColor(colors[i % colors.length]); + tl.draw(srcG, (float) (iw / 2 - tlb.getWidth() / 2 + charWidth), + (float) (ih / 2 + tlb.getHeight() / 2)); + charWidth += (float) shape.getBounds().getWidth(); + srcG.fillRect(i * rw, ih - rh, rw, rh); + srcG.setColor(colors[colors.length - 1 - i % colors.length]); + srcG.fillRect(i * rw, 0, rw, rh); + } + + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY); + ColorConvertOp theOp = new ColorConvertOp(cs, rhs); + + BufferedImage dstImg = + new BufferedImage(iw, ih, BufferedImage.TYPE_INT_RGB); + theOp.filter(srcImg, dstImg); + + g2.drawImage(srcImg, 10, 20, w / 2 - 20, h - 30, null); + g2.drawImage(dstImg, w / 2 + 10, 20, w / 2 - 20, h - 30, null); + } + + public static void main(String s[]) { + createDemoFrame(new ColorConvert()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Colors/Rotator3D.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Colors/Rotator3D.java new file mode 100644 index 00000000000..aeef05ac465 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Colors/Rotator3D.java @@ -0,0 +1,397 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Colors; + + +import static java.lang.Math.PI; +import static java.lang.Math.abs; +import static java.lang.Math.cos; +import static java.lang.Math.min; +import static java.lang.Math.random; +import static java.lang.Math.sin; +import static java.lang.Math.sqrt; +import java.awt.Color; +import java.awt.Graphics2D; +import java2d.AnimatingSurface; + + +/** + * 3D objects with color & lighting translated, rotated and scaled. + */ +@SuppressWarnings("serial") +public class Rotator3D extends AnimatingSurface { + + private Objects3D objs[] = new Objects3D[3]; + private static final int[][][] polygons = { + // Solid cube + { { 5, 1, 15, 13, 21, 23, 15 }, + { 5, 2, 21, 13, 19, 27, 21 }, + { 5, 3, 23, 15, 17, 25, 23 }, + { 5, 4, 19, 13, 15, 17, 19 }, + { 5, 5, 27, 21, 23, 25, 27 }, + { 5, 6, 27, 19, 17, 25, 27 } }, + // Polygonal faces cube + { { 5, 1, 21, 13, 19, 27, 21 }, + { 5, 5, 23, 15, 17, 25, 23 }, + { 4, 0, 15, 14, 16, 15 }, { 7, 6, 16, 14, 13, 12, 18, 17, 16 }, { 4, + 0, 12, 19, 18, 12 }, + { 4, 2, 22, 21, 20, 22 }, { 7, 0, 24, 23, 22, 20, 27, 26, 24 }, { 4, + 2, 24, 26, 25, 24 }, + { 4, 3, 15, 13, 23, 15 }, { 4, 0, 23, 13, 21, 23 }, + { 5, 0, 27, 26, 18, 19, 27 }, { 5, 4, 25, 17, 18, 26, 25 } }, + // Octahedron + { { 4, 3, 18, 21, 16, 18 }, { 4, 1, 20, 16, 18, 20 }, + { 4, 1, 18, 21, 16, 18 }, { 4, 3, 20, 17, 19, 20 }, + { 4, 2, 20, 26, 27, 20 }, { 5, 3, 26, 18, 16, 27, 26 }, + { 5, 0, 17, 24, 25, 19, 17 }, { 4, 3, 21, 25, 24, 21 }, + { 4, 4, 18, 21, 22, 18 }, { 4, 2, 22, 21, 17, 22 }, + { 4, 5, 20, 23, 16, 20 }, { 4, 1, 20, 23, 19, 20 }, + { 4, 6, 21, 23, 16, 21 }, { 4, 4, 21, 23, 19, 21 }, + { 4, 5, 20, 18, 22, 20 }, { 4, 6, 20, 22, 17, 20 } } + }; + private static final double[][][] points = { + // Points for solid cube & polygonal faces cube + { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 1, 0 }, { 0, -1, 0 }, { 0, 0, 1 }, + { 0, 0, -1 }, { 1, 0, 0 }, { -1, 0, 0 }, { 0, 1, 0 }, { 0, -1, 0 }, + { 0, 0, 1 }, { 0, 0, -1 }, { 1, 1, 0 }, { 1, 1, 1 }, { 0, 1, 1 }, + { -1, 1, 1 }, { -1, 1, 0 }, { -1, 1, -1 }, { 0, 1, -1 }, + { 1, 1, -1 }, + { 1, -1, 0 }, { 1, -1, 1 }, { 0, -1, 1 }, { -1, -1, 1 }, + { -1, -1, 0 }, + { -1, -1, -1 }, { 0, -1, -1 }, { 1, -1, -1 } }, + // Points for octahedron + { { 0, 0, 1 }, { 0, 0, -1 }, { -0.8165, 0.4714, 0.33333 }, + { 0.8165, -0.4714, -0.33333 }, { 0.8165, 0.4714, 0.33333 }, + { -0.8165, -0.4714, -0.33333 }, { 0, -0.9428, 0.3333 }, + { 0, 0.9428, -0.33333 }, { 0, 0, 1 }, { 0, 0, -1 }, + { -0.8165, 0.4714, 0.33333 }, { 0.8165, -0.4714, -0.33333 }, + { 0.8165, 0.4714, 0.33333 }, { -0.8165, -0.4714, -0.33333 }, + { 0, -0.9428, 0.33333 }, { 0, 0.9428, -0.33333 }, + { -1.2247, -0.7071, 1 }, { 1.2247, 0.7071, -1 }, + { 0, 1.4142, 1 }, { 0, -1.4142, -1 }, { -1.2247, 0.7071, -1 }, + { 1.2247, -0.7071, 1 }, { 0.61237, 1.06066, 0 }, + { -0.61237, -1.06066, 0 }, { 1.2247, 0, 0 }, + { 0.61237, -1.06066, 0 }, { -0.61237, 1.06066, 0 }, + { -1.2247, 0, 0 } } + }; + private static final int[][][] faces = { + // Solid cube + { { 1, 1 }, { 1, 2 }, { 1, 3 }, { 1, 4 }, { 1, 0 }, { 1, 5 } }, + // Polygonal faces cube + { { 1, 0 }, { 1, 1 }, { 3, 2, 3, 4 }, { 3, 5, 6, 7 }, { 2, 8, 9 }, { 2, + 10, 11 } }, + // Octahedron + { { 1, 2 }, { 1, 3 }, { 2, 4, 5 }, { 2, 6, 7 }, { 2, 8, 9 }, + { 2, 10, 11 }, { 2, 12, 13 }, { 2, 14, 15 } }, }; + + public Rotator3D() { + setBackground(Color.white); + } + + @Override + public void reset(int w, int h) { + objs[0] = new Objects3D(polygons[0], points[0], faces[0], w, h); + objs[1] = new Objects3D(polygons[1], points[0], faces[1], w, h); + objs[2] = new Objects3D(polygons[2], points[1], faces[2], w, h); + } + + @Override + public void step(int w, int h) { + for (Objects3D obj : objs) { + if (obj != null) { + obj.step(w, h); + } + } + } + + @Override + public void render(int w, int h, Graphics2D g2) { + for (Objects3D obj : objs) { + if (obj != null) { + obj.render(g2); + } + } + } + + public static void main(String argv[]) { + createDemoFrame(new Rotator3D()); + } + + + /** + * 3D Objects : Solid Cube, Cube & Octahedron with polygonal faces. + */ + public class Objects3D { + + private final int UP = 0; + private final int DOWN = 1; + private int[][] polygons; + private double[][] points; + private int npoint; + private int[][] faces; + private int nface; + private int ncolour = 10; + private Color[][] colours = new Color[ncolour][7]; + private double[] lightvec = { 0, 1, 1 }; + private double Zeye = 10; + private double angle; + private Matrix3D orient, tmp, tmp2, tmp3; + private int scaleDirection; + private double scale, scaleAmt; + private double ix = 3.0, iy = 3.0; + private double[][] rotPts; + private int[][] scrPts; + private int xx[] = new int[20]; + private int yy[] = new int[20]; + private double x, y; + private int p, j; + private int colour; + private double bounce, persp; + + public Objects3D(int[][] polygons, + double[][] points, + int[][] faces, + int w, + int h) { + + this.polygons = polygons; + this.points = points; + this.faces = faces; + npoint = points.length; + nface = faces.length; + + x = w * random(); + y = h * random(); + + ix = random() > 0.5 ? ix : -ix; + iy = random() > 0.5 ? iy : -iy; + + rotPts = new double[npoint][3]; + scrPts = new int[npoint][2]; + + for (int i = 0; i < ncolour; i++) { + int val = 255 - (ncolour - i - 1) * 100 / ncolour; + Color[] c = { + new Color(val, val, val), // white + new Color(val, 0, 0), // red + new Color(0, val, 0), // green + new Color(0, 0, val), // blue + new Color(val, val, 0), // yellow + new Color(0, val, val), // cyan + new Color(val, 0, val) // magenta + }; + colours[i] = c; + } + + double len = sqrt(lightvec[0] * lightvec[0] + lightvec[1] + * lightvec[1] + lightvec[2] * lightvec[2]); + lightvec[0] = lightvec[0] / len; + lightvec[1] = lightvec[1] / len; + lightvec[2] = lightvec[2] / len; + + double max = 0; + for (int i = 0; i < npoint; i++) { + len = sqrt(points[i][0] * points[i][0] + points[i][1] + * points[i][1] + points[i][2] * points[i][2]); + if (len > max) { + max = len; + } + } + + for (int i = 0; i < nface; i++) { + len = sqrt(points[i][0] * points[i][0] + points[i][1] + * points[i][1] + points[i][2] * points[i][2]); + points[i][0] = points[i][0] / len; + points[i][1] = points[i][1] / len; + points[i][2] = points[i][2] / len; + } + + orient = new Matrix3D(); + tmp = new Matrix3D(); + tmp2 = new Matrix3D(); + tmp3 = new Matrix3D(); + tmp.Rotation(2, 0, PI / 50); + CalcScrPts((double) w / 3, (double) h / 3, 0); + + scale = min(w / 3 / max / 1.2, h / 3 / max / 1.2); + scaleAmt = scale; + scale *= random() * 1.5; + scaleDirection = scaleAmt < scale ? DOWN : UP; + } + + private Color getColour(int f, int index) { + colour = (int) ((rotPts[f][0] * lightvec[0] + rotPts[f][1] + * lightvec[1] + rotPts[f][2] * lightvec[2]) * ncolour); + if (colour < 0) { + colour = 0; + } + if (colour > ncolour - 1) { + colour = ncolour - 1; + } + return colours[colour][polygons[faces[f][index]][1]]; + } + + private void CalcScrPts(double x, double y, double z) { + for (p = 0; p < npoint; p++) { + + rotPts[p][2] = points[p][0] * orient.M[2][0] + + points[p][1] * orient.M[2][1] + + points[p][2] * orient.M[2][2]; + + rotPts[p][0] = points[p][0] * orient.M[0][0] + + points[p][1] * orient.M[0][1] + + points[p][2] * orient.M[0][2]; + + rotPts[p][1] = -points[p][0] * orient.M[1][0] + - points[p][1] * orient.M[1][1] + - points[p][2] * orient.M[1][2]; + } + for (p = nface; p < npoint; p++) { + rotPts[p][2] += z; + persp = (Zeye - rotPts[p][2]) / (scale * Zeye); + scrPts[p][0] = (int) (rotPts[p][0] / persp + x); + scrPts[p][1] = (int) (rotPts[p][1] / persp + y); + } + } + + private boolean faceUp(int f) { + return (rotPts[f][0] * rotPts[nface + f][0] + rotPts[f][1] * rotPts[nface + + f][1] + rotPts[f][2] * (rotPts[nface + f][2] - Zeye) < 0); + } + + public void step(int w, int h) { + x += ix; + y += iy; + if (x > w - scale) { + x = w - scale - 1; + ix = -w / 100 - 1; + } + if (x - scale < 0) { + x = 2 + scale; + ix = w / 100 + random() * 3; + } + if (y > h - scale) { + y = h - scale - 2; + iy = -h / 100 - 1; + } + if (y - scale < 0) { + y = 2 + scale; + iy = h / 100 + random() * 3; + } + + angle += random() * 0.15; + tmp3.Rotation(1, 2, angle); + tmp2.Rotation(1, 0, angle * sqrt(2) / 2); + tmp.Rotation(0, 2, angle * PI / 4); + orient.M = tmp3.Times(tmp2.Times(tmp.M)); + bounce = abs(cos(0.5 * (angle))) * 2 - 1; + + if (scale > scaleAmt * 1.4) { + scaleDirection = DOWN; + } + if (scale < scaleAmt * 0.4) { + scaleDirection = UP; + } + if (scaleDirection == UP) { + scale += random(); + } + if (scaleDirection == DOWN) { + scale -= random(); + } + + CalcScrPts(x, y, bounce); + } + + public void render(Graphics2D g2) { + for (int f = 0; f < nface; f++) { + if (faceUp(f)) { + for (j = 1; j < faces[f][0] + 1; j++) { + DrawPoly(g2, faces[f][j], getColour(f, j)); + } + } + } + } + + private void DrawPoly(Graphics2D g2, int poly, Color colour) { + for (int point = 2; point < polygons[poly][0] + 2; point++) { + xx[point - 2] = scrPts[polygons[poly][point]][0]; + yy[point - 2] = scrPts[polygons[poly][point]][1]; + } + g2.setColor(colour); + g2.fillPolygon(xx, yy, polygons[poly][0]); + g2.setColor(Color.black); + g2.drawPolygon(xx, yy, polygons[poly][0]); + } + + + /** + * A 3D matrix object. + */ + public class Matrix3D { + + public double[][] M = { { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 } }; + private double[][] tmp = new double[3][3]; + private int row, col, k; + + public void Rotation(int i, int j, double angle) { + for (row = 0; row < 3; row++) { + for (col = 0; col < 3; col++) { + if (row != col) { + M[row][col] = 0.0; + } else { + M[row][col] = 1.0; + } + } + } + M[i][i] = cos(angle); + M[j][j] = cos(angle); + M[i][j] = sin(angle); + M[j][i] = -sin(angle); + } + + public double[][] Times(double[][] N) { + for (row = 0; row < 3; row++) { + for (col = 0; col < 3; col++) { + tmp[row][col] = 0.0; + for (k = 0; k < 3; k++) { + tmp[row][col] += M[row][k] * N[k][col]; + } + } + } + return tmp; + } + } // End Matrix3D + } // End Objects3D +} // End Rotator3D + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Composite/ACimages.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Composite/ACimages.java new file mode 100644 index 00000000000..c34a44ee5da --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Composite/ACimages.java @@ -0,0 +1,127 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Composite; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.BLUE; +import static java.awt.Color.CYAN; +import static java.awt.Color.GREEN; +import static java.awt.Color.LIGHT_GRAY; +import static java.awt.Color.MAGENTA; +import static java.awt.Color.ORANGE; +import static java.awt.Color.PINK; +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.Color; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Shape; +import java.awt.font.TextLayout; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; +import java2d.Surface; + + +/** + * Compositing shapes on images. + */ +@SuppressWarnings("serial") +public class ACimages extends Surface { + + private static final String s[] = { "box", "fight", "magnify", + "boxwave", "globe", "snooze", + "tip", "thumbsup", "dukeplug" }; + private static Image imgs[] = new Image[s.length]; + private static Color colors[] = { BLUE, CYAN, GREEN, + MAGENTA, ORANGE, PINK, RED, YELLOW, LIGHT_GRAY }; + + public ACimages() { + setBackground(WHITE); + for (int i = 0; i < imgs.length; i++) { + imgs[i] = getImage(s[i] + ".png"); + } + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + float alpha = 0.0f; + int iw = w / 3; + int ih = (h - 45) / 3; + float xx = 0, yy = 15; + + for (int i = 0; i < imgs.length; i++) { + + xx = (i % 3 == 0) ? 0 : xx + w / 3; + switch (i) { + case 3: + yy = h / 3 + 15; + break; + case 6: + yy = h / 3 * 2 + 15; + } + + g2.setComposite(AlphaComposite.SrcOver); + g2.setColor(BLACK); + AlphaComposite ac = AlphaComposite.SrcOver.derive(alpha += .1f); + String str = "a=" + Float.toString(alpha).substring(0, 3); + new TextLayout(str, g2.getFont(), g2.getFontRenderContext()).draw(g2, xx + + 3, yy - 2); + + Shape shape = null; + + switch (i % 3) { + case 0: + shape = new Ellipse2D.Float(xx, yy, iw, ih); + break; + case 1: + shape = new RoundRectangle2D.Float(xx, yy, iw, ih, 25, 25); + break; + case 2: + shape = new Rectangle2D.Float(xx, yy, iw, ih); + break; + } + g2.setColor(colors[i]); + g2.setComposite(ac); + g2.fill(shape); + g2.drawImage(imgs[i], (int) xx, (int) yy, iw, ih, null); + } + } + + public static void main(String s[]) { + createDemoFrame(new ACimages()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Composite/ACrules.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Composite/ACrules.java new file mode 100644 index 00000000000..8c3259f80ac --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Composite/ACrules.java @@ -0,0 +1,263 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Composite; + + +import static java.awt.AlphaComposite.Clear; +import static java.awt.AlphaComposite.Dst; +import static java.awt.AlphaComposite.DstAtop; +import static java.awt.AlphaComposite.DstIn; +import static java.awt.AlphaComposite.DstOut; +import static java.awt.AlphaComposite.DstOver; +import static java.awt.AlphaComposite.Src; +import static java.awt.AlphaComposite.SrcAtop; +import static java.awt.AlphaComposite.SrcIn; +import static java.awt.AlphaComposite.SrcOut; +import static java.awt.AlphaComposite.SrcOver; +import static java.awt.AlphaComposite.Xor; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.font.FontRenderContext; +import java.awt.font.LineMetrics; +import java.awt.font.TextLayout; +import java.awt.geom.GeneralPath; +import java.awt.image.BufferedImage; +import java2d.AnimatingSurface; + + +/** + * All the AlphaCompositing Rules demonstrated. + */ +@SuppressWarnings("serial") +public class ACrules extends AnimatingSurface { + + private static String compNames[] = { + "Src", + "SrcOver", + "SrcIn", + "SrcOut", + "SrcAtop", + "Clear", + "Dst", + "DstOver", + "DstIn", + "DstOut", + "DstAtop", + "Xor", }; + private static final AlphaComposite compObjs[] = { + Src, SrcOver, SrcIn, SrcOut, SrcAtop, Clear, + Dst, DstOver, DstIn, DstOut, DstAtop, Xor, }; + private static final int NUM_RULES = compObjs.length; + private static final int HALF_NUM_RULES = NUM_RULES / 2; + private int fadeIndex; + private static float fadeValues[][] = { + { 1.0f, -0.1f, 0.0f, 1.0f, 0.0f, 1.0f }, + { 0.0f, 0.1f, 1.0f, 1.0f, -0.1f, 0.0f }, + { 1.0f, 0.0f, 1.0f, 0.0f, 0.1f, 1.0f }, }; + private static String fadeNames[] = { + "Src => transparent, Dest opaque", + "Src => opaque, Dest => transparent", + "Src opaque, Dest => opaque", }; + private static Font f = new Font("serif", Font.PLAIN, 10); + private float srca = fadeValues[fadeIndex][0]; + private float dsta = fadeValues[fadeIndex][3]; + private String fadeLabel = fadeNames[0]; + private BufferedImage statBI, animBI; + private int PADLEFT, PADRIGHT, HPAD; + private int PADABOVE, PADBELOW, VPAD; + private int RECTWIDTH, RECTHEIGHT; + private int PADDEDHEIGHT; + private GeneralPath srcpath = new GeneralPath(); + private GeneralPath dstpath = new GeneralPath(); + private LineMetrics lm; + private BufferedImage dBI, sBI; + private GradientPaint gradientDst, gradientSrc; + + public ACrules() { + setBackground(Color.white); + } + + @Override + public void reset(int w, int h) { + setSleepAmount(400); + FontRenderContext frc = new FontRenderContext(null, false, false); + lm = f.getLineMetrics(compNames[0], frc); + + PADLEFT = (w < 150) ? 10 : 15; + PADRIGHT = (w < 150) ? 10 : 15; + HPAD = (PADLEFT + PADRIGHT); + PADBELOW = (h < 250) ? 1 : 2; + PADABOVE = PADBELOW + (int) lm.getHeight(); + VPAD = (PADABOVE + PADBELOW); + RECTWIDTH = w / 4 - HPAD; + RECTWIDTH = (RECTWIDTH < 6) ? 6 : RECTWIDTH; + RECTHEIGHT = (h - VPAD) / HALF_NUM_RULES - VPAD; + RECTHEIGHT = (RECTHEIGHT < 6) ? 6 : RECTHEIGHT; + PADDEDHEIGHT = (RECTHEIGHT + VPAD); + + srcpath.reset(); + srcpath.moveTo(0, 0); + srcpath.lineTo(RECTWIDTH, 0); + srcpath.lineTo(0, RECTHEIGHT); + srcpath.closePath(); + + dstpath.reset(); + dstpath.moveTo(0, 0); + dstpath.lineTo(RECTWIDTH, RECTHEIGHT); + dstpath.lineTo(RECTWIDTH, 0); + dstpath.closePath(); + + dBI = new BufferedImage(RECTWIDTH, RECTHEIGHT, + BufferedImage.TYPE_INT_ARGB); + sBI = new BufferedImage(RECTWIDTH, RECTHEIGHT, + BufferedImage.TYPE_INT_ARGB); + gradientDst = new GradientPaint(0, 0, + new Color(1.0f, 0.0f, 0.0f, 1.0f), + 0, RECTHEIGHT, + new Color(1.0f, 0.0f, 0.0f, 0.0f)); + gradientSrc = new GradientPaint(0, 0, + new Color(0.0f, 0.0f, 1.0f, 1.0f), + RECTWIDTH, 0, + new Color(0.0f, 0.0f, 1.0f, 0.0f)); + statBI = new BufferedImage(w / 2, h, BufferedImage.TYPE_INT_RGB); + statBI = drawCompBI(statBI, true); + animBI = new BufferedImage(w / 2, h, BufferedImage.TYPE_INT_RGB); + } + + @Override + public void step(int w, int h) { + if (getSleepAmount() == 5000) { + setSleepAmount(200); + } + + srca = srca + fadeValues[fadeIndex][1]; + dsta = dsta + fadeValues[fadeIndex][4]; + fadeLabel = fadeNames[fadeIndex]; + if (srca < 0 || srca > 1.0 || dsta < 0 || dsta > 1.0) { + setSleepAmount(5000); + srca = fadeValues[fadeIndex][2]; + dsta = fadeValues[fadeIndex][5]; + if (fadeIndex++ == fadeValues.length - 1) { + fadeIndex = 0; + } + } + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + if (statBI == null || animBI == null) { + return; + } + g2.drawImage(statBI, 0, 0, null); + g2.drawImage(drawCompBI(animBI, false), w / 2, 0, null); + + g2.setColor(Color.black); + FontRenderContext frc = g2.getFontRenderContext(); + TextLayout tl = new TextLayout("AC Rules", g2.getFont(), frc); + tl.draw(g2, 15.0f, (float) tl.getBounds().getHeight() + 3.0f); + + tl = new TextLayout(fadeLabel, f, frc); + float x = (float) (w * 0.75 - tl.getBounds().getWidth() / 2); + if ((x + tl.getBounds().getWidth()) > w) { + x = (float) (w - tl.getBounds().getWidth()); + } + tl.draw(g2, x, (float) tl.getBounds().getHeight() + 3.0f); + } + + private BufferedImage drawCompBI(BufferedImage bi, boolean doGradient) { + Graphics2D big = bi.createGraphics(); + big.setColor(getBackground()); + big.fillRect(0, 0, bi.getWidth(), bi.getHeight()); + big.setRenderingHint(RenderingHints.KEY_ANTIALIASING, AntiAlias); + big.setFont(f); + + Graphics2D gD = dBI.createGraphics(); + gD.setRenderingHint(RenderingHints.KEY_ANTIALIASING, AntiAlias); + Graphics2D gS = sBI.createGraphics(); + gS.setRenderingHint(RenderingHints.KEY_ANTIALIASING, AntiAlias); + + int x = 0, y = 0; + int yy = (int) lm.getHeight() + VPAD; + + for (int i = 0; i < compNames.length; i++) { + y = (i == 0 || i == HALF_NUM_RULES) ? yy : y + PADDEDHEIGHT; + x = (i >= HALF_NUM_RULES) ? bi.getWidth() / 2 + PADLEFT : PADLEFT; + big.translate(x, y); + + gD.setComposite(Clear); + gD.fillRect(0, 0, RECTWIDTH, RECTHEIGHT); + gD.setComposite(Src); + if (doGradient) { + gD.setPaint(gradientDst); + gD.fillRect(0, 0, RECTWIDTH, RECTHEIGHT); + } else { + gD.setPaint(new Color(1.0f, 0.0f, 0.0f, dsta)); + gD.fill(dstpath); + } + + gS.setComposite(Clear); + gS.fillRect(0, 0, RECTWIDTH, RECTHEIGHT); + gS.setComposite(Src); + if (doGradient) { + gS.setPaint(gradientSrc); + gS.fillRect(0, 0, RECTWIDTH, RECTHEIGHT); + } else { + gS.setPaint(new Color(0.0f, 0.0f, 1.0f, srca)); + gS.fill(srcpath); + } + + gD.setComposite(compObjs[i]); + gD.drawImage(sBI, 0, 0, null); + + big.drawImage(dBI, 0, 0, null); + big.setColor(Color.black); + big.drawString(compNames[i], 0, -lm.getDescent()); + big.drawRect(0, 0, RECTWIDTH, RECTHEIGHT); + big.translate(-x, -y); + } + + gD.dispose(); + gS.dispose(); + big.dispose(); + + return bi; + } + + public static void main(String argv[]) { + createDemoFrame(new ACrules()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Composite/FadeAnim.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Composite/FadeAnim.java new file mode 100644 index 00000000000..9059efb4f26 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Composite/FadeAnim.java @@ -0,0 +1,486 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Composite; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.BLUE; +import static java.awt.Color.CYAN; +import static java.awt.Color.GREEN; +import static java.awt.Color.LIGHT_GRAY; +import static java.awt.Color.MAGENTA; +import static java.awt.Color.ORANGE; +import static java.awt.Color.PINK; +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.BasicStroke; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.TexturePaint; +import java.awt.geom.Arc2D; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.QuadCurve2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.List; +import java2d.AnimatingControlsSurface; +import java2d.CustomControls; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JSlider; +import javax.swing.JToolBar; +import javax.swing.SwingConstants; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + + +/** + * Animation of compositing shapes, text and images fading in and out. + */ +@SuppressWarnings("serial") +public final class FadeAnim extends AnimatingControlsSurface { + + private static final TexturePaint texturePaint; + + static { + int w = 10; + int h = 10; + BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + Graphics2D gi = bi.createGraphics(); + Color oc = BLUE; + Color ic = GREEN; + gi.setPaint(new GradientPaint(0, 0, oc, w * .35f, h * .35f, ic)); + gi.fillRect(0, 0, w / 2, h / 2); + gi.setPaint(new GradientPaint(w, 0, oc, w * .65f, h * .35f, ic)); + gi.fillRect(w / 2, 0, w / 2, h / 2); + gi.setPaint(new GradientPaint(0, h, oc, w * .35f, h * .65f, ic)); + gi.fillRect(0, h / 2, w / 2, h / 2); + gi.setPaint(new GradientPaint(w, h, oc, w * .65f, h * .65f, ic)); + gi.fillRect(w / 2, h / 2, w / 2, h / 2); + texturePaint = new TexturePaint(bi, new Rectangle(0, 0, w, h)); + } + private static BasicStroke bs = new BasicStroke(6); + private static Font fonts[] = { + new Font(Font.SERIF, Font.PLAIN, 64), + new Font(Font.SERIF, Font.BOLD | Font.ITALIC, 24), + new Font(Font.MONOSPACED, Font.BOLD, 36), + new Font(Font.SANS_SERIF, Font.BOLD | Font.ITALIC, 48), + new Font(Font.SANS_SERIF, Font.PLAIN, 52) }; + private static String strings[] = { + "Alpha", "Composite", "Src", "SrcOver", + "SrcIn", "SrcOut", "Clear", "DstOver", "DstIn" }; + private static String imgs[] = { + "jumptojavastrip.png", "duke.png", "star7.png" }; + private static Paint paints[] = { + RED, BLUE, GREEN, MAGENTA, + ORANGE, PINK, CYAN, texturePaint, + YELLOW, LIGHT_GRAY, WHITE }; + private List objects = new ArrayList(20); + private int numShapes, numStrings, numImages; + + public FadeAnim() { + setBackground(BLACK); + setStrings(2); + setImages(3); + setShapes(8); + setControls(new Component[] { new DemoControls(this) }); + setConstraints(new String[] { BorderLayout.EAST }); + } + + public void setImages(int num) { + + if (num < numImages) { + List images = new ArrayList(objects.size()); + for (ObjectData obj : objects) { + if (obj.object instanceof Image) { + images.add(obj); + } + } + objects.removeAll(images.subList(num, images.size())); + } else { + Dimension d = getSize(); + for (int i = numImages; i < num; i++) { + Object obj = getImage(imgs[i % imgs.length]); + if (imgs[i % imgs.length].equals("jumptojavastrip.png")) { + int iw = ((Image) obj).getWidth(null); + int ih = ((Image) obj).getHeight(null); + BufferedImage bimage = new BufferedImage(iw, ih, + BufferedImage.TYPE_INT_RGB); + bimage.createGraphics().drawImage((Image) obj, 0, 0, null); + obj = bimage; + } + ObjectData od = new ObjectData(obj, BLACK); + od.reset(d.width, d.height); + objects.add(od); + } + } + numImages = num; + } + + public void setStrings(int num) { + + if (num < numStrings) { + List textDatas = new ArrayList( + objects.size()); + //for (int i = 0; i < objects.size(); i++) { + for (ObjectData obj : objects) { + if (obj.object instanceof TextData) { + textDatas.add(obj); + } + } + objects.removeAll(textDatas.subList(num, textDatas.size())); + } else { + Dimension d = getSize(); + for (int i = numStrings; i < num; i++) { + int j = i % fonts.length; + int k = i % strings.length; + Object obj = new TextData(strings[k], fonts[j], this); + ObjectData od = new ObjectData(obj, paints[i % paints.length]); + od.reset(d.width, d.height); + objects.add(od); + } + } + numStrings = num; + } + + public void setShapes(int num) { + + if (num < numShapes) { + List shapes = new ArrayList(objects.size()); + //for (int i = 0; i < objects.size(); i++) { + for (ObjectData obj : objects) { + if (obj.object instanceof Shape) { + shapes.add(obj); + } + } + objects.removeAll(shapes.subList(num, shapes.size())); + } else { + Dimension d = getSize(); + for (int i = numShapes; i < num; i++) { + Object obj = null; + switch (i % 7) { + case 0: + obj = new GeneralPath(); + break; + case 1: + obj = new Rectangle2D.Double(); + break; + case 2: + obj = new Ellipse2D.Double(); + break; + case 3: + obj = new Arc2D.Double(); + break; + case 4: + obj = new RoundRectangle2D.Double(); + break; + case 5: + obj = new CubicCurve2D.Double(); + break; + case 6: + obj = new QuadCurve2D.Double(); + break; + } + ObjectData od = new ObjectData(obj, paints[i % paints.length]); + od.reset(d.width, d.height); + objects.add(od); + } + } + numShapes = num; + } + + @Override + public void reset(int w, int h) { + for (int i = 0; i < objects.size(); i++) { + objects.get(i).reset(w, h); + } + } + + @Override + public void step(int w, int h) { + for (int i = 0; i < objects.size(); i++) { + objects.get(i).step(w, h); + } + } + + @Override + public void render(int w, int h, Graphics2D g2) { + for (int i = 0; i < objects.size(); i++) { + ObjectData od = objects.get(i); + AlphaComposite ac = AlphaComposite.getInstance( + AlphaComposite.SRC_OVER, od.alpha); + g2.setComposite(ac); + g2.setPaint(od.paint); + g2.translate(od.x, od.y); + + if (od.object instanceof Image) { + g2.drawImage((Image) od.object, 0, 0, this); + } else if (od.object instanceof TextData) { + g2.setFont(((TextData) od.object).font); + g2.drawString(((TextData) od.object).string, 0, 0); + } else if (od.object instanceof QuadCurve2D + || od.object instanceof CubicCurve2D) { + g2.setStroke(bs); + g2.draw((Shape) od.object); + } else if (od.object instanceof Shape) { + g2.fill((Shape) od.object); + } + g2.translate(-od.x, -od.y); + } + } + + public static void main(String argv[]) { + createDemoFrame(new FadeAnim()); + } + + + static class TextData extends Object { + + public String string; + public Font font; + public int width, height; + + public TextData(String str, Font font, Component cmp) { + string = str; + this.font = font; + FontMetrics fm = cmp.getFontMetrics(font); + width = fm.stringWidth(str); + height = fm.getHeight(); + } + } + + + static class ObjectData extends Object { + + final int UP = 0; + final int DOWN = 1; + Object object; + BufferedImage bimg; + Paint paint; + double x, y; + float alpha; + int alphaDirection; + int imgX; + + public ObjectData(Object object, Paint paint) { + this.object = object; + this.paint = paint; + if (object instanceof BufferedImage) { + bimg = (BufferedImage) object; + this.object = bimg.getSubimage(0, 0, 80, 80); + } + getRandomXY(300, 250); + alpha = (float) Math.random(); + alphaDirection = Math.random() > 0.5 ? UP : DOWN; + } + + private void getRandomXY(int w, int h) { + if (object instanceof TextData) { + x = Math.random() * (w - ((TextData) object).width); + y = Math.random() * h; + y = y < ((TextData) object).height ? ((TextData) object).height + : y; + } else if (object instanceof Image) { + x = Math.random() * (w - ((Image) object).getWidth(null)); + y = Math.random() * (h - ((Image) object).getHeight(null)); + } else if (object instanceof Shape) { + Rectangle bounds = ((Shape) object).getBounds(); + x = Math.random() * (w - bounds.width); + y = Math.random() * (h - bounds.height); + } + } + + public void reset(int w, int h) { + getRandomXY(w, h); + double ww = 20 + Math.random() * ((w == 0 ? 400 : w) / 4); + double hh = 20 + Math.random() * ((h == 0 ? 300 : h) / 4); + if (object instanceof Ellipse2D) { + ((Ellipse2D) object).setFrame(0, 0, ww, hh); + } else if (object instanceof Rectangle2D) { + ((Rectangle2D) object).setRect(0, 0, ww, ww); + } else if (object instanceof RoundRectangle2D) { + ((RoundRectangle2D) object).setRoundRect(0, 0, hh, hh, 20, 20); + } else if (object instanceof Arc2D) { + ((Arc2D) object).setArc(0, 0, hh, hh, 45, 270, Arc2D.PIE); + } else if (object instanceof QuadCurve2D) { + ((QuadCurve2D) object).setCurve(0, 0, w * .2, h * .4, w * .4, 0); + } else if (object instanceof CubicCurve2D) { + ((CubicCurve2D) object).setCurve(0, 0, 30, -60, 60, 60, 90, 0); + } else if (object instanceof GeneralPath) { + GeneralPath p = new GeneralPath(); + float size = (float) ww; + p.moveTo(-size / 2.0f, -size / 8.0f); + p.lineTo(+size / 2.0f, -size / 8.0f); + p.lineTo(-size / 4.0f, +size / 2.0f); + p.lineTo(+0.0f, -size / 2.0f); + p.lineTo(+size / 4.0f, +size / 2.0f); + p.closePath(); + object = p; + } + } + + public void step(int w, int h) { + if (object instanceof BufferedImage) { + if ((imgX += 80) == 800) { + imgX = 0; + } + object = bimg.getSubimage(imgX, 0, 80, 80); + } + if (alphaDirection == UP) { + if ((alpha += 0.05) > .99) { + alphaDirection = DOWN; + alpha = 1.0f; + } + } else if (alphaDirection == DOWN) { + if ((alpha -= .05) < 0.01) { + alphaDirection = UP; + alpha = 0; + getRandomXY(w, h); + } + } + } + } + + + static class DemoControls extends CustomControls implements ChangeListener { + + FadeAnim demo; + JSlider shapeSlider, stringSlider, imageSlider; + Font font = new Font(Font.SERIF, Font.BOLD, 10); + + @SuppressWarnings("LeakingThisInConstructor") + public DemoControls(FadeAnim demo) { + super(demo.name); + this.demo = demo; + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + add(Box.createVerticalStrut(5)); + + JToolBar toolbar = new JToolBar(SwingConstants.VERTICAL); + toolbar.setFloatable(false); + shapeSlider = new JSlider(SwingConstants.HORIZONTAL, 0, 20, + demo.numShapes); + shapeSlider.addChangeListener(this); + TitledBorder tb = new TitledBorder(new EtchedBorder()); + tb.setTitleFont(font); + tb.setTitle(String.valueOf(demo.numShapes) + " Shapes"); + shapeSlider.setBorder(tb); + shapeSlider.setPreferredSize(new Dimension(80, 45)); + shapeSlider.setOpaque(true); + toolbar.addSeparator(); + toolbar.add(shapeSlider); + toolbar.addSeparator(); + + stringSlider = new JSlider(SwingConstants.HORIZONTAL, 0, 10, + demo.numStrings); + stringSlider.addChangeListener(this); + tb = new TitledBorder(new EtchedBorder()); + tb.setTitleFont(font); + tb.setTitle(String.valueOf(demo.numStrings) + " Strings"); + stringSlider.setBorder(tb); + stringSlider.setPreferredSize(new Dimension(80, 45)); + stringSlider.setOpaque(true); + toolbar.add(stringSlider); + toolbar.addSeparator(); + + imageSlider = new JSlider(SwingConstants.HORIZONTAL, 0, 10, + demo.numImages); + imageSlider.addChangeListener(this); + tb = new TitledBorder(new EtchedBorder()); + tb.setTitleFont(font); + tb.setTitle(String.valueOf(demo.numImages) + " Images"); + imageSlider.setBorder(tb); + imageSlider.setPreferredSize(new Dimension(80, 45)); + imageSlider.setOpaque(true); + toolbar.add(imageSlider); + toolbar.addSeparator(); + + add(toolbar); + } + + @Override + public void stateChanged(ChangeEvent e) { + JSlider slider = (JSlider) e.getSource(); + int value = slider.getValue(); + TitledBorder tb = (TitledBorder) slider.getBorder(); + if (slider.equals(shapeSlider)) { + tb.setTitle(String.valueOf(value) + " Shapes"); + demo.setShapes(value); + } else if (slider.equals(stringSlider)) { + tb.setTitle(String.valueOf(value) + " Strings"); + demo.setStrings(value); + } else if (slider.equals(imageSlider)) { + tb.setTitle(String.valueOf(value) + " Images"); + demo.setImages(value); + } + slider.repaint(); + if (!demo.animating.running()) { + demo.repaint(); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(80, 0); + } + + @Override + public void run() { + try { + Thread.sleep(999); + } catch (InterruptedException e) { + return; + } + shapeSlider.setValue((int) (Math.random() * 5)); + stringSlider.setValue(10); + thread = null; + } + } // End DemoControls +} // End FadeAnim + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/AllFonts.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/AllFonts.java new file mode 100644 index 00000000000..ace14995060 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/AllFonts.java @@ -0,0 +1,181 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Fonts; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.GRAY; +import static java.awt.Color.WHITE; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.GraphicsEnvironment; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import java2d.AnimatingControlsSurface; +import java2d.CustomControls; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JSlider; +import javax.swing.SwingConstants; +import javax.swing.border.EtchedBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + + +/** + * Scrolling text of fonts returned from GraphicsEnvironment.getAllFonts(). + */ +@SuppressWarnings("serial") +public class AllFonts extends AnimatingControlsSurface { + + private static final List fonts = new ArrayList(); + + static { + GraphicsEnvironment ge = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + for (Font font : ge.getAllFonts()) { + if (font.canDisplayUpTo(font.getName()) != 0) { + fonts.add(font); + } + } + } + private int nStrs; + private int strH; + private int fi; + protected int fsize = 14; + protected List v = new ArrayList(); + + public AllFonts() { + setBackground(WHITE); + setSleepAmount(500); + setControls(new Component[] { new DemoControls(this) }); + } + + public void handleThread(int state) { + } + + @Override + public void reset(int w, int h) { + v.clear(); + Font f = fonts.get(0).deriveFont(Font.PLAIN, fsize); + FontMetrics fm = getFontMetrics(f); + strH = (fm.getAscent() + fm.getDescent()); + nStrs = h / strH + 1; + fi = 0; + } + + @Override + public void step(int w, int h) { + if (fi < fonts.size()) { + v.add(fonts.get(fi).deriveFont(Font.PLAIN, fsize)); + } + if (v.size() == nStrs && !v.isEmpty() || fi > fonts.size()) { + v.remove(0); + } + fi = v.isEmpty() ? 0 : ++fi; + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + g2.setColor(BLACK); + + int yy = (fi >= fonts.size()) ? 0 : h - v.size() * strH - strH / 2; + + for (int i = 0; i < v.size(); i++) { + Font f = v.get(i); + int sw = getFontMetrics(f).stringWidth(f.getName()); + g2.setFont(f); + g2.drawString(f.getName(), (w / 2 - sw / 2), yy += strH); + } + } + + public static void main(String argv[]) { + createDemoFrame(new AllFonts()); + } + + + static class DemoControls extends CustomControls implements ActionListener, + ChangeListener { + + AllFonts demo; + JSlider slider; + int fsize[] = { 8, 14, 18, 24 }; + JMenuItem menuitem[] = new JMenuItem[fsize.length]; + Font font[] = new Font[fsize.length]; + + @SuppressWarnings("LeakingThisInConstructor") + public DemoControls(AllFonts demo) { + this.demo = demo; + setBackground(GRAY); + + int sleepAmount = (int) demo.getSleepAmount(); + slider = new JSlider(SwingConstants.HORIZONTAL, 0, 999, sleepAmount); + slider.setBorder(new EtchedBorder()); + slider.setPreferredSize(new Dimension(90, 22)); + slider.addChangeListener(this); + add(slider); + JMenuBar menubar = new JMenuBar(); + add(menubar); + JMenu menu = menubar.add(new JMenu("Font Size")); + for (int i = 0; i < fsize.length; i++) { + font[i] = new Font(Font.SERIF, Font.PLAIN, fsize[i]); + menuitem[i] = menu.add(new JMenuItem(String.valueOf(fsize[i]))); + menuitem[i].setFont(font[i]); + menuitem[i].addActionListener(this); + } + } + + @Override + public void actionPerformed(ActionEvent e) { + for (int i = 0; i < fsize.length; i++) { + if (e.getSource().equals(menuitem[i])) { + demo.fsize = fsize[i]; + Dimension d = demo.getSize(); + demo.reset(d.width, d.height); + break; + } + } + } + + @Override + public void stateChanged(ChangeEvent e) { + demo.setSleepAmount(slider.getValue()); + } + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/AttributedStr.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/AttributedStr.java new file mode 100644 index 00000000000..a36dd140fe1 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/AttributedStr.java @@ -0,0 +1,190 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Fonts; + + +import static java.awt.Font.BOLD; +import static java.awt.Font.ITALIC; +import static java.awt.Font.PLAIN; +import static java.awt.font.TextAttribute.BACKGROUND; +import static java.awt.font.TextAttribute.CHAR_REPLACEMENT; +import static java.awt.font.TextAttribute.FONT; +import static java.awt.font.TextAttribute.FOREGROUND; +import static java.awt.font.TextAttribute.UNDERLINE; +import static java.awt.font.TextAttribute.UNDERLINE_ON; +import java.awt.Color; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.TexturePaint; +import java.awt.font.FontRenderContext; +import java.awt.font.GraphicAttribute; +import java.awt.font.ImageGraphicAttribute; +import java.awt.font.LineBreakMeasurer; +import java.awt.font.ShapeGraphicAttribute; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.image.BufferedImage; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java2d.Surface; + + +/** + * Demonstrates how to build an AttributedString and then render the + * string broken over lines. + */ +@SuppressWarnings("serial") +public class AttributedStr extends Surface { + + static final Color black = new Color(20, 20, 20); + static final Color blue = new Color(94, 105, 176); + static final Color yellow = new Color(255, 255, 140); + static final Color red = new Color(149, 43, 42); + static final Color white = new Color(240, 240, 255); + static final String text = + " A quick brown fox jumped over the lazy duke "; + static final AttributedString as = new AttributedString(text); + static AttributedCharacterIterator aci; + + static { + Shape shape = new Ellipse2D.Double(0, 25, 12, 12); + ShapeGraphicAttribute sga = new ShapeGraphicAttribute(shape, + GraphicAttribute.TOP_ALIGNMENT, false); + as.addAttribute(CHAR_REPLACEMENT, sga, 0, 1); + + + Font font = new Font("sanserif", BOLD | ITALIC, 20); + int index = text.indexOf("quick"); + as.addAttribute(FONT, font, index, index + 5); + + index = text.indexOf("brown"); + font = new Font(Font.SERIF, BOLD, 20); + as.addAttribute(FONT, font, index, index + 5); + as.addAttribute(FOREGROUND, red, index, index + 5); + + index = text.indexOf("fox"); + AffineTransform fontAT = new AffineTransform(); + fontAT.rotate(Math.toRadians(10)); + Font fx = new Font(Font.SERIF, BOLD, 30).deriveFont(fontAT); + as.addAttribute(FONT, fx, index, index + 1); + as.addAttribute(FONT, fx, index + 1, index + 2); + as.addAttribute(FONT, fx, index + 2, index + 3); + + fontAT.setToRotation(Math.toRadians(-4)); + fx = font.deriveFont(fontAT); + index = text.indexOf("jumped"); + as.addAttribute(FONT, fx, index, index + 6); + + font = new Font(Font.SERIF, BOLD | ITALIC, 30); + index = text.indexOf("over"); + as.addAttribute(UNDERLINE, UNDERLINE_ON, index, index + 4); + as.addAttribute(FOREGROUND, white, index, index + 4); + as.addAttribute(FONT, font, index, text.length()); + + font = new Font(Font.DIALOG, PLAIN, 20); + int i = text.indexOf("duke"); + as.addAttribute(FONT, font, index, i - 1); + + BufferedImage bi = new BufferedImage(4, 4, BufferedImage.TYPE_INT_ARGB); + bi.setRGB(0, 0, 0xffffffff); + TexturePaint tp = new TexturePaint(bi, new Rectangle(0, 0, 4, 4)); + as.addAttribute(BACKGROUND, tp, i, i + 4); + font = new Font(Font.SERIF, BOLD, 40); + as.addAttribute(FONT, font, i, i + 4); + } + + public AttributedStr() { + setBackground(Color.white); + + Font font = getFont("A.ttf"); + if (font != null) { + font = font.deriveFont(PLAIN, 70); + } else { + font = new Font(Font.SERIF, PLAIN, 50); + } + int index = text.indexOf("A") + 1; + as.addAttribute(FONT, font, 0, index); + as.addAttribute(FOREGROUND, white, 0, index); + + font = new Font(Font.DIALOG, PLAIN, 40); + int size = getFontMetrics(font).getHeight(); + BufferedImage bi = + new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); + Graphics2D big = bi.createGraphics(); + big.drawImage(getImage("snooze.png"), 0, 0, size, size, null); + ImageGraphicAttribute iga = + new ImageGraphicAttribute(bi, GraphicAttribute.TOP_ALIGNMENT); + as.addAttribute(CHAR_REPLACEMENT, iga, text.length() - 1, text.length()); + + aci = as.getIterator(); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + float x = 5, y = 0; + FontRenderContext frc = g2.getFontRenderContext(); + LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc); + + g2.setPaint(new GradientPaint(0, h, blue, w, 0, black)); + g2.fillRect(0, 0, w, h); + + g2.setColor(white); + String s = "AttributedString LineBreakMeasurer"; + Font font = new Font(Font.SERIF, PLAIN, 12); + TextLayout tl = new TextLayout(s, font, frc); + + tl.draw(g2, 5, y += (float) tl.getBounds().getHeight()); + + g2.setColor(yellow); + + while (y < h - tl.getAscent()) { + lbm.setPosition(0); + while (lbm.getPosition() < text.length()) { + tl = lbm.nextLayout(w - x); + if (!tl.isLeftToRight()) { + x = w - tl.getAdvance(); + } + tl.draw(g2, x, y += tl.getAscent()); + y += tl.getDescent() + tl.getLeading(); + } + } + } + + public static void main(String s[]) { + createDemoFrame(new AttributedStr()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/Highlighting.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/Highlighting.java new file mode 100644 index 00000000000..3149e5679a7 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/Highlighting.java @@ -0,0 +1,135 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Fonts; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.CYAN; +import static java.awt.Color.LIGHT_GRAY; +import static java.awt.Color.WHITE; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.TextHitInfo; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java2d.AnimatingSurface; + + +/** + * Highlighting of text showing the caret, the highlight & the character + * advances. + */ +@SuppressWarnings("serial") +public class Highlighting extends AnimatingSurface { + + private static String text[] = { "HIGHLIGHTING", "OpenJDK" }; + private static Color colors[] = { CYAN, LIGHT_GRAY }; + private static Font smallF = new Font("Monospaced", Font.PLAIN, 8); + private int[] curPos; + private TextLayout[] layouts; + private Font[] fonts; + + public Highlighting() { + setBackground(WHITE); + fonts = new Font[2]; + layouts = new TextLayout[fonts.length]; + curPos = new int[fonts.length]; + } + + @Override + public void reset(int w, int h) { + fonts[0] = new Font("Monospaced", Font.PLAIN, w / text[0].length() + 8); + fonts[1] = new Font("Serif", Font.BOLD, w / text[1].length()); + for (int i = 0; i < layouts.length; i++) { + curPos[i] = 0; + } + } + + @Override + public void step(int w, int h) { + setSleepAmount(900); + for (int i = 0; i < 2; i++) { + if (layouts[i] == null) { + continue; + } + if (curPos[i]++ == layouts[i].getCharacterCount()) { + curPos[i] = 0; + } + } + } + + @Override + public void render(int w, int h, Graphics2D g2) { + FontRenderContext frc = g2.getFontRenderContext(); + for (int i = 0; i < 2; i++) { + layouts[i] = new TextLayout(text[i], fonts[i], frc); + float rw = layouts[i].getAdvance(); + float rx = ((w - rw) / 2); + float ry = ((i == 0) ? h / 3 : h * 0.75f); + + // draw highlighted shape + Shape hilite = layouts[i].getLogicalHighlightShape(0, curPos[i]); + AffineTransform at = AffineTransform.getTranslateInstance(rx, ry); + hilite = at.createTransformedShape(hilite); + float hy = (float) hilite.getBounds2D().getY(); + float hh = (float) hilite.getBounds2D().getHeight(); + g2.setColor(colors[i]); + g2.fill(hilite); + + // get caret shape + Shape[] shapes = layouts[i].getCaretShapes(curPos[i]); + Shape caret = at.createTransformedShape(shapes[0]); + + g2.setColor(BLACK); + layouts[i].draw(g2, rx, ry); + g2.draw(caret); + g2.draw(new Rectangle2D.Float(rx, hy, rw, hh)); + + // Display character advances. + for (int j = 0; j <= layouts[i].getCharacterCount(); j++) { + float[] cInfo = layouts[i].getCaretInfo(TextHitInfo.leading(j)); + String str = String.valueOf((int) cInfo[0]); + TextLayout tl = new TextLayout(str, smallF, frc); + tl.draw(g2, rx + cInfo[0] - tl.getAdvance() / 2, hy + hh + tl. + getAscent() + 1.0f); + } + } + } + + public static void main(String argv[]) { + createDemoFrame(new Highlighting()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/Outline.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/Outline.java new file mode 100644 index 00000000000..84917936b67 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/Outline.java @@ -0,0 +1,115 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Fonts; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.BLUE; +import static java.awt.Color.GREEN; +import static java.awt.Color.MAGENTA; +import static java.awt.Color.RED; +import static java.awt.Color.WHITE; +import java.awt.BasicStroke; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java2d.Surface; + + +/** + * Rendering text as an outline shape. + */ +@SuppressWarnings("serial") +public class Outline extends Surface { + + public Outline() { + setBackground(WHITE); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + FontRenderContext frc = g2.getFontRenderContext(); + Font f = new Font(Font.SANS_SERIF, Font.PLAIN, w / 8); + Font f1 = new Font(Font.SANS_SERIF, Font.ITALIC, w / 8); + String s = "AttributedString"; + AttributedString as = new AttributedString(s); + as.addAttribute(TextAttribute.FONT, f, 0, 10); + as.addAttribute(TextAttribute.FONT, f1, 10, s.length()); + AttributedCharacterIterator aci = as.getIterator(); + TextLayout tl = new TextLayout(aci, frc); + float sw = (float) tl.getBounds().getWidth(); + float sh = (float) tl.getBounds().getHeight(); + Shape sha = tl.getOutline(AffineTransform.getTranslateInstance(w / 2 - sw + / 2, h * 0.2 + sh / 2)); + g2.setColor(BLUE); + g2.setStroke(new BasicStroke(1.5f)); + g2.draw(sha); + g2.setColor(MAGENTA); + g2.fill(sha); + + f = new Font(Font.SERIF, Font.BOLD, w / 6); + tl = new TextLayout("Outline", f, frc); + sw = (float) tl.getBounds().getWidth(); + sh = (float) tl.getBounds().getHeight(); + sha = tl.getOutline(AffineTransform.getTranslateInstance(w / 2 - sw / 2, h + * 0.5 + sh / 2)); + g2.setColor(BLACK); + g2.draw(sha); + g2.setColor(RED); + g2.fill(sha); + + f = new Font(Font.SANS_SERIF, Font.ITALIC, w / 8); + AffineTransform fontAT = new AffineTransform(); + fontAT.shear(-0.2, 0.0); + Font derivedFont = f.deriveFont(fontAT); + tl = new TextLayout("Italic-Shear", derivedFont, frc); + sw = (float) tl.getBounds().getWidth(); + sh = (float) tl.getBounds().getHeight(); + sha = tl.getOutline(AffineTransform.getTranslateInstance(w / 2 - sw / 2, h + * 0.80f + sh / 2)); + g2.setColor(GREEN); + g2.draw(sha); + g2.setColor(BLACK); + g2.fill(sha); + } + + public static void main(String s[]) { + createDemoFrame(new Outline()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/Tree.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/Tree.java new file mode 100644 index 00000000000..17fde4caaba --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Fonts/Tree.java @@ -0,0 +1,129 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Fonts; + + +import static java.awt.Color.BLUE; +import static java.awt.Color.GREEN; +import static java.awt.Color.RED; +import static java.awt.Color.WHITE; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java2d.AnimatingSurface; + + +/** + * Transformation of characters. + */ +@SuppressWarnings("serial") +public class Tree extends AnimatingSurface { + + private char theC = 'A'; + private Character theT = new Character(theC); + private Character theR = new Character((char) (theC + 1)); + + public Tree() { + setBackground(WHITE); + } + + @Override + public void reset(int w, int h) { + } + + @Override + public void step(int w, int h) { + setSleepAmount(4000); + theT = new Character(theC = ((char) (theC + 1))); + theR = new Character((char) (theC + 1)); + if (theR.compareTo(new Character('z')) == 0) { + theC = 'A'; + } + } + + @Override + public void render(int w, int h, Graphics2D g2) { + int mindim = Math.min(w, h); + AffineTransform at = new AffineTransform(); + at.translate((w - mindim) / 2.0, + (h - mindim) / 2.0); + at.scale(mindim, mindim); + at.translate(0.5, 0.5); + at.scale(0.3, 0.3); + at.translate(-(Twidth + Rwidth), FontHeight / 4.0); + g2.transform(at); + tree(g2, mindim * 0.3, 0); + + } + static Font theFont = new Font(Font.SERIF, Font.PLAIN, 1); + static double Twidth = 0.6; + static double Rwidth = 0.6; + static double FontHeight = 0.75; + static Color colors[] = { BLUE, + RED.darker(), + GREEN.darker() }; + + public void tree(Graphics2D g2d, double size, int phase) { + g2d.setColor(colors[phase % 3]); + new TextLayout(theT.toString(), theFont, g2d.getFontRenderContext()). + draw(g2d, 0.0f, 0.0f); + if (size > 10.0) { + AffineTransform at = new AffineTransform(); + at.setToTranslation(Twidth, -0.1); + at.scale(0.6, 0.6); + g2d.transform(at); + size *= 0.6; + new TextLayout(theR.toString(), theFont, g2d.getFontRenderContext()). + draw(g2d, 0.0f, 0.0f); + at.setToTranslation(Rwidth + 0.75, 0); + g2d.transform(at); + Graphics2D g2dt = (Graphics2D) g2d.create(); + at.setToRotation(-Math.PI / 2.0); + g2dt.transform(at); + tree(g2dt, size, phase + 1); + g2dt.dispose(); + at.setToTranslation(.75, 0); + at.rotate(-Math.PI / 2.0); + at.scale(-1.0, 1.0); + at.translate(-Twidth, 0); + g2d.transform(at); + tree(g2d, size, phase); + } + g2d.setTransform(new AffineTransform()); + } + + public static void main(String argv[]) { + createDemoFrame(new Tree()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Images/DukeAnim.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Images/DukeAnim.java new file mode 100644 index 00000000000..7bd6f2b1874 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Images/DukeAnim.java @@ -0,0 +1,97 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Images; + + +import java.awt.*; +import javax.swing.JButton; +import java.awt.image.ImageObserver; +import java2d.AnimatingSurface; +import java2d.DemoPanel; + + +/** + * Animated gif with a transparent background. + */ +@SuppressWarnings("serial") +public class DukeAnim extends AnimatingSurface implements ImageObserver { + + private static Image agif, clouds; + private static int aw, ah, cw; + private int x; + private JButton b; + + @SuppressWarnings("LeakingThisInConstructor") + public DukeAnim() { + setBackground(Color.white); + clouds = getImage("clouds.jpg"); + agif = getImage("duke.running.gif"); + aw = agif.getWidth(this) / 2; + ah = agif.getHeight(this) / 2; + cw = clouds.getWidth(this); + dontThread = true; + } + + @Override + public void reset(int w, int h) { + b = ((DemoPanel) getParent()).tools.startStopB; + } + + @Override + public void step(int w, int h) { + } + + @Override + public void render(int w, int h, Graphics2D g2) { + if ((x -= 3) <= -cw) { + x = w; + } + g2.drawImage(clouds, x, 10, cw, h - 20, this); + g2.drawImage(agif, w / 2 - aw, h / 2 - ah, this); + } + + @Override + public boolean imageUpdate(Image img, int infoflags, + int x, int y, int width, int height) { + if (b.isSelected() && (infoflags & ALLBITS) != 0) { + repaint(); + } + if (b.isSelected() && (infoflags & FRAMEBITS) != 0) { + repaint(); + } + return isShowing(); + } + + public static void main(String s[]) { + createDemoFrame(new DukeAnim()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Images/ImageOps.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Images/ImageOps.java new file mode 100644 index 00000000000..93ace5beb9f --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Images/ImageOps.java @@ -0,0 +1,277 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Images; + + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ByteLookupTable; +import java.awt.image.ConvolveOp; +import java.awt.image.Kernel; +import java.awt.image.LookupOp; +import java.awt.image.RescaleOp; +import java2d.ControlsSurface; +import java2d.CustomControls; +import javax.swing.JComboBox; +import javax.swing.JSlider; +import javax.swing.SwingConstants; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + + +/** + * Images drawn using operators such as ConvolveOp LowPass & Sharpen, + * LookupOp and RescaleOp. + */ +@SuppressWarnings("serial") +public class ImageOps extends ControlsSurface implements ChangeListener { + + protected JSlider slider1, slider2; + private static final String imgName[] = { "bld.jpg", "boat.png" }; + private static final BufferedImage img[] = new BufferedImage[imgName.length]; + private static final String opsName[] = { + "Threshold", "RescaleOp", "Invert", "Yellow Invert", "3x3 Blur", + "3x3 Sharpen", "3x3 Edge", "5x5 Edge" }; + private static final BufferedImageOp biop[] = + new BufferedImageOp[opsName.length]; + private static int rescaleFactor = 128; + private static float rescaleOffset = 0; + private static final int low = 100, high = 200; + private int opsIndex, imgIndex; + + static { + thresholdOp(low, high); + int i = 1; + biop[i++] = new RescaleOp(1.0f, 0, null); + byte invert[] = new byte[256]; + byte ordered[] = new byte[256]; + for (int j = 0; j < 256; j++) { + invert[j] = (byte) (256 - j); + ordered[j] = (byte) j; + } + biop[i++] = new LookupOp(new ByteLookupTable(0, invert), null); + byte[][] yellowInvert = new byte[][] { invert, invert, ordered }; + biop[i++] = new LookupOp(new ByteLookupTable(0, yellowInvert), null); + int dim[][] = { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 5, 5 } }; + float data[][] = { { 0.1f, 0.1f, 0.1f, // 3x3 blur + 0.1f, 0.2f, 0.1f, + 0.1f, 0.1f, 0.1f }, + { -1.0f, -1.0f, -1.0f, // 3x3 sharpen + -1.0f, 9.0f, -1.0f, + -1.0f, -1.0f, -1.0f }, + { 0.f, -1.f, 0.f, // 3x3 edge + -1.f, 5.f, -1.f, + 0.f, -1.f, 0.f }, + { -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, // 5x5 edge + -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 24.0f, -1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, -1.0f } }; + for (int j = 0; j < data.length; j++, i++) { + biop[i] = new ConvolveOp(new Kernel(dim[j][0], dim[j][1], data[j])); + } + } + + @SuppressWarnings("LeakingThisInConstructor") + public ImageOps() { + setDoubleBuffered(true); + setBackground(Color.white); + for (int i = 0; i < imgName.length; i++) { + Image image = getImage(imgName[i]); + int iw = image.getWidth(this); + int ih = image.getHeight(this); + img[i] = new BufferedImage(iw, ih, BufferedImage.TYPE_INT_RGB); + img[i].createGraphics().drawImage(image, 0, 0, null); + } + slider1 = new JSlider(SwingConstants.VERTICAL, 0, 255, low); + slider1.setPreferredSize(new Dimension(15, 100)); + slider1.addChangeListener(this); + slider2 = new JSlider(SwingConstants.VERTICAL, 0, 255, high); + slider2.setPreferredSize(new Dimension(15, 100)); + slider2.addChangeListener(this); + setControls(new Component[] { new DemoControls(this), slider1, slider2 }); + setConstraints(new String[] { + BorderLayout.NORTH, BorderLayout.WEST, BorderLayout.EAST }); + } + + public static void thresholdOp(int low, int high) { + byte threshold[] = new byte[256]; + for (int j = 0; j < 256; j++) { + if (j > high) { + threshold[j] = (byte) 255; + } else if (j < low) { + threshold[j] = (byte) 0; + } else { + threshold[j] = (byte) j; + } + } + biop[0] = new LookupOp(new ByteLookupTable(0, threshold), null); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + int iw = img[imgIndex].getWidth(null); + int ih = img[imgIndex].getHeight(null); + AffineTransform oldXform = g2.getTransform(); + g2.scale(((double) w) / iw, ((double) h) / ih); + g2.drawImage(img[imgIndex], biop[opsIndex], 0, 0); + g2.setTransform(oldXform); + } + + @Override + public void stateChanged(ChangeEvent e) { + if (e.getSource().equals(slider1)) { + if (opsIndex == 0) { + thresholdOp(slider1.getValue(), high); + } else { + rescaleFactor = slider1.getValue(); + biop[1] = new RescaleOp(rescaleFactor / 128.0f, rescaleOffset, + null); + } + } else { + if (opsIndex == 0) { + thresholdOp(low, slider2.getValue()); + } else { + rescaleOffset = slider2.getValue(); + biop[1] = new RescaleOp(rescaleFactor / 128.0f, rescaleOffset, + null); + } + + } + repaint(); + } + + public static void main(String s[]) { + createDemoFrame(new ImageOps()); + } + + + static class DemoControls extends CustomControls implements ActionListener { + + ImageOps demo; + JComboBox imgCombo, opsCombo; + Font font = new Font(Font.SERIF, Font.PLAIN, 10); + + @SuppressWarnings("LeakingThisInConstructor") + public DemoControls(ImageOps demo) { + super(demo.name); + this.demo = demo; + add(imgCombo = new JComboBox()); + imgCombo.setFont(font); + for (String name : ImageOps.imgName) { + imgCombo.addItem(name); + } + imgCombo.addActionListener(this); + add(opsCombo = new JComboBox()); + opsCombo.setFont(font); + for (String name : ImageOps.opsName) { + opsCombo.addItem(name); + } + opsCombo.addActionListener(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource().equals(opsCombo)) { + demo.opsIndex = opsCombo.getSelectedIndex(); + if (demo.opsIndex == 0) { + demo.slider1.setValue(ImageOps.low); + demo.slider2.setValue(ImageOps.high); + demo.slider1.setEnabled(true); + demo.slider2.setEnabled(true); + } else if (demo.opsIndex == 1) { + demo.slider1.setValue(ImageOps.rescaleFactor); + demo.slider2.setValue((int) ImageOps.rescaleOffset); + demo.slider1.setEnabled(true); + demo.slider2.setEnabled(true); + } else { + demo.slider1.setEnabled(false); + demo.slider2.setEnabled(false); + } + } else if (e.getSource().equals(imgCombo)) { + demo.imgIndex = imgCombo.getSelectedIndex(); + } + demo.repaint(10); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 39); + } + + @Override + @SuppressWarnings("SleepWhileHoldingLock") + public void run() { + try { + Thread.sleep(1111); + } catch (Exception e) { + return; + } + Thread me = Thread.currentThread(); + while (thread == me) { + for (int i = 0; i < ImageOps.imgName.length; i++) { + imgCombo.setSelectedIndex(i); + for (int j = 0; j < ImageOps.opsName.length; j++) { + opsCombo.setSelectedIndex(j); + if (j <= 1) { + for (int k = 50; k <= 200; k += 10) { + demo.slider1.setValue(k); + try { + Thread.sleep(200); + } catch (InterruptedException e) { + return; + } + } + } + try { + Thread.sleep(4444); + } catch (InterruptedException e) { + return; + } + } + } + } + thread = null; + } + } // End DemoControls +} // End ImageOps + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Images/JPEGFlip.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Images/JPEGFlip.java new file mode 100644 index 00000000000..9f7aac490d6 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Images/JPEGFlip.java @@ -0,0 +1,182 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Images; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.GREEN; +import static java.awt.Color.RED; +import static java.awt.Color.WHITE; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.geom.GeneralPath; +import java.awt.geom.Path2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java2d.Surface; +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.plugins.jpeg.JPEGImageWriteParam; +import javax.imageio.stream.ImageOutputStream; + + +/** + * Render a filled star & duke into a BufferedImage, save the BufferedImage + * as a JPEG, display the BufferedImage, using the decoded JPEG BufferedImage + * display the JPEG flipped BufferedImage. + */ +@SuppressWarnings("serial") +public class JPEGFlip extends Surface { + + private static Image img; + + public JPEGFlip() { + setBackground(WHITE); + img = getImage("duke.png"); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + int hh = h / 2; + + BufferedImage bi = new BufferedImage(w, hh, BufferedImage.TYPE_INT_RGB); + Graphics2D big = bi.createGraphics(); + + // .. use rendering hints from J2DCanvas .. + big.setRenderingHints(g2.getRenderingHints()); + + big.setBackground(getBackground()); + big.clearRect(0, 0, w, hh); + + big.setColor(GREEN.darker()); + GeneralPath p = new GeneralPath(Path2D.WIND_NON_ZERO); + p.moveTo(-w / 2.0f, -hh / 8.0f); + p.lineTo(+w / 2.0f, -hh / 8.0f); + p.lineTo(-w / 4.0f, +hh / 2.0f); + p.lineTo(+0.0f, -hh / 2.0f); + p.lineTo(+w / 4.0f, +hh / 2.0f); + p.closePath(); + big.translate(w / 2, hh / 2); + big.fill(p); + + float scale = 0.09f; + int iw = (int) (scale * w); + int ih = (int) (img.getHeight(null) * iw / img.getWidth(null)); + big.drawImage(img, -iw / 2, -ih / 2, iw, ih, this); + + g2.drawImage(bi, 0, 0, this); + g2.setFont(new Font("Dialog", Font.PLAIN, 10)); + g2.setColor(BLACK); + g2.drawString("BufferedImage", 4, 12); + + + BufferedImage bi1 = null; + ImageOutputStream ios = null; + // To write the jpeg to a file uncomment the File* lines and + // comment out the ByteArray*Stream lines. + //FileOutputStream out = null; + ByteArrayOutputStream out = null; + //FileInputStream in = null; + ByteArrayInputStream in = null; + try { + //File file = new File("images", "test.jpg"); + //out = new FileOutputStream(file); + out = new ByteArrayOutputStream(); + ios = ImageIO.createImageOutputStream(out); + ImageWriter encoder = + ImageIO.getImageWritersByFormatName("JPEG").next(); + JPEGImageWriteParam param = new JPEGImageWriteParam(null); + + param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + param.setCompressionQuality(1.0f); + + encoder.setOutput(ios); + encoder.write(null, new IIOImage(bi, null, null), param); + + //in = new FileInputStream(file); + in = new ByteArrayInputStream(out.toByteArray()); + bi1 = ImageIO.read(in); + } catch (Exception ex) { + g2.setColor(RED); + g2.drawString("Error encoding or decoding the image", 5, hh * 2 - 5); + return; + } finally { + if (ios != null) { + try { + ios.close(); + } catch (IOException ex) { + Logger.getLogger(JPEGFlip.class.getName()).log(Level.SEVERE, + null, ex); + } + } + if (out != null) { + try { + out.close(); + } catch (IOException ex) { + Logger.getLogger(JPEGFlip.class.getName()).log(Level.SEVERE, + null, ex); + } + } + if (in != null) { + try { + in.close(); + } catch (IOException ex) { + Logger.getLogger(JPEGFlip.class.getName()).log(Level.SEVERE, + null, ex); + } + } + } + + if (bi1 == null) { + g2.setColor(RED); + g2.drawString("Error reading the image", 5, hh * 2 - 5); + return; + } + + g2.drawImage(bi1, w, hh * 2, -w, -hh, null); + + g2.drawString("JPEGImage Flipped", 4, hh * 2 - 4); + g2.drawLine(0, hh, w, hh); + } + + public static void main(String s[]) { + createDemoFrame(new JPEGFlip()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Images/WarpImage.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Images/WarpImage.java new file mode 100644 index 00000000000..627700c13f2 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Images/WarpImage.java @@ -0,0 +1,134 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Images; + + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java2d.AnimatingSurface; + + +/** + * Warps a image on a CubicCurve2D flattened path. + */ +@SuppressWarnings("serial") +public class WarpImage extends AnimatingSurface { + + private static int iw, ih, iw2, ih2; + private static Image img; + private static final int FORWARD = 0; + private static final int BACK = 1; + private Point2D pts[]; + private int direction = FORWARD; + private int pNum; + private int x, y; + + @SuppressWarnings("LeakingThisInConstructor") + public WarpImage() { + setBackground(Color.white); + img = getImage("surfing.png"); + iw = img.getWidth(this); + ih = img.getHeight(this); + iw2 = iw / 2; + ih2 = ih / 2; + } + + @Override + public void reset(int w, int h) { + pNum = 0; + direction = FORWARD; + CubicCurve2D cc = new CubicCurve2D.Float( + w * .2f, h * .5f, w * .4f, 0, w * .6f, h, w * .8f, h * .5f); + PathIterator pi = cc.getPathIterator(null, 0.1); + Point2D tmp[] = new Point2D[200]; + int i = 0; + while (!pi.isDone()) { + float[] coords = new float[6]; + switch (pi.currentSegment(coords)) { + case PathIterator.SEG_MOVETO: + case PathIterator.SEG_LINETO: + tmp[i] = new Point2D.Float(coords[0], coords[1]); + } + i++; + pi.next(); + } + pts = new Point2D[i]; + System.arraycopy(tmp, 0, pts, 0, i); + } + + @Override + public void step(int w, int h) { + if (pts == null) { + return; + } + x = (int) pts[pNum].getX(); + y = (int) pts[pNum].getY(); + if (direction == FORWARD) { + if (++pNum == pts.length) { + direction = BACK; + } + } + if (direction == BACK) { + if (--pNum == 0) { + direction = FORWARD; + } + } + } + + @Override + public void render(int w, int h, Graphics2D g2) { + g2.drawImage(img, + 0, 0, x, y, + 0, 0, iw2, ih2, + this); + g2.drawImage(img, + x, 0, w, y, + iw2, 0, iw, ih2, + this); + g2.drawImage(img, + 0, y, x, h, + 0, ih2, iw2, ih, + this); + g2.drawImage(img, + x, y, w, h, + iw2, ih2, iw, ih, + this); + } + + public static void main(String argv[]) { + createDemoFrame(new WarpImage()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/Caps.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/Caps.java new file mode 100644 index 00000000000..335c4351def --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/Caps.java @@ -0,0 +1,81 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Lines; + + +import static java.awt.BasicStroke.CAP_BUTT; +import static java.awt.BasicStroke.CAP_ROUND; +import static java.awt.BasicStroke.CAP_SQUARE; +import static java.awt.BasicStroke.JOIN_MITER; +import static java.awt.Color.BLACK; +import static java.awt.Color.WHITE; +import java.awt.BasicStroke; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; +import java.awt.geom.Line2D; +import java2d.Surface; + + +/** + * Shows the three different styles of stroke ending. + */ +@SuppressWarnings("serial") +public class Caps extends Surface { + + private static int cap[] = { CAP_BUTT, CAP_ROUND, CAP_SQUARE }; + private static String desc[] = { "Butt Cap", "Round Cap", "Square Cap" }; + + public Caps() { + setBackground(WHITE); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + FontRenderContext frc = g2.getFontRenderContext(); + Font font = g2.getFont(); + g2.setColor(BLACK); + for (int i = 0; i < cap.length; i++) { + g2.setStroke(new BasicStroke(15, cap[i], JOIN_MITER)); + g2.draw(new Line2D.Float(w / 4, (i + 1) * h / 4, w - w / 4, (i + 1) + * h / 4)); + TextLayout tl = new TextLayout(desc[i], font, frc); + tl.draw(g2, (float) (w / 2 - tl.getBounds().getWidth() / 2), (i + 1) + * h / 4 - 10); + } + } + + public static void main(String s[]) { + createDemoFrame(new Caps()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/Dash.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/Dash.java new file mode 100644 index 00000000000..2e5e1c9cf2b --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/Dash.java @@ -0,0 +1,134 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Lines; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.WHITE; +import java.awt.BasicStroke; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; +import java.awt.geom.Arc2D; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.Ellipse2D; +import java.awt.geom.QuadCurve2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; +import java2d.Surface; + + +/** + * Various shapes stroked with a dashing pattern. + */ +@SuppressWarnings("serial") +public class Dash extends Surface { + + public Dash() { + setBackground(WHITE); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + FontRenderContext frc = g2.getFontRenderContext(); + Font font = g2.getFont(); + TextLayout tl = new TextLayout("Dashes", font, frc); + float sw = (float) tl.getBounds().getWidth(); + float sh = tl.getAscent() + tl.getDescent(); + g2.setColor(BLACK); + tl.draw(g2, (w / 2 - sw / 2), sh + 5); + + BasicStroke dotted = new BasicStroke(3, BasicStroke.CAP_ROUND, + BasicStroke.JOIN_ROUND, 0, new float[] { 0, 6, 0, 6 }, 0); + g2.setStroke(dotted); + g2.drawRect(3, 3, w - 6, h - 6); + + int x = 0; + int y = h - 34; + BasicStroke bs[] = new BasicStroke[6]; + + float j = 1.1f; + for (int i = 0; i < bs.length; i++, j += 1.0f) { + float dash[] = { j }; + BasicStroke b = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f); + g2.setStroke(b); + g2.drawLine(20, y, w - 20, y); + bs[i] = new BasicStroke(3.0f, BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f); + y += 5; + } + + Shape shape = null; + y = 0; + for (int i = 0; i < 6; i++) { + x = (i == 0 || i == 3) ? (w / 3 - w / 5) / 2 : x + w / 3; + y = (i <= 2) ? (int) sh + h / 12 : h / 2; + + g2.setStroke(bs[i]); + g2.translate(x, y); + switch (i) { + case 0: + shape = new Arc2D.Float(0.0f, 0.0f, w / 5, h / 4, 45, 270, + Arc2D.PIE); + break; + case 1: + shape = new Ellipse2D.Float(0.0f, 0.0f, w / 5, h / 4); + break; + case 2: + shape = new RoundRectangle2D.Float(0.0f, 0.0f, w / 5, h / 4, + 10.0f, 10.0f); + break; + case 3: + shape = new Rectangle2D.Float(0.0f, 0.0f, w / 5, h / 4); + break; + case 4: + shape = new QuadCurve2D.Float(0.0f, 0.0f, w / 10, h / 2, w + / 5, 0.0f); + break; + case 5: + shape = new CubicCurve2D.Float(0.0f, 0.0f, w / 15, h / 2, w + / 10, h / 4, w / 5, 0.0f); + break; + } + + g2.draw(shape); + g2.translate(-x, -y); + } + } + + public static void main(String argv[]) { + createDemoFrame(new Dash()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/Joins.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/Joins.java new file mode 100644 index 00000000000..bead0a26fae --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/Joins.java @@ -0,0 +1,247 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Lines; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.WHITE; +import java.awt.BasicStroke; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.geom.GeneralPath; +import java2d.ControlsSurface; +import java2d.CustomControls; +import javax.swing.Icon; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JSlider; +import javax.swing.JToolBar; +import javax.swing.SwingConstants; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + + +/** + * BasicStroke join types and width sizes illustrated. Control for + * rendering a shape returned from BasicStroke.createStrokedShape(Shape). + */ +@SuppressWarnings("serial") +public class Joins extends ControlsSurface { + + protected int joinType = BasicStroke.JOIN_MITER; + protected float bswidth = 20.0f; + protected JSlider slider; + protected JLabel label; + + public Joins() { + setBackground(WHITE); + slider = new JSlider(SwingConstants.VERTICAL, 0, 100, + (int) (bswidth * 2)); + slider.setPreferredSize(new Dimension(15, 100)); + slider.addChangeListener(new ChangeListener() { + + public void stateChanged(ChangeEvent e) { + // when using these sliders use double buffering, which means + // ignoring when DemoSurface.imageType = 'On Screen' + if (getImageType() <= 1) { + setImageType(2); + } + bswidth = slider.getValue() / 2.0f; + label.setText(" Width = " + String.valueOf(bswidth)); + label.repaint(); + repaint(); + } + }); + setControls(new Component[] { new DemoControls(this), slider }); + setConstraints(new String[] { BorderLayout.NORTH, BorderLayout.WEST }); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + BasicStroke bs = new BasicStroke(bswidth, + BasicStroke.CAP_BUTT, joinType); + GeneralPath p = new GeneralPath(); + p.moveTo(-w / 4.0f, -h / 12.0f); + p.lineTo(+w / 4.0f, -h / 12.0f); + p.lineTo(-w / 6.0f, +h / 4.0f); + p.lineTo(+0.0f, -h / 4.0f); + p.lineTo(+w / 6.0f, +h / 4.0f); + p.closePath(); + p.closePath(); + g2.translate(w / 2, h / 2); + g2.setColor(BLACK); + g2.draw(bs.createStrokedShape(p)); + } + + public static void main(String s[]) { + createDemoFrame(new Joins()); + } + + + class DemoControls extends CustomControls implements ActionListener { + + Joins demo; + int joinType[] = { BasicStroke.JOIN_MITER, + BasicStroke.JOIN_ROUND, BasicStroke.JOIN_BEVEL }; + String joinName[] = { "Mitered Join", "Rounded Join", "Beveled Join" }; + JMenu menu; + JMenuItem menuitem[] = new JMenuItem[joinType.length]; + JoinIcon icons[] = new JoinIcon[joinType.length]; + JToolBar toolbar; + + @SuppressWarnings("LeakingThisInConstructor") + public DemoControls(Joins demo) { + super(demo.name); + setBorder(new CompoundBorder(getBorder(), + new EmptyBorder(2, 2, 2, 2))); + this.demo = demo; + setLayout(new BorderLayout()); + label = new JLabel(" Width = " + String.valueOf(demo.bswidth)); + Font font = new Font(Font.SERIF, Font.BOLD, 14); + label.setFont(font); + add("West", label); + JMenuBar menubar = new JMenuBar(); + add("East", menubar); + menu = menubar.add(new JMenu(joinName[0])); + menu.setFont(font = new Font(Font.SERIF, Font.PLAIN, 10)); + ActionListener actionListener = new ActionListener() { + + public void actionPerformed(ActionEvent e) { + throw new UnsupportedOperationException("Not supported yet."); + } + }; + for (int i = 0; i < joinType.length; i++) { + icons[i] = new JoinIcon(joinType[i]); + menuitem[i] = menu.add(new JMenuItem(joinName[i])); + menuitem[i].setFont(font); + menuitem[i].setIcon(icons[i]); + menuitem[i].addActionListener(this); + } + menu.setIcon(icons[0]); + } + + @Override + public void actionPerformed(ActionEvent e) { + for (int i = 0; i < joinType.length; i++) { + if (e.getSource().equals(menuitem[i])) { + demo.joinType = joinType[i]; + menu.setIcon(icons[i]); + menu.setText(joinName[i]); + break; + } + } + demo.repaint(); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 37); + } + + @Override + @SuppressWarnings("SleepWhileHoldingLock") + public void run() { + try { + Thread.sleep(999); + } catch (Exception e) { + return; + } + Thread me = Thread.currentThread(); + while (thread == me) { + for (int i = 0; i < menuitem.length; i++) { + menuitem[i].doClick(); + for (int k = 10; k < 60; k += 2) { + demo.slider.setValue(k); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + return; + } + } + try { + Thread.sleep(999); + } catch (InterruptedException e) { + return; + } + } + } + thread = null; + } + + + class JoinIcon implements Icon { + + int joinType; + + public JoinIcon(int joinType) { + this.joinType = joinType; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + ((Graphics2D) g).setRenderingHint( + RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + BasicStroke bs = new BasicStroke(8.0f, + BasicStroke.CAP_BUTT, joinType); + ((Graphics2D) g).setStroke(bs); + GeneralPath p = new GeneralPath(); + p.moveTo(0, 3); + p.lineTo(getIconWidth() - 2, getIconHeight() / 2); + p.lineTo(0, getIconHeight()); + ((Graphics2D) g).draw(p); + } + + @Override + public int getIconWidth() { + return 20; + } + + @Override + public int getIconHeight() { + return 20; + } + } // End JoinIcon class + } // End DemoControls class +} // End Joins class + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/LineAnim.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/LineAnim.java new file mode 100644 index 00000000000..0a4ebc791fa --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Lines/LineAnim.java @@ -0,0 +1,164 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Lines; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.GRAY; +import static java.awt.Color.LIGHT_GRAY; +import static java.awt.Color.PINK; +import static java.awt.Color.WHITE; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java2d.AnimatingSurface; + + +/** + * Lines & Paths animation illustrating BasicStroke attributes. + */ +@SuppressWarnings("serial") +public class LineAnim extends AnimatingSurface { + + private static int caps[] = { BasicStroke.CAP_BUTT, + BasicStroke.CAP_SQUARE, BasicStroke.CAP_ROUND }; + private static int joins[] = { BasicStroke.JOIN_MITER, + BasicStroke.JOIN_BEVEL, BasicStroke.JOIN_ROUND }; + private static Color colors[] = { GRAY, PINK, LIGHT_GRAY }; + private static BasicStroke bs1 = new BasicStroke(1.0f); + private static final int CLOCKWISE = 0; + private Line2D lines[] = new Line2D[3]; + private int rAmt[] = new int[lines.length]; + private int direction[] = new int[lines.length]; + private int speed[] = new int[lines.length]; + private BasicStroke strokes[] = new BasicStroke[lines.length]; + private GeneralPath path; + private Point2D[] pts; + private float size; + private Ellipse2D ellipse = new Ellipse2D.Double(); + + public LineAnim() { + setBackground(WHITE); + } + + @Override + public void reset(int w, int h) { + size = (w > h) ? h / 6f : w / 6f; + for (int i = 0; i < lines.length; i++) { + lines[i] = new Line2D.Float(0, 0, size, 0); + strokes[i] = new BasicStroke(size / 3, caps[i], joins[i]); + rAmt[i] = i * 360 / lines.length; + direction[i] = i % 2; + speed[i] = i + 1; + } + + path = new GeneralPath(); + path.moveTo(size, -size / 2); + path.lineTo(size + size / 2, 0); + path.lineTo(size, +size / 2); + + ellipse.setFrame(w / 2 - size * 2 - 4.5f, h / 2 - size * 2 - 4.5f, size + * 4, size * 4); + PathIterator pi = ellipse.getPathIterator(null, 0.9); + Point2D[] points = new Point2D[100]; + int num_pts = 0; + while (!pi.isDone()) { + float[] pt = new float[6]; + switch (pi.currentSegment(pt)) { + case PathIterator.SEG_MOVETO: + case PathIterator.SEG_LINETO: + points[num_pts] = new Point2D.Float(pt[0], pt[1]); + num_pts++; + } + pi.next(); + } + pts = new Point2D[num_pts]; + System.arraycopy(points, 0, pts, 0, num_pts); + } + + @Override + public void step(int w, int h) { + for (int i = 0; i < lines.length; i++) { + if (direction[i] == CLOCKWISE) { + rAmt[i] += speed[i]; + if (rAmt[i] == 360) { + rAmt[i] = 0; + } + } else { + rAmt[i] -= speed[i]; + if (rAmt[i] == 0) { + rAmt[i] = 360; + } + } + } + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + ellipse.setFrame(w / 2 - size, h / 2 - size, size * 2, size * 2); + g2.setColor(BLACK); + g2.draw(ellipse); + + for (int i = 0; i < lines.length; i++) { + AffineTransform at = AffineTransform.getTranslateInstance(w / 2, h + / 2); + at.rotate(Math.toRadians(rAmt[i])); + g2.setStroke(strokes[i]); + g2.setColor(colors[i]); + g2.draw(at.createTransformedShape(lines[i])); + g2.draw(at.createTransformedShape(path)); + + int j = (int) ((double) rAmt[i] / 360 * pts.length); + j = (j == pts.length) ? pts.length - 1 : j; + ellipse.setFrame(pts[j].getX(), pts[j].getY(), 9, 9); + g2.fill(ellipse); + } + + g2.setStroke(bs1); + g2.setColor(BLACK); + for (int i = 0; i < pts.length; i++) { + ellipse.setFrame(pts[i].getX(), pts[i].getY(), 9, 9); + g2.draw(ellipse); + } + } + + public static void main(String argv[]) { + createDemoFrame(new LineAnim()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Mix/Balls.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Mix/Balls.java new file mode 100644 index 00000000000..3bf57361648 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Mix/Balls.java @@ -0,0 +1,359 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Mix; + + +import static java.awt.Color.BLUE; +import static java.awt.Color.GREEN; +import static java.awt.Color.ORANGE; +import static java.awt.Color.RED; +import static java.awt.Color.WHITE; +import static java.awt.Color.YELLOW; +import static java.lang.Math.random; +import static java.lang.Math.sqrt; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferByte; +import java.awt.image.IndexColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java2d.AnimatingControlsSurface; +import java2d.CustomControls; +import javax.swing.AbstractButton; +import javax.swing.JComboBox; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; + + +/** + * Animated color bouncing balls with custom controls. + */ +@SuppressWarnings("serial") +public class Balls extends AnimatingControlsSurface { + + private static Color colors[] = { RED, ORANGE, YELLOW, GREEN.darker(), BLUE, + new Color(75, 00, 82), new Color(238, 130, 238) }; + private long now, deltaT, lasttime; + private boolean active; + protected Ball balls[] = new Ball[colors.length]; + protected boolean clearToggle; + protected JComboBox combo; + + public Balls() { + setBackground(WHITE); + for (int i = 0; i < colors.length; i++) { + balls[i] = new Ball(colors[i], 30); + } + balls[0].isSelected = true; + balls[3].isSelected = true; + balls[4].isSelected = true; + balls[6].isSelected = true; + setControls(new Component[] { new DemoControls(this) }); + } + + @Override + public void reset(int w, int h) { + if (w > 400 && h > 100) { + combo.setSelectedIndex(5); + } + } + + @Override + public void step(int w, int h) { + if (lasttime == 0) { + lasttime = System.currentTimeMillis(); + } + now = System.currentTimeMillis(); + deltaT = now - lasttime; + active = false; + for (Ball ball : balls) { + if (ball == null) { + return; + } + ball.step(deltaT, w, h); + if (ball.Vy > .02 || -ball.Vy > .02 || ball.y + ball.bsize < h) { + active = true; + } + } + if (!active) { + for (Ball ball : balls) { + ball.Vx = (float) random() / 4.0f - 0.125f; + ball.Vy = -(float) random() / 4.0f - 0.2f; + } + clearToggle = true; + } + } + + @Override + public void render(int w, int h, Graphics2D g2) { + for (Ball b : balls) { + if (b == null || b.imgs[b.index] == null || !b.isSelected) { + continue; + } + g2.drawImage(b.imgs[b.index], (int) b.x, (int) b.y, this); + } + lasttime = now; + } + + public static void main(String argv[]) { + createDemoFrame(new Balls()); + } + + + protected static final class Ball { + + public static final int nImgs = 5; + public int bsize; + public float x, y; + public float Vx = 0.1f; + public float Vy = 0.05f; + public BufferedImage imgs[]; + // Pick a random starting image index, but not the last: we're going UP + // and that would throw us off the end. + public int index = (int) (random() * (nImgs - 1)); + private static final float inelasticity = .96f; + private static final float Ax = 0.0f; + private static final float Ay = 0.0002f; + private static final int UP = 0; + private static final int DOWN = 1; + private int indexDirection = UP; + private float jitter; + private Color color; + private boolean isSelected; + + public Ball(Color color, int bsize) { + this.color = color; + makeImages(bsize); + } + + public void makeImages(int bsize) { + this.bsize = bsize * 2; + int R = bsize; + byte[] data = new byte[R * 2 * R * 2]; + int maxr = 0; + for (int Y = 2 * R; --Y >= 0;) { + int x0 = (int) (sqrt(R * R - (Y - R) * (Y - R)) + 0.5); + int p = Y * (R * 2) + R - x0; + for (int X = -x0; X < x0; X++) { + int xx = X + 15; + int yy = Y - R + 15; + int r = (int) (Math.hypot(xx, yy) + 0.5); + if (r > maxr) { + maxr = r; + } + data[p++] = r <= 0 ? 1 : (byte) r; + } + } + + imgs = new BufferedImage[nImgs]; + + int bg = 255; + byte red[] = new byte[256]; + red[0] = (byte) bg; + byte green[] = new byte[256]; + green[0] = (byte) bg; + byte blue[] = new byte[256]; + blue[0] = (byte) bg; + + for (int r = 0; r < imgs.length; r++) { + float b = 0.5f + ((r + 1f) / imgs.length / 2f); + for (int i = maxr; i >= 1; --i) { + float d = (float) i / maxr; + red[i] = (byte) blend(blend(color.getRed(), 255, d), bg, b); + green[i] = (byte) blend(blend(color.getGreen(), 255, d), bg, + b); + blue[i] = + (byte) blend(blend(color.getBlue(), 255, d), bg, b); + } + IndexColorModel icm = new IndexColorModel(8, maxr + 1, + red, green, blue, 0); + DataBufferByte dbb = new DataBufferByte(data, data.length); + int bandOffsets[] = { 0 }; + WritableRaster wr = Raster.createInterleavedRaster(dbb, + R * 2, R * 2, R * 2, 1, bandOffsets, null); + imgs[r] = new BufferedImage(icm, wr, icm.isAlphaPremultiplied(), + null); + } + } + + private int blend(int fg, int bg, float fgfactor) { + return (int) (bg + (fg - bg) * fgfactor); + } + + public void step(long deltaT, int w, int h) { + + jitter = (float) random() * .01f - .005f; + + x += Vx * deltaT + (Ax / 2.0) * deltaT * deltaT; + y += Vy * deltaT + (Ay / 2.0) * deltaT * deltaT; + if (x <= 0.0f) { + x = 0.0f; + Vx = -Vx * inelasticity + jitter; + //collision_x = true; + } + if (x + bsize >= w) { + x = w - bsize; + Vx = -Vx * inelasticity + jitter; + //collision_x = true; + } + if (y <= 0) { + y = 0; + Vy = -Vy * inelasticity + jitter; + //collision_y = true; + } + if (y + bsize >= h) { + y = h - bsize; + Vx *= inelasticity; + Vy = -Vy * inelasticity + jitter; + //collision_y = true; + } + Vy = Vy + Ay * deltaT; + Vx = Vx + Ax * deltaT; + + if (indexDirection == UP) { + index++; + } + if (indexDirection == DOWN) { + --index; + } + if (index + 1 == nImgs) { + indexDirection = DOWN; + } + if (index == 0) { + indexDirection = UP; + } + } + } // End class Ball + + + final class DemoControls extends CustomControls implements ActionListener { + + Balls demo; + JToolBar toolbar; + + @SuppressWarnings("LeakingThisInConstructor") + public DemoControls(Balls demo) { + super(demo.name); + this.demo = demo; + add(toolbar = new JToolBar()); + toolbar.setFloatable(false); + addTool("Clear", true); + addTool("R", demo.balls[0].isSelected); + addTool("O", demo.balls[1].isSelected); + addTool("Y", demo.balls[2].isSelected); + addTool("G", demo.balls[3].isSelected); + addTool("B", demo.balls[4].isSelected); + addTool("I", demo.balls[5].isSelected); + addTool("V", demo.balls[6].isSelected); + add(combo = new JComboBox()); + combo.addItem("10"); + combo.addItem("20"); + combo.addItem("30"); + combo.addItem("40"); + combo.addItem("50"); + combo.addItem("60"); + combo.addItem("70"); + combo.addItem("80"); + combo.setSelectedIndex(2); + combo.addActionListener(this); + } + + public void addTool(String str, boolean state) { + JToggleButton b = + (JToggleButton) toolbar.add(new JToggleButton(str)); + b.setFocusPainted(false); + b.setSelected(state); + b.addActionListener(this); + int width = b.getPreferredSize().width; + Dimension prefSize = new Dimension(width, 21); + b.setPreferredSize(prefSize); + b.setMaximumSize(prefSize); + b.setMinimumSize(prefSize); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource() instanceof JComboBox) { + int size = Integer.parseInt((String) combo.getSelectedItem()); + for (Ball ball : demo.balls) { + ball.makeImages(size); + } + return; + } + JToggleButton b = (JToggleButton) e.getSource(); + if (b.getText().equals("Clear")) { + demo.clearSurface = b.isSelected(); + } else { + int index = toolbar.getComponentIndex(b) - 1; + demo.balls[index].isSelected = b.isSelected(); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 40); + } + + @Override + @SuppressWarnings("SleepWhileHoldingLock") + public void run() { + try { + Thread.sleep(999); + } catch (Exception e) { + return; + } + Thread me = Thread.currentThread(); + ((AbstractButton) toolbar.getComponentAtIndex(2)).doClick(); + while (thread == me) { + try { + Thread.sleep(222); + } catch (InterruptedException e) { + return; + } + if (demo.clearToggle) { + if (demo.clearSurface) { + combo.setSelectedIndex((int) (random() * 5)); + } + ((AbstractButton) toolbar.getComponentAtIndex(0)).doClick(); + demo.clearToggle = false; + } + } + thread = null; + } + } // End DemoControls +} // End Balls + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Mix/BezierScroller.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Mix/BezierScroller.java new file mode 100644 index 00000000000..f4939af3256 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Mix/BezierScroller.java @@ -0,0 +1,389 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Mix; + + +import static java.awt.Color.LIGHT_GRAY; +import static java.awt.Color.WHITE; +import static java.lang.Math.random; +import java.awt.AlphaComposite; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.geom.GeneralPath; +import java.awt.geom.Path2D; +import java.awt.geom.PathIterator; +import java.awt.image.BufferedImage; +import java.io.BufferedReader; +import java.io.FileReader; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import java2d.AnimatingControlsSurface; +import java2d.CustomControls; +import javax.swing.AbstractButton; +import javax.swing.JComboBox; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; + + +/** + * Animated Bezier Curve shape with images at the control points. + * README.txt file scrolling up. Composited Image fading in and out. + */ +@SuppressWarnings("serial") +public class BezierScroller extends AnimatingControlsSurface { + + private static String appletStrs[] = { " ", "J2Ddemo", + "BezierScroller - Animated Bezier Curve shape with images", + "For README.txt file scrolling run in application mode", " " }; + private static final int NUMPTS = 6; + private static Color greenBlend = new Color(0, 255, 0, 100); + private static Color blueBlend = new Color(0, 0, 255, 100); + private static Font font = new Font(Font.SERIF, Font.PLAIN, 12); + private static BasicStroke bs = new BasicStroke(3.0f); + private static Image hotj_img; + private static BufferedImage img; + private static final int UP = 0; + private static final int DOWN = 1; + private float animpts[] = new float[NUMPTS * 2]; + private float deltas[] = new float[NUMPTS * 2]; + private BufferedReader reader; + private int nStrs; + private int strH; + private int yy, ix, iy, imgX; + private List vector, appletVector; + private float alpha = 0.2f; + private int alphaDirection; + protected boolean doImage, doShape, doText; + protected boolean buttonToggle; + + /* + * Using this to scale down globe.png since we want a smaller version, + * I know it is 100 x 160 and has a transparent pixel. + */ + private Image scaled(Image src) { + int sw = src.getWidth(null); + int sh = src.getHeight(null); + int dw = sw/5; + int dh = sh/5; + BufferedImage bi = + new BufferedImage(dw, dh, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = bi.createGraphics(); + g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g2d.drawImage(src, 0, 0, dw, dh, 0, 0, sw, sh, null); + g2d.dispose(); + return bi; + } + + @SuppressWarnings("LeakingThisInConstructor") + public BezierScroller() { + setBackground(WHITE); + doShape = doText = true; + hotj_img = scaled(getImage("globe.png")); + Image image = getImage("jumptojavastrip.png"); + int iw = image.getWidth(this); + int ih = image.getHeight(this); + img = new BufferedImage(iw, ih, BufferedImage.TYPE_INT_RGB); + img.createGraphics().drawImage(image, 0, 0, this); + setControls(new Component[] { new DemoControls(this) }); + } + + public void animate(float[] pts, float[] deltas, int index, int limit) { + float newpt = pts[index] + deltas[index]; + if (newpt <= 0) { + newpt = -newpt; + deltas[index] = (float) (random() * 4.0 + 2.0); + } else if (newpt >= limit) { + newpt = 2.0f * limit - newpt; + deltas[index] = -(float) (random() * 4.0 + 2.0); + } + pts[index] = newpt; + } + + public void getFile() { + try { + String fName = "README.txt"; + if ((reader = new BufferedReader(new FileReader(fName))) != null) { + getLine(); + } + } catch (Exception e) { + reader = null; + } + if (reader == null) { + appletVector = new ArrayList(100); + for (int i = 0; i < 100; i++) { + appletVector.add(appletStrs[i % appletStrs.length]); + } + getLine(); + } + buttonToggle = true; + } + + public String getLine() { + String str = null; + if (reader != null) { + try { + if ((str = reader.readLine()) != null) { + if (str.length() == 0) { + str = " "; + } + vector.add(str); + } + } catch (Exception e) { + Logger.getLogger(BezierScroller.class.getName()).log( + Level.SEVERE, + null, e); + reader = null; + } + } else { + if (!appletVector.isEmpty()) { + vector.add(str = appletVector.remove(0)); + } + } + return str; + } + + @Override + public void reset(int w, int h) { + for (int i = 0; i < animpts.length; i += 2) { + animpts[i + 0] = (float) (random() * w); + animpts[i + 1] = (float) (random() * h); + deltas[i + 0] = (float) (random() * 6.0 + 4.0); + deltas[i + 1] = (float) (random() * 6.0 + 4.0); + if (animpts[i + 0] > w / 2.0f) { + deltas[i + 0] = -deltas[i + 0]; + } + if (animpts[i + 1] > h / 2.0f) { + deltas[i + 1] = -deltas[i + 1]; + } + } + FontMetrics fm = getFontMetrics(font); + strH = fm.getAscent() + fm.getDescent(); + nStrs = h / strH + 2; + vector = new ArrayList(nStrs); + ix = (int) (random() * (w - 80)); + iy = (int) (random() * (h - 80)); + } + + @Override + public void step(int w, int h) { + if (doText && vector.isEmpty()) { + getFile(); + } + if (doText) { + String s = getLine(); + if (s == null || vector.size() == nStrs && !vector.isEmpty()) { + vector.remove(0); + } + yy = (s == null) ? 0 : h - vector.size() * strH; + } + + for (int i = 0; i < animpts.length && doShape; i += 2) { + animate(animpts, deltas, i + 0, w); + animate(animpts, deltas, i + 1, h); + } + if (doImage && alphaDirection == UP) { + if ((alpha += 0.025) > .99) { + alphaDirection = DOWN; + alpha = 1.0f; + } + } else if (doImage && alphaDirection == DOWN) { + if ((alpha -= .02) < 0.01) { + alphaDirection = UP; + alpha = 0; + ix = (int) (random() * (w - 80)); + iy = (int) (random() * (h - 80)); + } + } + if (doImage) { + if ((imgX += 80) == 800) { + imgX = 0; + } + } + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + if (doText) { + g2.setColor(LIGHT_GRAY); + g2.setFont(font); + float y = yy; + //for (int i = 0; i < vector.size(); i++) { + for (String string : vector) { + g2.drawString(string, 1, y += strH); + } + } + + if (doShape) { + float[] ctrlpts = animpts; + int len = ctrlpts.length; + float prevx = ctrlpts[len - 2]; + float prevy = ctrlpts[len - 1]; + float curx = ctrlpts[0]; + float cury = ctrlpts[1]; + float midx = (curx + prevx) / 2.0f; + float midy = (cury + prevy) / 2.0f; + GeneralPath gp = new GeneralPath(Path2D.WIND_NON_ZERO); + gp.moveTo(midx, midy); + for (int i = 2; i <= ctrlpts.length; i += 2) { + float x1 = (midx + curx) / 2.0f; + float y1 = (midy + cury) / 2.0f; + prevx = curx; + prevy = cury; + if (i < ctrlpts.length) { + curx = ctrlpts[i + 0]; + cury = ctrlpts[i + 1]; + } else { + curx = ctrlpts[0]; + cury = ctrlpts[1]; + } + midx = (curx + prevx) / 2.0f; + midy = (cury + prevy) / 2.0f; + float x2 = (prevx + midx) / 2.0f; + float y2 = (prevy + midy) / 2.0f; + gp.curveTo(x1, y1, x2, y2, midx, midy); + } + gp.closePath(); + + g2.setColor(blueBlend); + g2.setStroke(bs); + g2.draw(gp); + g2.setColor(greenBlend); + g2.fill(gp); + + PathIterator pi = gp.getPathIterator(null); + float pts[] = new float[6]; + while (!pi.isDone()) { + if (pi.currentSegment(pts) == PathIterator.SEG_CUBICTO) { + g2.drawImage(hotj_img, (int) pts[0], (int) pts[1], this); + } + pi.next(); + } + } + + if (doImage) { + AlphaComposite ac = AlphaComposite.getInstance( + AlphaComposite.SRC_OVER, alpha); + g2.setComposite(ac); + g2.drawImage(img.getSubimage(imgX, 0, 80, 80), ix, iy, this); + } + } + + public static void main(String argv[]) { + createDemoFrame(new BezierScroller()); + } + + + static final class DemoControls extends CustomControls implements + ActionListener { + + BezierScroller demo; + JToolBar toolbar; + JComboBox combo; + + public DemoControls(BezierScroller demo) { + super(demo.name); + this.demo = demo; + add(toolbar = new JToolBar()); + toolbar.setFloatable(false); + addTool("Image", false); + addTool("Shape", true); + addTool("Text", true); + } + + public void addTool(String str, boolean state) { + JToggleButton b = + (JToggleButton) toolbar.add(new JToggleButton(str)); + b.setFocusPainted(false); + b.setSelected(state); + b.addActionListener(this); + int width = b.getPreferredSize().width; + Dimension prefSize = new Dimension(width, 21); + b.setPreferredSize(prefSize); + b.setMaximumSize(prefSize); + b.setMinimumSize(prefSize); + } + + @Override + public void actionPerformed(ActionEvent e) { + JToggleButton b = (JToggleButton) e.getSource(); + if (b.getText().equals("Image")) { + demo.doImage = b.isSelected(); + } else if (b.getText().equals("Shape")) { + demo.doShape = b.isSelected(); + } else { + demo.doText = b.isSelected(); + } + if (!demo.animating.running()) { + demo.repaint(); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 40); + } + + @Override + @SuppressWarnings("SleepWhileHoldingLock") + public void run() { + Thread me = Thread.currentThread(); + int i = 0; + while (thread == me) { + try { + Thread.sleep(250); + } catch (InterruptedException e) { + return; + } + if (demo.buttonToggle) { + ((AbstractButton) toolbar.getComponentAtIndex(i++ % 2)). + doClick(); + demo.buttonToggle = false; + } + } + thread = null; + } + } // End DemoControls +} // End BezierScroller + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Mix/Stars3D.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Mix/Stars3D.java new file mode 100644 index 00000000000..0ae7a133ebd --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Mix/Stars3D.java @@ -0,0 +1,328 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Mix; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.BLUE; +import static java.awt.Color.GREEN; +import static java.awt.Color.RED; +import static java.awt.Color.WHITE; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.font.FontRenderContext; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.awt.geom.Path2D; +import java.awt.geom.PathIterator; +import java.awt.geom.Rectangle2D; +import java2d.ControlsSurface; +import java2d.CustomControls; +import javax.swing.JLabel; +import javax.swing.JTextField; + + +/** + * Generate a 3D text shape with GeneralPath, render a number of small + * multi-colored rectangles and then render the 3D text shape. + */ +@SuppressWarnings("serial") +public class Stars3D extends ControlsSurface { + + private static Color colors[] = { RED, GREEN, WHITE }; + private static AffineTransform at = AffineTransform.getTranslateInstance(-5, + -5); + private Shape shape, tshape; + private Shape ribbon; + protected int fontSize = 72; + protected String text = "OpenJDK"; + protected int numStars = 300; + + public Stars3D() { + setBackground(BLACK); + setControls(new Component[] { new DemoControls(this) }); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + Rectangle2D rect = new Rectangle2D.Double(); + for (int i = 0; i < numStars; i++) { + g2.setColor(colors[i % 3]); + g2.setComposite(AlphaComposite.getInstance( + AlphaComposite.SRC_OVER, (float) Math.random())); + rect.setRect(w * Math.random(), h * Math.random(), 2, 2); + g2.fill(rect); + } + + FontRenderContext frc = g2.getFontRenderContext(); + Font font = new Font(Font.SERIF, Font.BOLD|Font.ITALIC, fontSize); + shape = font.createGlyphVector(frc, text).getOutline(); + tshape = at.createTransformedShape(shape); + PathIterator pi = shape.getPathIterator(null); + + float seg[] = new float[6]; + float tseg[] = new float[6]; + + GeneralPath working = new GeneralPath(Path2D.WIND_NON_ZERO); + float x = 0, y = 0; // Current point on the path + float tx = 0, ty = 0; // Transformed path point + float cx = 0, cy = 0; // Last moveTo point, for SEG_CLOSE + float tcx = 0, tcy = 0; // Transformed last moveTo point + + // + // Iterate through the Shape and build the ribbon + // by adding general path objects. + // + while (!pi.isDone()) { + int segType = pi.currentSegment(seg); + switch (segType) { + case PathIterator.SEG_MOVETO: + at.transform(seg, 0, tseg, 0, 1); + x = seg[0]; + y = seg[1]; + tx = tseg[0]; + ty = tseg[1]; + cx = x; + cy = y; + tcx = tx; + tcy = ty; + break; + case PathIterator.SEG_LINETO: + at.transform(seg, 0, tseg, 0, 1); + if (Line2D.relativeCCW(x, y, tx, ty, seg[0], seg[1]) < 0) { + working.moveTo(x, y); + working.lineTo(seg[0], seg[1]); + working.lineTo(tseg[0], tseg[1]); + working.lineTo(tx, ty); + working.lineTo(x, y); + } else { + working.moveTo(x, y); + working.lineTo(tx, ty); + working.lineTo(tseg[0], tseg[1]); + working.lineTo(seg[0], seg[1]); + working.lineTo(x, y); + } + + x = seg[0]; + y = seg[1]; + tx = tseg[0]; + ty = tseg[1]; + break; + + case PathIterator.SEG_QUADTO: + at.transform(seg, 0, tseg, 0, 2); + if (Line2D.relativeCCW(x, y, tx, ty, seg[2], seg[3]) < 0) { + working.moveTo(x, y); + working.quadTo(seg[0], seg[1], + seg[2], seg[3]); + working.lineTo(tseg[2], tseg[3]); + working.quadTo(tseg[0], tseg[1], + tx, ty); + working.lineTo(x, y); + } else { + working.moveTo(x, y); + working.lineTo(tx, ty); + working.quadTo(tseg[0], tseg[1], + tseg[2], tseg[3]); + working.lineTo(seg[2], seg[3]); + working.quadTo(seg[0], seg[1], + x, y); + } + + x = seg[2]; + y = seg[3]; + tx = tseg[2]; + ty = tseg[3]; + break; + + case PathIterator.SEG_CUBICTO: + at.transform(seg, 0, tseg, 0, 3); + if (Line2D.relativeCCW(x, y, tx, ty, seg[4], seg[5]) < 0) { + working.moveTo(x, y); + working.curveTo(seg[0], seg[1], + seg[2], seg[3], + seg[4], seg[5]); + working.lineTo(tseg[4], tseg[5]); + working.curveTo(tseg[2], tseg[3], + tseg[0], tseg[1], + tx, ty); + working.lineTo(x, y); + } else { + working.moveTo(x, y); + working.lineTo(tx, ty); + working.curveTo(tseg[0], tseg[1], + tseg[2], tseg[3], + tseg[4], tseg[5]); + working.lineTo(seg[4], seg[5]); + working.curveTo(seg[2], seg[3], + seg[0], seg[1], + x, y); + } + + x = seg[4]; + y = seg[5]; + tx = tseg[4]; + ty = tseg[5]; + break; + + case PathIterator.SEG_CLOSE: + if (Line2D.relativeCCW(x, y, tx, ty, cx, cy) < 0) { + working.moveTo(x, y); + working.lineTo(cx, cy); + working.lineTo(tcx, tcy); + working.lineTo(tx, ty); + working.lineTo(x, y); + } else { + working.moveTo(x, y); + working.lineTo(tx, ty); + working.lineTo(tcx, tcy); + working.lineTo(cx, cy); + working.lineTo(x, y); + } + x = cx; + y = cy; + tx = tcx; + ty = tcy; + } + pi.next(); + } // while + ribbon = working; + + if (composite != null) { + g2.setComposite(composite); + } else { + g2.setComposite(AlphaComposite.SrcOver); + } + Rectangle r = shape.getBounds(); + g2.translate(w * .5 - r.width * .5, h * .5 + r.height * .5); + + g2.setColor(BLUE); + g2.fill(tshape); + g2.setColor(new Color(255, 255, 255, 200)); + g2.fill(ribbon); + + g2.setColor(WHITE); + g2.fill(shape); + + g2.setColor(BLUE); + g2.draw(shape); + } + + public static void main(String argv[]) { + createDemoFrame(new Stars3D()); + } + + + static class DemoControls extends CustomControls implements ActionListener { + + Stars3D demo; + JTextField tf1, tf2; + + @SuppressWarnings("LeakingThisInConstructor") + public DemoControls(Stars3D demo) { + super(demo.name); + this.demo = demo; + JLabel l = new JLabel(" Text:"); + l.setForeground(BLACK); + add(l); + add(tf1 = new JTextField(demo.text)); + tf1.setPreferredSize(new Dimension(60, 20)); + tf1.addActionListener(this); + l = new JLabel(" Size:"); + l.setForeground(BLACK); + add(l); + add(tf2 = new JTextField(String.valueOf(demo.fontSize))); + tf2.setPreferredSize(new Dimension(30, 20)); + tf2.addActionListener(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + try { + if (e.getSource().equals(tf1)) { + demo.text = tf1.getText().trim(); + } else if (e.getSource().equals(tf2)) { + demo.fontSize = Integer.parseInt(tf2.getText().trim()); + if (demo.fontSize < 10) { + demo.fontSize = 10; + } + } + demo.repaint(); + } catch (Exception ignored) { + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 37); + } + + @Override + @SuppressWarnings("SleepWhileHoldingLock") + public void run() { + Thread me = Thread.currentThread(); + try { + Thread.sleep(999); + } catch (Exception e) { + return; + } + int length = getSize().width / 4; + int size[] = { length, length }; + String str[] = { "OpenJDK", "J2D" }; + while (thread == me) { + for (int i = 0; i < str.length; i++) { + demo.fontSize = size[i]; + tf2.setText(String.valueOf(demo.fontSize)); + tf1.setText(demo.text = str[i]); + demo.repaint(); + try { + Thread.sleep(5555); + } catch (InterruptedException e) { + return; + } + } + } + thread = null; + } + } // End DemoControls +} // End Stars3D + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/GradAnim.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/GradAnim.java new file mode 100644 index 00000000000..4b6f178257d --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/GradAnim.java @@ -0,0 +1,318 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Paint; + + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.LinearGradientPaint; +import java.awt.MultipleGradientPaint.CycleMethod; +import java.awt.Paint; +import java.awt.RadialGradientPaint; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.geom.Point2D; +import java2d.AnimatingControlsSurface; +import java2d.CustomControls; +import javax.swing.JComboBox; + + +/** + * GradientPaint animation. + */ +@SuppressWarnings("serial") +public class GradAnim extends AnimatingControlsSurface { + + private static final int BASIC_GRADIENT = 0; + private static final int LINEAR_GRADIENT = 1; + private static final int RADIAL_GRADIENT = 2; + private static final int FOCUS_GRADIENT = 3; + private static final int MAX_HUE = 256 * 6; + private animval x1, y1, x2, y2; + private int hue = (int) (Math.random() * MAX_HUE); + private int gradientType; + + public GradAnim() { + setBackground(Color.white); + setControls(new Component[] { new DemoControls(this) }); + x1 = new animval(0, 300, 2, 10); + y1 = new animval(0, 300, 2, 10); + x2 = new animval(0, 300, 2, 10); + y2 = new animval(0, 300, 2, 10); + gradientType = BASIC_GRADIENT; + } + + @Override + public void reset(int w, int h) { + x1.newlimits(0, w); + y1.newlimits(0, h); + x2.newlimits(0, w); + y2.newlimits(0, h); + } + + @Override + public void step(int w, int h) { + x1.anim(); + y1.anim(); + x2.anim(); + y2.anim(); + hue = (hue + (int) (Math.random() * 10)) % MAX_HUE; + } + + public static Color getColor(int hue) { + int leg = (hue / 256) % 6; + int step = (hue % 256) * 2; + int falling = (step < 256) ? 255 : 511 - step; + int rising = (step < 256) ? step : 255; + int r, g, b; + r = g = b = 0; + switch (leg) { + case 0: + r = 255; + break; + case 1: + r = falling; + g = rising; + break; + case 2: + g = 255; + break; + case 3: + g = falling; + b = rising; + break; + case 4: + b = 255; + break; + case 5: + b = falling; + r = rising; + break; + } + return new Color(r, g, b); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + float fx1 = x1.getFlt(); + float fy1 = y1.getFlt(); + float fx2 = x2.getFlt(); + float fy2 = y2.getFlt(); + + if ((fx1 == fx2) && (fy1 == fy2)) { + // just to prevent the points from being coincident + fx2++; + fy2++; + } + + Color c1 = getColor(hue); + Color c2 = getColor(hue + 256 * 3); + Paint gp; + + switch (gradientType) { + case BASIC_GRADIENT: + default: + gp = new GradientPaint(fx1, fy1, c1, + fx2, fy2, c2, + true); + break; + case LINEAR_GRADIENT: { + float[] fractions = new float[] { 0.0f, 0.2f, 1.0f }; + Color c3 = getColor(hue + 256 * 2); + Color[] colors = new Color[] { c1, c2, c3 }; + gp = new LinearGradientPaint(fx1, fy1, + fx2, fy2, + fractions, colors, + CycleMethod.REFLECT); + } + break; + + case RADIAL_GRADIENT: { + float[] fractions = { 0.0f, 0.2f, 0.8f, 1.0f }; + Color c3 = getColor(hue + 256 * 2); + Color c4 = getColor(hue + 256 * 4); + Color[] colors = new Color[] { c1, c2, c3, c4 }; + float radius = (float) Point2D.distance(fx1, fy1, fx2, fy2); + gp = new RadialGradientPaint(fx1, fy1, radius, + fractions, colors, + CycleMethod.REFLECT); + } + break; + + case FOCUS_GRADIENT: { + float[] fractions = { 0.0f, 0.2f, 0.8f, 1.0f }; + Color c3 = getColor(hue + 256 * 4); + Color c4 = getColor(hue + 256 * 2); + Color[] colors = new Color[] { c1, c2, c3, c4 }; + float radius = (float) Point2D.distance(fx1, fy1, fx2, fy2); + float max = Math.max(w, h); + // This function will map the smallest radius to + // max/10 when the points are next to each other, + // max when the points are max distance apart, + // and >max when they are further apart (in which + // case the focus clipping code in RGP will clip + // the focus to be inside the radius). + radius = max * (((radius / max) * 0.9f) + 0.1f); + gp = new RadialGradientPaint(fx2, fy2, radius, + fx1, fy1, + fractions, colors, + CycleMethod.REPEAT); + } + break; + } + g2.setPaint(gp); + g2.fillRect(0, 0, w, h); + g2.setColor(Color.yellow); + g2.drawLine(x1.getInt(), y1.getInt(), x2.getInt(), y2.getInt()); + } + + + public final class animval { + + float curval; + float lowval; + float highval; + float currate; + float lowrate; + float highrate; + + public animval(int lowval, int highval, + int lowrate, int highrate) { + this.lowval = lowval; + this.highval = highval; + this.lowrate = lowrate; + this.highrate = highrate; + this.curval = randval(lowval, highval); + this.currate = randval(lowrate, highrate); + } + + public float randval(float low, float high) { + return (float) (low + Math.random() * (high - low)); + } + + public float getFlt() { + return curval; + } + + public int getInt() { + return (int) curval; + } + + public void anim() { + curval += currate; + clip(); + } + + public void clip() { + if (curval > highval) { + curval = highval - (curval - highval); + if (curval < lowval) { + curval = highval; + } + currate = -randval(lowrate, highrate); + } else if (curval < lowval) { + curval = lowval + (lowval - curval); + if (curval > highval) { + curval = lowval; + } + currate = randval(lowrate, highrate); + } + } + + public void newlimits(int lowval, int highval) { + this.lowval = lowval; + this.highval = highval; + clip(); + } + } + + public static void main(String argv[]) { + createDemoFrame(new GradAnim()); + } + + + class DemoControls extends CustomControls implements ActionListener { + + GradAnim demo; + JComboBox combo; + + @SuppressWarnings("LeakingThisInConstructor") + public DemoControls(GradAnim demo) { + super(demo.name); + this.demo = demo; + combo = new JComboBox(); + combo.addActionListener(this); + combo.addItem("2-color GradientPaint"); + combo.addItem("3-color LinearGradientPaint"); + combo.addItem("4-color RadialGradientPaint"); + combo.addItem("4-color RadialGradientPaint with focus"); + combo.setSelectedIndex(0); + add(combo); + } + + @Override + public void actionPerformed(ActionEvent e) { + int index = combo.getSelectedIndex(); + if (index >= 0) { + demo.gradientType = index; + } + if (!demo.animating.running()) { + demo.repaint(); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 41); + } + + @Override + @SuppressWarnings("SleepWhileHoldingLock") + public void run() { + Thread me = Thread.currentThread(); + while (thread == me) { + for (int i = 0; i < combo.getItemCount(); i++) { + combo.setSelectedIndex(i); + try { + Thread.sleep(4444); + } catch (InterruptedException e) { + return; + } + } + } + thread = null; + } + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/Gradient.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/Gradient.java new file mode 100644 index 00000000000..073a4deea27 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/Gradient.java @@ -0,0 +1,215 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Paint; + + +import static java.awt.Color.black; +import static java.awt.Color.blue; +import static java.awt.Color.cyan; +import static java.awt.Color.green; +import static java.awt.Color.lightGray; +import static java.awt.Color.magenta; +import static java.awt.Color.orange; +import static java.awt.Color.red; +import static java.awt.Color.white; +import static java.awt.Color.yellow; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.font.TextLayout; +import java2d.ControlsSurface; +import java2d.CustomControls; +import javax.swing.Icon; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; + + +@SuppressWarnings("serial") +public class Gradient extends ControlsSurface { + + protected Color innerC, outerC; + + public Gradient() { + setBackground(white); + innerC = green; + outerC = blue; + setControls(new Component[] { new DemoControls(this) }); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + int w2 = w / 2; + int h2 = h / 2; + g2.setPaint(new GradientPaint(0, 0, outerC, w * .35f, h * .35f, innerC)); + g2.fillRect(0, 0, w2, h2); + g2.setPaint(new GradientPaint(w, 0, outerC, w * .65f, h * .35f, innerC)); + g2.fillRect(w2, 0, w2, h2); + g2.setPaint(new GradientPaint(0, h, outerC, w * .35f, h * .65f, innerC)); + g2.fillRect(0, h2, w2, h2); + g2.setPaint(new GradientPaint(w, h, outerC, w * .65f, h * .65f, innerC)); + g2.fillRect(w2, h2, w2, h2); + + g2.setColor(black); + TextLayout tl = new TextLayout( + "GradientPaint", g2.getFont(), g2.getFontRenderContext()); + tl.draw(g2, (int) (w / 2 - tl.getBounds().getWidth() / 2), + (int) (h / 2 + tl.getBounds().getHeight() / 2)); + } + + public static void main(String s[]) { + createDemoFrame(new Gradient()); + } + + + static class DemoControls extends CustomControls implements ActionListener { + + Gradient demo; + Color colors[] = { red, orange, yellow, green, blue, lightGray, cyan, + magenta }; + String colorName[] = { "Red", "Orange", "Yellow", "Green", + "Blue", "lightGray", "Cyan", "Magenta" }; + JMenuItem innerMI[] = new JMenuItem[colors.length]; + JMenuItem outerMI[] = new JMenuItem[colors.length]; + ColoredSquare squares[] = new ColoredSquare[colors.length]; + JMenu imenu, omenu; + + @SuppressWarnings("LeakingThisInConstructor") + public DemoControls(Gradient demo) { + super(demo.name); + this.demo = demo; + JMenuBar inMenuBar = new JMenuBar(); + add(inMenuBar); + JMenuBar outMenuBar = new JMenuBar(); + add(outMenuBar); + Font font = new Font(Font.SERIF, Font.PLAIN, 10); + + imenu = inMenuBar.add(new JMenu("Inner Color")); + imenu.setFont(font); + imenu.setIcon(new ColoredSquare(demo.innerC)); + omenu = outMenuBar.add(new JMenu("Outer Color")); + omenu.setFont(font); + omenu.setIcon(new ColoredSquare(demo.outerC)); + for (int i = 0; i < colors.length; i++) { + squares[i] = new ColoredSquare(colors[i]); + innerMI[i] = imenu.add(new JMenuItem(colorName[i])); + innerMI[i].setFont(font); + innerMI[i].setIcon(squares[i]); + innerMI[i].addActionListener(this); + outerMI[i] = omenu.add(new JMenuItem(colorName[i])); + outerMI[i].setFont(font); + outerMI[i].setIcon(squares[i]); + outerMI[i].addActionListener(this); + } + } + + @Override + public void actionPerformed(ActionEvent e) { + for (int i = 0; i < colors.length; i++) { + if (e.getSource().equals(innerMI[i])) { + demo.innerC = colors[i]; + imenu.setIcon(squares[i]); + break; + } else if (e.getSource().equals(outerMI[i])) { + demo.outerC = colors[i]; + omenu.setIcon(squares[i]); + break; + } + } + demo.repaint(); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 37); + } + + @Override + @SuppressWarnings("SleepWhileHoldingLock") + public void run() { + // goto double buffering + if (demo.getImageType() <= 1) { + demo.setImageType(2); + } + Thread me = Thread.currentThread(); + while (thread == me) { + for (int i = 0; i < innerMI.length; i++) { + if (i != 4) { + try { + Thread.sleep(4444); + } catch (InterruptedException e) { + return; + } + innerMI[i].doClick(); + } + } + } + thread = null; + } + + + class ColoredSquare implements Icon { + + Color color; + + public ColoredSquare(Color c) { + this.color = c; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + Color oldColor = g.getColor(); + g.setColor(color); + g.fill3DRect(x, y, getIconWidth(), getIconHeight(), true); + g.setColor(oldColor); + } + + @Override + public int getIconWidth() { + return 12; + } + + @Override + public int getIconHeight() { + return 12; + } + } // End ColoredSquare class + } // End DemoControls +} // End Gradient class + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/Texture.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/Texture.java new file mode 100644 index 00000000000..ee9c9253b2f --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/Texture.java @@ -0,0 +1,172 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Paint; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.GRAY; +import static java.awt.Color.GREEN; +import static java.awt.Color.LIGHT_GRAY; +import static java.awt.Color.WHITE; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.TexturePaint; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.image.BufferedImage; +import java2d.Surface; + + +/** + * TexturePaint of gradient, buffered image and shapes. + */ +@SuppressWarnings("serial") +public class Texture extends Surface { + + private static TexturePaint bluedots, greendots, triangles; + private static TexturePaint blacklines, gradient; + + static { + BufferedImage bi = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB); + Graphics2D gi = bi.createGraphics(); + gi.setBackground(WHITE); + gi.clearRect(0, 0, 10, 10); + GeneralPath p1 = new GeneralPath(); + p1.moveTo(0, 0); + p1.lineTo(5, 10); + p1.lineTo(10, 0); + p1.closePath(); + gi.setColor(LIGHT_GRAY); + gi.fill(p1); + triangles = new TexturePaint(bi, new Rectangle(0, 0, 10, 10)); + + bi = new BufferedImage(5, 5, BufferedImage.TYPE_INT_RGB); + gi = bi.createGraphics(); + gi.setColor(BLACK); + gi.fillRect(0, 0, 5, 5); + gi.setColor(GRAY); + gi.fillRect(1, 1, 4, 4); + blacklines = new TexturePaint(bi, new Rectangle(0, 0, 5, 5)); + + int w = 30; + int h = 30; + bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + gi = bi.createGraphics(); + Color oc = WHITE; + Color ic = LIGHT_GRAY; + gi.setPaint(new GradientPaint(0, 0, oc, w * .35f, h * .35f, ic)); + gi.fillRect(0, 0, w / 2, h / 2); + gi.setPaint(new GradientPaint(w, 0, oc, w * .65f, h * .35f, ic)); + gi.fillRect(w / 2, 0, w / 2, h / 2); + gi.setPaint(new GradientPaint(0, h, oc, w * .35f, h * .65f, ic)); + gi.fillRect(0, h / 2, w / 2, h / 2); + gi.setPaint(new GradientPaint(w, h, oc, w * .65f, h * .65f, ic)); + gi.fillRect(w / 2, h / 2, w / 2, h / 2); + gradient = new TexturePaint(bi, new Rectangle(0, 0, w, h)); + + bi = new BufferedImage(2, 2, BufferedImage.TYPE_INT_RGB); + bi.setRGB(0, 0, 0xffffffff); + bi.setRGB(1, 0, 0xffffffff); + bi.setRGB(0, 1, 0xffffffff); + bi.setRGB(1, 1, 0xff0000ff); + bluedots = new TexturePaint(bi, new Rectangle(0, 0, 2, 2)); + + bi = new BufferedImage(2, 2, BufferedImage.TYPE_INT_RGB); + bi.setRGB(0, 0, 0xffffffff); + bi.setRGB(1, 0, 0xffffffff); + bi.setRGB(0, 1, 0xffffffff); + bi.setRGB(1, 1, 0xff00ff00); + greendots = new TexturePaint(bi, new Rectangle(0, 0, 2, 2)); + } + + public Texture() { + setBackground(WHITE); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + Rectangle r = new Rectangle(10, 10, w - 20, h / 2 - 20); + g2.setPaint(gradient); + g2.fill(r); + g2.setPaint(GREEN); + g2.setStroke(new BasicStroke(20)); + g2.draw(r); + g2.setPaint(blacklines); + g2.setStroke(new BasicStroke(15)); + g2.draw(r); + + Font f = new Font(Font.SERIF, Font.BOLD, w / 5); + TextLayout tl = new TextLayout("Texture", f, g2.getFontRenderContext()); + int sw = (int) tl.getBounds().getWidth(); + int sh = (int) tl.getBounds().getHeight(); + Shape sha = tl.getOutline(AffineTransform.getTranslateInstance(w / 2 - sw + / 2, h * .25 + sh / 2)); + g2.setColor(BLACK); + g2.setStroke(new BasicStroke(3)); + g2.draw(sha); + g2.setPaint(greendots); + g2.fill(sha); + + r.setLocation(10, h / 2 + 10); + g2.setPaint(triangles); + g2.fill(r); + g2.setPaint(blacklines); + g2.setStroke(new BasicStroke(20)); + g2.draw(r); + g2.setPaint(GREEN); + g2.setStroke(new BasicStroke(4)); + g2.draw(r); + + f = new Font(Font.SERIF, Font.BOLD, w / 4); + tl = new TextLayout("Paint", f, g2.getFontRenderContext()); + sw = (int) tl.getBounds().getWidth(); + sh = (int) tl.getBounds().getHeight(); + sha = tl.getOutline(AffineTransform.getTranslateInstance(w / 2 - sw / 2, h + * .75 + sh / 2)); + g2.setColor(BLACK); + g2.setStroke(new BasicStroke(5)); + g2.draw(sha); + g2.setPaint(bluedots); + g2.fill(sha); + } + + public static void main(String s[]) { + createDemoFrame(new Texture()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/TextureAnim.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/TextureAnim.java new file mode 100644 index 00000000000..2c5f921d18a --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paint/TextureAnim.java @@ -0,0 +1,450 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Paint; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.GRAY; +import static java.awt.Color.LIGHT_GRAY; +import static java.awt.Color.WHITE; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.TexturePaint; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java2d.AnimatingControlsSurface; +import java2d.CustomControls; +import javax.swing.AbstractButton; +import javax.swing.Icon; +import javax.swing.JComboBox; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; +import javax.swing.plaf.metal.MetalBorders.ButtonBorder; + + +/** + * TexturePaint animation with controls for transformations. + */ +@SuppressWarnings("serial") +public final class TextureAnim extends AnimatingControlsSurface { + + public static final Color colorblend = new Color(0f, 0f, 1f, .5f); + protected static BufferedImage textureImg; + protected int bNum; + protected int tilesize; + private boolean newtexture; + private TexturePaint texturePaint; + private Rectangle tilerect; + private boolean bouncesize = false; + private boolean bouncerect = true; + private boolean rotate = false; + private boolean shearx = false; + private boolean sheary = false; + private boolean showanchor = true; + private AnimVal w, h, x, y, rot, shx, shy; + private static Image img[] = new Image[2]; + + public TextureAnim() { + img[0] = getImage("duke.gif"); // 8 bit gif + img[1] = getImage("duke.png"); // 24 bit png + + textureImg = makeImage(32, 0); + tilesize = textureImg.getWidth(); + w = new AnimVal(0, 200, 3, 10, tilesize); + h = new AnimVal(0, 200, 3, 10, tilesize); + x = new AnimVal(0, 200, 3, 10, 0); + y = new AnimVal(0, 200, 3, 10, 0); + rot = new AnimVal(-360, 360, 5, 15, 0); + shx = new AnimVal(-50, 50, 3, 10, 0); + shy = new AnimVal(-50, 50, 3, 10, 0); + tilerect = new Rectangle(x.getInt(), y.getInt(), + w.getInt(), h.getInt()); + texturePaint = new TexturePaint(textureImg, tilerect); + setControls(new Component[] { new DemoControls(this) }); + } + + protected BufferedImage makeImage(int size, int num) { + newtexture = true; + switch (bNum = num) { + case 0: + return makeRGBImage(size); + case 1: + return makeGIFImage(size); + case 2: + return makePNGImage(size); + } + return null; + } + + private BufferedImage makeRGBImage(int size) { + BufferedImage bi = new BufferedImage(size, size, + BufferedImage.TYPE_INT_RGB); + Graphics2D big = bi.createGraphics(); + big.setColor(WHITE); + big.fillRect(0, 0, size, size); + for (int j = 0; j < size; j++) { + float RED = j / (float) size; + for (int i = 0; i < size; i++) { + float GREEN = i / (float) size; + big.setColor(new Color(1.0f - RED, 1.0f - GREEN, 0.0f, 1.0f)); + big.drawLine(i, j, i, j); + } + } + return bi; + } + + private BufferedImage makeGIFImage(int d) { + BufferedImage bi = new BufferedImage(d, d, BufferedImage.TYPE_INT_RGB); + Graphics2D big = bi.createGraphics(); + big.drawImage(img[0], 0, 0, d, d, new Color(204, 204, 255), null); + return bi; + } + + private BufferedImage makePNGImage(int d) { + BufferedImage bi = new BufferedImage(d, d, BufferedImage.TYPE_INT_RGB); + Graphics2D big = bi.createGraphics(); + big.drawImage(img[1], 0, 0, d, d, LIGHT_GRAY, null); + return bi; + } + + @Override + public void reset(int width, int height) { + x.newlimits(-width / 4, width / 4 - w.getInt()); + y.newlimits(-height / 4, height / 4 - h.getInt()); + } + + @Override + public void step(int width, int height) { + if (tilesize != textureImg.getWidth()) { + tilesize = textureImg.getWidth(); + } + if (bouncesize) { + w.anim(); + h.anim(); + x.newlimits(-width / 4, width / 4 - w.getInt()); + y.newlimits(-height / 4, height / 4 - h.getInt()); + } else { + if (w.getInt() != tilesize) { + w.set(tilesize); + x.newlimits(-width / 4, width / 4 - w.getInt()); + } + if (h.getInt() != tilesize) { + h.set(tilesize); + y.newlimits(-height / 4, height / 4 - h.getInt()); + } + } + if (bouncerect) { + x.anim(); + y.anim(); + } + if (newtexture || x.getInt() != tilerect.x || y.getInt() != tilerect.y || w. + getInt() != tilerect.width || h.getInt() != tilerect.height) { + newtexture = false; + int X = x.getInt(); + int Y = y.getInt(); + int W = w.getInt(); + int H = h.getInt(); + tilerect = new Rectangle(X, Y, W, H); + texturePaint = new TexturePaint(textureImg, tilerect); + } + } + + @Override + public void render(int width, int height, Graphics2D g2) { + + g2.translate(width / 2, height / 2); + if (rotate) { + rot.anim(); + g2.rotate(Math.toRadians(rot.getFlt())); + } else { + rot.set(0); + } + if (shearx) { + shx.anim(); + g2.shear(shx.getFlt() / 100, 0.0f); + } else { + shx.set(0); + } + if (sheary) { + shy.anim(); + g2.shear(0.0f, shy.getFlt() / 100); + } else { + shy.set(0); + } + g2.setPaint(texturePaint); + g2.fillRect(-1000, -1000, 2000, 2000); + if (showanchor) { + g2.setColor(BLACK); + g2.setColor(colorblend); + g2.fill(tilerect); + } + } + + public static void main(String argv[]) { + createDemoFrame(new TextureAnim()); + } + + + static final class AnimVal { + + float curval; + float lowval; + float highval; + float currate; + float lowrate; + float highrate; + + public AnimVal(int lowval, int highval, + int lowrate, int highrate) { + this.lowval = lowval; + this.highval = highval; + this.lowrate = lowrate; + this.highrate = highrate; + this.curval = randval(lowval, highval); + this.currate = randval(lowrate, highrate); + } + + public AnimVal(int lowval, int highval, + int lowrate, int highrate, + int pos) { + this(lowval, highval, lowrate, highrate); + set(pos); + } + + public float randval(float low, float high) { + return (float) (low + Math.random() * (high - low)); + } + + public float getFlt() { + return curval; + } + + public int getInt() { + return (int) curval; + } + + public void anim() { + curval += currate; + clip(); + } + + public void set(float val) { + curval = val; + clip(); + } + + public void clip() { + if (curval > highval) { + curval = highval - (curval - highval); + if (curval < lowval) { + curval = highval; + } + currate = -randval(lowrate, highrate); + } else if (curval < lowval) { + curval = lowval + (lowval - curval); + if (curval > highval) { + curval = lowval; + } + currate = randval(lowrate, highrate); + } + } + + public void newlimits(int lowval, int highval) { + this.lowval = lowval; + this.highval = highval; + clip(); + } + } // End AnimVal class + + + final class DemoControls extends CustomControls implements ActionListener { + + TextureAnim demo; + JToolBar toolbar; + JComboBox combo; + JMenu menu; + JMenuItem menuitems[]; + int iconSize = 20; + ButtonBorder buttonBorder = new ButtonBorder(); + + @SuppressWarnings("LeakingThisInConstructor") + public DemoControls(TextureAnim demo) { + super(demo.name); + this.demo = demo; + menuitems = new JMenuItem[3]; + add(toolbar = new JToolBar()); + toolbar.setFloatable(false); + addTool("BO", "bounce", true); + addTool("SA", "show anchor", true); + addTool("RS", "resize", false); + addTool("RO", "rotate", false); + addTool("SX", "shear x", false); + addTool("SY", "shear y", false); + add(combo = new JComboBox()); + combo.addActionListener(this); + combo.addItem("8"); + combo.addItem("16"); + combo.addItem("32"); + combo.addItem("64"); + combo.addItem("80"); + combo.setSelectedIndex(2); + + JMenuBar menuBar = new JMenuBar(); + menu = menuBar.add(new JMenu()); + for (int i = 0; i < 3; i++) { + BufferedImage bimg = demo.makeImage(iconSize, i); + TexturedIcon icon = new TexturedIcon(bimg); + menuitems[i] = menu.add(new JMenuItem(icon)); + menuitems[i].addActionListener(this); + } + menu.setIcon(menuitems[0].getIcon()); + add(menuBar); + demo.bNum = 0; + } + + public void addTool(String str, String toolTip, boolean state) { + JToggleButton b = + (JToggleButton) toolbar.add(new JToggleButton(str)); + b.setBorder(buttonBorder); + b.setFocusPainted(false); + b.setSelected(state); + b.setToolTipText(toolTip); + b.addActionListener(this); + int width = b.getPreferredSize().width+10; + Dimension prefSize = new Dimension(width, 21); + b.setPreferredSize(prefSize); + b.setMaximumSize(prefSize); + b.setMinimumSize(prefSize); + } + + @Override + public void actionPerformed(ActionEvent e) { + Object obj = e.getSource(); + if (obj instanceof JComboBox) { + String selItem = (String) combo.getSelectedItem(); + if (selItem != null) { + int size = Integer.parseInt(selItem); + TextureAnim.textureImg = demo.makeImage(size, demo.bNum); + } + } else if (obj instanceof JMenuItem) { + for (int i = 0; i < menuitems.length; i++) { + if (obj.equals(menuitems[i])) { + TextureAnim.textureImg = + demo.makeImage(demo.tilesize, i); + menu.setIcon(menuitems[i].getIcon()); + break; + } + } + } else { + JToggleButton b = (JToggleButton) obj; + if (b.getText().equals("BO")) { + demo.bouncerect = b.isSelected(); + } else if (b.getText().equals("SA")) { + demo.showanchor = b.isSelected(); + } else if (b.getText().equals("RS")) { + demo.bouncesize = b.isSelected(); + } else if (b.getText().equals("RO")) { + demo.rotate = b.isSelected(); + } else if (b.getText().equals("SX")) { + demo.shearx = b.isSelected(); + } else if (b.getText().equals("SY")) { + demo.sheary = b.isSelected(); + } + } + if (!demo.animating.running()) { + demo.repaint(); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 41); + } + + @Override + @SuppressWarnings("SleepWhileHoldingLock") + public void run() { + Thread me = Thread.currentThread(); + while (thread == me) { + for (int i = 2; i < toolbar.getComponentCount(); i++) { + try { + Thread.sleep(4444); + } catch (InterruptedException e) { + return; + } + ((AbstractButton) toolbar.getComponentAtIndex(i)).doClick(); + } + } + thread = null; + } + + + class TexturedIcon implements Icon { + + BufferedImage bi; + + public TexturedIcon(BufferedImage bi) { + this.bi = bi; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + Graphics2D g2 = (Graphics2D) g; + Rectangle r = new Rectangle(x, y, iconSize, iconSize); + g2.setPaint(new TexturePaint(bi, r)); + g2.fillRect(x, y, iconSize, iconSize); + g2.setColor(GRAY); + g2.draw3DRect(x, y, iconSize - 1, iconSize - 1, true); + } + + @Override + public int getIconWidth() { + return iconSize; + } + + @Override + public int getIconHeight() { + return iconSize; + } + } // End TexturedIcon class + } // End DemoControls class +} // End TextureAnim class + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/Append.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/Append.java new file mode 100644 index 00000000000..a767410a14a --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/Append.java @@ -0,0 +1,83 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Paths; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.GRAY; +import static java.awt.Color.WHITE; +import java.awt.Graphics2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Path2D; +import java.awt.geom.Rectangle2D; +import java2d.Surface; + + +/** + * Simple append of rectangle to path with & without the connect. + */ +@SuppressWarnings("serial") +public class Append extends Surface { + + public Append() { + setBackground(WHITE); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + GeneralPath p = new GeneralPath(Path2D.WIND_NON_ZERO); + p.moveTo(w * 0.25f, h * 0.2f); + p.lineTo(w * 0.75f, h * 0.2f); + p.closePath(); + p.append(new Rectangle2D.Double(w * .4, h * .3, w * .2, h * .1), false); + g2.setColor(GRAY); + g2.fill(p); + g2.setColor(BLACK); + g2.draw(p); + g2.drawString("Append rect to path", (int) (w * .25), (int) (h * .2) - 5); + + p.reset(); + p.moveTo(w * 0.25f, h * 0.6f); + p.lineTo(w * 0.75f, h * 0.6f); + p.closePath(); + p.append(new Rectangle2D.Double(w * .4, h * .7, w * .2, h * .1), true); + g2.setColor(GRAY); + g2.fill(p); + g2.setColor(BLACK); + g2.draw(p); + g2.drawString("Append, connect", (int) (w * .25), (int) (h * .6) - 5); + } + + public static void main(String s[]) { + createDemoFrame(new Append()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/CurveQuadTo.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/CurveQuadTo.java new file mode 100644 index 00000000000..49b9af65b8a --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/CurveQuadTo.java @@ -0,0 +1,72 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Paths; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.LIGHT_GRAY; +import static java.awt.Color.WHITE; +import java.awt.Graphics2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Path2D; +import java2d.Surface; + + +/** + * Cubic & Quad curves implemented through GeneralPath. + */ +@SuppressWarnings("serial") +public class CurveQuadTo extends Surface { + + public CurveQuadTo() { + setBackground(WHITE); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + GeneralPath p = new GeneralPath(Path2D.WIND_EVEN_ODD); + p.moveTo(w * .2f, h * .25f); + p.curveTo(w * .4f, h * .5f, w * .6f, 0.0f, w * .8f, h * .25f); + p.moveTo(w * .2f, h * .6f); + p.quadTo(w * .5f, h * 1.0f, w * .8f, h * .6f); + g2.setColor(LIGHT_GRAY); + g2.fill(p); + g2.setColor(BLACK); + g2.draw(p); + g2.drawString("curveTo", (int) (w * .2), (int) (h * .25f) - 5); + g2.drawString("quadTo", (int) (w * .2), (int) (h * .6f) - 5); + } + + public static void main(String s[]) { + createDemoFrame(new CurveQuadTo()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/FillStroke.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/FillStroke.java new file mode 100644 index 00000000000..aedda421096 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/FillStroke.java @@ -0,0 +1,75 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Paths; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.LIGHT_GRAY; +import static java.awt.Color.WHITE; +import java.awt.BasicStroke; +import java.awt.Graphics2D; +import java.awt.font.TextLayout; +import java.awt.geom.GeneralPath; +import java.awt.geom.Path2D; +import java2d.Surface; + + +/** + * Basic implementation of GeneralPath, filling & drawing a path w/o closing it. + */ +@SuppressWarnings("serial") +public class FillStroke extends Surface { + + public FillStroke() { + setBackground(WHITE); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + GeneralPath p = new GeneralPath(Path2D.WIND_EVEN_ODD); + p.moveTo(w * .5f, h * .15f); + p.lineTo(w * .8f, h * .75f); + p.lineTo(w * .2f, h * .75f); + g2.setColor(LIGHT_GRAY); + g2.fill(p); + g2.setColor(BLACK); + g2.setStroke(new BasicStroke(10)); + g2.draw(p); + TextLayout tl = new TextLayout("Fill, Stroke w/o closePath", + g2.getFont(), g2.getFontRenderContext()); + tl.draw(g2, (float) (w / 2 - tl.getBounds().getWidth() / 2), h * .85f); + } + + public static void main(String s[]) { + createDemoFrame(new FillStroke()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/WindingRule.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/WindingRule.java new file mode 100644 index 00000000000..115b921934a --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Paths/WindingRule.java @@ -0,0 +1,92 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Paths; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.LIGHT_GRAY; +import static java.awt.Color.WHITE; +import java.awt.Graphics2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Path2D; +import java2d.Surface; + + +/** + * Rectangles filled to illustrate the GenerPath winding rule, determining + * the interior of a path. + */ +@SuppressWarnings("serial") +public class WindingRule extends Surface { + + public WindingRule() { + setBackground(WHITE); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + g2.translate(w * .2, h * .2); + + GeneralPath p = new GeneralPath(Path2D.WIND_NON_ZERO); + p.moveTo(0.0f, 0.0f); + p.lineTo(w * .5f, 0.0f); + p.lineTo(w * .5f, h * .2f); + p.lineTo(0.0f, h * .2f); + p.closePath(); + + p.moveTo(w * .05f, h * .05f); + p.lineTo(w * .55f, h * .05f); + p.lineTo(w * .55f, h * .25f); + p.lineTo(w * .05f, h * .25f); + p.closePath(); + + g2.setColor(LIGHT_GRAY); + g2.fill(p); + g2.setColor(BLACK); + g2.draw(p); + g2.drawString("NON_ZERO rule", 0, -5); + + g2.translate(0.0f, h * .45); + + p.setWindingRule(Path2D.WIND_EVEN_ODD); + g2.setColor(LIGHT_GRAY); + g2.fill(p); + g2.setColor(BLACK); + g2.draw(p); + g2.drawString("EVEN_ODD rule", 0, -5); + } + + public static void main(String s[]) { + createDemoFrame(new WindingRule()); + } +} diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Transforms/Rotate.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Transforms/Rotate.java new file mode 100644 index 00000000000..d602c51870d --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Transforms/Rotate.java @@ -0,0 +1,170 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Transforms; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.BLUE; +import static java.awt.Color.GRAY; +import static java.awt.Color.LIGHT_GRAY; +import static java.awt.Color.WHITE; +import static java.awt.Color.YELLOW; +import java.awt.BasicStroke; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java2d.ControlsSurface; +import java2d.CustomControls; +import javax.swing.JLabel; +import javax.swing.JTextField; + + +/** + * Rotate ellipses with controls for increment and emphasis. + * Emphasis is defined as which ellipses have a darker color and thicker stroke. + */ +@SuppressWarnings("serial") +public class Rotate extends ControlsSurface { + + protected double increment = 5.0; + protected int emphasis = 9; + + public Rotate() { + setBackground(WHITE); + setControls(new Component[] { new DemoControls(this) }); + } + + @Override + public void render(int w, int h, Graphics2D g2) { + int size = Math.min(w, h); + float ew = size / 4; + float eh = size - 20; + Ellipse2D ellipse = new Ellipse2D.Float(-ew / 2, -eh / 2, ew, eh); + for (double angdeg = 0; angdeg < 360; angdeg += increment) { + if (angdeg % emphasis == 0) { + g2.setColor(GRAY); + g2.setStroke(new BasicStroke(2.0f)); + } else { + g2.setColor(LIGHT_GRAY); + g2.setStroke(new BasicStroke(0.5f)); + } + AffineTransform at = AffineTransform.getTranslateInstance(w / 2, h + / 2); + at.rotate(Math.toRadians(angdeg)); + g2.draw(at.createTransformedShape(ellipse)); + } + g2.setColor(BLUE); + ellipse.setFrame(w / 2 - 10, h / 2 - 10, 20, 20); + g2.fill(ellipse); + g2.setColor(GRAY); + g2.setStroke(new BasicStroke(6)); + g2.draw(ellipse); + g2.setColor(YELLOW); + g2.setStroke(new BasicStroke(4)); + g2.draw(ellipse); + g2.setColor(BLACK); + g2.drawString("Rotate", 5, 15); + } + + public static void main(String s[]) { + createDemoFrame(new Rotate()); + } + + + static class DemoControls extends CustomControls implements ActionListener { + + Rotate demo; + JTextField tf1, tf2; + + @SuppressWarnings("LeakingThisInConstructor") + public DemoControls(Rotate demo) { + super(demo.name); + this.demo = demo; + JLabel l = new JLabel("Increment:"); + l.setForeground(BLACK); + add(l); + add(tf1 = new JTextField("5.0")); + tf1.setPreferredSize(new Dimension(30, 24)); + tf1.addActionListener(this); + add(l = new JLabel(" Emphasis:")); + l.setForeground(BLACK); + add(tf2 = new JTextField("9")); + tf2.setPreferredSize(new Dimension(30, 24)); + tf2.addActionListener(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + try { + if (e.getSource().equals(tf1)) { + demo.increment = Double.parseDouble(tf1.getText().trim()); + if (demo.increment < 1.0) { + demo.increment = 1.0; + } + } else { + demo.emphasis = Integer.parseInt(tf2.getText().trim()); + } + demo.repaint(); + } catch (Exception ex) { + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 39); + } + + @Override + @SuppressWarnings("SleepWhileHoldingLock") + public void run() { + Thread me = Thread.currentThread(); + while (thread == me) { + for (int i = 3; i < 13; i += 3) { + try { + Thread.sleep(4444); + } catch (InterruptedException e) { + return; + } + tf1.setText(String.valueOf(i)); + demo.increment = i; + demo.repaint(); + } + } + thread = null; + } + } // End DemoControls class +} // End Rotate class + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Transforms/SelectTx.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Transforms/SelectTx.java new file mode 100644 index 00000000000..7713ff65993 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Transforms/SelectTx.java @@ -0,0 +1,316 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Transforms; + + +import static java.awt.Color.BLACK; +import static java.awt.Color.ORANGE; +import static java.awt.Color.WHITE; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; +import java2d.AnimatingControlsSurface; +import java2d.CustomControls; +import javax.swing.AbstractButton; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; + + +/** + * Scaling or Shearing or Rotating an image & rectangle. + */ +@SuppressWarnings("serial") +public class SelectTx extends AnimatingControlsSurface { + + protected static final int RIGHT = 0; + private static final int LEFT = 1; + private static final int XMIDDLE = 2; + private static final int DOWN = 3; + private static final int UP = 4; + private static final int YMIDDLE = 5; + private static final int XupYup = 6; + private static final int XdownYdown = 7; + private static final String[] title = { "Scale", "Shear", "Rotate" }; + protected static final int SCALE = 0; + protected static final int SHEAR = 1; + protected static final int ROTATE = 2; + private Image original; + private int iw, ih; + protected int transformType = SHEAR; + protected double sx, sy; + protected double angdeg; + protected int direction = RIGHT; + protected int transformToggle; + + @SuppressWarnings("LeakingThisInConstructor") + public SelectTx() { + setBackground(WHITE); + original = getImage("painting.png"); + iw = original.getWidth(this); + ih = original.getHeight(this); + setControls(new Component[] { new DemoControls(this) }); + } + + @Override + public void reset(int w, int h) { + + iw = w > 3 ? w / 3 : 1; + ih = h > 3 ? h / 3 : 1; + + if (transformType == SCALE) { + direction = RIGHT; + sx = sy = 1.0; + } else if (transformType == SHEAR) { + direction = RIGHT; + sx = sy = 0; + } else { + angdeg = 0; + } + } + + @Override + public void step(int w, int h) { + int rw = iw + 10; + int rh = ih + 10; + + if (transformType == SCALE && direction == RIGHT) { + sx += .05; + if (w * .5 - iw * .5 + rw * sx + 10 > w) { + direction = DOWN; + } + } else if (transformType == SCALE && direction == DOWN) { + sy += .05; + if (h * .5 - ih * .5 + rh * sy + 20 > h) { + direction = LEFT; + } + } else if (transformType == SCALE && direction == LEFT) { + sx -= .05; + if (rw * sx - 10 <= -(w * .5 - iw * .5)) { + direction = UP; + } + } else if (transformType == SCALE && direction == UP) { + sy -= .05; + if (rh * sy - 20 <= -(h * .5 - ih * .5)) { + direction = RIGHT; + transformToggle = SHEAR; + } + } + + if (transformType == SHEAR && direction == RIGHT) { + sx += .05; + if (rw + 2 * rh * sx + 20 > w) { + direction = LEFT; + sx -= .1; + } + } else if (transformType == SHEAR && direction == LEFT) { + sx -= .05; + if (rw - 2 * rh * sx + 20 > w) { + direction = XMIDDLE; + } + } else if (transformType == SHEAR && direction == XMIDDLE) { + sx += .05; + if (sx > 0) { + direction = DOWN; + sx = 0; + } + } else if (transformType == SHEAR && direction == DOWN) { + sy -= .05; + if (rh - 2 * rw * sy + 20 > h) { + direction = UP; + sy += .1; + } + } else if (transformType == SHEAR && direction == UP) { + sy += .05; + if (rh + 2 * rw * sy + 20 > h) { + direction = YMIDDLE; + } + } else if (transformType == SHEAR && direction == YMIDDLE) { + sy -= .05; + if (sy < 0) { + direction = XupYup; + sy = 0; + } + } else if (transformType == SHEAR && direction == XupYup) { + sx += .05; + sy += .05; + if (rw + 2 * rh * sx + 30 > w || rh + 2 * rw * sy + 30 > h) { + direction = XdownYdown; + } + } else if (transformType == SHEAR && direction == XdownYdown) { + sy -= .05; + sx -= .05; + if (sy < 0) { + direction = RIGHT; + sx = sy = 0.0; + transformToggle = ROTATE; + } + } + + if (transformType == ROTATE) { + angdeg += 5; + if (angdeg == 360) { + angdeg = 0; + transformToggle = SCALE; + } + } + } + + @Override + public void render(int w, int h, Graphics2D g2) { + + Font font = g2.getFont(); + FontRenderContext frc = g2.getFontRenderContext(); + TextLayout tl = new TextLayout(title[transformType], font, frc); + g2.setColor(BLACK); + tl.draw(g2, (float) (w / 2 - tl.getBounds().getWidth() / 2), + (tl.getAscent() + tl.getDescent())); + + if (transformType == ROTATE) { + String s = Double.toString(angdeg); + g2.drawString("angdeg=" + s, 2, h - 4); + } else { + String s = Double.toString(sx); + s = (s.length() < 5) ? s : s.substring(0, 5); + TextLayout tlsx = new TextLayout("sx=" + s, font, frc); + tlsx.draw(g2, 2, h - 4); + + s = Double.toString(sy); + s = (s.length() < 5) ? s : s.substring(0, 5); + g2.drawString("sy=" + s, (int) (tlsx.getBounds().getWidth() + 4), h + - 4); + } + + if (transformType == SCALE) { + g2.translate(w / 2 - iw / 2, h / 2 - ih / 2); + g2.scale(sx, sy); + } else if (transformType == SHEAR) { + g2.translate(w / 2 - iw / 2, h / 2 - ih / 2); + g2.shear(sx, sy); + } else { + g2.rotate(Math.toRadians(angdeg), w / 2, h / 2); + g2.translate(w / 2 - iw / 2, h / 2 - ih / 2); + } + + g2.setColor(ORANGE); + g2.fillRect(0, 0, iw + 10, ih + 10); + g2.drawImage(original, 5, 5, iw, ih, ORANGE, this); + + } + + public static void main(String argv[]) { + createDemoFrame(new SelectTx()); + } + + + static final class DemoControls extends CustomControls implements + ActionListener { + + SelectTx demo; + JToolBar toolbar; + + public DemoControls(SelectTx demo) { + super(demo.name); + this.demo = demo; + add(toolbar = new JToolBar()); + toolbar.setFloatable(false); + addTool("Scale", false); + addTool("Shear", true); + addTool("Rotate", false); + } + + public void addTool(String str, boolean state) { + JToggleButton b = + (JToggleButton) toolbar.add(new JToggleButton(str)); + b.setFocusPainted(false); + b.setSelected(state); + b.addActionListener(this); + int width = b.getPreferredSize().width; + Dimension prefSize = new Dimension(width, 21); + b.setPreferredSize(prefSize); + b.setMaximumSize(prefSize); + b.setMinimumSize(prefSize); + } + + @Override + public void actionPerformed(ActionEvent e) { + for (int i = 0; i < toolbar.getComponentCount(); i++) { + JToggleButton b = (JToggleButton) toolbar.getComponentAtIndex(i); + b.setSelected(false); + } + JToggleButton b = (JToggleButton) e.getSource(); + b.setSelected(true); + if (b.getText().equals("Scale")) { + demo.transformType = SelectTx.SCALE; + demo.direction = SelectTx.RIGHT; + demo.sx = demo.sy = 1; + } else if (b.getText().equals("Shear")) { + demo.transformType = SelectTx.SHEAR; + demo.direction = SelectTx.RIGHT; + demo.sx = demo.sy = 0; + } else if (b.getText().equals("Rotate")) { + demo.transformType = SelectTx.ROTATE; + demo.angdeg = 0; + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 39); + } + + @Override + @SuppressWarnings("SleepWhileHoldingLock") + public void run() { + Thread me = Thread.currentThread(); + demo.transformToggle = demo.transformType; + while (thread == me) { + try { + Thread.sleep(222); + } catch (InterruptedException e) { + return; + } + if (demo.transformToggle != demo.transformType) { + ((AbstractButton) toolbar.getComponentAtIndex( + demo.transformToggle)).doClick(); + } + } + thread = null; + } + } // End DemoControls class +} // End SelectTx class + diff --git a/src/demo/share/jfc/J2Ddemo/java2d/demos/Transforms/TransformAnim.java b/src/demo/share/jfc/J2Ddemo/java2d/demos/Transforms/TransformAnim.java new file mode 100644 index 00000000000..3d2dd7a9739 --- /dev/null +++ b/src/demo/share/jfc/J2Ddemo/java2d/demos/Transforms/TransformAnim.java @@ -0,0 +1,519 @@ +/* + * + * Copyright (c) 2007, 2011, 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.demos.Transforms; + +import static java.awt.Color.BLACK; +import static java.awt.Color.BLUE; +import static java.awt.Color.CYAN; +import static java.awt.Color.GREEN; +import static java.awt.Color.LIGHT_GRAY; +import static java.awt.Color.MAGENTA; +import static java.awt.Color.ORANGE; +import static java.awt.Color.PINK; +import static java.awt.Color.RED; +import static java.awt.Color.WHITE; +import static java.awt.Color.YELLOW; +import static java.awt.Font.BOLD; +import static java.awt.Font.ITALIC; +import static java.awt.Font.PLAIN; +import java.awt.BasicStroke; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.TexturePaint; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.geom.AffineTransform; +import java.awt.geom.Arc2D; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.QuadCurve2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.List; +import java2d.AnimatingControlsSurface; +import java2d.CustomControls; +import javax.swing.AbstractButton; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JSlider; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; +import javax.swing.SwingConstants; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.metal.MetalBorders.ButtonBorder; + +/** + * Animation of shapes, text and images rotating, scaling and translating + * around a canvas. + */ +@SuppressWarnings("serial") +public final class TransformAnim extends AnimatingControlsSurface { + + private static final TexturePaint texturePaint; + static { + BufferedImage bi = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB); + Graphics2D gi = bi.createGraphics(); + gi.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + gi.setColor(RED); + gi.fillOval(0,0,9,9); + texturePaint = new TexturePaint(bi,new Rectangle(0,0,10,10)); + } + + private static BasicStroke bs = new BasicStroke(6); + private static Font fonts[] = { + new Font(Font.SERIF, PLAIN, 48), + new Font(Font.SERIF, BOLD|ITALIC, 24), + new Font(Font.MONOSPACED, BOLD, 36), + new Font(Font.SANS_SERIF, BOLD|ITALIC, 64), + new Font(Font.SANS_SERIF, PLAIN, 52)}; + private static String strings[] = { + "Transformation", "Rotate", "Translate", "Shear", "Scale" }; + private static String imgs[] = { "duke.png" }; + private static Paint paints[] = { + RED, BLUE, texturePaint, GREEN, MAGENTA, ORANGE, PINK, CYAN, + new Color(0, 255, 0, 128), new Color(0, 0, 255, 128), + YELLOW, LIGHT_GRAY, WHITE}; + private List objDatas = new ArrayList(13); + private int numShapes, numStrings, numImages; + protected boolean doRotate = true; + protected boolean doTranslate = true; + protected boolean doScale = true; + protected boolean doShear; + + + public TransformAnim() { + setBackground(BLACK); + setStrings(1); + setImages(2); + setShapes(10); + setControls(new Component[] { new DemoControls(this) }); + setConstraints(new String[] { BorderLayout.EAST }); + } + + + public void setImages(int num) { + if (num < numImages) { + List v = new ArrayList(objDatas.size()); + for (ObjData objData : objDatas) { + if (objData.object instanceof Image) { + v.add(objData); + } + } + objDatas.removeAll(v.subList(num, v.size())); + } else { + Dimension d = getSize(); + for (int i = numImages; i < num; i++) { + Object obj = getImage(imgs[i % imgs.length]); + ObjData objData = new ObjData(obj, BLACK); + objData.reset(d.width, d.height); + objDatas.add(objData); + } + } + numImages = num; + } + + + public void setStrings(int num) { + if (num < numStrings) { + List v = new ArrayList(objDatas.size()); + for (ObjData objData : objDatas) { + if (objData.object instanceof TextData) { + v.add(objData); + } + } + objDatas.removeAll(v.subList(num, v.size())); + } else { + Dimension d = getSize(); + for (int i = numStrings; i < num; i++) { + int j = i % fonts.length; + int k = i % strings.length; + Object obj = new TextData(strings[k], fonts[j]); + ObjData objData = new ObjData(obj, paints[i%paints.length]); + objData.reset(d.width, d.height); + objDatas.add(objData); + } + } + numStrings = num; + } + + + public void setShapes(int num) { + if (num < numShapes) { + List v = new ArrayList(objDatas.size()); + for (ObjData objData : objDatas) { + if (objData.object instanceof Shape) { + v.add(objData); + } + } + objDatas.removeAll(v.subList(num, v.size())); + } else { + Dimension d = getSize(); + for (int i = numShapes; i < num; i++) { + Object obj = null; + switch (i % 7) { + case 0 : obj = new GeneralPath(); break; + case 1 : obj = new Rectangle2D.Double(); break; + case 2 : obj = new Ellipse2D.Double(); break; + case 3 : obj = new Arc2D.Double(); break; + case 4 : obj = new RoundRectangle2D.Double(); break; + case 5 : obj = new CubicCurve2D.Double(); break; + case 6 : obj = new QuadCurve2D.Double(); break; + } + ObjData objData = new ObjData(obj, paints[i%paints.length]); + objData.reset(d.width, d.height); + objDatas.add(objData); + } + } + numShapes = num; + } + + + @Override + public void reset(int w, int h) { + for (ObjData objData : objDatas) { + objData.reset(w, h); + } + } + + + @Override + public void step(int w, int h) { + for (ObjData objData : objDatas) { + objData.step(w, h, this); + } + } + + + @Override + public void render(int w, int h, Graphics2D g2) { + for (ObjData objData : objDatas) { + g2.setTransform(objData.at); + g2.setPaint(objData.paint); + if (objData.object instanceof Image) { + g2.drawImage((Image) objData.object, 0, 0, this); + } else if (objData.object instanceof TextData) { + g2.setFont(((TextData) objData.object).font); + g2.drawString(((TextData) objData.object).string, 0, 0); + } else if (objData.object instanceof QuadCurve2D + || objData.object instanceof CubicCurve2D) + { + g2.setStroke(bs); + g2.draw((Shape) objData.object); + } else if (objData.object instanceof Shape) { + g2.fill((Shape) objData.object); + } + } + } + + + public static void main(String argv[]) { + createDemoFrame(new TransformAnim()); + } + + + static class TextData extends Object { + + public String string; + public Font font; + + public TextData(String str, Font font) { + string = str; + this.font = font; + } + } + + + static class ObjData extends Object { + Object object; + Paint paint; + static final int UP = 0; + static final int DOWN = 1; + double x, y; + double ix=5, iy=3; + int rotate; + double scale, shear; + int scaleDirection, shearDirection; + AffineTransform at = new AffineTransform(); + + + public ObjData(Object object, Paint paint) { + this.object = object; + this.paint = paint; + rotate = (int)(Math.random() * 360); + scale = Math.random() * 1.5; + scaleDirection = Math.random() > 0.5 ? UP : DOWN; + shear = Math.random() * 0.5; + shearDirection = Math.random() > 0.5 ? UP : DOWN; + } + + + public void reset(int w, int h) { + x = Math.random()*w; + y = Math.random()*h; + double ww = 20 + Math.random()*((w == 0 ? 400 : w)/4); + double hh = 20 + Math.random()*((h == 0 ? 300 : h)/4); + if (object instanceof Ellipse2D) { + ((Ellipse2D) object).setFrame(0, 0, ww, hh); + } else if (object instanceof Rectangle2D) { + ((Rectangle2D) object).setRect(0, 0, ww, ww); + } else if (object instanceof RoundRectangle2D) { + ((RoundRectangle2D) object).setRoundRect(0, 0, hh, hh, 20, 20); + } else if (object instanceof Arc2D) { + ((Arc2D) object).setArc(0, 0, hh, hh, 45, 270, Arc2D.PIE); + } else if (object instanceof QuadCurve2D) { + ((QuadCurve2D) object).setCurve(0, 0, w*.2, h*.4, w*.4, 0); + } else if (object instanceof CubicCurve2D) { + ((CubicCurve2D) object).setCurve(0,0,30,-60,60,60,90,0); + } else if (object instanceof GeneralPath) { + GeneralPath p = new GeneralPath(); + float size = (float) ww; + p.moveTo(- size / 2.0f, - size / 8.0f); + p.lineTo(+ size / 2.0f, - size / 8.0f); + p.lineTo(- size / 4.0f, + size / 2.0f); + p.lineTo(+ 0.0f, - size / 2.0f); + p.lineTo(+ size / 4.0f, + size / 2.0f); + p.closePath(); + object = p; + } + } + + + public void step(int w, int h, TransformAnim demo) { + at.setToIdentity(); + if (demo.doRotate) { + if ((rotate+=5) == 360) { + rotate = 0; + } + at.rotate(Math.toRadians(rotate), x, y); + } + at.translate(x, y); + if (demo.doTranslate) { + x += ix; + y += iy; + if (x > w) { + x = w - 1; + ix = Math.random() * -w/32 - 1; + } + if (x < 0) { + x = 2; + ix = Math.random() * w/32 + 1; + } + if (y > h ) { + y = h - 2; + iy = Math.random() * -h/32 - 1; + } + if (y < 0) { + y = 2; + iy = Math.random() * h/32 + 1; + } + } + if (demo.doScale && scaleDirection == UP) { + if ((scale += 0.05) > 1.5) { + scaleDirection = DOWN; + } + } else if (demo.doScale && scaleDirection == DOWN) { + if ((scale -= .05) < 0.5) { + scaleDirection = UP; + } + } + if (demo.doScale) { + at.scale(scale, scale); + } + if (demo.doShear && shearDirection == UP) { + if ((shear += 0.05) > 0.5) { + shearDirection = DOWN; + } + } else if (demo.doShear && shearDirection == DOWN) { + if ((shear -= .05) < -0.5) { + shearDirection = UP; + } + } + if (demo.doShear) { + at.shear(shear, shear); + } + } + } // End ObjData class + + + + static final class DemoControls extends CustomControls implements ActionListener, ChangeListener { + + TransformAnim demo; + JSlider shapeSlider, stringSlider, imageSlider; + Font font = new Font(Font.SERIF, Font.BOLD, 10); + JToolBar toolbar; + ButtonBorder buttonBorder = new ButtonBorder(); + + @SuppressWarnings("LeakingThisInConstructor") + public DemoControls(TransformAnim demo) { + super(demo.name); + this.demo = demo; + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + add(Box.createVerticalStrut(5)); + + JToolBar bar = new JToolBar(SwingConstants.VERTICAL); + bar.setFloatable(false); + shapeSlider = new JSlider(SwingConstants.HORIZONTAL,0,20,demo.numShapes); + shapeSlider.addChangeListener(this); + TitledBorder tb = new TitledBorder(new EtchedBorder()); + tb.setTitleFont(font); + tb.setTitle(String.valueOf(demo.numShapes) + " Shapes"); + shapeSlider.setBorder(tb); + shapeSlider.setOpaque(true); + shapeSlider.setPreferredSize(new Dimension(80,44)); + bar.add(shapeSlider); + bar.addSeparator(); + + stringSlider = new JSlider(SwingConstants.HORIZONTAL,0,10,demo.numStrings); + stringSlider.addChangeListener(this); + tb = new TitledBorder(new EtchedBorder()); + tb.setTitleFont(font); + tb.setTitle(String.valueOf(demo.numStrings) + " Strings"); + stringSlider.setBorder(tb); + stringSlider.setOpaque(true); + stringSlider.setPreferredSize(new Dimension(80,44)); + bar.add(stringSlider); + bar.addSeparator(); + + imageSlider = new JSlider(SwingConstants.HORIZONTAL,0,10,demo.numImages); + imageSlider.addChangeListener(this); + tb = new TitledBorder(new EtchedBorder()); + tb.setTitleFont(font); + tb.setTitle(String.valueOf(demo.numImages) + " Images"); + imageSlider.setBorder(tb); + imageSlider.setOpaque(true); + imageSlider.setPreferredSize(new Dimension(80,44)); + bar.add(imageSlider); + bar.addSeparator(); + add(bar); + + toolbar = new JToolBar(); + toolbar.setFloatable(false); + addButton("T", "translate", demo.doTranslate); + addButton("R", "rotate", demo.doRotate); + addButton("SC", "scale", demo.doScale); + addButton("SH", "shear", demo.doShear); + add(toolbar); + } + + + public void addButton(String s, String tt, boolean state) { + JToggleButton b = (JToggleButton) toolbar.add(new JToggleButton(s)); + b.setFont(font); + b.setSelected(state); + b.setToolTipText(tt); + b.setFocusPainted(false); + b.setBorder(buttonBorder); + b.addActionListener(this); + } + + + @Override + public void actionPerformed(ActionEvent e) { + JToggleButton b = (JToggleButton) e.getSource(); + if (b.getText().equals("T")) { + demo.doTranslate = b.isSelected(); + } else if (b.getText().equals("R")) { + demo.doRotate = b.isSelected(); + } else if (b.getText().equals("SC")) { + demo.doScale = b.isSelected(); + } else if (b.getText().equals("SH")) { + demo.doShear = b.isSelected(); + } + if (!demo.animating.running()) { + demo.repaint(); + } + } + + + @Override + public void stateChanged(ChangeEvent e) { + JSlider slider = (JSlider) e.getSource(); + int value = slider.getValue(); + TitledBorder tb = (TitledBorder) slider.getBorder(); + if (slider.equals(shapeSlider)) { + tb.setTitle(String.valueOf(value) + " Shapes"); + demo.setShapes(value); + } else if (slider.equals(stringSlider)) { + tb.setTitle(String.valueOf(value) + " Strings"); + demo.setStrings(value); + } else if (slider.equals(imageSlider)) { + tb.setTitle(String.valueOf(value) + " Images"); + demo.setImages(value); + } + if (!demo.animating.running()) { + demo.repaint(); + } + slider.repaint(); + } + + + @Override + public Dimension getPreferredSize() { + return new Dimension(80,38); + } + + + @Override + @SuppressWarnings("SleepWhileHoldingLock") + public void run() { + Thread me = Thread.currentThread(); + while (thread == me) { + for (int i = 1; i < toolbar.getComponentCount(); i++) { + try { + Thread.sleep(4444); + } catch (InterruptedException e) { return; } + ((AbstractButton) toolbar.getComponentAtIndex(i)).doClick(); + } + } + thread = null; + } + } // End DemoControls +} // End TransformAnim diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT index 99486f3dc7f..d8d1251eb69 100644 --- a/test/jdk/TEST.ROOT +++ b/test/jdk/TEST.ROOT @@ -18,7 +18,7 @@ keys=2d dnd headful i18n intermittent printer randomness # Tests that must run in othervm mode othervm.dirs=java/awt java/beans javax/accessibility javax/imageio javax/sound javax/swing javax/print \ -sun/applet com/apple/laf com/sun/java/accessibility com/sun/java/swing sanity/client \ +sun/applet com/apple/laf com/sun/java/accessibility com/sun/java/swing sanity/client demo/jfc \ javax/management com/sun/awt sun/awt sun/java2d javax/xml/jaxp/testng/validation java/lang/ProcessHandle # Tests that cannot run concurrently diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups index 2058c33f819..c45f56a5c24 100644 --- a/test/jdk/TEST.groups +++ b/test/jdk/TEST.groups @@ -359,13 +359,17 @@ jdk_sound = \ jdk_imageio = \ javax/imageio +jfc_demo = \ + demo/jfc + jdk_desktop = \ :jdk_awt \ :jdk_2d \ :jdk_beans \ :jdk_swing \ :jdk_sound \ - :jdk_imageio + :jdk_imageio \ + :jfc_demo # SwingSet3 tests. jdk_client_sanity = \ diff --git a/test/jdk/demo/jfc/J2Ddemo/J2DdemoTest.java b/test/jdk/demo/jfc/J2Ddemo/J2DdemoTest.java new file mode 100644 index 00000000000..62df090776c --- /dev/null +++ b/test/jdk/demo/jfc/J2Ddemo/J2DdemoTest.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @key headful + * @summary Test J2Ddemo.jar + * @run main/timeout=200 J2DdemoTest + */ + +import java.io.InputStream; +import java.io.IOException; +import java.io.File; +import java.io.BufferedInputStream; +import java.io.PrintStream; + +public class J2DdemoTest { + + public static void main(String args[]) throws Exception { + DemoRun test; + + /* Run the J2Ddemo.jar with the -runs=1 option */ + test = new DemoRun("demo/jfc/J2Ddemo/J2Ddemo.jar", "-runs=1"); + test.runit(); + + /* Make sure patterns in output look ok */ + if (test.output_contains("ERROR")) { + throw new RuntimeException("Test failed - ERROR seen in output"); + } + if (test.output_contains("Exception")) { + throw new RuntimeException("Test failed - Exception seen in output"); + } + + /* Must be a pass. */ + System.out.println("Test passed - cleanly terminated"); + } + + /* + * Helper class to direct process output to a StringBuffer + */ + static class MyInputStream implements Runnable { + private String name; + private BufferedInputStream in; + private StringBuffer buffer; + + /* Create MyInputStream that saves all output to a StringBuffer */ + MyInputStream(String name, InputStream in) { + this.name = name; + this.in = new BufferedInputStream(in); + buffer = new StringBuffer(4096); + Thread thr = new Thread(this); + thr.setDaemon(true); + thr.start(); + } + + /* Dump the buffer */ + void dump(PrintStream x) { + String str = buffer.toString(); + x.println(""); + x.println(str); + x.println(""); + } + + /* Check to see if a pattern is inside the output. */ + boolean contains(String pattern) { + String str = buffer.toString(); + return str.contains(pattern); + } + + /* Runs as a separate thread capturing all output in a StringBuffer */ + public void run() { + try { + byte b[] = new byte[100]; + for (;;) { + int n = in.read(b); + String str; + if (n < 0) { + break; + } + str = new String(b, 0, n); + buffer.append(str); + System.out.print(str); + } + } catch (IOException ioe) { /* skip */ } + } + } + + /* + * Generic run of a demo jar file. + */ + static class DemoRun { + + private String demo_name; + private String demo_options; + private MyInputStream output; + private MyInputStream error; + + /* Create a Demo run process */ + public DemoRun(String name, String options) + { + demo_name = name; + demo_options = options; + } + + /* + * Execute the demo + */ + public void runit() + { + String jre_home = System.getProperty("java.home"); + String sdk_home = (jre_home.endsWith("jre") ? + (jre_home + File.separator + "..") : + jre_home ); + String java = sdk_home + + File.separator + "bin" + + File.separator + "java"; + + /* VM options */ + String vm_opts[] = new String[0]; + String vopts = System.getProperty("test.vm.opts"); + if ( vopts != null && vopts.length()>0 ) { + vm_opts = vopts.split("\\p{Space}+"); + } else { + vm_opts = new String[0]; + } + + /* Command line */ + String cmd[] = new String[1 + vm_opts.length + 3]; + String cmdLine; + int i; + + i = 0; + cmdLine = ""; + cmdLine += (cmd[i++] = java); + cmdLine += " "; + for ( String vopt : vm_opts ) { + cmdLine += (cmd[i++] = vopt); + cmdLine += " "; + } + cmdLine += (cmd[i++] = "-jar"); + cmdLine += " "; + cmdLine += (cmd[i++] = sdk_home + File.separator + demo_name); + cmdLine += " "; + cmdLine += (cmd[i++] = demo_options); + + /* Begin process */ + Process p; + + System.out.println("Starting: " + cmdLine); + try { + p = Runtime.getRuntime().exec(cmd); + } catch ( IOException e ) { + throw new RuntimeException("Test failed - exec got IO exception"); + } + + /* Save process output in StringBuffers */ + output = new MyInputStream("Input Stream", p.getInputStream()); + error = new MyInputStream("Error Stream", p.getErrorStream()); + + /* Wait for process to complete, and if exit code is non-zero we fail */ + int exitStatus; + try { + exitStatus = p.waitFor(); + if ( exitStatus != 0) { + System.out.println("Exit code is " + exitStatus); + error.dump(System.out); + output.dump(System.out); + throw new RuntimeException("Test failed - " + + "exit return code non-zero " + + "(exitStatus==" + exitStatus + ")"); + } + } catch ( InterruptedException e ) { + throw new RuntimeException("Test failed - process interrupted"); + } + System.out.println("Completed: " + cmdLine); + } + + /* Does the pattern appear in the output of this process */ + public boolean output_contains(String pattern) + { + return output.contains(pattern) || error.contains(pattern); + } + } + +} + diff --git a/test/jdk/demo/jfc/TEST.properties b/test/jdk/demo/jfc/TEST.properties new file mode 100644 index 00000000000..3032a5cf793 --- /dev/null +++ b/test/jdk/demo/jfc/TEST.properties @@ -0,0 +1,2 @@ +modules=java.desktop +