picrate 0.0.2-java

Sign up to get free protection for your applications and to get access to all the features.
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
+ }