propane 2.7.2-java → 2.8.0.pre-java

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