propane 3.9.0-java → 3.10.0-java

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