propane 3.9.0-java → 3.10.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/CHANGELOG.md +2 -2
  4. data/README.md +3 -3
  5. data/Rakefile +6 -6
  6. data/lib/java/japplemenubar/JAppleMenuBar.java +88 -0
  7. data/lib/java/japplemenubar/libjAppleMenuBar.jnilib +0 -0
  8. data/lib/java/monkstone/ColorUtil.java +127 -0
  9. data/lib/java/monkstone/MathToolModule.java +287 -0
  10. data/lib/java/monkstone/PropaneLibrary.java +46 -0
  11. data/lib/java/monkstone/core/LibraryProxy.java +136 -0
  12. data/lib/java/monkstone/fastmath/DegLutTables.java +111 -0
  13. data/lib/java/monkstone/fastmath/Deglut.java +71 -0
  14. data/lib/java/monkstone/fastmath/package-info.java +6 -0
  15. data/lib/java/monkstone/filechooser/Chooser.java +39 -0
  16. data/{src/main → lib}/java/monkstone/noise/FastTerrain.java +0 -0
  17. data/{src/main → lib}/java/monkstone/noise/Noise.java +0 -0
  18. data/{src/main → lib}/java/monkstone/noise/NoiseGenerator.java +0 -0
  19. data/{src/main → lib}/java/monkstone/noise/NoiseMode.java +0 -0
  20. data/lib/java/monkstone/noise/OpenSimplex2F.java +881 -0
  21. data/lib/java/monkstone/noise/OpenSimplex2S.java +1106 -0
  22. data/{src/main → lib}/java/monkstone/noise/SmoothTerrain.java +0 -0
  23. data/lib/java/monkstone/slider/CustomHorizontalSlider.java +164 -0
  24. data/lib/java/monkstone/slider/CustomVerticalSlider.java +178 -0
  25. data/lib/java/monkstone/slider/SimpleHorizontalSlider.java +145 -0
  26. data/lib/java/monkstone/slider/SimpleSlider.java +166 -0
  27. data/lib/java/monkstone/slider/SimpleVerticalSlider.java +157 -0
  28. data/lib/java/monkstone/slider/Slider.java +61 -0
  29. data/lib/java/monkstone/slider/SliderBar.java +245 -0
  30. data/lib/java/monkstone/slider/SliderGroup.java +56 -0
  31. data/lib/java/monkstone/slider/WheelHandler.java +35 -0
  32. data/lib/java/monkstone/vecmath/GfxRender.java +86 -0
  33. data/lib/java/monkstone/vecmath/JRender.java +56 -0
  34. data/lib/java/monkstone/vecmath/ShapeRender.java +87 -0
  35. data/lib/java/monkstone/vecmath/package-info.java +20 -0
  36. data/lib/java/monkstone/vecmath/vec2/Vec2.java +802 -0
  37. data/lib/java/monkstone/vecmath/vec2/package-info.java +6 -0
  38. data/lib/java/monkstone/vecmath/vec3/Vec3.java +727 -0
  39. data/lib/java/monkstone/vecmath/vec3/package-info.java +6 -0
  40. data/lib/java/monkstone/videoevent/CaptureEvent.java +27 -0
  41. data/lib/java/monkstone/videoevent/MovieEvent.java +32 -0
  42. data/lib/java/monkstone/videoevent/package-info.java +20 -0
  43. data/lib/java/processing/awt/PGraphicsJava2D.java +3040 -0
  44. data/lib/java/processing/awt/PImageAWT.java +377 -0
  45. data/lib/java/processing/awt/PShapeJava2D.java +387 -0
  46. data/lib/java/processing/awt/PSurfaceAWT.java +1581 -0
  47. data/lib/java/processing/awt/ShimAWT.java +581 -0
  48. data/lib/java/processing/core/PApplet.java +15156 -0
  49. data/lib/java/processing/core/PConstants.java +523 -0
  50. data/lib/java/processing/core/PFont.java +1126 -0
  51. data/lib/java/processing/core/PGraphics.java +8600 -0
  52. data/lib/java/processing/core/PImage.java +3377 -0
  53. data/lib/java/processing/core/PMatrix.java +208 -0
  54. data/lib/java/processing/core/PMatrix2D.java +562 -0
  55. data/lib/java/processing/core/PMatrix3D.java +890 -0
  56. data/lib/java/processing/core/PShape.java +3561 -0
  57. data/lib/java/processing/core/PShapeOBJ.java +483 -0
  58. data/lib/java/processing/core/PShapeSVG.java +2016 -0
  59. data/lib/java/processing/core/PStyle.java +63 -0
  60. data/lib/java/processing/core/PSurface.java +198 -0
  61. data/lib/java/processing/core/PSurfaceNone.java +431 -0
  62. data/lib/java/processing/core/PVector.java +1066 -0
  63. data/lib/java/processing/core/ThinkDifferent.java +115 -0
  64. data/lib/java/processing/data/DoubleDict.java +850 -0
  65. data/lib/java/processing/data/DoubleList.java +928 -0
  66. data/lib/java/processing/data/FloatDict.java +847 -0
  67. data/lib/java/processing/data/FloatList.java +936 -0
  68. data/lib/java/processing/data/IntDict.java +807 -0
  69. data/lib/java/processing/data/IntList.java +936 -0
  70. data/lib/java/processing/data/JSONArray.java +1260 -0
  71. data/lib/java/processing/data/JSONObject.java +2282 -0
  72. data/lib/java/processing/data/JSONTokener.java +435 -0
  73. data/lib/java/processing/data/LongDict.java +802 -0
  74. data/lib/java/processing/data/LongList.java +937 -0
  75. data/lib/java/processing/data/Sort.java +46 -0
  76. data/lib/java/processing/data/StringDict.java +613 -0
  77. data/lib/java/processing/data/StringList.java +800 -0
  78. data/lib/java/processing/data/Table.java +4936 -0
  79. data/lib/java/processing/data/TableRow.java +198 -0
  80. data/lib/java/processing/data/XML.java +1156 -0
  81. data/lib/java/processing/dxf/RawDXF.java +404 -0
  82. data/lib/java/processing/event/Event.java +125 -0
  83. data/lib/java/processing/event/KeyEvent.java +70 -0
  84. data/lib/java/processing/event/MouseEvent.java +114 -0
  85. data/lib/java/processing/event/TouchEvent.java +57 -0
  86. data/lib/java/processing/javafx/PGraphicsFX2D.java +32 -0
  87. data/lib/java/processing/javafx/PSurfaceFX.java +173 -0
  88. data/lib/java/processing/net/Client.java +744 -0
  89. data/lib/java/processing/net/Server.java +388 -0
  90. data/lib/java/processing/opengl/FontTexture.java +378 -0
  91. data/lib/java/processing/opengl/FrameBuffer.java +513 -0
  92. data/lib/java/processing/opengl/LinePath.java +627 -0
  93. data/lib/java/processing/opengl/LineStroker.java +681 -0
  94. data/lib/java/processing/opengl/PGL.java +3483 -0
  95. data/lib/java/processing/opengl/PGraphics2D.java +615 -0
  96. data/lib/java/processing/opengl/PGraphics3D.java +281 -0
  97. data/lib/java/processing/opengl/PGraphicsOpenGL.java +13753 -0
  98. data/lib/java/processing/opengl/PJOGL.java +2008 -0
  99. data/lib/java/processing/opengl/PShader.java +1484 -0
  100. data/lib/java/processing/opengl/PShapeOpenGL.java +5269 -0
  101. data/lib/java/processing/opengl/PSurfaceJOGL.java +1385 -0
  102. data/lib/java/processing/opengl/Texture.java +1696 -0
  103. data/lib/java/processing/opengl/VertexBuffer.java +88 -0
  104. data/lib/java/processing/opengl/cursors/arrow.png +0 -0
  105. data/lib/java/processing/opengl/cursors/cross.png +0 -0
  106. data/lib/java/processing/opengl/cursors/hand.png +0 -0
  107. data/lib/java/processing/opengl/cursors/license.txt +27 -0
  108. data/lib/java/processing/opengl/cursors/move.png +0 -0
  109. data/lib/java/processing/opengl/cursors/text.png +0 -0
  110. data/lib/java/processing/opengl/cursors/wait.png +0 -0
  111. data/lib/java/processing/opengl/shaders/ColorFrag.glsl +32 -0
  112. data/lib/java/processing/opengl/shaders/ColorVert.glsl +34 -0
  113. data/lib/java/processing/opengl/shaders/LightFrag.glsl +33 -0
  114. data/lib/java/processing/opengl/shaders/LightVert.glsl +151 -0
  115. data/lib/java/processing/opengl/shaders/LineFrag.glsl +32 -0
  116. data/lib/java/processing/opengl/shaders/LineVert.glsl +100 -0
  117. data/lib/java/processing/opengl/shaders/MaskFrag.glsl +40 -0
  118. data/lib/java/processing/opengl/shaders/PointFrag.glsl +32 -0
  119. data/lib/java/processing/opengl/shaders/PointVert.glsl +56 -0
  120. data/lib/java/processing/opengl/shaders/TexFrag.glsl +37 -0
  121. data/lib/java/processing/opengl/shaders/TexLightFrag.glsl +37 -0
  122. data/lib/java/processing/opengl/shaders/TexLightVert.glsl +157 -0
  123. data/lib/java/processing/opengl/shaders/TexVert.glsl +38 -0
  124. data/lib/java/processing/pdf/PGraphicsPDF.java +581 -0
  125. data/lib/java/processing/svg/PGraphicsSVG.java +378 -0
  126. data/lib/propane/app.rb +8 -13
  127. data/lib/propane/version.rb +1 -1
  128. data/mvnw +3 -3
  129. data/mvnw.cmd +2 -2
  130. data/pom.rb +7 -2
  131. data/pom.xml +14 -2
  132. data/propane.gemspec +2 -2
  133. data/src/main/java/monkstone/FastNoiseModuleJava.java +127 -0
  134. data/src/main/java/monkstone/MathToolModule.java +30 -30
  135. data/src/main/java/monkstone/PropaneLibrary.java +2 -0
  136. data/src/main/java/monkstone/SmoothNoiseModuleJava.java +127 -0
  137. data/src/main/java/monkstone/fastmath/DegLutTables.java +15 -15
  138. data/src/main/java/monkstone/filechooser/Chooser.java +1 -1
  139. data/src/main/java/monkstone/noise/OpenSimplex2F.java +752 -820
  140. data/src/main/java/monkstone/noise/OpenSimplex2S.java +1138 -1106
  141. data/src/main/java/monkstone/slider/WheelHandler.java +1 -1
  142. data/src/main/java/monkstone/vecmath/JRender.java +6 -6
  143. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +20 -19
  144. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +12 -12
  145. data/src/main/java/processing/awt/PGraphicsJava2D.java +11 -3
  146. data/src/main/java/processing/core/PApplet.java +89 -89
  147. data/src/main/java/processing/core/PConstants.java +155 -163
  148. data/src/main/java/processing/opengl/PJOGL.java +6 -5
  149. data/vendors/Rakefile +1 -1
  150. metadata +136 -19
@@ -0,0 +1,377 @@
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) 2015 The Processing Foundation
7
+
8
+ This library is free software; you can redistribute it and/or
9
+ modify it under the terms of the GNU Lesser General Public
10
+ License version 2.1 as published by the Free Software Foundation.
11
+
12
+ This library is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General
18
+ Public License along with this library; if not, write to the
19
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20
+ Boston, MA 02111-1307 USA
21
+ */
22
+
23
+ package processing.awt;
24
+
25
+ import java.awt.Graphics2D;
26
+ import java.awt.Image;
27
+ import java.awt.RenderingHints;
28
+ import java.awt.Transparency;
29
+ import java.awt.image.BufferedImage;
30
+ import java.awt.image.DataBuffer;
31
+ import java.awt.image.DataBufferInt;
32
+ import java.awt.image.PixelGrabber;
33
+ import java.awt.image.WritableRaster;
34
+ import java.io.BufferedOutputStream;
35
+ import java.io.File;
36
+ import java.io.IOException;
37
+ import java.util.Iterator;
38
+
39
+ import javax.imageio.IIOImage;
40
+ import javax.imageio.ImageIO;
41
+ import javax.imageio.ImageTypeSpecifier;
42
+ import javax.imageio.ImageWriteParam;
43
+ import javax.imageio.ImageWriter;
44
+ import javax.imageio.metadata.IIOInvalidTreeException;
45
+ import javax.imageio.metadata.IIOMetadata;
46
+ import javax.imageio.metadata.IIOMetadataNode;
47
+
48
+ import processing.core.PApplet;
49
+ import processing.core.PImage;
50
+
51
+
52
+ public class PImageAWT extends PImage {
53
+
54
+ /**
55
+ * Construct a new PImage from a java.awt.Image. This constructor assumes
56
+ * that you've done the work of making sure a MediaTracker has been used
57
+ * to fully download the data and that the img is valid.
58
+ *
59
+ * @nowebref
60
+ * @param img assumes a MediaTracker has been used to fully download
61
+ * the data and the img is valid
62
+ */
63
+ public PImageAWT(Image img) {
64
+ format = RGB;
65
+ if (img instanceof BufferedImage) {
66
+ BufferedImage bi = (BufferedImage) img;
67
+ width = bi.getWidth();
68
+ height = bi.getHeight();
69
+ int type = bi.getType();
70
+ if (type == BufferedImage.TYPE_3BYTE_BGR ||
71
+ type == BufferedImage.TYPE_4BYTE_ABGR) {
72
+ pixels = new int[width * height];
73
+ bi.getRGB(0, 0, width, height, pixels, 0, width);
74
+ if (type == BufferedImage.TYPE_4BYTE_ABGR) {
75
+ format = ARGB;
76
+ } else {
77
+ opaque();
78
+ }
79
+ } else {
80
+ DataBuffer db = bi.getRaster().getDataBuffer();
81
+ if (db instanceof DataBufferInt) {
82
+ pixels = ((DataBufferInt) db).getData();
83
+ if (type == BufferedImage.TYPE_INT_ARGB) {
84
+ format = ARGB;
85
+ } else if (type == BufferedImage.TYPE_INT_RGB) {
86
+ opaque();
87
+ }
88
+ }
89
+ }
90
+ }
91
+ // Implements fall-through if not DataBufferInt above, or not a
92
+ // known type, or not DataBufferInt for the data itself.
93
+ if (pixels == null) { // go the old school Java 1.0 route
94
+ width = img.getWidth(null);
95
+ height = img.getHeight(null);
96
+ pixels = new int[width * height];
97
+ PixelGrabber pg =
98
+ new PixelGrabber(img, 0, 0, width, height, pixels, 0, width);
99
+ try {
100
+ pg.grabPixels();
101
+ } catch (InterruptedException e) { }
102
+ }
103
+ pixelDensity = 1;
104
+ pixelWidth = width;
105
+ pixelHeight = height;
106
+ }
107
+
108
+
109
+ /**
110
+ * Use the getNative() method instead, which allows library interfaces to be
111
+ * written in a cross-platform fashion for desktop, Android, and others.
112
+ * This is still included for PGraphics objects, which may need the image.
113
+ */
114
+ public Image getImage() { // ignore
115
+ return (Image) getNative();
116
+ }
117
+
118
+
119
+ /**
120
+ * Returns a native BufferedImage from this PImage.
121
+ */
122
+ @Override
123
+ public Object getNative() { // ignore
124
+ loadPixels();
125
+ int type = (format == RGB) ?
126
+ BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
127
+ BufferedImage image = new BufferedImage(pixelWidth, pixelHeight, type);
128
+ WritableRaster wr = image.getRaster();
129
+ wr.setDataElements(0, 0, pixelWidth, pixelHeight, pixels);
130
+ return image;
131
+ }
132
+
133
+
134
+ @Override
135
+ public void resize(int w, int h) { // ignore
136
+ if (w <= 0 && h <= 0) {
137
+ throw new IllegalArgumentException("width or height must be > 0 for resize");
138
+ }
139
+
140
+ if (w == 0) { // Use height to determine relative size
141
+ float diff = (float) h / (float) height;
142
+ w = (int) (width * diff);
143
+ } else if (h == 0) { // Use the width to determine relative size
144
+ float diff = (float) w / (float) width;
145
+ h = (int) (height * diff);
146
+ }
147
+
148
+ BufferedImage img =
149
+ shrinkImage((BufferedImage) getNative(), w*pixelDensity, h*pixelDensity);
150
+
151
+ PImage temp = new PImageAWT(img);
152
+ this.pixelWidth = temp.width;
153
+ this.pixelHeight = temp.height;
154
+
155
+ // Get the resized pixel array
156
+ this.pixels = temp.pixels;
157
+
158
+ this.width = pixelWidth / pixelDensity;
159
+ this.height = pixelHeight / pixelDensity;
160
+
161
+ // Mark the pixels array as altered
162
+ updatePixels();
163
+ }
164
+
165
+
166
+ // Adapted from getFasterScaledInstance() method from page 111 of
167
+ // "Filthy Rich Clients" by Chet Haase and Romain Guy
168
+ // Additional modifications and simplifications have been added,
169
+ // plus a fix to deal with an infinite loop if images are expanded.
170
+ // http://code.google.com/p/processing/issues/detail?id=1463
171
+ static private BufferedImage shrinkImage(BufferedImage img,
172
+ int targetWidth, int targetHeight) {
173
+ int type = (img.getTransparency() == Transparency.OPAQUE) ?
174
+ BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
175
+ BufferedImage outgoing = img;
176
+ BufferedImage scratchImage = null;
177
+ Graphics2D g2 = null;
178
+ int prevW = outgoing.getWidth();
179
+ int prevH = outgoing.getHeight();
180
+ boolean isTranslucent = img.getTransparency() != Transparency.OPAQUE;
181
+
182
+ // Use multi-step technique: start with original size, then scale down in
183
+ // multiple passes with drawImage() until the target size is reached
184
+ int w = img.getWidth();
185
+ int h = img.getHeight();
186
+
187
+ do {
188
+ if (w > targetWidth) {
189
+ w /= 2;
190
+ // if this is the last step, do the exact size
191
+ if (w < targetWidth) {
192
+ w = targetWidth;
193
+ }
194
+ } else if (targetWidth >= w) {
195
+ w = targetWidth;
196
+ }
197
+ if (h > targetHeight) {
198
+ h /= 2;
199
+ if (h < targetHeight) {
200
+ h = targetHeight;
201
+ }
202
+ } else if (targetHeight >= h) {
203
+ h = targetHeight;
204
+ }
205
+ if (scratchImage == null || isTranslucent) {
206
+ // Use a single scratch buffer for all iterations and then copy
207
+ // to the final, correctly-sized image before returning
208
+ scratchImage = new BufferedImage(w, h, type);
209
+ g2 = scratchImage.createGraphics();
210
+ }
211
+ g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
212
+ RenderingHints.VALUE_INTERPOLATION_BILINEAR);
213
+ g2.drawImage(outgoing, 0, 0, w, h, 0, 0, prevW, prevH, null);
214
+ prevW = w;
215
+ prevH = h;
216
+ outgoing = scratchImage;
217
+ } while (w != targetWidth || h != targetHeight);
218
+ g2.dispose();
219
+
220
+
221
+ // If we used a scratch buffer that is larger than our target size,
222
+ // create an image of the right size and copy the results into it
223
+ if (targetWidth != outgoing.getWidth() ||
224
+ targetHeight != outgoing.getHeight()) {
225
+ scratchImage = new BufferedImage(targetWidth, targetHeight, type);
226
+ g2 = scratchImage.createGraphics();
227
+ g2.drawImage(outgoing, 0, 0, null);
228
+ g2.dispose();
229
+ outgoing = scratchImage;
230
+ }
231
+ return outgoing;
232
+ }
233
+
234
+
235
+ @Override
236
+ protected boolean saveImpl(String filename) {
237
+ if (saveImageFormats == null) {
238
+ saveImageFormats = javax.imageio.ImageIO.getWriterFormatNames();
239
+ }
240
+ try {
241
+ if (saveImageFormats != null) {
242
+ for (String saveImageFormat : saveImageFormats) {
243
+ if (filename.endsWith("." + saveImageFormat)) {
244
+ if (!saveImageIO(filename)) {
245
+ System.err.println("Error while saving image.");
246
+ return false;
247
+ }
248
+ return true;
249
+ }
250
+ }
251
+ }
252
+ } catch (IOException e) {
253
+ }
254
+ return false;
255
+ }
256
+
257
+
258
+ protected String[] saveImageFormats;
259
+
260
+
261
+ /**
262
+ * Use ImageIO functions from Java 1.4 and later to handle image save.
263
+ * Various formats are supported, typically jpeg, png, bmp, and wbmp.
264
+ * To get a list of the supported formats for writing, use: <BR>
265
+ * <TT>println(javax.imageio.ImageIO.getReaderFormatNames())</TT>
266
+ *
267
+ * @path The path to which the file should be written.
268
+ */
269
+ protected boolean saveImageIO(String path) throws IOException {
270
+ try {
271
+ int outputFormat = (format == ARGB) ?
272
+ BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB;
273
+
274
+ String extension =
275
+ path.substring(path.lastIndexOf('.') + 1).toLowerCase();
276
+
277
+ // JPEG and BMP images that have an alpha channel set get pretty unhappy.
278
+ // BMP just doesn't write, and JPEG writes it as a CMYK image.
279
+ // http://code.google.com/p/processing/issues/detail?id=415
280
+ if (extension.equals("bmp") || extension.equals("jpg") || extension.equals("jpeg")) {
281
+ outputFormat = BufferedImage.TYPE_INT_RGB;
282
+ }
283
+
284
+ BufferedImage bimage = new BufferedImage(pixelWidth, pixelHeight, outputFormat);
285
+ bimage.setRGB(0, 0, pixelWidth, pixelHeight, pixels, 0, pixelWidth);
286
+
287
+ File file = new File(path);
288
+
289
+ ImageWriter writer = null;
290
+ ImageWriteParam param = null;
291
+ IIOMetadata metadata = null;
292
+
293
+ if (extension.equals("jpg") || extension.equals("jpeg")) {
294
+ if ((writer = imageioWriter("jpeg")) != null) {
295
+ // Set JPEG quality to 90% with baseline optimization. Setting this
296
+ // to 1 was a huge jump (about triple the size), so this seems good.
297
+ // Oddly, a smaller file size than Photoshop at 90%, but I suppose
298
+ // it's a completely different algorithm.
299
+ param = writer.getDefaultWriteParam();
300
+ param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
301
+ param.setCompressionQuality(0.9f);
302
+ }
303
+ }
304
+
305
+ if (extension.equals("png")) {
306
+ if ((writer = imageioWriter("png")) != null) {
307
+ param = writer.getDefaultWriteParam();
308
+ if (false) {
309
+ metadata = imageioDPI(writer, param, 100);
310
+ }
311
+ }
312
+ }
313
+
314
+ if (writer != null) {
315
+ try (BufferedOutputStream output = new BufferedOutputStream(PApplet.createOutput(file))) {
316
+ writer.setOutput(ImageIO.createImageOutputStream(output));
317
+ // writer.write(null, new IIOImage(bimage, null, null), param);
318
+ writer.write(metadata, new IIOImage(bimage, null, metadata), param);
319
+ writer.dispose();
320
+
321
+ output.flush();
322
+ }
323
+ return true;
324
+ }
325
+ // If iter.hasNext() somehow fails up top, it falls through to here
326
+ return javax.imageio.ImageIO.write(bimage, extension, file);
327
+
328
+ } catch (IOException e) {
329
+ throw new IOException("image save failed.");
330
+ }
331
+ }
332
+
333
+
334
+ private ImageWriter imageioWriter(String extension) {
335
+ Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName(extension);
336
+ if (iter.hasNext()) {
337
+ return iter.next();
338
+ }
339
+ return null;
340
+ }
341
+
342
+
343
+ private IIOMetadata imageioDPI(ImageWriter writer, ImageWriteParam param, double dpi) {
344
+ // http://stackoverflow.com/questions/321736/how-to-set-dpi-information-in-an-image
345
+ ImageTypeSpecifier typeSpecifier =
346
+ ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
347
+ IIOMetadata metadata =
348
+ writer.getDefaultImageMetadata(typeSpecifier, param);
349
+
350
+ if (!metadata.isReadOnly() && metadata.isStandardMetadataFormatSupported()) {
351
+ // for PNG, it's dots per millimeter
352
+ double dotsPerMilli = dpi / 25.4;
353
+
354
+ IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize");
355
+ horiz.setAttribute("value", Double.toString(dotsPerMilli));
356
+
357
+ IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize");
358
+ vert.setAttribute("value", Double.toString(dotsPerMilli));
359
+
360
+ IIOMetadataNode dim = new IIOMetadataNode("Dimension");
361
+ dim.appendChild(horiz);
362
+ dim.appendChild(vert);
363
+
364
+ IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0");
365
+ root.appendChild(dim);
366
+
367
+ try {
368
+ metadata.mergeTree("javax_imageio_1.0", root);
369
+ return metadata;
370
+
371
+ } catch (IIOInvalidTreeException e) {
372
+ System.err.println("Could not set the DPI of the output image");
373
+ }
374
+ }
375
+ return null;
376
+ }
377
+ }
@@ -0,0 +1,387 @@
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) 2015 The Processing Foundation
7
+
8
+ This library is free software; you can redistribute it and/or
9
+ modify it under the terms of the GNU Lesser General Public
10
+ License version 2.1 as published by the Free Software Foundation.
11
+
12
+ This library is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General
18
+ Public License along with this library; if not, write to the
19
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20
+ Boston, MA 02111-1307 USA
21
+ */
22
+
23
+ package processing.awt;
24
+
25
+ import java.awt.Paint;
26
+ import java.awt.PaintContext;
27
+ import java.awt.Rectangle;
28
+ import java.awt.RenderingHints;
29
+ import java.awt.geom.AffineTransform;
30
+ import java.awt.geom.Point2D;
31
+ import java.awt.geom.Rectangle2D;
32
+ import java.awt.image.ColorModel;
33
+ import java.awt.image.Raster;
34
+ import java.awt.image.WritableRaster;
35
+
36
+ import processing.core.PApplet;
37
+ import processing.core.PGraphics;
38
+ import processing.core.PShapeSVG;
39
+ import processing.data.*;
40
+
41
+
42
+ /**
43
+ * Implements features for PShape that are specific to AWT and Java2D.
44
+ * At the moment, this is gradients and java.awt.Paint handling.
45
+ */
46
+ public class PShapeJava2D extends PShapeSVG {
47
+ Paint strokeGradientPaint;
48
+ Paint fillGradientPaint;
49
+
50
+
51
+ public PShapeJava2D(XML svg) {
52
+ super(svg);
53
+ }
54
+
55
+
56
+ public PShapeJava2D(PShapeSVG parent, XML properties, boolean parseKids) {
57
+ super(parent, properties, parseKids);
58
+ }
59
+
60
+
61
+ @Override
62
+ protected void setParent(PShapeSVG parent) {
63
+ super.setParent(parent);
64
+
65
+ if (parent instanceof PShapeJava2D) {
66
+ PShapeJava2D pj = (PShapeJava2D) parent;
67
+ fillGradientPaint = pj.fillGradientPaint;
68
+ strokeGradientPaint = pj.strokeGradientPaint;
69
+
70
+ } else { // parent is null or not Java2D
71
+ fillGradientPaint = null;
72
+ strokeGradientPaint = null;
73
+ }
74
+ }
75
+
76
+
77
+ /** Factory method for subclasses. */
78
+ @Override
79
+ protected PShapeSVG createShape(PShapeSVG parent, XML properties, boolean parseKids) {
80
+ return new PShapeJava2D(parent, properties, parseKids);
81
+ }
82
+
83
+
84
+ /*
85
+ @Override
86
+ public void setColor(String colorText, boolean isFill) {
87
+ super.setColor(colorText, isFill);
88
+
89
+ if (fillGradient != null) {
90
+ fillGradientPaint = calcGradientPaint(fillGradient);
91
+ }
92
+ if (strokeGradient != null) {
93
+ strokeGradientPaint = calcGradientPaint(strokeGradient);
94
+ }
95
+ }
96
+ */
97
+
98
+
99
+ static class LinearGradientPaint implements Paint {
100
+ float x1, y1, x2, y2;
101
+ float[] offset;
102
+ int[] color;
103
+ int count;
104
+ float opacity;
105
+
106
+ public LinearGradientPaint(float x1, float y1, float x2, float y2,
107
+ float[] offset, int[] color, int count,
108
+ float opacity) {
109
+ this.x1 = x1;
110
+ this.y1 = y1;
111
+ this.x2 = x2;
112
+ this.y2 = y2;
113
+ this.offset = offset;
114
+ this.color = color;
115
+ this.count = count;
116
+ this.opacity = opacity;
117
+ }
118
+
119
+ @Override
120
+ public PaintContext createContext(ColorModel cm,
121
+ Rectangle deviceBounds, Rectangle2D userBounds,
122
+ AffineTransform xform, RenderingHints hints) {
123
+ Point2D t1 = xform.transform(new Point2D.Float(x1, y1), null);
124
+ Point2D t2 = xform.transform(new Point2D.Float(x2, y2), null);
125
+ return new LinearGradientContext((float) t1.getX(), (float) t1.getY(),
126
+ (float) t2.getX(), (float) t2.getY());
127
+ }
128
+
129
+ @Override
130
+ public int getTransparency() {
131
+ return TRANSLUCENT; // why not.. rather than checking each color
132
+ }
133
+
134
+ public class LinearGradientContext implements PaintContext {
135
+ int ACCURACY = 2;
136
+ float tx1, ty1, tx2, ty2;
137
+
138
+ public LinearGradientContext(float tx1, float ty1, float tx2, float ty2) {
139
+ this.tx1 = tx1;
140
+ this.ty1 = ty1;
141
+ this.tx2 = tx2;
142
+ this.ty2 = ty2;
143
+ }
144
+
145
+ @Override
146
+ public void dispose() { }
147
+
148
+ @Override
149
+ public ColorModel getColorModel() { return ColorModel.getRGBdefault(); }
150
+
151
+ @Override
152
+ public Raster getRaster(int x, int y, int w, int h) {
153
+ WritableRaster raster =
154
+ getColorModel().createCompatibleWritableRaster(w, h);
155
+
156
+ int[] data = new int[w * h * 4];
157
+
158
+ // make normalized version of base vector
159
+ float nx = tx2 - tx1;
160
+ float ny = ty2 - ty1;
161
+ float len = (float) Math.sqrt(nx*nx + ny*ny);
162
+ if (len != 0) {
163
+ nx /= len;
164
+ ny /= len;
165
+ }
166
+
167
+ int span = (int) PApplet.dist(tx1, ty1, tx2, ty2) * ACCURACY;
168
+ if (span <= 0) {
169
+ //System.err.println("span is too small");
170
+ // annoying edge case where the gradient isn't legit
171
+ int index = 0;
172
+ for (int j = 0; j < h; j++) {
173
+ for (int i = 0; i < w; i++) {
174
+ data[index++] = 0;
175
+ data[index++] = 0;
176
+ data[index++] = 0;
177
+ data[index++] = 255;
178
+ }
179
+ }
180
+
181
+ } else {
182
+ int[][] interp = new int[span][4];
183
+ int prev = 0;
184
+ for (int i = 1; i < count; i++) {
185
+ int c0 = color[i-1];
186
+ int c1 = color[i];
187
+ int last = (int) (offset[i] * (span-1));
188
+ //System.out.println("last is " + last);
189
+ for (int j = prev; j <= last; j++) {
190
+ float btwn = PApplet.norm(j, prev, last);
191
+ interp[j][0] = (int) PApplet.lerp((c0 >> 16) & 0xff, (c1 >> 16) & 0xff, btwn);
192
+ interp[j][1] = (int) PApplet.lerp((c0 >> 8) & 0xff, (c1 >> 8) & 0xff, btwn);
193
+ interp[j][2] = (int) PApplet.lerp(c0 & 0xff, c1 & 0xff, btwn);
194
+ interp[j][3] = (int) (PApplet.lerp((c0 >> 24) & 0xff, (c1 >> 24) & 0xff, btwn) * opacity);
195
+ //System.out.println(j + " " + interp[j][0] + " " + interp[j][1] + " " + interp[j][2]);
196
+ }
197
+ prev = last;
198
+ }
199
+
200
+ int index = 0;
201
+ for (int j = 0; j < h; j++) {
202
+ for (int i = 0; i < w; i++) {
203
+ //float distance = 0; //PApplet.dist(cx, cy, x + i, y + j);
204
+ //int which = PApplet.min((int) (distance * ACCURACY), interp.length-1);
205
+ float px = (x + i) - tx1;
206
+ float py = (y + j) - ty1;
207
+ // distance up the line is the dot product of the normalized
208
+ // vector of the gradient start/stop by the point being tested
209
+ int which = (int) ((px*nx + py*ny) * ACCURACY);
210
+ if (which < 0) which = 0;
211
+ if (which > interp.length-1) which = interp.length-1;
212
+ //if (which > 138) System.out.println("grabbing " + which);
213
+
214
+ data[index++] = interp[which][0];
215
+ data[index++] = interp[which][1];
216
+ data[index++] = interp[which][2];
217
+ data[index++] = interp[which][3];
218
+ }
219
+ }
220
+ }
221
+ raster.setPixels(0, 0, w, h, data);
222
+
223
+ return raster;
224
+ }
225
+ }
226
+ }
227
+
228
+
229
+ static class RadialGradientPaint implements Paint {
230
+ float cx, cy, radius;
231
+ float[] offset;
232
+ int[] color;
233
+ int count;
234
+ float opacity;
235
+
236
+ public RadialGradientPaint(float cx, float cy, float radius,
237
+ float[] offset, int[] color, int count,
238
+ float opacity) {
239
+ this.cx = cx;
240
+ this.cy = cy;
241
+ this.radius = radius;
242
+ this.offset = offset;
243
+ this.color = color;
244
+ this.count = count;
245
+ this.opacity = opacity;
246
+ }
247
+
248
+ @Override
249
+ public PaintContext createContext(ColorModel cm,
250
+ Rectangle deviceBounds, Rectangle2D userBounds,
251
+ AffineTransform xform, RenderingHints hints) {
252
+ return new RadialGradientContext();
253
+ }
254
+
255
+ @Override
256
+ public int getTransparency() {
257
+ return TRANSLUCENT;
258
+ }
259
+
260
+ public class RadialGradientContext implements PaintContext {
261
+ int ACCURACY = 5;
262
+
263
+ @Override
264
+ public void dispose() {}
265
+
266
+ @Override
267
+ public ColorModel getColorModel() { return ColorModel.getRGBdefault(); }
268
+
269
+ @Override
270
+ public Raster getRaster(int x, int y, int w, int h) {
271
+ WritableRaster raster =
272
+ getColorModel().createCompatibleWritableRaster(w, h);
273
+
274
+ int span = (int) radius * ACCURACY;
275
+ int[][] interp = new int[span][4];
276
+ int prev = 0;
277
+ for (int i = 1; i < count; i++) {
278
+ int c0 = color[i-1];
279
+ int c1 = color[i];
280
+ int last = (int) (offset[i] * (span - 1));
281
+ for (int j = prev; j <= last; j++) {
282
+ float btwn = PApplet.norm(j, prev, last);
283
+ interp[j][0] = (int) PApplet.lerp((c0 >> 16) & 0xff, (c1 >> 16) & 0xff, btwn);
284
+ interp[j][1] = (int) PApplet.lerp((c0 >> 8) & 0xff, (c1 >> 8) & 0xff, btwn);
285
+ interp[j][2] = (int) PApplet.lerp(c0 & 0xff, c1 & 0xff, btwn);
286
+ interp[j][3] = (int) (PApplet.lerp((c0 >> 24) & 0xff, (c1 >> 24) & 0xff, btwn) * opacity);
287
+ }
288
+ prev = last;
289
+ }
290
+
291
+ int[] data = new int[w * h * 4];
292
+ int index = 0;
293
+ for (int j = 0; j < h; j++) {
294
+ for (int i = 0; i < w; i++) {
295
+ float distance = PApplet.dist(cx, cy, x + i, y + j);
296
+ int which = PApplet.min((int) (distance * ACCURACY), interp.length-1);
297
+
298
+ data[index++] = interp[which][0];
299
+ data[index++] = interp[which][1];
300
+ data[index++] = interp[which][2];
301
+ data[index++] = interp[which][3];
302
+ }
303
+ }
304
+ raster.setPixels(0, 0, w, h, data);
305
+
306
+ return raster;
307
+ }
308
+ }
309
+ }
310
+
311
+
312
+ protected Paint calcGradientPaint(Gradient gradient) {
313
+ if (gradient instanceof LinearGradient) {
314
+ // System.out.println("creating linear gradient");
315
+ LinearGradient grad = (LinearGradient) gradient;
316
+ return new LinearGradientPaint(grad.x1, grad.y1, grad.x2, grad.y2,
317
+ grad.offset, grad.color, grad.count,
318
+ opacity);
319
+
320
+ } else if (gradient instanceof RadialGradient) {
321
+ // System.out.println("creating radial gradient");
322
+ RadialGradient grad = (RadialGradient) gradient;
323
+ return new RadialGradientPaint(grad.cx, grad.cy, grad.r,
324
+ grad.offset, grad.color, grad.count,
325
+ opacity);
326
+ }
327
+ return null;
328
+ }
329
+
330
+
331
+ // protected Paint calcGradientPaint(Gradient gradient,
332
+ // float x1, float y1, float x2, float y2) {
333
+ // if (gradient instanceof LinearGradient) {
334
+ // LinearGradient grad = (LinearGradient) gradient;
335
+ // return new LinearGradientPaint(x1, y1, x2, y2,
336
+ // grad.offset, grad.color, grad.count,
337
+ // opacity);
338
+ // }
339
+ // throw new RuntimeException("Not a linear gradient.");
340
+ // }
341
+
342
+
343
+ // protected Paint calcGradientPaint(Gradient gradient,
344
+ // float cx, float cy, float r) {
345
+ // if (gradient instanceof RadialGradient) {
346
+ // RadialGradient grad = (RadialGradient) gradient;
347
+ // return new RadialGradientPaint(cx, cy, r,
348
+ // grad.offset, grad.color, grad.count,
349
+ // opacity);
350
+ // }
351
+ // throw new RuntimeException("Not a radial gradient.");
352
+ // }
353
+
354
+
355
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
356
+
357
+
358
+ @Override
359
+ protected void styles(PGraphics g) {
360
+ super.styles(g);
361
+
362
+ //if (g instanceof PGraphicsJava2D) {
363
+ PGraphicsJava2D p2d = (PGraphicsJava2D) g;
364
+
365
+ if (strokeGradient != null) {
366
+ p2d.strokeGradient = true;
367
+ if (strokeGradientPaint == null) {
368
+ strokeGradientPaint = calcGradientPaint(strokeGradient);
369
+ }
370
+ p2d.strokeGradientObject = strokeGradientPaint;
371
+ } else {
372
+ // need to shut off, in case parent object has a gradient applied
373
+ //p2d.strokeGradient = false;
374
+ }
375
+ if (fillGradient != null) {
376
+ p2d.fillGradient = true;
377
+ if (fillGradientPaint == null) {
378
+ fillGradientPaint = calcGradientPaint(fillGradient);
379
+ }
380
+ p2d.fillGradientObject = fillGradientPaint;
381
+ } else {
382
+ // need to shut off, in case parent object has a gradient applied
383
+ //p2d.fillGradient = false;
384
+ }
385
+ //}
386
+ }
387
+ }