picrate 0.0.2-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +47 -0
  3. data/.mvn/extensions.xml +9 -0
  4. data/.mvn/wrapper/maven-wrapper.properties +1 -0
  5. data/.travis.yml +10 -0
  6. data/CHANGELOG.md +4 -0
  7. data/LICENSE.md +165 -0
  8. data/README.md +51 -0
  9. data/Rakefile +59 -0
  10. data/bin/picrate +8 -0
  11. data/docs/.gitignore +6 -0
  12. data/docs/_config.yml +30 -0
  13. data/docs/_includes/footer.html +38 -0
  14. data/docs/_includes/head.html +16 -0
  15. data/docs/_includes/header.html +27 -0
  16. data/docs/_includes/icon-github.html +1 -0
  17. data/docs/_includes/icon-github.svg +1 -0
  18. data/docs/_includes/icon-twitter.html +1 -0
  19. data/docs/_includes/icon-twitter.svg +1 -0
  20. data/docs/_includes/navigation.html +24 -0
  21. data/docs/_layouts/default.html +20 -0
  22. data/docs/_layouts/page.html +14 -0
  23. data/docs/_layouts/post.html +15 -0
  24. data/docs/_posts/2018-05-06-getting_started.md +8 -0
  25. data/docs/_posts/2018-05-06-install_jruby.md +35 -0
  26. data/docs/_sass/_base.scss +206 -0
  27. data/docs/_sass/_layout.scss +242 -0
  28. data/docs/_sass/_syntax-highlighting.scss +71 -0
  29. data/docs/about.md +10 -0
  30. data/docs/css/main.scss +38 -0
  31. data/docs/favicon.ico +0 -0
  32. data/docs/feed.xml +30 -0
  33. data/docs/index.html +38 -0
  34. data/lib/picrate.rb +10 -0
  35. data/lib/picrate/app.rb +187 -0
  36. data/lib/picrate/creators/sketch_class.rb +57 -0
  37. data/lib/picrate/creators/sketch_factory.rb +12 -0
  38. data/lib/picrate/creators/sketch_writer.rb +21 -0
  39. data/lib/picrate/helper_methods.rb +214 -0
  40. data/lib/picrate/helpers/numeric.rb +9 -0
  41. data/lib/picrate/library.rb +69 -0
  42. data/lib/picrate/library_loader.rb +53 -0
  43. data/lib/picrate/native_folder.rb +35 -0
  44. data/lib/picrate/native_loader.rb +27 -0
  45. data/lib/picrate/runner.rb +81 -0
  46. data/lib/picrate/version.rb +4 -0
  47. data/library/boids/boids.rb +209 -0
  48. data/library/chooser/chooser.rb +19 -0
  49. data/library/control_panel/control_panel.rb +182 -0
  50. data/library/library_proxy/README.md +99 -0
  51. data/library/library_proxy/library_proxy.rb +14 -0
  52. data/library/slider/slider.rb +42 -0
  53. data/library/vector_utils/vector_utils.rb +69 -0
  54. data/library/video_event/video_event.rb +3 -0
  55. data/license.txt +508 -0
  56. data/picrate.gemspec +35 -0
  57. data/pom.rb +122 -0
  58. data/pom.xml +214 -0
  59. data/src/main/java/japplemenubar/JAppleMenuBar.java +88 -0
  60. data/src/main/java/japplemenubar/libjAppleMenuBar.jnilib +0 -0
  61. data/src/main/java/monkstone/ColorUtil.java +115 -0
  62. data/src/main/java/monkstone/MathToolModule.java +236 -0
  63. data/src/main/java/monkstone/PicrateLibrary.java +47 -0
  64. data/src/main/java/monkstone/core/LibraryProxy.java +127 -0
  65. data/src/main/java/monkstone/fastmath/Deglut.java +122 -0
  66. data/src/main/java/monkstone/fastmath/package-info.java +6 -0
  67. data/src/main/java/monkstone/filechooser/Chooser.java +48 -0
  68. data/src/main/java/monkstone/noise/SimplexNoise.java +465 -0
  69. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +168 -0
  70. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +182 -0
  71. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +149 -0
  72. data/src/main/java/monkstone/slider/SimpleSlider.java +196 -0
  73. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +163 -0
  74. data/src/main/java/monkstone/slider/Slider.java +67 -0
  75. data/src/main/java/monkstone/slider/SliderBar.java +277 -0
  76. data/src/main/java/monkstone/slider/SliderGroup.java +78 -0
  77. data/src/main/java/monkstone/slider/WheelHandler.java +35 -0
  78. data/src/main/java/monkstone/vecmath/AppRender.java +87 -0
  79. data/src/main/java/monkstone/vecmath/JRender.java +56 -0
  80. data/src/main/java/monkstone/vecmath/ShapeRender.java +87 -0
  81. data/src/main/java/monkstone/vecmath/package-info.java +20 -0
  82. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +757 -0
  83. data/src/main/java/monkstone/vecmath/vec2/package-info.java +6 -0
  84. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +727 -0
  85. data/src/main/java/monkstone/vecmath/vec3/package-info.java +6 -0
  86. data/src/main/java/monkstone/videoevent/VideoInterface.java +42 -0
  87. data/src/main/java/monkstone/videoevent/package-info.java +20 -0
  88. data/src/main/java/processing/awt/PGraphicsJava2D.java +3098 -0
  89. data/src/main/java/processing/awt/PShapeJava2D.java +401 -0
  90. data/src/main/java/processing/awt/PSurfaceAWT.java +1660 -0
  91. data/src/main/java/processing/core/PApplet.java +17647 -0
  92. data/src/main/java/processing/core/PConstants.java +1033 -0
  93. data/src/main/java/processing/core/PFont.java +1250 -0
  94. data/src/main/java/processing/core/PGraphics.java +9614 -0
  95. data/src/main/java/processing/core/PImage.java +3608 -0
  96. data/src/main/java/processing/core/PMatrix.java +347 -0
  97. data/src/main/java/processing/core/PMatrix2D.java +694 -0
  98. data/src/main/java/processing/core/PMatrix3D.java +1153 -0
  99. data/src/main/java/processing/core/PShape.java +4332 -0
  100. data/src/main/java/processing/core/PShapeOBJ.java +544 -0
  101. data/src/main/java/processing/core/PShapeSVG.java +1987 -0
  102. data/src/main/java/processing/core/PStyle.java +208 -0
  103. data/src/main/java/processing/core/PSurface.java +242 -0
  104. data/src/main/java/processing/core/PSurfaceNone.java +479 -0
  105. data/src/main/java/processing/core/PVector.java +1140 -0
  106. data/src/main/java/processing/data/FloatDict.java +829 -0
  107. data/src/main/java/processing/data/FloatList.java +912 -0
  108. data/src/main/java/processing/data/IntDict.java +796 -0
  109. data/src/main/java/processing/data/IntList.java +913 -0
  110. data/src/main/java/processing/data/JSONArray.java +1260 -0
  111. data/src/main/java/processing/data/JSONObject.java +2282 -0
  112. data/src/main/java/processing/data/JSONTokener.java +435 -0
  113. data/src/main/java/processing/data/Sort.java +46 -0
  114. data/src/main/java/processing/data/StringDict.java +601 -0
  115. data/src/main/java/processing/data/StringList.java +775 -0
  116. data/src/main/java/processing/data/Table.java +4923 -0
  117. data/src/main/java/processing/data/TableRow.java +198 -0
  118. data/src/main/java/processing/data/XML.java +1149 -0
  119. data/src/main/java/processing/event/Event.java +108 -0
  120. data/src/main/java/processing/event/KeyEvent.java +70 -0
  121. data/src/main/java/processing/event/MouseEvent.java +149 -0
  122. data/src/main/java/processing/event/TouchEvent.java +57 -0
  123. data/src/main/java/processing/javafx/PGraphicsFX2D.java +354 -0
  124. data/src/main/java/processing/opengl/FontTexture.java +379 -0
  125. data/src/main/java/processing/opengl/FrameBuffer.java +503 -0
  126. data/src/main/java/processing/opengl/LinePath.java +623 -0
  127. data/src/main/java/processing/opengl/LineStroker.java +685 -0
  128. data/src/main/java/processing/opengl/PGL.java +3366 -0
  129. data/src/main/java/processing/opengl/PGraphics2D.java +615 -0
  130. data/src/main/java/processing/opengl/PGraphics3D.java +281 -0
  131. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +13634 -0
  132. data/src/main/java/processing/opengl/PJOGL.java +1966 -0
  133. data/src/main/java/processing/opengl/PShader.java +1478 -0
  134. data/src/main/java/processing/opengl/PShapeOpenGL.java +5234 -0
  135. data/src/main/java/processing/opengl/PSurfaceJOGL.java +1315 -0
  136. data/src/main/java/processing/opengl/Texture.java +1670 -0
  137. data/src/main/java/processing/opengl/VertexBuffer.java +88 -0
  138. data/src/main/java/processing/opengl/cursors/arrow.png +0 -0
  139. data/src/main/java/processing/opengl/cursors/cross.png +0 -0
  140. data/src/main/java/processing/opengl/cursors/hand.png +0 -0
  141. data/src/main/java/processing/opengl/cursors/license.txt +27 -0
  142. data/src/main/java/processing/opengl/cursors/move.png +0 -0
  143. data/src/main/java/processing/opengl/cursors/text.png +0 -0
  144. data/src/main/java/processing/opengl/cursors/wait.png +0 -0
  145. data/src/main/java/processing/opengl/shaders/ColorFrag.glsl +32 -0
  146. data/src/main/java/processing/opengl/shaders/ColorVert.glsl +34 -0
  147. data/src/main/java/processing/opengl/shaders/LightFrag.glsl +33 -0
  148. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +154 -0
  149. data/src/main/java/processing/opengl/shaders/LightVert.glsl +151 -0
  150. data/src/main/java/processing/opengl/shaders/LineFrag.glsl +32 -0
  151. data/src/main/java/processing/opengl/shaders/LineVert.glsl +100 -0
  152. data/src/main/java/processing/opengl/shaders/MaskFrag.glsl +40 -0
  153. data/src/main/java/processing/opengl/shaders/PointFrag.glsl +32 -0
  154. data/src/main/java/processing/opengl/shaders/PointVert.glsl +56 -0
  155. data/src/main/java/processing/opengl/shaders/TexFrag.glsl +37 -0
  156. data/src/main/java/processing/opengl/shaders/TexLightFrag.glsl +37 -0
  157. data/src/main/java/processing/opengl/shaders/TexLightVert-vc4.glsl +160 -0
  158. data/src/main/java/processing/opengl/shaders/TexLightVert.glsl +157 -0
  159. data/src/main/java/processing/opengl/shaders/TexVert.glsl +38 -0
  160. data/src/main/resources/icon/icon-1024.png +0 -0
  161. data/src/main/resources/icon/icon-128.png +0 -0
  162. data/src/main/resources/icon/icon-16.png +0 -0
  163. data/src/main/resources/icon/icon-256.png +0 -0
  164. data/src/main/resources/icon/icon-32.png +0 -0
  165. data/src/main/resources/icon/icon-48.png +0 -0
  166. data/src/main/resources/icon/icon-512.png +0 -0
  167. data/src/main/resources/icon/icon-64.png +0 -0
  168. data/src/main/resources/license.txt +508 -0
  169. data/test/create_test.rb +68 -0
  170. data/test/deglut_spec_test.rb +24 -0
  171. data/test/helper_methods_test.rb +58 -0
  172. data/test/math_tool_test.rb +75 -0
  173. data/test/respond_to_test.rb +215 -0
  174. data/test/sketches/key_event.rb +37 -0
  175. data/test/sketches/library/my_library/my_library.rb +32 -0
  176. data/test/test_helper.rb +3 -0
  177. data/test/vecmath_spec_test.rb +522 -0
  178. data/vendors/Rakefile +127 -0
  179. metadata +289 -0
@@ -0,0 +1,6 @@
1
+ /*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+ package monkstone.vecmath.vec3;
@@ -0,0 +1,42 @@
1
+ /*
2
+ * Copyright (c) 2018 Martin Prout
3
+ *
4
+ * This library is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 3.0 of the License, or (at your option) any later version.
8
+ *
9
+ * http://creativecommons.org/licenses/LGPL/2.1/
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+ package monkstone.videoevent;
22
+ import processing.video.Movie;
23
+ import processing.video.Capture;
24
+ /**
25
+ * This interface makes it easier/possible to use the reflection methods
26
+ * from Movie and Capture classes in Propane::App in propane
27
+ *
28
+ */
29
+ public interface VideoInterface {
30
+ /**
31
+ * Used to implement reflection method in PApplet
32
+ * @see processing.video.Movie
33
+ * @param movie Movie
34
+ */
35
+ public void movieEvent(Movie movie);
36
+ /**
37
+ * Used to implement reflection method in PApplet
38
+ * @see processing.video.Capture
39
+ * @param capture Capture
40
+ */
41
+ public void captureEvent(Capture capture);
42
+ }
@@ -0,0 +1,20 @@
1
+ /*
2
+ * Copyright (c) 2018 Martin Prout
3
+ *
4
+ * This library is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 3.0 of the License, or (at your option) any later version.
8
+ *
9
+ * http://creativecommons.org/licenses/LGPL/2.1/
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+ package monkstone.videoevent;
@@ -0,0 +1,3098 @@
1
+ /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
+
3
+ /*
4
+ Part of the Processing project - http://processing.org
5
+
6
+ Copyright (c) 2013-15 The Processing Foundation
7
+ Copyright (c) 2005-13 Ben Fry and Casey Reas
8
+
9
+ This library is free software; you can redistribute it and/or
10
+ modify it under the terms of the GNU Lesser General Public
11
+ License as published by the Free Software Foundation; either
12
+ version 2.1 of the License, or (at your option) any later version.
13
+
14
+ This library is distributed in the hope that it will be useful,
15
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
+ Lesser General Public License for more details.
18
+
19
+ You should have received a copy of the GNU Lesser General
20
+ Public License along with this library; if not, write to the
21
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
22
+ Boston, MA 02111-1307 USA
23
+ */
24
+
25
+ package processing.awt;
26
+
27
+ import java.awt.*;
28
+ import java.awt.font.TextAttribute;
29
+ import java.awt.geom.*;
30
+ import java.awt.image.*;
31
+ import java.util.Arrays;
32
+ import java.util.HashMap;
33
+ import java.util.Map;
34
+
35
+ import processing.core.*;
36
+
37
+
38
+ /**
39
+ * Subclass for PGraphics that implements the graphics API using Java2D.
40
+ * <p>
41
+ * To get access to the Java 2D "Graphics2D" object for the default
42
+ * renderer, use:
43
+ * <PRE>
44
+ * Graphics2D g2 = (Graphics2D) g.getNative();
45
+ * </PRE>
46
+ * This will let you do Graphics2D calls directly, but is not supported
47
+ * in any way shape or form. Which just means "have fun, but don't complain
48
+ * if it breaks."
49
+ * <p>
50
+ * Advanced <a href="http://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-Desktop/html/java2d.html">debugging notes</a> for Java2D.
51
+ */
52
+ public class PGraphicsJava2D extends PGraphics {
53
+ //// BufferStrategy strategy;
54
+ //// BufferedImage bimage;
55
+ //// VolatileImage vimage;
56
+ // Canvas canvas;
57
+ //// boolean useCanvas = true;
58
+ // boolean useCanvas = false;
59
+ //// boolean useRetina = true;
60
+ //// boolean useOffscreen = true; // ~40fps
61
+ // boolean useOffscreen = false;
62
+
63
+ /**
64
+ *
65
+ */
66
+
67
+ public Graphics2D g2;
68
+ // protected BufferedImage offscreen;
69
+
70
+ Composite defaultComposite;
71
+
72
+ GeneralPath gpath;
73
+
74
+ // path for contours so gpath can be closed
75
+ GeneralPath auxPath;
76
+
77
+ boolean openContour;
78
+
79
+ /// break the shape at the next vertex (next vertex() call is a moveto())
80
+ boolean breakShape;
81
+
82
+ /// coordinates for internal curve calculation
83
+ float[] curveCoordX;
84
+ float[] curveCoordY;
85
+ float[] curveDrawX;
86
+ float[] curveDrawY;
87
+
88
+ int transformCount;
89
+ AffineTransform transformStack[] =
90
+ new AffineTransform[MATRIX_STACK_DEPTH];
91
+ double[] transform = new double[6];
92
+
93
+ Line2D.Float line = new Line2D.Float();
94
+ Ellipse2D.Float ellipse = new Ellipse2D.Float();
95
+ Rectangle2D.Float rect = new Rectangle2D.Float();
96
+ Arc2D.Float arc = new Arc2D.Float();
97
+
98
+ /**
99
+ *
100
+ */
101
+ protected Color tintColorObject;
102
+
103
+ /**
104
+ *
105
+ */
106
+ protected Color fillColorObject;
107
+
108
+ /**
109
+ *
110
+ */
111
+ public boolean fillGradient;
112
+
113
+ /**
114
+ *
115
+ */
116
+ public Paint fillGradientObject;
117
+
118
+ /**
119
+ *
120
+ */
121
+ protected Stroke strokeObject;
122
+
123
+ /**
124
+ *
125
+ */
126
+ protected Color strokeColorObject;
127
+
128
+ /**
129
+ *
130
+ */
131
+ public boolean strokeGradient;
132
+
133
+ /**
134
+ *
135
+ */
136
+ public Paint strokeGradientObject;
137
+
138
+ Font fontObject;
139
+
140
+
141
+
142
+ //////////////////////////////////////////////////////////////
143
+
144
+ // INTERNAL
145
+
146
+ /**
147
+ *
148
+ */
149
+
150
+
151
+ public PGraphicsJava2D() { }
152
+
153
+
154
+ //public void setParent(PApplet parent)
155
+
156
+
157
+ //public void setPrimary(boolean primary)
158
+
159
+
160
+ //public void setPath(String path)
161
+
162
+
163
+ // /**
164
+ // * Called in response to a resize event, handles setting the
165
+ // * new width and height internally, as well as re-allocating
166
+ // * the pixel buffer for the new size.
167
+ // *
168
+ // * Note that this will nuke any cameraMode() settings.
169
+ // */
170
+ // @Override
171
+ // public void setSize(int iwidth, int iheight) { // ignore
172
+ // width = iwidth;
173
+ // height = iheight;
174
+ //
175
+ // allocate();
176
+ // reapplySettings();
177
+ // }
178
+
179
+
180
+ // @Override
181
+ // protected void allocate() {
182
+ // //surface.initImage(this, width, height);
183
+ // surface.initImage(this);
184
+ // }
185
+
186
+
187
+ /*
188
+ @Override
189
+ protected void allocate() {
190
+ // Tried this with RGB instead of ARGB for the primarySurface version,
191
+ // but didn't see any performance difference (OS X 10.6, Java 6u24).
192
+ // For 0196, also attempted RGB instead of ARGB, but that causes
193
+ // strange things to happen with blending.
194
+ // image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
195
+ if (primarySurface) {
196
+ if (useCanvas) {
197
+ if (canvas != null) {
198
+ parent.removeListeners(canvas);
199
+ parent.remove(canvas);
200
+ }
201
+ canvas = new Canvas();
202
+ canvas.setIgnoreRepaint(true);
203
+
204
+ // parent.setLayout(new BorderLayout());
205
+ // parent.add(canvas, BorderLayout.CENTER);
206
+ parent.add(canvas);
207
+ // canvas.validate();
208
+ // parent.doLayout();
209
+
210
+ if (canvas.getWidth() != width || canvas.getHeight() != height) {
211
+ PApplet.debug("PGraphicsJava2D comp size being set to " + width + "x" + height);
212
+ canvas.setSize(width, height);
213
+ } else {
214
+ PApplet.debug("PGraphicsJava2D comp size already " + width + "x" + height);
215
+ }
216
+
217
+ parent.addListeners(canvas);
218
+ // canvas.createBufferStrategy(1);
219
+ // g2 = (Graphics2D) canvas.getGraphics();
220
+
221
+ } else {
222
+ parent.updateListeners(parent); // in case they're already there
223
+
224
+ // using a compatible image here doesn't seem to provide any performance boost
225
+
226
+ if (useOffscreen) {
227
+ // Needs to be RGB otherwise there's a major performance hit [0204]
228
+ // http://code.google.com/p/processing/issues/detail?id=729
229
+ image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
230
+ // GraphicsConfiguration gc = parent.getGraphicsConfiguration();
231
+ // image = gc.createCompatibleImage(width, height);
232
+ offscreen = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
233
+ // offscreen = gc.createCompatibleImage(width, height);
234
+ g2 = (Graphics2D) offscreen.getGraphics();
235
+
236
+ } else {
237
+ // System.out.println("hopefully faster " + width + " " + height);
238
+ // new Exception().printStackTrace(System.out);
239
+
240
+ GraphicsConfiguration gc = canvas.getGraphicsConfiguration();
241
+ // If not realized (off-screen, i.e the Color Selector Tool),
242
+ // gc will be null.
243
+ if (gc == null) {
244
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
245
+ gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
246
+ }
247
+
248
+ image = gc.createCompatibleImage(width, height);
249
+ g2 = (Graphics2D) image.getGraphics();
250
+ }
251
+ }
252
+ } else { // not the primary surface
253
+ // Since this buffer's offscreen anyway, no need for the extra offscreen
254
+ // buffer. However, unlike the primary surface, this feller needs to be
255
+ // ARGB so that blending ("alpha" compositing) will work properly.
256
+ image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
257
+ g2 = (Graphics2D) image.getGraphics();
258
+ }
259
+ */
260
+
261
+ /*
262
+ if (primarySurface) {
263
+ Canvas canvas = ((PSurfaceAWT) surface).canvas;
264
+
265
+ GraphicsConfiguration gc = canvas.getGraphicsConfiguration();
266
+ // If not realized (off-screen, i.e the Color Selector Tool),
267
+ // gc will be null.
268
+ if (gc == null) {
269
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
270
+ gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
271
+ }
272
+
273
+ image = gc.createCompatibleImage(width, height);
274
+ g2 = (Graphics2D) image.getGraphics();
275
+
276
+ } else {
277
+
278
+ }
279
+ g2 = (Graphics2D) image.getGraphics();
280
+ }
281
+ */
282
+
283
+
284
+ //public void dispose()
285
+
286
+
287
+ @Override
288
+ public PSurface createSurface() {
289
+ return surface = new PSurfaceAWT(this);
290
+ }
291
+
292
+
293
+ /**
294
+ * Still need a means to get the java.awt.Image object, since getNative()
295
+ * is going to return the {@link Graphics2D} object.
296
+ * @return
297
+ */
298
+ @Override
299
+ public Image getImage() {
300
+ return image;
301
+ }
302
+
303
+
304
+ /** Returns the java.awt.Graphics2D object used by this renderer.
305
+ * @return */
306
+ @Override
307
+ public Object getNative() {
308
+ return g2;
309
+ }
310
+
311
+
312
+ //////////////////////////////////////////////////////////////
313
+
314
+ // FRAME
315
+
316
+
317
+ // @Override
318
+ // public boolean canDraw() {
319
+ // return true;
320
+ // }
321
+
322
+
323
+ // @Override
324
+ // public void requestDraw() {
325
+ //// EventQueue.invokeLater(new Runnable() {
326
+ //// public void run() {
327
+ // parent.handleDraw();
328
+ //// }
329
+ //// });
330
+ // }
331
+
332
+
333
+ // Graphics2D g2old;
334
+
335
+ /**
336
+ *
337
+ * @return
338
+ */
339
+
340
+ public Graphics2D checkImage() {
341
+ if (image == null ||
342
+ ((BufferedImage) image).getWidth() != width*pixelDensity ||
343
+ ((BufferedImage) image).getHeight() != height*pixelDensity) {
344
+ // ((VolatileImage) image).getWidth() != width ||
345
+ // ((VolatileImage) image).getHeight() != height) {
346
+ // image = new BufferedImage(width * pixelFactor, height * pixelFactor
347
+ // format == RGB ? BufferedImage.TYPE_INT_ARGB);
348
+
349
+ GraphicsConfiguration gc = null;
350
+ if (surface != null) {
351
+ Component comp = null; //surface.getComponent();
352
+ if (comp == null) {
353
+ // System.out.println("component null, but parent.frame is " + parent.frame);
354
+ comp = parent.frame;
355
+ }
356
+ if (comp != null) {
357
+ gc = comp.getGraphicsConfiguration();
358
+ }
359
+ }
360
+ // If not realized (off-screen, i.e the Color Selector Tool), gc will be null.
361
+ if (gc == null) {
362
+ //System.err.println("GraphicsConfiguration null in initImage()");
363
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
364
+ gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
365
+ }
366
+
367
+ // Formerly this was broken into separate versions based on offscreen or
368
+ // not, but we may as well create a compatible image; it won't hurt, right?
369
+ int wide = width * pixelDensity;
370
+ int high = height * pixelDensity;
371
+ // System.out.println("re-creating image");
372
+ image = gc.createCompatibleImage(wide, high, Transparency.TRANSLUCENT);
373
+ // image = gc.createCompatibleVolatileImage(wide, high);
374
+ //image = surface.getComponent().createImage(width, height);
375
+ }
376
+ return (Graphics2D) image.getGraphics();
377
+ }
378
+
379
+
380
+ @Override
381
+ public void beginDraw() {
382
+ g2 = checkImage();
383
+
384
+ // Calling getGraphics() seems to nuke several settings.
385
+ // It seems to be re-creating a new Graphics2D object each time.
386
+ // https://github.com/processing/processing/issues/3331
387
+ if (strokeObject != null) {
388
+ g2.setStroke(strokeObject);
389
+ }
390
+ // https://github.com/processing/processing/issues/2617
391
+ if (fontObject != null) {
392
+ g2.setFont(fontObject);
393
+ }
394
+ // https://github.com/processing/processing/issues/4019
395
+ if (blendMode != 0) {
396
+ blendMode(blendMode);
397
+ }
398
+ handleSmooth();
399
+
400
+ /*
401
+ // NOTE: Calling image.getGraphics() will create a new Graphics context,
402
+ // even if it's for the same image that's already had a context created.
403
+ // Seems like a speed/memory issue, and also requires that all smoothing,
404
+ // stroke, font and other props be reset. Can't find a good answer about
405
+ // whether getGraphics() and dispose() on each frame is 1) better practice
406
+ // and 2) minimal overhead, however. Instinct suggests #1 may be true,
407
+ // but #2 seems a problem.
408
+ if (primarySurface && !useOffscreen) {
409
+ GraphicsConfiguration gc = canvas.getGraphicsConfiguration();
410
+ if (false) {
411
+ if (image == null || ((VolatileImage) image).validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE) {
412
+ image = gc.createCompatibleVolatileImage(width, height);
413
+ g2 = (Graphics2D) image.getGraphics();
414
+ reapplySettings = true;
415
+ }
416
+ } else {
417
+ if (image == null) {
418
+ image = gc.createCompatibleImage(width, height);
419
+ PApplet.debug("created new image, type is " + image);
420
+ g2 = (Graphics2D) image.getGraphics();
421
+ reapplySettings = true;
422
+ }
423
+ }
424
+ }
425
+
426
+ if (useCanvas && primarySurface) {
427
+ if (parent.frameCount == 0) {
428
+ canvas.createBufferStrategy(2);
429
+ strategy = canvas.getBufferStrategy();
430
+ PApplet.debug("PGraphicsJava2D.beginDraw() strategy is " + strategy);
431
+ BufferCapabilities caps = strategy.getCapabilities();
432
+ caps = strategy.getCapabilities();
433
+ PApplet.debug("PGraphicsJava2D.beginDraw() caps are " +
434
+ " flipping: " + caps.isPageFlipping() +
435
+ " front/back accel: " + caps.getFrontBufferCapabilities().isAccelerated() + " " +
436
+ "/" + caps.getBackBufferCapabilities().isAccelerated());
437
+ }
438
+ GraphicsConfiguration gc = canvas.getGraphicsConfiguration();
439
+
440
+ if (bimage == null ||
441
+ bimage.getWidth() != width ||
442
+ bimage.getHeight() != height) {
443
+ PApplet.debug("PGraphicsJava2D creating new image");
444
+ bimage = gc.createCompatibleImage(width, height);
445
+ // image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
446
+ g2 = bimage.createGraphics();
447
+ defaultComposite = g2.getComposite();
448
+ reapplySettings = true;
449
+ }
450
+ }
451
+ */
452
+
453
+ checkSettings();
454
+ resetMatrix(); // reset model matrix
455
+ vertexCount = 0;
456
+ }
457
+
458
+
459
+ /**
460
+ * Smoothing for Java2D is 2 for bilinear, and 3 for bicubic (the default).
461
+ * Internally, smooth(1) is the default, smooth(0) is noSmooth().
462
+ */
463
+ protected void handleSmooth() {
464
+ if (smooth == 0) {
465
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
466
+ RenderingHints.VALUE_ANTIALIAS_OFF);
467
+ g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
468
+ RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
469
+ g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
470
+ RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
471
+
472
+ } else {
473
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
474
+ RenderingHints.VALUE_ANTIALIAS_ON);
475
+
476
+ if (smooth == 1 || smooth == 3) { // default is bicubic
477
+ g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
478
+ RenderingHints.VALUE_INTERPOLATION_BICUBIC);
479
+ } else if (smooth == 2) {
480
+ g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
481
+ RenderingHints.VALUE_INTERPOLATION_BILINEAR);
482
+ }
483
+
484
+ // http://docs.oracle.com/javase/tutorial/2d/text/renderinghints.html
485
+ // Oracle Java text anti-aliasing on OS X looks like s*t compared to the
486
+ // text rendering with Apple's old Java 6. Below, several attempts to fix:
487
+ g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
488
+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
489
+ // Turns out this is the one that actually makes things work.
490
+ // Kerning is still screwed up, however.
491
+ g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
492
+ RenderingHints.VALUE_FRACTIONALMETRICS_ON);
493
+ // g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
494
+ // RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
495
+ // g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
496
+ // RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
497
+
498
+ // g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
499
+ // RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
500
+ }
501
+ }
502
+
503
+
504
+ @Override
505
+ public void endDraw() {
506
+ // hm, mark pixels as changed, because this will instantly do a full
507
+ // copy of all the pixels to the surface.. so that's kind of a mess.
508
+ //updatePixels();
509
+
510
+ if (primaryGraphics) {
511
+ /*
512
+ //if (canvas != null) {
513
+ if (useCanvas) {
514
+ //System.out.println(canvas);
515
+
516
+ // alternate version
517
+ //canvas.repaint(); // ?? what to do for swapping buffers
518
+
519
+ // System.out.println("endDraw() frameCount is " + parent.frameCount);
520
+ // if (parent.frameCount != 0) {
521
+ redraw();
522
+ // }
523
+
524
+ } else if (useOffscreen) {
525
+ // don't copy the pixels/data elements of the buffered image directly,
526
+ // since it'll disable the nice speedy pipeline stuff, sending all drawing
527
+ // into a world of suck that's rough 6 trillion times slower.
528
+ synchronized (image) {
529
+ //System.out.println("inside j2d sync");
530
+ image.getGraphics().drawImage(offscreen, 0, 0, null);
531
+ }
532
+
533
+ } else {
534
+ // changed to not dispose and get on each frame,
535
+ // otherwise a new Graphics context is used on each frame
536
+ // g2.dispose();
537
+ // System.out.println("not doing anything special in endDraw()");
538
+ }
539
+ */
540
+ } else {
541
+ // TODO this is probably overkill for most tasks...
542
+ loadPixels();
543
+ }
544
+
545
+ // // Marking as modified, and then calling updatePixels() in
546
+ // // the super class, which just sets the mx1, my1, mx2, my2
547
+ // // coordinates of the modified area. This avoids doing the
548
+ // // full copy of the pixels to the surface in this.updatePixels().
549
+ // setModified();
550
+ // super.updatePixels();
551
+
552
+ // Marks pixels as modified so that the pixels will be updated.
553
+ // Also sets mx1/y1/x2/y2 so that OpenGL will pick it up.
554
+ setModified();
555
+
556
+ g2.dispose();
557
+ }
558
+
559
+
560
+ /*
561
+ private void redraw() {
562
+ // only need this check if the validate() call will use redraw()
563
+ // if (strategy == null) return;
564
+ do {
565
+ PApplet.debug("PGraphicsJava2D.redraw() top of outer do { } block");
566
+ do {
567
+ PApplet.debug("PGraphicsJava2D.redraw() top of inner do { } block");
568
+ PApplet.debug("strategy is " + strategy);
569
+ Graphics bsg = strategy.getDrawGraphics();
570
+ // if (vimage != null) {
571
+ // bsg.drawImage(vimage, 0, 0, null);
572
+ // } else {
573
+ bsg.drawImage(bimage, 0, 0, null);
574
+ // if (parent.frameCount == 0) {
575
+ // try {
576
+ // ImageIO.write(image, "jpg", new java.io.File("/Users/fry/Desktop/buff.jpg"));
577
+ // } catch (IOException e) {
578
+ // e.printStackTrace();
579
+ // }
580
+ // }
581
+ // }
582
+ bsg.dispose();
583
+
584
+ // the strategy version
585
+ // g2.dispose();
586
+ // if (!strategy.contentsLost()) {
587
+ // if (parent.frameCount != 0) {
588
+ // Toolkit.getDefaultToolkit().sync();
589
+ // }
590
+ // } else {
591
+ // System.out.println("XXXXX strategy contents lost");
592
+ // }
593
+ // }
594
+ // }
595
+ } while (strategy.contentsRestored());
596
+
597
+ PApplet.debug("PGraphicsJava2D.redraw() showing strategy");
598
+ strategy.show();
599
+
600
+ } while (strategy.contentsLost());
601
+ PApplet.debug("PGraphicsJava2D.redraw() out of do { } block");
602
+ }
603
+ */
604
+
605
+
606
+
607
+ //////////////////////////////////////////////////////////////
608
+
609
+ // SETTINGS
610
+
611
+
612
+ //protected void checkSettings()
613
+
614
+
615
+ @Override
616
+ protected void defaultSettings() {
617
+ // if (!useCanvas) {
618
+ // // Papered over another threading issue...
619
+ // // See if this comes back now that the other issue is fixed.
620
+ //// while (g2 == null) {
621
+ //// try {
622
+ //// System.out.println("sleeping until g2 is available");
623
+ //// Thread.sleep(5);
624
+ //// } catch (InterruptedException e) { }
625
+ //// }
626
+ defaultComposite = g2.getComposite();
627
+ // }
628
+ super.defaultSettings();
629
+ }
630
+
631
+
632
+ //protected void reapplySettings()
633
+
634
+
635
+
636
+ //////////////////////////////////////////////////////////////
637
+
638
+ // HINT
639
+
640
+
641
+ @Override
642
+ public void hint(int which) {
643
+ // take care of setting the hint
644
+ super.hint(which);
645
+
646
+ // Avoid badness when drawing shorter strokes.
647
+ // http://code.google.com/p/processing/issues/detail?id=1068
648
+ // Unfortunately cannot always be enabled, because it makes the
649
+ // stroke in many standard Processing examples really gross.
650
+ if (which == ENABLE_STROKE_PURE) {
651
+ g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
652
+ RenderingHints.VALUE_STROKE_PURE);
653
+ } else if (which == DISABLE_STROKE_PURE) {
654
+ g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
655
+ RenderingHints.VALUE_STROKE_DEFAULT);
656
+ }
657
+ }
658
+
659
+
660
+
661
+ //////////////////////////////////////////////////////////////
662
+
663
+ // SHAPE CREATION
664
+
665
+
666
+ @Override
667
+ protected PShape createShapeFamily(int type) {
668
+ return new PShape(this, type);
669
+ }
670
+
671
+
672
+ @Override
673
+ protected PShape createShapePrimitive(int kind, float... p) {
674
+ return new PShape(this, kind, p);
675
+ }
676
+
677
+
678
+ // @Override
679
+ // public PShape createShape(PShape source) {
680
+ // return PShapeOpenGL.createShape2D(this, source);
681
+ // }
682
+
683
+
684
+ /*
685
+ protected PShape createShapeImpl(PGraphicsJava2D pg, int type) {
686
+ PShape shape = null;
687
+ if (type == PConstants.GROUP) {
688
+ shape = new PShape(pg, PConstants.GROUP);
689
+ } else if (type == PShape.PATH) {
690
+ shape = new PShape(pg, PShape.PATH);
691
+ } else if (type == PShape.GEOMETRY) {
692
+ shape = new PShape(pg, PShape.GEOMETRY);
693
+ }
694
+ // defaults to false, don't assign it and make complexity for overrides
695
+ //shape.set3D(false);
696
+ return shape;
697
+ }
698
+ */
699
+
700
+
701
+ /*
702
+ static protected PShape createShapeImpl(PGraphicsJava2D pg,
703
+ int kind, float... p) {
704
+ PShape shape = null;
705
+ int len = p.length;
706
+
707
+ if (kind == POINT) {
708
+ if (len != 2) {
709
+ showWarning("Wrong number of parameters");
710
+ return null;
711
+ }
712
+ shape = new PShape(pg, PShape.PRIMITIVE);
713
+ shape.setKind(POINT);
714
+ } else if (kind == LINE) {
715
+ if (len != 4) {
716
+ showWarning("Wrong number of parameters");
717
+ return null;
718
+ }
719
+ shape = new PShape(pg, PShape.PRIMITIVE);
720
+ shape.setKind(LINE);
721
+ } else if (kind == TRIANGLE) {
722
+ if (len != 6) {
723
+ showWarning("Wrong number of parameters");
724
+ return null;
725
+ }
726
+ shape = new PShape(pg, PShape.PRIMITIVE);
727
+ shape.setKind(TRIANGLE);
728
+ } else if (kind == QUAD) {
729
+ if (len != 8) {
730
+ showWarning("Wrong number of parameters");
731
+ return null;
732
+ }
733
+ shape = new PShape(pg, PShape.PRIMITIVE);
734
+ shape.setKind(QUAD);
735
+ } else if (kind == RECT) {
736
+ if (len != 4 && len != 5 && len != 8 && len != 9) {
737
+ showWarning("Wrong number of parameters");
738
+ return null;
739
+ }
740
+ shape = new PShape(pg, PShape.PRIMITIVE);
741
+ shape.setKind(RECT);
742
+ } else if (kind == ELLIPSE) {
743
+ if (len != 4 && len != 5) {
744
+ showWarning("Wrong number of parameters");
745
+ return null;
746
+ }
747
+ shape = new PShape(pg, PShape.PRIMITIVE);
748
+ shape.setKind(ELLIPSE);
749
+ } else if (kind == ARC) {
750
+ if (len != 6 && len != 7) {
751
+ showWarning("Wrong number of parameters");
752
+ return null;
753
+ }
754
+ shape = new PShape(pg, PShape.PRIMITIVE);
755
+ shape.setKind(ARC);
756
+ } else if (kind == BOX) {
757
+ showWarning("Primitive not supported in 2D");
758
+ } else if (kind == SPHERE) {
759
+ showWarning("Primitive not supported in 2D");
760
+ } else {
761
+ showWarning("Unrecognized primitive type");
762
+ }
763
+
764
+ if (shape != null) {
765
+ shape.setParams(p);
766
+ }
767
+
768
+ // defaults to false, don't assign it and make complexity for overrides
769
+ //shape.set3D(false);
770
+
771
+ return shape;
772
+ }
773
+ */
774
+
775
+
776
+
777
+ //////////////////////////////////////////////////////////////
778
+
779
+ // SHAPES
780
+
781
+
782
+ @Override
783
+ public void beginShape(int kind) {
784
+ //super.beginShape(kind);
785
+ shape = kind;
786
+ vertexCount = 0;
787
+ curveVertexCount = 0;
788
+
789
+ // set gpath to null, because when mixing curves and straight
790
+ // lines, vertexCount will be set back to zero, so vertexCount == 1
791
+ // is no longer a good indicator of whether the shape is new.
792
+ // this way, just check to see if gpath is null, and if it isn't
793
+ // then just use it to continue the shape.
794
+ gpath = null;
795
+ auxPath = null;
796
+ }
797
+
798
+
799
+ //public boolean edge(boolean e)
800
+
801
+
802
+ //public void normal(float nx, float ny, float nz) {
803
+
804
+
805
+ //public void textureMode(int mode)
806
+
807
+
808
+ @Override
809
+ public void texture(PImage image) {
810
+ showMethodWarning("texture");
811
+ }
812
+
813
+
814
+ @Override
815
+ public void vertex(float x, float y) {
816
+ curveVertexCount = 0;
817
+ //float vertex[];
818
+
819
+ if (vertexCount == vertices.length) {
820
+ float temp[][] = new float[vertexCount<<1][VERTEX_FIELD_COUNT];
821
+ System.arraycopy(vertices, 0, temp, 0, vertexCount);
822
+ vertices = temp;
823
+ //message(CHATTER, "allocating more vertices " + vertices.length);
824
+ }
825
+ // not everyone needs this, but just easier to store rather
826
+ // than adding another moving part to the code...
827
+ vertices[vertexCount][X] = x;
828
+ vertices[vertexCount][Y] = y;
829
+ vertexCount++;
830
+
831
+ switch (shape) {
832
+
833
+ case POINTS:
834
+ point(x, y);
835
+ break;
836
+
837
+ case LINES:
838
+ if ((vertexCount % 2) == 0) {
839
+ line(vertices[vertexCount-2][X],
840
+ vertices[vertexCount-2][Y], x, y);
841
+ }
842
+ break;
843
+
844
+ case TRIANGLES:
845
+ if ((vertexCount % 3) == 0) {
846
+ triangle(vertices[vertexCount - 3][X],
847
+ vertices[vertexCount - 3][Y],
848
+ vertices[vertexCount - 2][X],
849
+ vertices[vertexCount - 2][Y],
850
+ x, y);
851
+ }
852
+ break;
853
+
854
+ case TRIANGLE_STRIP:
855
+ if (vertexCount >= 3) {
856
+ triangle(vertices[vertexCount - 2][X],
857
+ vertices[vertexCount - 2][Y],
858
+ vertices[vertexCount - 1][X],
859
+ vertices[vertexCount - 1][Y],
860
+ vertices[vertexCount - 3][X],
861
+ vertices[vertexCount - 3][Y]);
862
+ }
863
+ break;
864
+
865
+ case TRIANGLE_FAN:
866
+ if (vertexCount >= 3) {
867
+ // This is an unfortunate implementation because the stroke for an
868
+ // adjacent triangle will be repeated. However, if the stroke is not
869
+ // redrawn, it will replace the adjacent line (when it lines up
870
+ // perfectly) or show a faint line (when off by a small amount).
871
+ // The alternative would be to wait, then draw the shape as a
872
+ // polygon fill, followed by a series of vertices. But that's a
873
+ // poor method when used with PDF, DXF, or other recording objects,
874
+ // since discrete triangles would likely be preferred.
875
+ triangle(vertices[0][X],
876
+ vertices[0][Y],
877
+ vertices[vertexCount - 2][X],
878
+ vertices[vertexCount - 2][Y],
879
+ x, y);
880
+ }
881
+ break;
882
+
883
+ case QUAD:
884
+ case QUADS:
885
+ if ((vertexCount % 4) == 0) {
886
+ quad(vertices[vertexCount - 4][X],
887
+ vertices[vertexCount - 4][Y],
888
+ vertices[vertexCount - 3][X],
889
+ vertices[vertexCount - 3][Y],
890
+ vertices[vertexCount - 2][X],
891
+ vertices[vertexCount - 2][Y],
892
+ x, y);
893
+ }
894
+ break;
895
+
896
+ case QUAD_STRIP:
897
+ // 0---2---4
898
+ // | | |
899
+ // 1---3---5
900
+ if ((vertexCount >= 4) && ((vertexCount % 2) == 0)) {
901
+ quad(vertices[vertexCount - 4][X],
902
+ vertices[vertexCount - 4][Y],
903
+ vertices[vertexCount - 2][X],
904
+ vertices[vertexCount - 2][Y],
905
+ x, y,
906
+ vertices[vertexCount - 3][X],
907
+ vertices[vertexCount - 3][Y]);
908
+ }
909
+ break;
910
+
911
+ case POLYGON:
912
+ if (gpath == null) {
913
+ gpath = new GeneralPath();
914
+ gpath.moveTo(x, y);
915
+ } else if (breakShape) {
916
+ gpath.moveTo(x, y);
917
+ breakShape = false;
918
+ } else {
919
+ gpath.lineTo(x, y);
920
+ }
921
+ break;
922
+ }
923
+ }
924
+
925
+
926
+ @Override
927
+ public void vertex(float x, float y, float z) {
928
+ showDepthWarningXYZ("vertex");
929
+ }
930
+
931
+ @Override
932
+ public void vertex(float[] v) {
933
+ vertex(v[X], v[Y]);
934
+ }
935
+
936
+
937
+ @Override
938
+ public void vertex(float x, float y, float u, float v) {
939
+ showVariationWarning("vertex(x, y, u, v)");
940
+ }
941
+
942
+
943
+ @Override
944
+ public void vertex(float x, float y, float z, float u, float v) {
945
+ showDepthWarningXYZ("vertex");
946
+ }
947
+
948
+
949
+ @Override
950
+ public void beginContour() {
951
+ if (openContour) {
952
+ PGraphics.showWarning("Already called beginContour()");
953
+ return;
954
+ }
955
+
956
+ // draw contours to auxiliary path so main path can be closed later
957
+ GeneralPath contourPath = auxPath;
958
+ auxPath = gpath;
959
+ gpath = contourPath;
960
+
961
+ if (contourPath != null) { // first contour does not break
962
+ breakShape = true;
963
+ }
964
+
965
+ openContour = true;
966
+ }
967
+
968
+
969
+ @Override
970
+ public void endContour() {
971
+ if (!openContour) {
972
+ PGraphics.showWarning("Need to call beginContour() first");
973
+ return;
974
+ }
975
+
976
+ // close this contour
977
+ if (gpath != null) gpath.closePath();
978
+
979
+ // switch back to main path
980
+ GeneralPath contourPath = gpath;
981
+ gpath = auxPath;
982
+ auxPath = contourPath;
983
+
984
+ openContour = false;
985
+ }
986
+
987
+
988
+ @Override
989
+ public void endShape(int mode) {
990
+ if (openContour) { // correct automagically, notify user
991
+ endContour();
992
+ PGraphics.showWarning("Missing endContour() before endShape()");
993
+ }
994
+ if (gpath != null) { // make sure something has been drawn
995
+ if (shape == POLYGON) {
996
+ if (mode == CLOSE) {
997
+ gpath.closePath();
998
+ }
999
+ if (auxPath != null) {
1000
+ gpath.append(auxPath, false);
1001
+ }
1002
+ drawShape(gpath);
1003
+ }
1004
+ }
1005
+ shape = 0;
1006
+ }
1007
+
1008
+ //////////////////////////////////////////////////////////////
1009
+
1010
+ // CLIPPING
1011
+
1012
+
1013
+ @Override
1014
+ protected void clipImpl(float x1, float y1, float x2, float y2) {
1015
+ g2.setClip(new Rectangle2D.Float(x1, y1, x2 - x1, y2 - y1));
1016
+ }
1017
+
1018
+
1019
+ @Override
1020
+ public void noClip() {
1021
+ g2.setClip(null);
1022
+ }
1023
+
1024
+
1025
+
1026
+ //////////////////////////////////////////////////////////////
1027
+
1028
+ // BLEND
1029
+
1030
+ /**
1031
+ * ( begin auto-generated from blendMode.xml )
1032
+ *
1033
+ * This is a new reference entry for Processing 2.0. It will be updated shortly.
1034
+ *
1035
+ * ( end auto-generated )
1036
+ *
1037
+ * @webref Rendering
1038
+ * @param mode the blending mode to use
1039
+ */
1040
+ @Override
1041
+ protected void blendModeImpl() {
1042
+ if (blendMode == BLEND) {
1043
+ g2.setComposite(defaultComposite);
1044
+
1045
+ } else {
1046
+ g2.setComposite(new Composite() {
1047
+
1048
+ @Override
1049
+ public CompositeContext createContext(ColorModel srcColorModel,
1050
+ ColorModel dstColorModel,
1051
+ RenderingHints hints) {
1052
+ return new BlendingContext(blendMode);
1053
+ }
1054
+ });
1055
+ }
1056
+ }
1057
+
1058
+
1059
+ // Blending implementation cribbed from portions of Romain Guy's
1060
+ // demo and terrific writeup on blending modes in Java 2D.
1061
+ // http://www.curious-creature.org/2006/09/20/new-blendings-modes-for-java2d/
1062
+ private static final class BlendingContext implements CompositeContext {
1063
+ private int mode;
1064
+
1065
+ private BlendingContext(int mode) {
1066
+ this.mode = mode;
1067
+ }
1068
+
1069
+ public void dispose() { }
1070
+
1071
+ public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
1072
+ // not sure if this is really necessary, since we control our buffers
1073
+ if (src.getSampleModel().getDataType() != DataBuffer.TYPE_INT ||
1074
+ dstIn.getSampleModel().getDataType() != DataBuffer.TYPE_INT ||
1075
+ dstOut.getSampleModel().getDataType() != DataBuffer.TYPE_INT) {
1076
+ throw new IllegalStateException("Source and destination must store pixels as INT.");
1077
+ }
1078
+
1079
+ int width = Math.min(src.getWidth(), dstIn.getWidth());
1080
+ int height = Math.min(src.getHeight(), dstIn.getHeight());
1081
+
1082
+ int[] srcPixels = new int[width];
1083
+ int[] dstPixels = new int[width];
1084
+
1085
+ for (int y = 0; y < height; y++) {
1086
+ src.getDataElements(0, y, width, 1, srcPixels);
1087
+ dstIn.getDataElements(0, y, width, 1, dstPixels);
1088
+ for (int x = 0; x < width; x++) {
1089
+ dstPixels[x] = blendColor(dstPixels[x], srcPixels[x], mode);
1090
+ }
1091
+ dstOut.setDataElements(0, y, width, 1, dstPixels);
1092
+ }
1093
+ }
1094
+ }
1095
+
1096
+
1097
+
1098
+ //////////////////////////////////////////////////////////////
1099
+
1100
+ // BEZIER VERTICES
1101
+
1102
+
1103
+ @Override
1104
+ public void bezierVertex(float x1, float y1,
1105
+ float x2, float y2,
1106
+ float x3, float y3) {
1107
+ bezierVertexCheck();
1108
+ gpath.curveTo(x1, y1, x2, y2, x3, y3);
1109
+ }
1110
+
1111
+
1112
+ @Override
1113
+ public void bezierVertex(float x2, float y2, float z2,
1114
+ float x3, float y3, float z3,
1115
+ float x4, float y4, float z4) {
1116
+ showDepthWarningXYZ("bezierVertex");
1117
+ }
1118
+
1119
+
1120
+
1121
+ //////////////////////////////////////////////////////////////
1122
+
1123
+ // QUADRATIC BEZIER VERTICES
1124
+
1125
+
1126
+ @Override
1127
+ public void quadraticVertex(float ctrlX, float ctrlY,
1128
+ float endX, float endY) {
1129
+ bezierVertexCheck();
1130
+ Point2D cur = gpath.getCurrentPoint();
1131
+
1132
+ float x1 = (float) cur.getX();
1133
+ float y1 = (float) cur.getY();
1134
+
1135
+ bezierVertex(x1 + ((ctrlX-x1)*2/3.0f), y1 + ((ctrlY-y1)*2/3.0f),
1136
+ endX + ((ctrlX-endX)*2/3.0f), endY + ((ctrlY-endY)*2/3.0f),
1137
+ endX, endY);
1138
+ }
1139
+
1140
+
1141
+ @Override
1142
+ public void quadraticVertex(float x2, float y2, float z2,
1143
+ float x4, float y4, float z4) {
1144
+ showDepthWarningXYZ("quadVertex");
1145
+ }
1146
+
1147
+
1148
+
1149
+ //////////////////////////////////////////////////////////////
1150
+
1151
+ // CURVE VERTICES
1152
+
1153
+
1154
+ @Override
1155
+ protected void curveVertexCheck() {
1156
+ super.curveVertexCheck();
1157
+
1158
+ if (curveCoordX == null) {
1159
+ curveCoordX = new float[4];
1160
+ curveCoordY = new float[4];
1161
+ curveDrawX = new float[4];
1162
+ curveDrawY = new float[4];
1163
+ }
1164
+ }
1165
+
1166
+
1167
+ @Override
1168
+ protected void curveVertexSegment(float x1, float y1,
1169
+ float x2, float y2,
1170
+ float x3, float y3,
1171
+ float x4, float y4) {
1172
+ curveCoordX[0] = x1;
1173
+ curveCoordY[0] = y1;
1174
+
1175
+ curveCoordX[1] = x2;
1176
+ curveCoordY[1] = y2;
1177
+
1178
+ curveCoordX[2] = x3;
1179
+ curveCoordY[2] = y3;
1180
+
1181
+ curveCoordX[3] = x4;
1182
+ curveCoordY[3] = y4;
1183
+
1184
+ curveToBezierMatrix.mult(curveCoordX, curveDrawX);
1185
+ curveToBezierMatrix.mult(curveCoordY, curveDrawY);
1186
+
1187
+ // since the paths are continuous,
1188
+ // only the first point needs the actual moveto
1189
+ if (gpath == null) {
1190
+ gpath = new GeneralPath();
1191
+ gpath.moveTo(curveDrawX[0], curveDrawY[0]);
1192
+ }
1193
+
1194
+ gpath.curveTo(curveDrawX[1], curveDrawY[1],
1195
+ curveDrawX[2], curveDrawY[2],
1196
+ curveDrawX[3], curveDrawY[3]);
1197
+ }
1198
+
1199
+
1200
+ @Override
1201
+ public void curveVertex(float x, float y, float z) {
1202
+ showDepthWarningXYZ("curveVertex");
1203
+ }
1204
+
1205
+
1206
+
1207
+ //////////////////////////////////////////////////////////////
1208
+
1209
+ // RENDERER
1210
+
1211
+
1212
+ //public void flush()
1213
+
1214
+
1215
+
1216
+ //////////////////////////////////////////////////////////////
1217
+
1218
+ // POINT, LINE, TRIANGLE, QUAD
1219
+
1220
+
1221
+ @Override
1222
+ public void point(float x, float y) {
1223
+ if (stroke) {
1224
+ // if (strokeWeight > 1) {
1225
+ line(x, y, x + EPSILON, y + EPSILON);
1226
+ // } else {
1227
+ // set((int) screenX(x, y), (int) screenY(x, y), strokeColor);
1228
+ // }
1229
+ }
1230
+ }
1231
+
1232
+
1233
+ @Override
1234
+ public void line(float x1, float y1, float x2, float y2) {
1235
+ line.setLine(x1, y1, x2, y2);
1236
+ strokeShape(line);
1237
+ }
1238
+
1239
+
1240
+ @Override
1241
+ public void triangle(float x1, float y1, float x2, float y2,
1242
+ float x3, float y3) {
1243
+ gpath = new GeneralPath();
1244
+ gpath.moveTo(x1, y1);
1245
+ gpath.lineTo(x2, y2);
1246
+ gpath.lineTo(x3, y3);
1247
+ gpath.closePath();
1248
+ drawShape(gpath);
1249
+ }
1250
+
1251
+
1252
+ @Override
1253
+ public void quad(float x1, float y1, float x2, float y2,
1254
+ float x3, float y3, float x4, float y4) {
1255
+ GeneralPath gp = new GeneralPath();
1256
+ gp.moveTo(x1, y1);
1257
+ gp.lineTo(x2, y2);
1258
+ gp.lineTo(x3, y3);
1259
+ gp.lineTo(x4, y4);
1260
+ gp.closePath();
1261
+ drawShape(gp);
1262
+ }
1263
+
1264
+
1265
+
1266
+ //////////////////////////////////////////////////////////////
1267
+
1268
+ // RECT
1269
+
1270
+
1271
+ //public void rectMode(int mode)
1272
+
1273
+
1274
+ //public void rect(float a, float b, float c, float d)
1275
+
1276
+
1277
+ @Override
1278
+ protected void rectImpl(float x1, float y1, float x2, float y2) {
1279
+ rect.setFrame(x1, y1, x2-x1, y2-y1);
1280
+ drawShape(rect);
1281
+ }
1282
+
1283
+
1284
+
1285
+ //////////////////////////////////////////////////////////////
1286
+
1287
+ // ELLIPSE
1288
+
1289
+
1290
+ //public void ellipseMode(int mode)
1291
+
1292
+
1293
+ //public void ellipse(float a, float b, float c, float d)
1294
+
1295
+
1296
+ @Override
1297
+ protected void ellipseImpl(float x, float y, float w, float h) {
1298
+ ellipse.setFrame(x, y, w, h);
1299
+ drawShape(ellipse);
1300
+ }
1301
+
1302
+
1303
+
1304
+ //////////////////////////////////////////////////////////////
1305
+
1306
+ // ARC
1307
+
1308
+
1309
+ //public void arc(float a, float b, float c, float d,
1310
+ // float start, float stop)
1311
+
1312
+
1313
+ @Override
1314
+ protected void arcImpl(float x, float y, float w, float h,
1315
+ float start, float stop, int mode) {
1316
+ // 0 to 90 in java would be 0 to -90 for p5 renderer
1317
+ // but that won't work, so -90 to 0?
1318
+
1319
+ start = -start * RAD_TO_DEG;
1320
+ stop = -stop * RAD_TO_DEG;
1321
+
1322
+ // ok to do this because already checked for NaN
1323
+ // while (start < 0) {
1324
+ // start += 360;
1325
+ // stop += 360;
1326
+ // }
1327
+ // if (start > stop) {
1328
+ // float temp = start;
1329
+ // start = stop;
1330
+ // stop = temp;
1331
+ // }
1332
+ float sweep = stop - start;
1333
+
1334
+ // The defaults, before 2.0b7, were to stroke as Arc2D.OPEN, and then fill
1335
+ // using Arc2D.PIE. That's a little wonky, but it's here for compatability.
1336
+ int fillMode = Arc2D.PIE;
1337
+ int strokeMode = Arc2D.OPEN;
1338
+
1339
+ if (mode == OPEN) {
1340
+ fillMode = Arc2D.OPEN;
1341
+ //strokeMode = Arc2D.OPEN;
1342
+
1343
+ } else if (mode == PIE) {
1344
+ //fillMode = Arc2D.PIE;
1345
+ strokeMode = Arc2D.PIE;
1346
+
1347
+ } else if (mode == CHORD) {
1348
+ fillMode = Arc2D.CHORD;
1349
+ strokeMode = Arc2D.CHORD;
1350
+ }
1351
+
1352
+ if (fill) {
1353
+ //System.out.println("filla");
1354
+ arc.setArc(x, y, w, h, start, sweep, fillMode);
1355
+ fillShape(arc);
1356
+ }
1357
+ if (stroke) {
1358
+ //System.out.println("strokey");
1359
+ arc.setArc(x, y, w, h, start, sweep, strokeMode);
1360
+ strokeShape(arc);
1361
+ }
1362
+ }
1363
+
1364
+
1365
+
1366
+ //////////////////////////////////////////////////////////////
1367
+
1368
+ // JAVA2D SHAPE/PATH HANDLING
1369
+
1370
+ /**
1371
+ *
1372
+ * @param s
1373
+ */
1374
+
1375
+
1376
+ protected void fillShape(Shape s) {
1377
+ if (fillGradient) {
1378
+ g2.setPaint(fillGradientObject);
1379
+ g2.fill(s);
1380
+ } else if (fill) {
1381
+ g2.setColor(fillColorObject);
1382
+ g2.fill(s);
1383
+ }
1384
+ }
1385
+
1386
+ /**
1387
+ *
1388
+ * @param s
1389
+ */
1390
+ protected void strokeShape(Shape s) {
1391
+ if (strokeGradient) {
1392
+ g2.setPaint(strokeGradientObject);
1393
+ g2.draw(s);
1394
+ } else if (stroke) {
1395
+ g2.setColor(strokeColorObject);
1396
+ g2.draw(s);
1397
+ }
1398
+ }
1399
+
1400
+ /**
1401
+ *
1402
+ * @param s
1403
+ */
1404
+ protected void drawShape(Shape s) {
1405
+ if (fillGradient) {
1406
+ g2.setPaint(fillGradientObject);
1407
+ g2.fill(s);
1408
+ } else if (fill) {
1409
+ g2.setColor(fillColorObject);
1410
+ g2.fill(s);
1411
+ }
1412
+ if (strokeGradient) {
1413
+ g2.setPaint(strokeGradientObject);
1414
+ g2.draw(s);
1415
+ } else if (stroke) {
1416
+ g2.setColor(strokeColorObject);
1417
+ g2.draw(s);
1418
+ }
1419
+ }
1420
+
1421
+
1422
+
1423
+ //////////////////////////////////////////////////////////////
1424
+
1425
+ // BOX
1426
+
1427
+
1428
+ //public void box(float size)
1429
+
1430
+
1431
+ @Override
1432
+ public void box(float w, float h, float d) {
1433
+ showMethodWarning("box");
1434
+ }
1435
+
1436
+
1437
+
1438
+ //////////////////////////////////////////////////////////////
1439
+
1440
+ // SPHERE
1441
+
1442
+
1443
+ //public void sphereDetail(int res)
1444
+
1445
+
1446
+ //public void sphereDetail(int ures, int vres)
1447
+
1448
+
1449
+ @Override
1450
+ public void sphere(float r) {
1451
+ showMethodWarning("sphere");
1452
+ }
1453
+
1454
+
1455
+
1456
+ //////////////////////////////////////////////////////////////
1457
+
1458
+ // BEZIER
1459
+
1460
+
1461
+ //public float bezierPoint(float a, float b, float c, float d, float t)
1462
+
1463
+
1464
+ //public float bezierTangent(float a, float b, float c, float d, float t)
1465
+
1466
+
1467
+ //protected void bezierInitCheck()
1468
+
1469
+
1470
+ //protected void bezierInit()
1471
+
1472
+
1473
+ /** Ignored (not needed) in Java 2D. */
1474
+ @Override
1475
+ public void bezierDetail(int detail) {
1476
+ }
1477
+
1478
+
1479
+ //public void bezier(float x1, float y1,
1480
+ // float x2, float y2,
1481
+ // float x3, float y3,
1482
+ // float x4, float y4)
1483
+
1484
+
1485
+ //public void bezier(float x1, float y1, float z1,
1486
+ // float x2, float y2, float z2,
1487
+ // float x3, float y3, float z3,
1488
+ // float x4, float y4, float z4)
1489
+
1490
+
1491
+
1492
+ //////////////////////////////////////////////////////////////
1493
+
1494
+ // CURVE
1495
+
1496
+
1497
+ //public float curvePoint(float a, float b, float c, float d, float t)
1498
+
1499
+
1500
+ //public float curveTangent(float a, float b, float c, float d, float t)
1501
+
1502
+
1503
+ /** Ignored (not needed) in Java 2D. */
1504
+ @Override
1505
+ public void curveDetail(int detail) {
1506
+ }
1507
+
1508
+ //public void curveTightness(float tightness)
1509
+
1510
+
1511
+ //protected void curveInitCheck()
1512
+
1513
+
1514
+ //protected void curveInit()
1515
+
1516
+
1517
+ //public void curve(float x1, float y1,
1518
+ // float x2, float y2,
1519
+ // float x3, float y3,
1520
+ // float x4, float y4)
1521
+
1522
+
1523
+ //public void curve(float x1, float y1, float z1,
1524
+ // float x2, float y2, float z2,
1525
+ // float x3, float y3, float z3,
1526
+ // float x4, float y4, float z4)
1527
+
1528
+
1529
+
1530
+ // //////////////////////////////////////////////////////////////
1531
+ //
1532
+ // // SMOOTH
1533
+ //
1534
+ //
1535
+ // @Override
1536
+ // public void smooth() {
1537
+ // smooth = true;
1538
+ //
1539
+ // if (quality == 0) {
1540
+ // quality = 4; // change back to bicubic
1541
+ // }
1542
+ //
1543
+ // g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
1544
+ // RenderingHints.VALUE_ANTIALIAS_ON);
1545
+ //
1546
+ // g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
1547
+ // quality == 4 ?
1548
+ // RenderingHints.VALUE_INTERPOLATION_BICUBIC :
1549
+ // RenderingHints.VALUE_INTERPOLATION_BILINEAR);
1550
+ //
1551
+ // // http://docs.oracle.com/javase/tutorial/2d/text/renderinghints.html
1552
+ // // Oracle Java text anti-aliasing on OS X looks like s*t compared to the
1553
+ // // text rendering with Apple's old Java 6. Below, several attempts to fix:
1554
+ // g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
1555
+ // RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
1556
+ // // Turns out this is the one that actually makes things work.
1557
+ // // Kerning is still screwed up, however.
1558
+ // g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
1559
+ // RenderingHints.VALUE_FRACTIONALMETRICS_ON);
1560
+ //// g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
1561
+ //// RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
1562
+ //// g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
1563
+ //// RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
1564
+ //
1565
+ //// g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
1566
+ //// RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
1567
+ //
1568
+ // }
1569
+ //
1570
+ //
1571
+ // @Override
1572
+ // public void smooth(int quality) {
1573
+ // this.quality = quality;
1574
+ // if (quality == 0) {
1575
+ // noSmooth();
1576
+ // } else {
1577
+ // smooth();
1578
+ // }
1579
+ // }
1580
+ //
1581
+ //
1582
+ // @Override
1583
+ // public void noSmooth() {
1584
+ // smooth = false;
1585
+ // quality = 0; // https://github.com/processing/processing/issues/3113
1586
+ // g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
1587
+ // RenderingHints.VALUE_ANTIALIAS_OFF);
1588
+ // g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
1589
+ // RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
1590
+ // g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
1591
+ // RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
1592
+ // }
1593
+
1594
+
1595
+
1596
+ //////////////////////////////////////////////////////////////
1597
+
1598
+ // IMAGE
1599
+
1600
+
1601
+ //public void imageMode(int mode)
1602
+
1603
+
1604
+ //public void image(PImage image, float x, float y)
1605
+
1606
+
1607
+ //public void image(PImage image, float x, float y, float c, float d)
1608
+
1609
+
1610
+ //public void image(PImage image,
1611
+ // float a, float b, float c, float d,
1612
+ // int u1, int v1, int u2, int v2)
1613
+
1614
+
1615
+ /**
1616
+ * Handle renderer-specific image drawing.
1617
+ * @param who
1618
+ */
1619
+ @Override
1620
+ protected void imageImpl(PImage who,
1621
+ float x1, float y1, float x2, float y2,
1622
+ int u1, int v1, int u2, int v2) {
1623
+ // Image not ready yet, or an error
1624
+ if (who.width <= 0 || who.height <= 0) return;
1625
+
1626
+ ImageCache cash = (ImageCache) getCache(who);
1627
+
1628
+ // Nuke the cache if the image was resized
1629
+ if (cash != null) {
1630
+ if (who.pixelWidth != cash.image.getWidth() ||
1631
+ who.pixelHeight != cash.image.getHeight()) {
1632
+ cash = null;
1633
+ }
1634
+ }
1635
+
1636
+ if (cash == null) {
1637
+ //System.out.println("making new image cache");
1638
+ cash = new ImageCache(); //who);
1639
+ setCache(who, cash);
1640
+ who.updatePixels(); // mark the whole thing for update
1641
+ who.setModified();
1642
+ }
1643
+
1644
+ // If image previously was tinted, or the color changed
1645
+ // or the image was tinted, and tint is now disabled
1646
+ if ((tint && !cash.tinted) ||
1647
+ (tint && (cash.tintedColor != tintColor)) ||
1648
+ (!tint && cash.tinted)) {
1649
+ // For tint change, mark all pixels as needing update.
1650
+ who.updatePixels();
1651
+ }
1652
+
1653
+ if (who.isModified()) {
1654
+ if (who.pixels == null) {
1655
+ // This might be a PGraphics that hasn't been drawn to yet.
1656
+ // Can't just bail because the cache has been created above.
1657
+ // https://github.com/processing/processing/issues/2208
1658
+ who.pixels = new int[who.pixelWidth * who.pixelHeight];
1659
+ }
1660
+ cash.update(who, tint, tintColor);
1661
+ who.setModified(false);
1662
+ }
1663
+
1664
+ u1 *= who.pixelDensity;
1665
+ v1 *= who.pixelDensity;
1666
+ u2 *= who.pixelDensity;
1667
+ v2 *= who.pixelDensity;
1668
+
1669
+ g2.drawImage(((ImageCache) getCache(who)).image,
1670
+ (int) x1, (int) y1, (int) x2, (int) y2,
1671
+ u1, v1, u2, v2, null);
1672
+
1673
+ // Every few years I think "nah, Java2D couldn't possibly be that f*king
1674
+ // slow, why are we doing this by hand?" then comes the affirmation:
1675
+ // Composite oldComp = null;
1676
+ // if (false && tint) {
1677
+ // oldComp = g2.getComposite();
1678
+ // int alpha = (tintColor >> 24) & 0xff;
1679
+ // System.out.println("using alpha composite");
1680
+ // Composite alphaComp =
1681
+ // AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha / 255f);
1682
+ // g2.setComposite(alphaComp);
1683
+ // }
1684
+ //
1685
+ // long t = System.currentTimeMillis();
1686
+ // g2.drawImage(who.getImage(),
1687
+ // (int) x1, (int) y1, (int) x2, (int) y2,
1688
+ // u1, v1, u2, v2, null);
1689
+ // System.out.println(System.currentTimeMillis() - t);
1690
+ //
1691
+ // if (oldComp != null) {
1692
+ // g2.setComposite(oldComp);
1693
+ // }
1694
+ }
1695
+
1696
+
1697
+ static class ImageCache {
1698
+ boolean tinted;
1699
+ int tintedColor;
1700
+ int[] tintedTemp; // one row of tinted pixels
1701
+ BufferedImage image;
1702
+ // BufferedImage compat;
1703
+
1704
+ // public ImageCache(PImage source) {
1705
+ //// this.source = source;
1706
+ // // even if RGB, set the image type to ARGB, because the
1707
+ // // image may have an alpha value for its tint().
1708
+ //// int type = BufferedImage.TYPE_INT_ARGB;
1709
+ // //System.out.println("making new buffered image");
1710
+ //// image = new BufferedImage(source.width, source.height, type);
1711
+ // }
1712
+
1713
+ /**
1714
+ * Update the pixels of the cache image. Already determined that the tint
1715
+ * has changed, or the pixels have changed, so should just go through
1716
+ * with the update without further checks.
1717
+ */
1718
+ public void update(PImage source, boolean tint, int tintColor) {
1719
+ //int bufferType = BufferedImage.TYPE_INT_ARGB;
1720
+ int targetType = ARGB;
1721
+ boolean opaque = (tintColor & 0xFF000000) == 0xFF000000;
1722
+ if (source.format == RGB) {
1723
+ if (!tint || (tint && opaque)) {
1724
+ //bufferType = BufferedImage.TYPE_INT_RGB;
1725
+ targetType = RGB;
1726
+ }
1727
+ }
1728
+ // boolean wrongType = (image != null) && (image.getType() != bufferType);
1729
+ // if ((image == null) || wrongType) {
1730
+ // image = new BufferedImage(source.width, source.height, bufferType);
1731
+ // }
1732
+ // Must always use an ARGB image, otherwise will write zeros
1733
+ // in the alpha channel when drawn to the screen.
1734
+ // https://github.com/processing/processing/issues/2030
1735
+ if (image == null) {
1736
+ image = new BufferedImage(source.pixelWidth, source.pixelHeight,
1737
+ BufferedImage.TYPE_INT_ARGB);
1738
+ }
1739
+
1740
+ WritableRaster wr = image.getRaster();
1741
+ if (tint) {
1742
+ if (tintedTemp == null || tintedTemp.length != source.pixelWidth) {
1743
+ tintedTemp = new int[source.pixelWidth];
1744
+ }
1745
+ int a2 = (tintColor >> 24) & 0xff;
1746
+ // System.out.println("tint color is " + a2);
1747
+ // System.out.println("source.pixels[0] alpha is " + (source.pixels[0] >>> 24));
1748
+ int r2 = (tintColor >> 16) & 0xff;
1749
+ int g2 = (tintColor >> 8) & 0xff;
1750
+ int b2 = (tintColor) & 0xff;
1751
+
1752
+ //if (bufferType == BufferedImage.TYPE_INT_RGB) {
1753
+ if (targetType == RGB) {
1754
+ // The target image is opaque, meaning that the source image has no
1755
+ // alpha (is not ARGB), and the tint has no alpha.
1756
+ int index = 0;
1757
+ for (int y = 0; y < source.pixelHeight; y++) {
1758
+ for (int x = 0; x < source.pixelWidth; x++) {
1759
+ int argb1 = source.pixels[index++];
1760
+ int r1 = (argb1 >> 16) & 0xff;
1761
+ int g1 = (argb1 >> 8) & 0xff;
1762
+ int b1 = (argb1) & 0xff;
1763
+
1764
+ // Prior to 2.1, the alpha channel was commented out here,
1765
+ // but can't remember why (just thought unnecessary b/c of RGB?)
1766
+ // https://github.com/processing/processing/issues/2030
1767
+ tintedTemp[x] = 0xFF000000 |
1768
+ (((r2 * r1) & 0xff00) << 8) |
1769
+ ((g2 * g1) & 0xff00) |
1770
+ (((b2 * b1) & 0xff00) >> 8);
1771
+ }
1772
+ wr.setDataElements(0, y, source.pixelWidth, 1, tintedTemp);
1773
+ }
1774
+ // could this be any slower?
1775
+ // float[] scales = { tintR, tintG, tintB };
1776
+ // float[] offsets = new float[3];
1777
+ // RescaleOp op = new RescaleOp(scales, offsets, null);
1778
+ // op.filter(image, image);
1779
+
1780
+ //} else if (bufferType == BufferedImage.TYPE_INT_ARGB) {
1781
+ } else if (targetType == ARGB) {
1782
+ if (source.format == RGB &&
1783
+ (tintColor & 0xffffff) == 0xffffff) {
1784
+ int hi = tintColor & 0xff000000;
1785
+ int index = 0;
1786
+ for (int y = 0; y < source.pixelHeight; y++) {
1787
+ for (int x = 0; x < source.pixelWidth; x++) {
1788
+ tintedTemp[x] = hi | (source.pixels[index++] & 0xFFFFFF);
1789
+ }
1790
+ wr.setDataElements(0, y, source.pixelWidth, 1, tintedTemp);
1791
+ }
1792
+ } else {
1793
+ int index = 0;
1794
+ for (int y = 0; y < source.pixelHeight; y++) {
1795
+ if (source.format == RGB) {
1796
+ int alpha = tintColor & 0xFF000000;
1797
+ for (int x = 0; x < source.pixelWidth; x++) {
1798
+ int argb1 = source.pixels[index++];
1799
+ int r1 = (argb1 >> 16) & 0xff;
1800
+ int g1 = (argb1 >> 8) & 0xff;
1801
+ int b1 = (argb1) & 0xff;
1802
+ tintedTemp[x] = alpha |
1803
+ (((r2 * r1) & 0xff00) << 8) |
1804
+ ((g2 * g1) & 0xff00) |
1805
+ (((b2 * b1) & 0xff00) >> 8);
1806
+ }
1807
+ } else if (source.format == ARGB) {
1808
+ for (int x = 0; x < source.pixelWidth; x++) {
1809
+ int argb1 = source.pixels[index++];
1810
+ int a1 = (argb1 >> 24) & 0xff;
1811
+ int r1 = (argb1 >> 16) & 0xff;
1812
+ int g1 = (argb1 >> 8) & 0xff;
1813
+ int b1 = (argb1) & 0xff;
1814
+ tintedTemp[x] =
1815
+ (((a2 * a1) & 0xff00) << 16) |
1816
+ (((r2 * r1) & 0xff00) << 8) |
1817
+ ((g2 * g1) & 0xff00) |
1818
+ (((b2 * b1) & 0xff00) >> 8);
1819
+ }
1820
+ } else if (source.format == ALPHA) {
1821
+ int lower = tintColor & 0xFFFFFF;
1822
+ for (int x = 0; x < source.pixelWidth; x++) {
1823
+ int a1 = source.pixels[index++];
1824
+ tintedTemp[x] =
1825
+ (((a2 * a1) & 0xff00) << 16) | lower;
1826
+ }
1827
+ }
1828
+ wr.setDataElements(0, y, source.pixelWidth, 1, tintedTemp);
1829
+ }
1830
+ }
1831
+ // Not sure why ARGB images take the scales in this order...
1832
+ // float[] scales = { tintR, tintG, tintB, tintA };
1833
+ // float[] offsets = new float[4];
1834
+ // RescaleOp op = new RescaleOp(scales, offsets, null);
1835
+ // op.filter(image, image);
1836
+ }
1837
+ } else { // !tint
1838
+ if (targetType == RGB && (source.pixels[0] >> 24 == 0)) {
1839
+ // If it's an RGB image and the high bits aren't set, need to set
1840
+ // the high bits to opaque because we're drawing ARGB images.
1841
+ source.filter(OPAQUE);
1842
+ // Opting to just manipulate the image here, since it shouldn't
1843
+ // affect anything else (and alpha(get(x, y)) should return 0xff).
1844
+ // Wel also make no guarantees about the values of the pixels array
1845
+ // in a PImage and how the high bits will be set.
1846
+ }
1847
+ // If no tint, just shove the pixels on in there verbatim
1848
+ wr.setDataElements(0, 0, source.pixelWidth, source.pixelHeight, source.pixels);
1849
+ }
1850
+ this.tinted = tint;
1851
+ this.tintedColor = tintColor;
1852
+
1853
+ // GraphicsConfiguration gc = parent.getGraphicsConfiguration();
1854
+ // compat = gc.createCompatibleImage(image.getWidth(),
1855
+ // image.getHeight(),
1856
+ // Transparency.TRANSLUCENT);
1857
+ //
1858
+ // Graphics2D g = compat.createGraphics();
1859
+ // g.drawImage(image, 0, 0, null);
1860
+ // g.dispose();
1861
+ }
1862
+ }
1863
+
1864
+
1865
+
1866
+ //////////////////////////////////////////////////////////////
1867
+
1868
+ // SHAPE
1869
+
1870
+
1871
+ //public void shapeMode(int mode)
1872
+
1873
+
1874
+ //public void shape(PShape shape)
1875
+
1876
+
1877
+ //public void shape(PShape shape, float x, float y)
1878
+
1879
+
1880
+ //public void shape(PShape shape, float x, float y, float c, float d)
1881
+
1882
+
1883
+ //////////////////////////////////////////////////////////////
1884
+
1885
+ // SHAPE I/O
1886
+
1887
+
1888
+ //public PShape loadShape(String filename)
1889
+
1890
+
1891
+ @Override
1892
+ public PShape loadShape(String filename, String options) {
1893
+ String extension = PApplet.getExtension(filename);
1894
+ if (extension.equals("svg") || extension.equals("svgz")) {
1895
+ return new PShapeJava2D(parent.loadXML(filename));
1896
+ }
1897
+ PGraphics.showWarning("Unsupported format: " + filename);
1898
+ return null;
1899
+ }
1900
+
1901
+
1902
+
1903
+ //////////////////////////////////////////////////////////////
1904
+
1905
+ // TEXT ATTRIBTUES
1906
+
1907
+
1908
+ //public void textAlign(int align)
1909
+
1910
+
1911
+ //public void textAlign(int alignX, int alignY)
1912
+
1913
+
1914
+ @Override
1915
+ public float textAscent() {
1916
+ if (textFont == null) {
1917
+ defaultFontOrDeath("textAscent");
1918
+ }
1919
+
1920
+ Font font = (Font) textFont.getNative();
1921
+ if (font != null) {
1922
+ //return getFontMetrics(font).getAscent();
1923
+ return g2.getFontMetrics(font).getAscent();
1924
+ }
1925
+ return super.textAscent();
1926
+ }
1927
+
1928
+
1929
+ @Override
1930
+ public float textDescent() {
1931
+ if (textFont == null) {
1932
+ defaultFontOrDeath("textDescent");
1933
+ }
1934
+ Font font = (Font) textFont.getNative();
1935
+ if (font != null) {
1936
+ //return getFontMetrics(font).getDescent();
1937
+ return g2.getFontMetrics(font).getDescent();
1938
+ }
1939
+ return super.textDescent();
1940
+ }
1941
+
1942
+
1943
+ //public void textFont(PFont which)
1944
+
1945
+
1946
+ //public void textFont(PFont which, float size)
1947
+
1948
+
1949
+ //public void textLeading(float leading)
1950
+
1951
+
1952
+ //public void textMode(int mode)
1953
+
1954
+
1955
+ @Override
1956
+ protected boolean textModeCheck(int mode) {
1957
+ return mode == MODEL;
1958
+ }
1959
+
1960
+
1961
+ /**
1962
+ * Same as parent, but override for native version of the font.
1963
+ * <p/>
1964
+ * Called from textFontImpl and textSizeImpl, so the metrics
1965
+ * will get recorded properly.
1966
+ */
1967
+ @Override
1968
+ protected void handleTextSize(float size) {
1969
+ // if a native version available, derive this font
1970
+ Font font = (Font) textFont.getNative();
1971
+ // don't derive again if the font size has not changed
1972
+ if (font != null) {
1973
+ if (font.getSize2D() != size) {
1974
+ Map<TextAttribute, Object> map =
1975
+ new HashMap<>();
1976
+ map.put(TextAttribute.SIZE, size);
1977
+ map.put(TextAttribute.KERNING,
1978
+ TextAttribute.KERNING_ON);
1979
+ // map.put(TextAttribute.TRACKING,
1980
+ // TextAttribute.TRACKING_TIGHT);
1981
+ font = font.deriveFont(map);
1982
+ }
1983
+ g2.setFont(font);
1984
+ textFont.setNative(font);
1985
+ fontObject = font;
1986
+
1987
+ /*
1988
+ Map<TextAttribute, ?> attrs = font.getAttributes();
1989
+ for (TextAttribute ta : attrs.keySet()) {
1990
+ System.out.println(ta + " -> " + attrs.get(ta));
1991
+ }
1992
+ */
1993
+ }
1994
+
1995
+ // take care of setting the textSize and textLeading vars
1996
+ // this has to happen second, because it calls textAscent()
1997
+ // (which requires the native font metrics to be set)
1998
+ super.handleTextSize(size);
1999
+ }
2000
+
2001
+
2002
+ //public float textWidth(char c)
2003
+
2004
+
2005
+ //public float textWidth(String str)
2006
+
2007
+
2008
+ @Override
2009
+ protected float textWidthImpl(char buffer[], int start, int stop) {
2010
+ if (textFont == null) {
2011
+ defaultFontOrDeath("textWidth");
2012
+ }
2013
+ // Avoid "Zero length string passed to TextLayout constructor" error
2014
+ if (start == stop) {
2015
+ return 0;
2016
+ }
2017
+
2018
+ Font font = (Font) textFont.getNative();
2019
+ // System.out.println(font);
2020
+ //if (font != null && (textFont.isStream() || hints[ENABLE_NATIVE_FONTS])) {
2021
+ if (font != null) {
2022
+ // System.out.println("using charswidth for " + new String(buffer, start, stop-start));
2023
+ // maybe should use one of the newer/fancier functions for this?
2024
+ // int length = stop - start;
2025
+ // FontMetrics metrics = getFontMetrics(font);
2026
+ FontMetrics metrics = g2.getFontMetrics(font);
2027
+ // Using fractional metrics makes the measurement worse, not better,
2028
+ // at least on OS X 10.6 (November, 2010).
2029
+ // TextLayout returns the same value as charsWidth().
2030
+ // System.err.println("using native");
2031
+ // g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
2032
+ // RenderingHints.VALUE_FRACTIONALMETRICS_ON);
2033
+ // float m1 = metrics.charsWidth(buffer, start, length);
2034
+ // float m2 = (float) metrics.getStringBounds(buffer, start, stop, g2).getWidth();
2035
+ // TextLayout tl = new TextLayout(new String(buffer, start, length), font, g2.getFontRenderContext());
2036
+ // float m3 = (float) tl.getBounds().getWidth();
2037
+ // System.err.println(m1 + " " + m2 + " " + m3);
2038
+ ////// return m1;
2039
+ //// return m2;
2040
+ //// return metrics.charsWidth(buffer, start, length);
2041
+ // return m2;
2042
+ return (float)
2043
+ metrics.getStringBounds(buffer, start, stop, g2).getWidth();
2044
+ }
2045
+ // System.err.println("not native");
2046
+ return super.textWidthImpl(buffer, start, stop);
2047
+ }
2048
+
2049
+
2050
+ // protected void beginTextScreenMode() {
2051
+ // loadPixels();
2052
+ // }
2053
+
2054
+
2055
+ // protected void endTextScreenMode() {
2056
+ // updatePixels();
2057
+ // }
2058
+
2059
+
2060
+ //////////////////////////////////////////////////////////////
2061
+
2062
+ // TEXT
2063
+
2064
+ // None of the variations of text() are overridden from PGraphics.
2065
+
2066
+
2067
+
2068
+ //////////////////////////////////////////////////////////////
2069
+
2070
+ // TEXT IMPL
2071
+
2072
+
2073
+ //protected void textLineAlignImpl(char buffer[], int start, int stop,
2074
+ // float x, float y)
2075
+
2076
+
2077
+ @Override
2078
+ protected void textLineImpl(char buffer[], int start, int stop,
2079
+ float x, float y) {
2080
+ Font font = (Font) textFont.getNative();
2081
+ // if (font != null && (textFont.isStream() || hints[ENABLE_NATIVE_FONTS])) {
2082
+ if (font != null) {
2083
+ /*
2084
+ // save the current setting for text smoothing. note that this is
2085
+ // different from the smooth() function, because the font smoothing
2086
+ // is controlled when the font is created, not now as it's drawn.
2087
+ // fixed a bug in 0116 that handled this incorrectly.
2088
+ Object textAntialias =
2089
+ g2.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING);
2090
+
2091
+ // override the current text smoothing setting based on the font
2092
+ // (don't change the global smoothing settings)
2093
+ g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
2094
+ textFont.smooth ?
2095
+ RenderingHints.VALUE_ANTIALIAS_ON :
2096
+ RenderingHints.VALUE_ANTIALIAS_OFF);
2097
+ */
2098
+ Object antialias =
2099
+ g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
2100
+ if (antialias == null) {
2101
+ // if smooth() and noSmooth() not called, this will be null (0120)
2102
+ antialias = RenderingHints.VALUE_ANTIALIAS_DEFAULT;
2103
+ }
2104
+
2105
+ // override the current smoothing setting based on the font
2106
+ // also changes global setting for antialiasing, but this is because it's
2107
+ // not possible to enable/disable them independently in some situations.
2108
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
2109
+ textFont.isSmooth() ?
2110
+ RenderingHints.VALUE_ANTIALIAS_ON :
2111
+ RenderingHints.VALUE_ANTIALIAS_OFF);
2112
+
2113
+ g2.setColor(fillColorObject);
2114
+
2115
+ int length = stop - start;
2116
+ if (length != 0) {
2117
+ g2.drawChars(buffer, start, length, (int) (x + 0.5f), (int) (y + 0.5f));
2118
+ // better to use round here? also, drawChars now just calls drawString
2119
+ // g2.drawString(new String(buffer, start, stop - start), Math.round(x), Math.round(y));
2120
+
2121
+ // better to use drawString() with floats? (nope, draws the same)
2122
+ //g2.drawString(new String(buffer, start, length), x, y);
2123
+
2124
+ // this didn't seem to help the scaling issue, and creates garbage
2125
+ // because of a fairly heavyweight new temporary object
2126
+ // java.awt.font.GlyphVector gv =
2127
+ // font.createGlyphVector(g2.getFontRenderContext(), new String(buffer, start, stop - start));
2128
+ // g2.drawGlyphVector(gv, x, y);
2129
+ }
2130
+
2131
+ // return to previous smoothing state if it was changed
2132
+ //g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, textAntialias);
2133
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antialias);
2134
+
2135
+ } else { // otherwise just do the default
2136
+ super.textLineImpl(buffer, start, stop, x, y);
2137
+ }
2138
+ }
2139
+
2140
+
2141
+ // /**
2142
+ // * Convenience method to get a legit FontMetrics object. Where possible,
2143
+ // * override this any renderer subclass so that you're not using what's
2144
+ // * returned by getDefaultToolkit() to get your metrics.
2145
+ // */
2146
+ // @SuppressWarnings("deprecation")
2147
+ // public FontMetrics getFontMetrics(Font font) { // ignore
2148
+ // Frame frame = parent.frame;
2149
+ // if (frame != null) {
2150
+ // return frame.getToolkit().getFontMetrics(font);
2151
+ // }
2152
+ // return Toolkit.getDefaultToolkit().getFontMetrics(font);
2153
+ // }
2154
+ //
2155
+ //
2156
+ // /**
2157
+ // * Convenience method to jump through some Java2D hoops and get an FRC.
2158
+ // */
2159
+ // public FontRenderContext getFontRenderContext(Font font) { // ignore
2160
+ // return getFontMetrics(font).getFontRenderContext();
2161
+ // }
2162
+
2163
+ /*
2164
+ Toolkit toolkit;
2165
+
2166
+ @SuppressWarnings("deprecation")
2167
+ protected FontMetrics getFontMetrics(Font font) {
2168
+ if (toolkit == null) {
2169
+ try {
2170
+ Canvas canvas = (Canvas) surface.getNative();
2171
+ toolkit = canvas.getToolkit();
2172
+ } catch (Exception e) {
2173
+ // May error out if it's a PSurfaceNone or similar
2174
+ toolkit = Toolkit.getDefaultToolkit();
2175
+ }
2176
+ }
2177
+ return toolkit.getFontMetrics(font);
2178
+ //return (g2 != null) ? g2.getFontMetrics(font) : super.getFontMetrics(font);
2179
+ }
2180
+ */
2181
+
2182
+
2183
+ //////////////////////////////////////////////////////////////
2184
+
2185
+ // MATRIX STACK
2186
+
2187
+
2188
+ @Override
2189
+ public void pushMatrix() {
2190
+ if (transformCount == transformStack.length) {
2191
+ throw new RuntimeException("pushMatrix() cannot use push more than " +
2192
+ transformStack.length + " times");
2193
+ }
2194
+ transformStack[transformCount] = g2.getTransform();
2195
+ transformCount++;
2196
+ }
2197
+
2198
+
2199
+ @Override
2200
+ public void popMatrix() {
2201
+ if (transformCount == 0) {
2202
+ throw new RuntimeException("missing a pushMatrix() " +
2203
+ "to go with that popMatrix()");
2204
+ }
2205
+ transformCount--;
2206
+ g2.setTransform(transformStack[transformCount]);
2207
+ }
2208
+
2209
+
2210
+
2211
+ //////////////////////////////////////////////////////////////
2212
+
2213
+ // MATRIX TRANSFORMS
2214
+
2215
+
2216
+ @Override
2217
+ public void translate(float tx, float ty) {
2218
+ g2.translate(tx, ty);
2219
+ }
2220
+
2221
+
2222
+ //public void translate(float tx, float ty, float tz)
2223
+
2224
+
2225
+ @Override
2226
+ public void rotate(float angle) {
2227
+ g2.rotate(angle);
2228
+ }
2229
+
2230
+
2231
+ @Override
2232
+ public void rotateX(float angle) {
2233
+ showDepthWarning("rotateX");
2234
+ }
2235
+
2236
+
2237
+ @Override
2238
+ public void rotateY(float angle) {
2239
+ showDepthWarning("rotateY");
2240
+ }
2241
+
2242
+
2243
+ @Override
2244
+ public void rotateZ(float angle) {
2245
+ showDepthWarning("rotateZ");
2246
+ }
2247
+
2248
+
2249
+ @Override
2250
+ public void rotate(float angle, float vx, float vy, float vz) {
2251
+ showVariationWarning("rotate");
2252
+ }
2253
+
2254
+
2255
+ @Override
2256
+ public void scale(float s) {
2257
+ g2.scale(s, s);
2258
+ }
2259
+
2260
+
2261
+ @Override
2262
+ public void scale(float sx, float sy) {
2263
+ g2.scale(sx, sy);
2264
+ }
2265
+
2266
+
2267
+ @Override
2268
+ public void scale(float sx, float sy, float sz) {
2269
+ showDepthWarningXYZ("scale");
2270
+ }
2271
+
2272
+
2273
+ @Override
2274
+ public void shearX(float angle) {
2275
+ g2.shear(Math.tan(angle), 0);
2276
+ }
2277
+
2278
+
2279
+ @Override
2280
+ public void shearY(float angle) {
2281
+ g2.shear(0, Math.tan(angle));
2282
+ }
2283
+
2284
+
2285
+
2286
+ //////////////////////////////////////////////////////////////
2287
+
2288
+ // MATRIX MORE
2289
+
2290
+
2291
+ @Override
2292
+ public void resetMatrix() {
2293
+ g2.setTransform(new AffineTransform());
2294
+ g2.scale(pixelDensity, pixelDensity);
2295
+ }
2296
+
2297
+
2298
+ //public void applyMatrix(PMatrix2D source)
2299
+
2300
+
2301
+ @Override
2302
+ public void applyMatrix(float n00, float n01, float n02,
2303
+ float n10, float n11, float n12) {
2304
+ //System.out.println("PGraphicsJava2D.applyMatrix()");
2305
+ //System.out.println(new AffineTransform(n00, n10, n01, n11, n02, n12));
2306
+ g2.transform(new AffineTransform(n00, n10, n01, n11, n02, n12));
2307
+ //g2.transform(new AffineTransform(n00, n01, n02, n10, n11, n12));
2308
+ }
2309
+
2310
+
2311
+ //public void applyMatrix(PMatrix3D source)
2312
+
2313
+
2314
+ @Override
2315
+ public void applyMatrix(float n00, float n01, float n02, float n03,
2316
+ float n10, float n11, float n12, float n13,
2317
+ float n20, float n21, float n22, float n23,
2318
+ float n30, float n31, float n32, float n33) {
2319
+ showVariationWarning("applyMatrix");
2320
+ }
2321
+
2322
+
2323
+
2324
+ //////////////////////////////////////////////////////////////
2325
+
2326
+ // MATRIX GET/SET
2327
+
2328
+
2329
+ @Override
2330
+ public PMatrix getMatrix() {
2331
+ return getMatrix((PMatrix2D) null);
2332
+ }
2333
+
2334
+
2335
+ @Override
2336
+ public PMatrix2D getMatrix(PMatrix2D target) {
2337
+ if (target == null) {
2338
+ target = new PMatrix2D();
2339
+ }
2340
+ g2.getTransform().getMatrix(transform);
2341
+ target.set((float) transform[0], (float) transform[2], (float) transform[4],
2342
+ (float) transform[1], (float) transform[3], (float) transform[5]);
2343
+ return target;
2344
+ }
2345
+
2346
+
2347
+ @Override
2348
+ public PMatrix3D getMatrix(PMatrix3D target) {
2349
+ showVariationWarning("getMatrix");
2350
+ return target;
2351
+ }
2352
+
2353
+
2354
+ //public void setMatrix(PMatrix source)
2355
+
2356
+
2357
+ @Override
2358
+ public void setMatrix(PMatrix2D source) {
2359
+ g2.setTransform(new AffineTransform(source.m00, source.m10,
2360
+ source.m01, source.m11,
2361
+ source.m02, source.m12));
2362
+ }
2363
+
2364
+
2365
+ @Override
2366
+ public void setMatrix(PMatrix3D source) {
2367
+ showVariationWarning("setMatrix");
2368
+ }
2369
+
2370
+
2371
+ @Override
2372
+ public void printMatrix() {
2373
+ getMatrix((PMatrix2D) null).print();
2374
+ }
2375
+
2376
+
2377
+
2378
+ //////////////////////////////////////////////////////////////
2379
+
2380
+ // CAMERA and PROJECTION
2381
+
2382
+ // Inherit the plaintive warnings from PGraphics
2383
+
2384
+
2385
+ //public void beginCamera()
2386
+ //public void endCamera()
2387
+ //public void camera()
2388
+ //public void camera(float eyeX, float eyeY, float eyeZ,
2389
+ // float centerX, float centerY, float centerZ,
2390
+ // float upX, float upY, float upZ)
2391
+ //public void printCamera()
2392
+
2393
+ //public void ortho()
2394
+ //public void ortho(float left, float right,
2395
+ // float bottom, float top,
2396
+ // float near, float far)
2397
+ //public void perspective()
2398
+ //public void perspective(float fov, float aspect, float near, float far)
2399
+ //public void frustum(float left, float right,
2400
+ // float bottom, float top,
2401
+ // float near, float far)
2402
+ //public void printProjection()
2403
+
2404
+
2405
+
2406
+ //////////////////////////////////////////////////////////////
2407
+
2408
+ // SCREEN and MODEL transforms
2409
+
2410
+
2411
+ @Override
2412
+ public float screenX(float x, float y) {
2413
+ g2.getTransform().getMatrix(transform);
2414
+ return (float)transform[0]*x + (float)transform[2]*y + (float)transform[4];
2415
+ }
2416
+
2417
+
2418
+ @Override
2419
+ public float screenY(float x, float y) {
2420
+ g2.getTransform().getMatrix(transform);
2421
+ return (float)transform[1]*x + (float)transform[3]*y + (float)transform[5];
2422
+ }
2423
+
2424
+
2425
+ @Override
2426
+ public float screenX(float x, float y, float z) {
2427
+ showDepthWarningXYZ("screenX");
2428
+ return 0;
2429
+ }
2430
+
2431
+
2432
+ @Override
2433
+ public float screenY(float x, float y, float z) {
2434
+ showDepthWarningXYZ("screenY");
2435
+ return 0;
2436
+ }
2437
+
2438
+
2439
+ @Override
2440
+ public float screenZ(float x, float y, float z) {
2441
+ showDepthWarningXYZ("screenZ");
2442
+ return 0;
2443
+ }
2444
+
2445
+
2446
+ //public float modelX(float x, float y, float z)
2447
+
2448
+
2449
+ //public float modelY(float x, float y, float z)
2450
+
2451
+
2452
+ //public float modelZ(float x, float y, float z)
2453
+
2454
+
2455
+
2456
+ //////////////////////////////////////////////////////////////
2457
+
2458
+ // STYLE
2459
+
2460
+ // pushStyle(), popStyle(), style() and getStyle() inherited.
2461
+
2462
+
2463
+
2464
+ //////////////////////////////////////////////////////////////
2465
+
2466
+ // STROKE CAP/JOIN/WEIGHT
2467
+
2468
+
2469
+ @Override
2470
+ public void strokeCap(int cap) {
2471
+ super.strokeCap(cap);
2472
+ strokeImpl();
2473
+ }
2474
+
2475
+
2476
+ @Override
2477
+ public void strokeJoin(int join) {
2478
+ super.strokeJoin(join);
2479
+ strokeImpl();
2480
+ }
2481
+
2482
+
2483
+ @Override
2484
+ public void strokeWeight(float weight) {
2485
+ super.strokeWeight(weight);
2486
+ strokeImpl();
2487
+ }
2488
+
2489
+ /**
2490
+ *
2491
+ */
2492
+ protected void strokeImpl() {
2493
+ int cap = BasicStroke.CAP_BUTT;
2494
+ if (strokeCap == ROUND) {
2495
+ cap = BasicStroke.CAP_ROUND;
2496
+ } else if (strokeCap == PROJECT) {
2497
+ cap = BasicStroke.CAP_SQUARE;
2498
+ }
2499
+
2500
+ int join = BasicStroke.JOIN_BEVEL;
2501
+ if (strokeJoin == MITER) {
2502
+ join = BasicStroke.JOIN_MITER;
2503
+ } else if (strokeJoin == ROUND) {
2504
+ join = BasicStroke.JOIN_ROUND;
2505
+ }
2506
+
2507
+ strokeObject = new BasicStroke(strokeWeight, cap, join);
2508
+ g2.setStroke(strokeObject);
2509
+ }
2510
+
2511
+
2512
+
2513
+ //////////////////////////////////////////////////////////////
2514
+
2515
+ // STROKE
2516
+
2517
+ // noStroke() and stroke() inherited from PGraphics.
2518
+
2519
+
2520
+ @Override
2521
+ protected void strokeFromCalc() {
2522
+ super.strokeFromCalc();
2523
+ strokeColorObject = new Color(strokeColor, true);
2524
+ strokeGradient = false;
2525
+ }
2526
+
2527
+
2528
+
2529
+ //////////////////////////////////////////////////////////////
2530
+
2531
+ // TINT
2532
+
2533
+ // noTint() and tint() inherited from PGraphics.
2534
+
2535
+
2536
+ @Override
2537
+ protected void tintFromCalc() {
2538
+ super.tintFromCalc();
2539
+ // TODO actually implement tinted images
2540
+ tintColorObject = new Color(tintColor, true);
2541
+ }
2542
+
2543
+
2544
+
2545
+ //////////////////////////////////////////////////////////////
2546
+
2547
+ // FILL
2548
+
2549
+ // noFill() and fill() inherited from PGraphics.
2550
+
2551
+
2552
+ @Override
2553
+ protected void fillFromCalc() {
2554
+ super.fillFromCalc();
2555
+ fillColorObject = new Color(fillColor, true);
2556
+ fillGradient = false;
2557
+ }
2558
+
2559
+
2560
+
2561
+ //////////////////////////////////////////////////////////////
2562
+
2563
+ // MATERIAL PROPERTIES
2564
+
2565
+
2566
+ //public void ambient(int rgb)
2567
+ //public void ambient(float gray)
2568
+ //public void ambient(float x, float y, float z)
2569
+ //protected void ambientFromCalc()
2570
+ //public void specular(int rgb)
2571
+ //public void specular(float gray)
2572
+ //public void specular(float x, float y, float z)
2573
+ //protected void specularFromCalc()
2574
+ //public void shininess(float shine)
2575
+ //public void emissive(int rgb)
2576
+ //public void emissive(float gray)
2577
+ //public void emissive(float x, float y, float z )
2578
+ //protected void emissiveFromCalc()
2579
+
2580
+
2581
+
2582
+ //////////////////////////////////////////////////////////////
2583
+
2584
+ // LIGHTS
2585
+
2586
+
2587
+ //public void lights()
2588
+ //public void noLights()
2589
+ //public void ambientLight(float red, float green, float blue)
2590
+ //public void ambientLight(float red, float green, float blue,
2591
+ // float x, float y, float z)
2592
+ //public void directionalLight(float red, float green, float blue,
2593
+ // float nx, float ny, float nz)
2594
+ //public void pointLight(float red, float green, float blue,
2595
+ // float x, float y, float z)
2596
+ //public void spotLight(float red, float green, float blue,
2597
+ // float x, float y, float z,
2598
+ // float nx, float ny, float nz,
2599
+ // float angle, float concentration)
2600
+ //public void lightFalloff(float constant, float linear, float quadratic)
2601
+ //public void lightSpecular(float x, float y, float z)
2602
+ //protected void lightPosition(int num, float x, float y, float z)
2603
+ //protected void lightDirection(int num, float x, float y, float z)
2604
+
2605
+
2606
+
2607
+ //////////////////////////////////////////////////////////////
2608
+
2609
+ // BACKGROUND
2610
+
2611
+
2612
+ int[] clearPixels;
2613
+
2614
+ /**
2615
+ *
2616
+ * @param color
2617
+ */
2618
+ protected void clearPixels(int color) {
2619
+ // On a hi-res display, image may be larger than width/height
2620
+ int imageWidth = image.getWidth(null);
2621
+ int imageHeight = image.getHeight(null);
2622
+
2623
+ // Create a small array that can be used to set the pixels several times.
2624
+ // Using a single-pixel line of length 'width' is a tradeoff between
2625
+ // speed (setting each pixel individually is too slow) and memory
2626
+ // (an array for width*height would waste lots of memory if it stayed
2627
+ // resident, and would terrify the gc if it were re-created on each trip
2628
+ // to background().
2629
+ // WritableRaster raster = ((BufferedImage) image).getRaster();
2630
+ // WritableRaster raster = image.getRaster();
2631
+ WritableRaster raster = getRaster();
2632
+ if ((clearPixels == null) || (clearPixels.length < imageWidth)) {
2633
+ clearPixels = new int[imageWidth];
2634
+ }
2635
+ Arrays.fill(clearPixels, 0, imageWidth, backgroundColor);
2636
+ for (int i = 0; i < imageHeight; i++) {
2637
+ raster.setDataElements(0, i, imageWidth, 1, clearPixels);
2638
+ }
2639
+ }
2640
+
2641
+ // background() methods inherited from PGraphics, along with the
2642
+ // PImage version of backgroundImpl(), since it just calls set().
2643
+
2644
+
2645
+ //public void backgroundImpl(PImage image)
2646
+
2647
+
2648
+ @Override
2649
+ public void backgroundImpl() {
2650
+ if (backgroundAlpha) {
2651
+ clearPixels(backgroundColor);
2652
+
2653
+ } else {
2654
+ Color bgColor = new Color(backgroundColor);
2655
+ // seems to fire an additional event that causes flickering,
2656
+ // like an extra background erase on OS X
2657
+ // if (canvas != null) {
2658
+ // canvas.setBackground(bgColor);
2659
+ // }
2660
+ //new Exception().printStackTrace(System.out);
2661
+ // in case people do transformations before background(),
2662
+ // need to handle this with a push/reset/pop
2663
+ Composite oldComposite = g2.getComposite();
2664
+ g2.setComposite(defaultComposite);
2665
+
2666
+ pushMatrix();
2667
+ resetMatrix();
2668
+ g2.setColor(bgColor); //, backgroundAlpha));
2669
+ // g2.fillRect(0, 0, width, height);
2670
+ // On a hi-res display, image may be larger than width/height
2671
+ if (image != null) {
2672
+ // image will be null in subclasses (i.e. PDF)
2673
+ g2.fillRect(0, 0, image.getWidth(null), image.getHeight(null));
2674
+ } else {
2675
+ // hope for the best if image is null
2676
+ g2.fillRect(0, 0, width, height);
2677
+ }
2678
+ popMatrix();
2679
+
2680
+ g2.setComposite(oldComposite);
2681
+ }
2682
+ }
2683
+
2684
+
2685
+
2686
+ //////////////////////////////////////////////////////////////
2687
+
2688
+ // COLOR MODE
2689
+
2690
+ // All colorMode() variations are inherited from PGraphics.
2691
+
2692
+
2693
+
2694
+ //////////////////////////////////////////////////////////////
2695
+
2696
+ // COLOR CALC
2697
+
2698
+ // colorCalc() and colorCalcARGB() inherited from PGraphics.
2699
+
2700
+
2701
+
2702
+ //////////////////////////////////////////////////////////////
2703
+
2704
+ // COLOR DATATYPE STUFFING
2705
+
2706
+ // final color() variations inherited.
2707
+
2708
+
2709
+
2710
+ //////////////////////////////////////////////////////////////
2711
+
2712
+ // COLOR DATATYPE EXTRACTION
2713
+
2714
+ // final methods alpha, red, green, blue,
2715
+ // hue, saturation, and brightness all inherited.
2716
+
2717
+
2718
+
2719
+ //////////////////////////////////////////////////////////////
2720
+
2721
+ // COLOR DATATYPE INTERPOLATION
2722
+
2723
+ // both lerpColor variants inherited.
2724
+
2725
+
2726
+
2727
+ //////////////////////////////////////////////////////////////
2728
+
2729
+ // BEGIN/END RAW
2730
+
2731
+
2732
+ @Override
2733
+ public void beginRaw(PGraphics recorderRaw) {
2734
+ showMethodWarning("beginRaw");
2735
+ }
2736
+
2737
+
2738
+ @Override
2739
+ public void endRaw() {
2740
+ showMethodWarning("endRaw");
2741
+ }
2742
+
2743
+
2744
+
2745
+ //////////////////////////////////////////////////////////////
2746
+
2747
+ // WARNINGS and EXCEPTIONS
2748
+
2749
+ // showWarning and showException inherited.
2750
+
2751
+
2752
+
2753
+ //////////////////////////////////////////////////////////////
2754
+
2755
+ // RENDERER SUPPORT QUERIES
2756
+
2757
+
2758
+ //public boolean displayable() // true
2759
+
2760
+
2761
+ //public boolean is2D() // true
2762
+
2763
+
2764
+ //public boolean is3D() // false
2765
+
2766
+
2767
+
2768
+ //////////////////////////////////////////////////////////////
2769
+
2770
+ // PIMAGE METHODS
2771
+
2772
+
2773
+ // getImage, setCache, getCache, removeCache, isModified, setModified
2774
+
2775
+ /**
2776
+ *
2777
+ * @return
2778
+ */
2779
+
2780
+
2781
+ protected WritableRaster getRaster() {
2782
+ WritableRaster raster = null;
2783
+ if (primaryGraphics) {
2784
+ /*
2785
+ // 'offscreen' will probably be removed in the next release
2786
+ if (useOffscreen) {
2787
+ raster = offscreen.getRaster();
2788
+ } else*/ if (image instanceof VolatileImage) {
2789
+ // when possible, we'll try VolatileImage
2790
+ raster = ((VolatileImage) image).getSnapshot().getRaster();
2791
+ }
2792
+ }
2793
+ if (raster == null) {
2794
+ raster = ((BufferedImage) image).getRaster();
2795
+ }
2796
+
2797
+ // On Raspberry Pi (and perhaps other platforms, the color buffer won't
2798
+ // necessarily be the int array that we'd like. Need to convert it here.
2799
+ // Not that this would probably mean getRaster() would need to work more
2800
+ // like loadRaster/updateRaster because the pixels will need to be
2801
+ // temporarily moved to (and later from) a buffer that's understood by
2802
+ // the rest of the Processing source.
2803
+ // https://github.com/processing/processing/issues/2010
2804
+ if (raster.getTransferType() != DataBuffer.TYPE_INT) {
2805
+ System.err.println("See https://github.com/processing/processing/issues/2010");
2806
+ throw new RuntimeException("Pixel operations are not supported on this device.");
2807
+ }
2808
+ return raster;
2809
+ }
2810
+
2811
+
2812
+ @Override
2813
+ public void loadPixels() {
2814
+ if (pixels == null || (pixels.length != pixelWidth*pixelHeight)) {
2815
+ pixels = new int[pixelWidth * pixelHeight];
2816
+ }
2817
+
2818
+ WritableRaster raster = getRaster();
2819
+ raster.getDataElements(0, 0, pixelWidth, pixelHeight, pixels);
2820
+ if (raster.getNumBands() == 3) {
2821
+ // Java won't set the high bits when RGB, returns 0 for alpha
2822
+ // https://github.com/processing/processing/issues/2030
2823
+ for (int i = 0; i < pixels.length; i++) {
2824
+ pixels[i] = 0xff000000 | pixels[i];
2825
+ }
2826
+ }
2827
+ //((BufferedImage) image).getRGB(0, 0, width, height, pixels, 0, width);
2828
+ // WritableRaster raster = ((BufferedImage) (useOffscreen && primarySurface ? offscreen : image)).getRaster();
2829
+ // WritableRaster raster = image.getRaster();
2830
+ }
2831
+
2832
+
2833
+ // /**
2834
+ // * Update the pixels[] buffer to the PGraphics image.
2835
+ // * <P>
2836
+ // * Unlike in PImage, where updatePixels() only requests that the
2837
+ // * update happens, in PGraphicsJava2D, this will happen immediately.
2838
+ // */
2839
+ // @Override
2840
+ // public void updatePixels() {
2841
+ // //updatePixels(0, 0, width, height);
2842
+ //// WritableRaster raster = ((BufferedImage) (useOffscreen && primarySurface ? offscreen : image)).getRaster();
2843
+ //// WritableRaster raster = image.getRaster();
2844
+ // updatePixels(0, 0, width, height);
2845
+ // }
2846
+
2847
+
2848
+ /**
2849
+ * Update the pixels[] buffer to the PGraphics image.
2850
+ * <P>
2851
+ * Unlike in PImage, where updatePixels() only requests that the
2852
+ * update happens, in PGraphicsJava2D, this will happen immediately.
2853
+ * @param c
2854
+ * @param d
2855
+ */
2856
+ @Override
2857
+ public void updatePixels(int x, int y, int c, int d) {
2858
+ //if ((x == 0) && (y == 0) && (c == width) && (d == height)) {
2859
+ // System.err.format("%d %d %d %d .. w/h = %d %d .. pw/ph = %d %d %n", x, y, c, d, width, height, pixelWidth, pixelHeight);
2860
+ if ((x != 0) || (y != 0) || (c != pixelWidth) || (d != pixelHeight)) {
2861
+ // Show a warning message, but continue anyway.
2862
+ showVariationWarning("updatePixels(x, y, w, h)");
2863
+ // new Exception().printStackTrace(System.out);
2864
+ }
2865
+ // updatePixels();
2866
+ if (pixels != null) {
2867
+ getRaster().setDataElements(0, 0, pixelWidth, pixelHeight, pixels);
2868
+ }
2869
+ modified = true;
2870
+ }
2871
+
2872
+
2873
+ // @Override
2874
+ // protected void updatePixelsImpl(int x, int y, int w, int h) {
2875
+ // super.updatePixelsImpl(x, y, w, h);
2876
+ //
2877
+ // if ((x != 0) || (y != 0) || (w != width) || (h != height)) {
2878
+ // // Show a warning message, but continue anyway.
2879
+ // showVariationWarning("updatePixels(x, y, w, h)");
2880
+ // }
2881
+ // getRaster().setDataElements(0, 0, width, height, pixels);
2882
+ // }
2883
+
2884
+
2885
+
2886
+ //////////////////////////////////////////////////////////////
2887
+
2888
+ // GET/SET
2889
+
2890
+
2891
+ static int getset[] = new int[1];
2892
+
2893
+
2894
+ @Override
2895
+ public int get(int x, int y) {
2896
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) return 0;
2897
+ //return ((BufferedImage) image).getRGB(x, y);
2898
+ // WritableRaster raster = ((BufferedImage) (useOffscreen && primarySurface ? offscreen : image)).getRaster();
2899
+ WritableRaster raster = getRaster();
2900
+ raster.getDataElements(x, y, getset);
2901
+ if (raster.getNumBands() == 3) {
2902
+ // https://github.com/processing/processing/issues/2030
2903
+ return getset[0] | 0xff000000;
2904
+ }
2905
+ return getset[0];
2906
+ }
2907
+
2908
+
2909
+ //public PImage get(int x, int y, int w, int h)
2910
+
2911
+
2912
+ @Override
2913
+ protected void getImpl(int sourceX, int sourceY,
2914
+ int sourceWidth, int sourceHeight,
2915
+ PImage target, int targetX, int targetY) {
2916
+ // last parameter to getRGB() is the scan size of the *target* buffer
2917
+ //((BufferedImage) image).getRGB(x, y, w, h, output.pixels, 0, w);
2918
+ // WritableRaster raster =
2919
+ // ((BufferedImage) (useOffscreen && primarySurface ? offscreen : image)).getRaster();
2920
+ WritableRaster raster = getRaster();
2921
+
2922
+ if (sourceWidth == target.pixelWidth && sourceHeight == target.pixelHeight) {
2923
+ raster.getDataElements(sourceX, sourceY, sourceWidth, sourceHeight, target.pixels);
2924
+ // https://github.com/processing/processing/issues/2030
2925
+ if (raster.getNumBands() == 3) {
2926
+ target.filter(OPAQUE);
2927
+ }
2928
+
2929
+ } else {
2930
+ // TODO optimize, incredibly inefficient to reallocate this much memory
2931
+ int[] temp = new int[sourceWidth * sourceHeight];
2932
+ raster.getDataElements(sourceX, sourceY, sourceWidth, sourceHeight, temp);
2933
+
2934
+ // Copy the temporary output pixels over to the outgoing image
2935
+ int sourceOffset = 0;
2936
+ int targetOffset = targetY*target.pixelWidth + targetX;
2937
+ for (int y = 0; y < sourceHeight; y++) {
2938
+ if (raster.getNumBands() == 3) {
2939
+ for (int i = 0; i < sourceWidth; i++) {
2940
+ // Need to set the high bits for this feller
2941
+ // https://github.com/processing/processing/issues/2030
2942
+ target.pixels[targetOffset + i] = 0xFF000000 | temp[sourceOffset + i];
2943
+ }
2944
+ } else {
2945
+ System.arraycopy(temp, sourceOffset, target.pixels, targetOffset, sourceWidth);
2946
+ }
2947
+ sourceOffset += sourceWidth;
2948
+ targetOffset += target.pixelWidth;
2949
+ }
2950
+ }
2951
+ }
2952
+
2953
+
2954
+ @Override
2955
+ public void set(int x, int y, int argb) {
2956
+ if ((x < 0) || (y < 0) || (x >= pixelWidth) || (y >= pixelHeight)) return;
2957
+ // ((BufferedImage) image).setRGB(x, y, argb);
2958
+ getset[0] = argb;
2959
+ // WritableRaster raster = ((BufferedImage) (useOffscreen && primarySurface ? offscreen : image)).getRaster();
2960
+ // WritableRaster raster = image.getRaster();
2961
+ getRaster().setDataElements(x, y, getset);
2962
+ }
2963
+
2964
+
2965
+ //public void set(int x, int y, PImage img)
2966
+
2967
+
2968
+ @Override
2969
+ protected void setImpl(PImage sourceImage,
2970
+ int sourceX, int sourceY,
2971
+ int sourceWidth, int sourceHeight,
2972
+ int targetX, int targetY) {
2973
+ WritableRaster raster = getRaster();
2974
+ // ((BufferedImage) (useOffscreen && primarySurface ? offscreen : image)).getRaster();
2975
+
2976
+ if ((sourceX == 0) && (sourceY == 0) &&
2977
+ (sourceWidth == sourceImage.pixelWidth) &&
2978
+ (sourceHeight == sourceImage.pixelHeight)) {
2979
+ // System.out.format("%d %d %dx%d %d%n", targetX, targetY,
2980
+ // sourceImage.width, sourceImage.height,
2981
+ // sourceImage.pixels.length);
2982
+ raster.setDataElements(targetX, targetY,
2983
+ sourceImage.pixelWidth, sourceImage.pixelHeight,
2984
+ sourceImage.pixels);
2985
+ } else {
2986
+ // TODO optimize, incredibly inefficient to reallocate this much memory
2987
+ PImage temp = sourceImage.get(sourceX, sourceY, sourceWidth, sourceHeight);
2988
+ raster.setDataElements(targetX, targetY, temp.pixelWidth, temp.pixelHeight, temp.pixels);
2989
+ }
2990
+ }
2991
+
2992
+
2993
+
2994
+ //////////////////////////////////////////////////////////////
2995
+
2996
+ // MASK
2997
+
2998
+
2999
+ static final String MASK_WARNING =
3000
+ "mask() cannot be used on the main drawing surface";
3001
+
3002
+
3003
+ @Override
3004
+ public void mask(int[] alpha) {
3005
+ if (primaryGraphics) {
3006
+ showWarning(MASK_WARNING);
3007
+
3008
+ } else {
3009
+ super.mask(alpha);
3010
+ }
3011
+ }
3012
+
3013
+
3014
+ @Override
3015
+ public void mask(PImage alpha) {
3016
+ if (primaryGraphics) {
3017
+ showWarning(MASK_WARNING);
3018
+
3019
+ } else {
3020
+ super.mask(alpha);
3021
+ }
3022
+ }
3023
+
3024
+
3025
+
3026
+ //////////////////////////////////////////////////////////////
3027
+
3028
+ // FILTER
3029
+
3030
+ // Because the PImage versions call loadPixels() and
3031
+ // updatePixels(), no need to override anything here.
3032
+
3033
+
3034
+ //public void filter(int kind)
3035
+
3036
+
3037
+ //public void filter(int kind, float param)
3038
+
3039
+
3040
+
3041
+ //////////////////////////////////////////////////////////////
3042
+
3043
+ // COPY
3044
+
3045
+
3046
+ @Override
3047
+ public void copy(int sx, int sy, int sw, int sh,
3048
+ int dx, int dy, int dw, int dh) {
3049
+ if ((sw != dw) || (sh != dh)) {
3050
+ g2.drawImage(image, dx, dy, dx + dw, dy + dh, sx, sy, sx + sw, sy + sh, null);
3051
+
3052
+ } else {
3053
+ dx = dx - sx; // java2d's "dx" is the delta, not dest
3054
+ dy = dy - sy;
3055
+ g2.copyArea(sx, sy, sw, sh, dx, dy);
3056
+ }
3057
+ }
3058
+
3059
+
3060
+ @Override
3061
+ public void copy(PImage src,
3062
+ int sx, int sy, int sw, int sh,
3063
+ int dx, int dy, int dw, int dh) {
3064
+ g2.drawImage((Image) src.getNative(),
3065
+ dx, dy, dx + dw, dy + dh,
3066
+ sx, sy, sx + sw, sy + sh, null);
3067
+ }
3068
+
3069
+
3070
+
3071
+ //////////////////////////////////////////////////////////////
3072
+
3073
+ // BLEND
3074
+
3075
+
3076
+ // static public int blendColor(int c1, int c2, int mode)
3077
+
3078
+
3079
+ // public void blend(int sx, int sy, int sw, int sh,
3080
+ // int dx, int dy, int dw, int dh, int mode)
3081
+
3082
+
3083
+ // public void blend(PImage src,
3084
+ // int sx, int sy, int sw, int sh,
3085
+ // int dx, int dy, int dw, int dh, int mode)
3086
+
3087
+
3088
+
3089
+ //////////////////////////////////////////////////////////////
3090
+
3091
+ // SAVE
3092
+
3093
+
3094
+ // public void save(String filename) {
3095
+ // loadPixels();
3096
+ // super.save(filename);
3097
+ // }
3098
+ }