propane 3.3.1-java → 3.6.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. checksums.yaml +4 -4
  2. data/.mvn/extensions.xml +1 -2
  3. data/.mvn/wrapper/MavenWrapperDownloader.java +117 -0
  4. data/.mvn/wrapper/maven-wrapper.properties +2 -3
  5. data/.travis.yml +9 -0
  6. data/CHANGELOG.md +17 -5
  7. data/Gemfile +2 -0
  8. data/README.md +17 -8
  9. data/Rakefile +16 -30
  10. data/bin/propane +3 -1
  11. data/lib/propane.rb +6 -4
  12. data/lib/propane/app.rb +20 -10
  13. data/lib/propane/creators/sketch_class.rb +7 -1
  14. data/lib/propane/creators/sketch_factory.rb +4 -2
  15. data/lib/propane/creators/sketch_writer.rb +1 -0
  16. data/lib/propane/helper_methods.rb +23 -24
  17. data/lib/propane/helpers/numeric.rb +2 -0
  18. data/lib/propane/helpers/version_error.rb +1 -0
  19. data/lib/propane/library.rb +5 -1
  20. data/lib/propane/library_loader.rb +2 -0
  21. data/lib/propane/native_folder.rb +21 -15
  22. data/lib/propane/native_loader.rb +3 -0
  23. data/lib/propane/runner.rb +14 -6
  24. data/lib/propane/version.rb +2 -1
  25. data/library/boids/boids.rb +21 -11
  26. data/library/color_group/color_group.rb +28 -0
  27. data/library/control_panel/control_panel.rb +8 -5
  28. data/library/dxf/dxf.rb +6 -0
  29. data/library/file_chooser/chooser.rb +10 -9
  30. data/library/file_chooser/file_chooser.rb +10 -9
  31. data/library/library_proxy/library_proxy.rb +2 -0
  32. data/library/net/net.rb +7 -0
  33. data/library/simplex_noise/simplex_noise.rb +2 -0
  34. data/library/slider/slider.rb +23 -22
  35. data/library/vector_utils/vector_utils.rb +4 -0
  36. data/library/video_event/video_event.rb +4 -1
  37. data/mvnw +127 -51
  38. data/mvnw.cmd +182 -145
  39. data/pom.rb +53 -50
  40. data/pom.xml +17 -8
  41. data/propane.gemspec +13 -11
  42. data/src/main/java/monkstone/ColorUtil.java +13 -1
  43. data/src/main/java/monkstone/MathToolModule.java +253 -203
  44. data/src/main/java/monkstone/PropaneLibrary.java +2 -2
  45. data/src/main/java/monkstone/fastmath/Deglut.java +1 -1
  46. data/src/main/java/monkstone/filechooser/Chooser.java +2 -1
  47. data/src/main/java/monkstone/noise/SimplexNoise.java +2 -2
  48. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +1 -1
  49. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
  50. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +1 -1
  51. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +1 -1
  52. data/src/main/java/monkstone/slider/SliderBar.java +1 -1
  53. data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
  54. data/src/main/java/monkstone/slider/WheelHandler.java +7 -6
  55. data/src/main/java/monkstone/vecmath/package-info.java +1 -1
  56. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +2 -2
  57. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -1
  58. data/src/main/java/monkstone/videoevent/CaptureEvent.java +27 -0
  59. data/src/main/java/monkstone/videoevent/{VideoInterface.java → MovieEvent.java} +11 -27
  60. data/src/main/java/monkstone/videoevent/package-info.java +1 -1
  61. data/src/main/java/processing/awt/PGraphicsJava2D.java +2164 -1661
  62. data/src/main/java/processing/awt/PImageAWT.java +377 -0
  63. data/src/main/java/processing/awt/PShapeJava2D.java +280 -268
  64. data/src/main/java/processing/awt/PSurfaceAWT.java +942 -829
  65. data/src/main/java/processing/awt/ShimAWT.java +581 -0
  66. data/src/main/java/processing/core/PApplet.java +831 -824
  67. data/src/main/java/processing/core/PConstants.java +477 -447
  68. data/src/main/java/processing/core/PFont.java +914 -880
  69. data/src/main/java/processing/core/PGraphics.java +229 -213
  70. data/src/main/java/processing/core/PImage.java +620 -318
  71. data/src/main/java/processing/core/PMatrix.java +172 -159
  72. data/src/main/java/processing/core/PMatrix2D.java +478 -409
  73. data/src/main/java/processing/core/PMatrix3D.java +762 -735
  74. data/src/main/java/processing/core/PShape.java +2888 -2652
  75. data/src/main/java/processing/core/PShapeOBJ.java +436 -415
  76. data/src/main/java/processing/core/PShapeSVG.java +1702 -1479
  77. data/src/main/java/processing/core/PStyle.java +40 -37
  78. data/src/main/java/processing/core/PSurface.java +139 -97
  79. data/src/main/java/processing/core/PSurfaceNone.java +296 -208
  80. data/src/main/java/processing/core/PVector.java +997 -965
  81. data/src/main/java/processing/core/ThinkDifferent.java +12 -17
  82. data/src/main/java/processing/data/DoubleDict.java +756 -710
  83. data/src/main/java/processing/data/DoubleList.java +749 -696
  84. data/src/main/java/processing/data/FloatDict.java +748 -702
  85. data/src/main/java/processing/data/FloatList.java +751 -697
  86. data/src/main/java/processing/data/IntDict.java +720 -673
  87. data/src/main/java/processing/data/IntList.java +699 -633
  88. data/src/main/java/processing/data/JSONArray.java +931 -873
  89. data/src/main/java/processing/data/JSONObject.java +1262 -1165
  90. data/src/main/java/processing/data/JSONTokener.java +351 -341
  91. data/src/main/java/processing/data/LongDict.java +710 -663
  92. data/src/main/java/processing/data/LongList.java +701 -635
  93. data/src/main/java/processing/data/Sort.java +37 -41
  94. data/src/main/java/processing/data/StringDict.java +525 -486
  95. data/src/main/java/processing/data/StringList.java +626 -580
  96. data/src/main/java/processing/data/Table.java +3690 -3510
  97. data/src/main/java/processing/data/TableRow.java +182 -183
  98. data/src/main/java/processing/data/XML.java +957 -883
  99. data/src/main/java/processing/dxf/RawDXF.java +404 -0
  100. data/src/main/java/processing/event/Event.java +87 -66
  101. data/src/main/java/processing/event/KeyEvent.java +48 -41
  102. data/src/main/java/processing/event/MouseEvent.java +88 -113
  103. data/src/main/java/processing/event/TouchEvent.java +10 -6
  104. data/src/main/java/processing/javafx/PGraphicsFX2D.java +20 -345
  105. data/src/main/java/processing/javafx/PSurfaceFX.java +149 -121
  106. data/src/main/java/processing/net/Client.java +744 -0
  107. data/src/main/java/processing/net/Server.java +388 -0
  108. data/src/main/java/processing/opengl/FontTexture.java +289 -270
  109. data/src/main/java/processing/opengl/FrameBuffer.java +386 -364
  110. data/src/main/java/processing/opengl/LinePath.java +547 -500
  111. data/src/main/java/processing/opengl/LineStroker.java +588 -581
  112. data/src/main/java/processing/opengl/PGL.java +3047 -2914
  113. data/src/main/java/processing/opengl/PGraphics2D.java +408 -315
  114. data/src/main/java/processing/opengl/PGraphics3D.java +107 -72
  115. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +12378 -12075
  116. data/src/main/java/processing/opengl/PJOGL.java +1753 -1670
  117. data/src/main/java/processing/opengl/PShader.java +1266 -1257
  118. data/src/main/java/processing/opengl/PShapeOpenGL.java +4678 -4580
  119. data/src/main/java/processing/opengl/PSurfaceJOGL.java +1114 -1027
  120. data/src/main/java/processing/opengl/Texture.java +1492 -1401
  121. data/src/main/java/processing/opengl/VertexBuffer.java +57 -55
  122. data/test/create_test.rb +21 -20
  123. data/test/deglut_spec_test.rb +4 -2
  124. data/test/helper_methods_test.rb +49 -20
  125. data/test/math_tool_test.rb +39 -32
  126. data/test/native_folder.rb +47 -0
  127. data/test/respond_to_test.rb +3 -2
  128. data/test/sketches/key_event.rb +2 -2
  129. data/test/sketches/library/my_library/my_library.rb +3 -0
  130. data/test/test_helper.rb +2 -0
  131. data/test/vecmath_spec_test.rb +35 -22
  132. data/vendors/Rakefile +33 -62
  133. metadata +54 -45
  134. data/src/main/java/processing/core/util/image/ImageLoadFacade.java +0 -161
  135. data/src/main/java/processing/core/util/image/ImageSaveFacade.java +0 -169
  136. data/src/main/java/processing/core/util/image/constants/TifConstants.java +0 -45
  137. data/src/main/java/processing/core/util/image/load/AwtImageLoadStrategy.java +0 -80
  138. data/src/main/java/processing/core/util/image/load/Base64StringImageLoadStrategy.java +0 -73
  139. data/src/main/java/processing/core/util/image/load/FallbackImageLoadStrategy.java +0 -70
  140. data/src/main/java/processing/core/util/image/load/ImageIoImageLoadStrategy.java +0 -132
  141. data/src/main/java/processing/core/util/image/load/ImageLoadStrategy.java +0 -48
  142. data/src/main/java/processing/core/util/image/load/ImageLoadUtil.java +0 -45
  143. data/src/main/java/processing/core/util/image/load/TgaImageLoadStrategy.java +0 -255
  144. data/src/main/java/processing/core/util/image/load/TiffImageLoadStrategy.java +0 -98
  145. data/src/main/java/processing/core/util/image/save/ImageSaveStrategy.java +0 -49
  146. data/src/main/java/processing/core/util/image/save/ImageSaveUtil.java +0 -48
  147. data/src/main/java/processing/core/util/image/save/ImageWriterImageSaveStrategy.java +0 -179
  148. data/src/main/java/processing/core/util/image/save/SaveImageException.java +0 -41
  149. data/src/main/java/processing/core/util/image/save/TgaImageSaveStrategy.java +0 -198
  150. data/src/main/java/processing/core/util/image/save/TiffImageSaveStrategy.java +0 -91
  151. data/src/main/java/processing/core/util/image/save/TiffNakedFilenameImageSaveStrategy.java +0 -57
  152. data/src/main/java/processing/core/util/io/InputFactory.java +0 -285
  153. data/src/main/java/processing/core/util/io/PathUtil.java +0 -109
  154. data/src/main/java/processing/opengl/shaders/LightVert-brcm.glsl +0 -154
  155. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +0 -154
  156. data/src/main/java/processing/opengl/shaders/TexLightVert-brcm.glsl +0 -160
  157. data/src/main/java/processing/opengl/shaders/TexLightVert-vc4.glsl +0 -160
@@ -0,0 +1,388 @@
1
+ /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
+
3
+ /*
4
+ Server - basic network server implementation
5
+ Part of the Processing project - http://processing.org
6
+
7
+ Copyright (c) 2004-2007 Ben Fry and Casey Reas
8
+ The previous version of this code was developed by Hernando Barragan
9
+
10
+ This library is free software; you can redistribute it and/or
11
+ modify it under the terms of the GNU Lesser General Public
12
+ License as published by the Free Software Foundation; either
13
+ version 2.1 of the License, or (at your option) any later version.
14
+
15
+ This library is distributed in the hope that it will be useful,
16
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
+ Lesser General Public License for more details.
19
+
20
+ You should have received a copy of the GNU Lesser General
21
+ Public License along with this library; if not, write to the
22
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23
+ Boston, MA 02111-1307 USA
24
+ */
25
+
26
+ package processing.net;
27
+
28
+ import processing.core.*;
29
+
30
+ import java.io.*;
31
+ import java.lang.reflect.*;
32
+ import java.net.*;
33
+
34
+
35
+ /**
36
+ * ( begin auto-generated from Server.xml )
37
+ *
38
+ * A server sends and receives data to and from its associated clients
39
+ * (other programs connected to it). When a server is started, it begins
40
+ * listening for connections on the port specified by the <b>port</b>
41
+ * parameter. Computers have many ports for transferring data and some are
42
+ * commonly used so be sure to not select one of these. For example, web
43
+ * servers usually use port 80 and POP mail uses port 110.
44
+ *
45
+ *
46
+ * @webref net
47
+ * @usage application
48
+ * @brief The server class is used to create server objects which send and receives data to and from its associated clients (other programs connected to it).
49
+ * @instanceName server any variable of type Server
50
+ */
51
+ public class Server implements Runnable {
52
+ PApplet parent;
53
+ Method serverEventMethod;
54
+
55
+ volatile Thread thread;
56
+ ServerSocket server;
57
+ int port;
58
+
59
+ protected final Object clientsLock = new Object[0];
60
+ /** Number of clients currently connected. */
61
+ public int clientCount;
62
+ /** Array of client objects, useful length is determined by clientCount. */
63
+ public Client[] clients;
64
+
65
+
66
+ /**
67
+ * @param parent typically use "this"
68
+ * @param port port used to transfer data
69
+ */
70
+ public Server(PApplet parent, int port) {
71
+ this(parent, port, null);
72
+ }
73
+
74
+
75
+ /**
76
+ * @param parent typically use "this"
77
+ * @param port port used to transfer data
78
+ * @param host when multiple NICs are in use, the ip (or name) to bind from
79
+ */
80
+ public Server(PApplet parent, int port, String host) {
81
+ this.parent = parent;
82
+ this.port = port;
83
+
84
+ try {
85
+ if (host == null) {
86
+ server = new ServerSocket(this.port);
87
+ } else {
88
+ server = new ServerSocket(this.port, 10, InetAddress.getByName(host));
89
+ }
90
+ //clients = new Vector();
91
+ clients = new Client[10];
92
+
93
+ thread = new Thread(this);
94
+ thread.start();
95
+
96
+ parent.registerMethod("dispose", this);
97
+
98
+ // reflection to check whether host applet has a call for
99
+ // public void serverEvent(Server s, Client c);
100
+ // which is called when a new guy connects
101
+ try {
102
+ serverEventMethod =
103
+ parent.getClass().getMethod("serverEvent", Server.class, Client.class);
104
+ } catch (Exception e) {
105
+ // no such method, or an error.. which is fine, just ignore
106
+ }
107
+
108
+ } catch (IOException e) {
109
+ //e.printStackTrace();
110
+ thread = null;
111
+ throw new RuntimeException(e);
112
+ //errorMessage("<init>", e);
113
+ }
114
+ }
115
+
116
+
117
+ /**
118
+ * ( begin auto-generated from Server_disconnect.xml )
119
+ *
120
+ * Disconnect a particular client.
121
+ *
122
+ *
123
+ * @brief Disconnect a particular client.
124
+ * @webref server:server
125
+ * @param client the client to disconnect
126
+ */
127
+ public void disconnect(Client client) {
128
+ client.stop();
129
+ synchronized (clientsLock) {
130
+ int index = clientIndex(client);
131
+ if (index != -1) {
132
+ removeIndex(index);
133
+ }
134
+ }
135
+ }
136
+
137
+
138
+ protected void removeIndex(int index) {
139
+ synchronized (clientsLock) {
140
+ clientCount--;
141
+ // shift down the remaining clients
142
+ for (int i = index; i < clientCount; i++) {
143
+ clients[i] = clients[i + 1];
144
+ }
145
+ // mark last empty var for garbage collection
146
+ clients[clientCount] = null;
147
+ }
148
+ }
149
+
150
+
151
+ protected void disconnectAll() {
152
+ synchronized (clientsLock) {
153
+ for (int i = 0; i < clientCount; i++) {
154
+ try {
155
+ clients[i].stop();
156
+ } catch (Exception e) {
157
+ // ignore
158
+ }
159
+ clients[i] = null;
160
+ }
161
+ clientCount = 0;
162
+ }
163
+ }
164
+
165
+
166
+ protected void addClient(Client client) {
167
+ synchronized (clientsLock) {
168
+ if (clientCount == clients.length) {
169
+ clients = (Client[]) PApplet.expand(clients);
170
+ }
171
+ clients[clientCount++] = client;
172
+ }
173
+ }
174
+
175
+
176
+ protected int clientIndex(Client client) {
177
+ synchronized (clientsLock) {
178
+ for (int i = 0; i < clientCount; i++) {
179
+ if (clients[i] == client) {
180
+ return i;
181
+ }
182
+ }
183
+ return -1;
184
+ }
185
+ }
186
+
187
+
188
+ /**
189
+ * ( begin auto-generated from Server_active.xml )
190
+ *
191
+ * Returns true if this server is still active and hasn't run
192
+ * into any trouble.
193
+ *
194
+ *
195
+ * @webref server:server
196
+ * @brief Return true if this server is still active.
197
+ */
198
+ public boolean active() {
199
+ return thread != null;
200
+ }
201
+
202
+
203
+ static public String ip() {
204
+ try {
205
+ return InetAddress.getLocalHost().getHostAddress();
206
+ } catch (UnknownHostException e) {
207
+
208
+ return null;
209
+ }
210
+ }
211
+
212
+
213
+ // the last index used for available. can't just cycle through
214
+ // the clients in order from 0 each time, because if client 0 won't
215
+ // shut up, then the rest of the clients will never be heard from.
216
+ int lastAvailable = -1;
217
+
218
+ /**
219
+ * ( begin auto-generated from Server_available.xml )
220
+ *
221
+ * Returns the next client in line with a new message.
222
+ *
223
+ *
224
+ * @brief Returns the next client in line with a new message.
225
+ * @webref server
226
+ * @usage application
227
+ */
228
+ public Client available() {
229
+ synchronized (clientsLock) {
230
+ int index = lastAvailable + 1;
231
+ if (index >= clientCount) index = 0;
232
+
233
+ for (int i = 0; i < clientCount; i++) {
234
+ int which = (index + i) % clientCount;
235
+ Client client = clients[which];
236
+ //Check for valid client
237
+ if (!client.active()){
238
+ removeIndex(which); //Remove dead client
239
+ i--; //Don't skip the next client
240
+ //If the client has data make sure lastAvailable
241
+ //doesn't end up skipping the next client
242
+ which--;
243
+ //fall through to allow data from dead clients
244
+ //to be retreived.
245
+ }
246
+ if (client.available() > 0) {
247
+ lastAvailable = which;
248
+ return client;
249
+ }
250
+ }
251
+ }
252
+ return null;
253
+ }
254
+
255
+
256
+ /**
257
+ * ( begin auto-generated from Server_stop.xml )
258
+ *
259
+ * Disconnects all clients and stops the server.
260
+ *
261
+ *
262
+ * <h3>Advanced</h3>
263
+ * Use this to shut down the server if you finish using it while your applet
264
+ * is still running. Otherwise, it will be automatically be shut down by the
265
+ * host PApplet using dispose(), which is identical.
266
+ * @brief Disconnects all clients and stops the server.
267
+ * @webref server
268
+ * @usage application
269
+ */
270
+ public void stop() {
271
+ dispose();
272
+ }
273
+
274
+
275
+ /**
276
+ * Disconnect all clients and stop the server: internal use only.
277
+ */
278
+ public void dispose() {
279
+ thread = null;
280
+
281
+ if (clients != null) {
282
+ disconnectAll();
283
+ clientCount = 0;
284
+ clients = null;
285
+ }
286
+
287
+ try {
288
+ if (server != null) {
289
+ server.close();
290
+ server = null;
291
+ }
292
+ } catch (IOException e) {
293
+
294
+ }
295
+ }
296
+
297
+
298
+ @Override
299
+ public void run() {
300
+ while (Thread.currentThread() == thread) {
301
+ try {
302
+ Socket socket = server.accept();
303
+ Client client = new Client(parent, socket);
304
+ synchronized (clientsLock) {
305
+ addClient(client);
306
+ if (serverEventMethod != null) {
307
+ try {
308
+ serverEventMethod.invoke(parent, this, client);
309
+ } catch (Exception e) {
310
+ System.err.println("Disabling serverEvent() for port " + port);
311
+ Throwable cause = e;
312
+ // unwrap the exception if it came from the user code
313
+ if (e instanceof InvocationTargetException && e.getCause() != null) {
314
+ cause = e.getCause();
315
+ }
316
+ cause.printStackTrace();
317
+ serverEventMethod = null;
318
+ }
319
+ }
320
+ }
321
+ } catch (SocketException e) {
322
+ //thrown when server.close() is called and server is waiting on accept
323
+ System.err.println("Server SocketException: " + e.getMessage());
324
+ thread = null;
325
+ } catch (IOException e) {
326
+ //errorMessage("run", e);
327
+
328
+ thread = null;
329
+ }
330
+ }
331
+ }
332
+
333
+
334
+ /**
335
+ * ( begin auto-generated from Server_write.xml )
336
+ *
337
+ * Writes a value to all the connected clients. It sends bytes out from the
338
+ * Server object.
339
+ *
340
+ *
341
+ * @webref server
342
+ * @brief Writes data to all connected clients
343
+ * @param data data to write
344
+ */
345
+ public void write(int data) { // will also cover char
346
+ synchronized (clientsLock) {
347
+ int index = 0;
348
+ while (index < clientCount) {
349
+ if (clients[index].active()) {
350
+ clients[index].write(data);
351
+ index++;
352
+ } else {
353
+ removeIndex(index);
354
+ }
355
+ }
356
+ }
357
+ }
358
+
359
+
360
+ public void write(byte data[]) {
361
+ synchronized (clientsLock) {
362
+ int index = 0;
363
+ while (index < clientCount) {
364
+ if (clients[index].active()) {
365
+ clients[index].write(data);
366
+ index++;
367
+ } else {
368
+ removeIndex(index);
369
+ }
370
+ }
371
+ }
372
+ }
373
+
374
+
375
+ public void write(String data) {
376
+ synchronized (clientsLock) {
377
+ int index = 0;
378
+ while (index < clientCount) {
379
+ if (clients[index].active()) {
380
+ clients[index].write(data);
381
+ index++;
382
+ } else {
383
+ removeIndex(index);
384
+ }
385
+ }
386
+ }
387
+ }
388
+ }
@@ -1,3 +1,5 @@
1
+ /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
+
1
3
  /*
2
4
  Part of the Processing project - http://processing.org
3
5
 
@@ -18,7 +20,8 @@
18
20
  Public License along with this library; if not, write to the
19
21
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20
22
  Boston, MA 02111-1307 USA
21
- */
23
+ */
24
+
22
25
  package processing.opengl;
23
26
 
24
27
  import processing.core.PApplet;
@@ -30,204 +33,216 @@ import processing.core.PImage;
30
33
  import java.util.HashMap;
31
34
 
32
35
  /**
33
- * All the infrastructure needed for optimized font rendering in OpenGL.
34
- * Basically, this special class is needed because fonts in Processing are
35
- * handled by a separate PImage for each glyph. For performance reasons, all
36
- * these glyphs should be stored in a single OpenGL texture (otherwise,
37
- * rendering a string of text would involve binding and un-binding several
38
- * textures. PFontTexture manages the correspondence between individual glyphs
39
- * and the large OpenGL texture containing them. Also, in the case that the font
40
- * size is very large, one single OpenGL texture might not be enough to store
41
- * all the glyphs, so PFontTexture also takes care of spreading a single font
36
+ * All the infrastructure needed for optimized font rendering
37
+ * in OpenGL. Basically, this special class is needed because
38
+ * fonts in Processing are handled by a separate PImage for each
39
+ * glyph. For performance reasons, all these glyphs should be
40
+ * stored in a single OpenGL texture (otherwise, rendering a
41
+ * string of text would involve binding and un-binding several
42
+ * textures.
43
+ * PFontTexture manages the correspondence between individual
44
+ * glyphs and the large OpenGL texture containing them. Also,
45
+ * in the case that the font size is very large, one single
46
+ * OpenGL texture might not be enough to store all the glyphs,
47
+ * so PFontTexture also takes care of spreading a single font
42
48
  * over several textures.
43
- *
44
49
  * @author Andres Colubri
45
50
  */
46
51
  class FontTexture implements PConstants {
52
+ protected PGL pgl;
53
+ protected boolean is3D;
47
54
 
48
- protected PGL pgl;
49
- protected boolean is3D;
50
-
51
- protected int minSize;
52
- protected int maxSize;
53
- protected int offsetX;
54
- protected int offsetY;
55
- protected int lineHeight;
56
- protected Texture[] textures = null;
57
- protected PImage[] images = null;
58
- protected int lastTex;
59
- protected TextureInfo[] glyphTexinfos;
60
- protected HashMap<PFont.Glyph, TextureInfo> texinfoMap;
61
-
62
- public FontTexture(PGraphicsOpenGL pg, PFont font, boolean is3D) {
63
- pgl = pg.pgl;
64
- this.is3D = is3D;
65
-
66
- initTexture(pg, font);
67
- }
55
+ protected int minSize;
56
+ protected int maxSize;
57
+ protected int offsetX;
58
+ protected int offsetY;
59
+ protected int lineHeight;
60
+ protected Texture[] textures = null;
61
+ protected PImage[] images = null;
62
+ protected int lastTex;
63
+ protected TextureInfo[] glyphTexinfos;
64
+ protected HashMap<PFont.Glyph, TextureInfo> texinfoMap;
68
65
 
69
- protected void allocate() {
70
- // Nothing to do here: the font textures will allocate
71
- // themselves.
72
- }
66
+ public FontTexture(PGraphicsOpenGL pg, PFont font, boolean is3D) {
67
+ pgl = pg.pgl;
68
+ this.is3D = is3D;
73
69
 
74
- protected void dispose() {
75
- for (int i = 0; i < textures.length; i++) {
76
- textures[i].dispose();
77
- }
78
- }
70
+ initTexture(pg, font);
71
+ }
79
72
 
80
- protected void initTexture(PGraphicsOpenGL pg, PFont font) {
81
- lastTex = -1;
82
73
 
83
- int spow = PGL.nextPowerOfTwo(font.getSize());
84
- minSize = PApplet.min(PGraphicsOpenGL.maxTextureSize,
85
- PApplet.max(PGL.MIN_FONT_TEX_SIZE, spow));
86
- maxSize = PApplet.min(PGraphicsOpenGL.maxTextureSize,
87
- PApplet.max(PGL.MAX_FONT_TEX_SIZE, 2 * spow));
74
+ protected void allocate() {
75
+ // Nothing to do here: the font textures will allocate
76
+ // themselves.
77
+ }
88
78
 
89
- if (maxSize < spow) {
90
- PGraphics.showWarning("The font size is too large to be properly "
91
- + "displayed with OpenGL");
92
- }
93
79
 
94
- addTexture(pg);
80
+ protected void dispose() {
81
+ for (Texture texture : textures) {
82
+ texture.dispose();
83
+ }
84
+ }
95
85
 
96
- offsetX = 0;
97
- offsetY = 0;
98
- lineHeight = 0;
99
86
 
100
- texinfoMap = new HashMap<PFont.Glyph, TextureInfo>();
101
- glyphTexinfos = new TextureInfo[font.getGlyphCount()];
102
- addAllGlyphsToTexture(pg, font);
87
+ protected void initTexture(PGraphicsOpenGL pg, PFont font) {
88
+ lastTex = -1;
89
+
90
+ int spow = PGL.nextPowerOfTwo(font.getSize());
91
+ minSize = PApplet.min(PGraphicsOpenGL.maxTextureSize,
92
+ PApplet.max(PGL.MIN_FONT_TEX_SIZE, spow));
93
+ maxSize = PApplet.min(PGraphicsOpenGL.maxTextureSize,
94
+ PApplet.max(PGL.MAX_FONT_TEX_SIZE, 2 * spow));
95
+
96
+ if (maxSize < spow) {
97
+ PGraphics.showWarning("The font size is too large to be properly " +
98
+ "displayed with OpenGL");
103
99
  }
104
100
 
105
- public boolean addTexture(PGraphicsOpenGL pg) {
106
- int w, h;
107
- boolean resize;
108
-
109
- w = maxSize;
110
- if (-1 < lastTex && textures[lastTex].glHeight < maxSize) {
111
- // The height of the current texture is less than the maximum, this
112
- // means we can replace it with a larger texture.
113
- h = PApplet.min(2 * textures[lastTex].glHeight, maxSize);
114
- resize = true;
115
- } else {
116
- h = minSize;
117
- resize = false;
118
- }
101
+ addTexture(pg);
119
102
 
120
- Texture tex;
121
- if (is3D) {
122
- // Bilinear sampling ensures that the texture doesn't look pixelated
123
- // either when it is magnified or minified...
124
- tex = new Texture(pg, w, h,
125
- new Texture.Parameters(ARGB, Texture.BILINEAR, false));
126
- } else {
127
- // ...however, the effect of bilinear sampling is to add some blurriness
128
- // to the text in its original size. In 2D, we assume that text will be
129
- // shown at its original size, so linear sampling is chosen instead (which
130
- // only affects minimized text).
131
- tex = new Texture(pg, w, h,
132
- new Texture.Parameters(ARGB, Texture.LINEAR, false));
133
- }
103
+ offsetX = 0;
104
+ offsetY = 0;
105
+ lineHeight = 0;
134
106
 
135
- if (textures == null) {
136
- textures = new Texture[1];
137
- textures[0] = tex;
138
- images = new PImage[1];
139
- images[0] = pg.wrapTexture(tex);
140
- lastTex = 0;
141
- } else if (resize) {
142
- // Replacing old smaller texture with larger one.
143
- // But first we must copy the contents of the older
144
- // texture into the new one.
145
- Texture tex0 = textures[lastTex];
146
- tex.put(tex0);
147
- textures[lastTex] = tex;
148
-
149
- pg.setCache(images[lastTex], tex);
150
- images[lastTex].width = tex.width;
151
- images[lastTex].height = tex.height;
152
- } else {
153
- // Adding new texture to the list.
154
- lastTex = textures.length;
155
- Texture[] tempTex = new Texture[lastTex + 1];
156
- PApplet.arrayCopy(textures, tempTex, textures.length);
157
- tempTex[lastTex] = tex;
158
- textures = tempTex;
159
-
160
- PImage[] tempImg = new PImage[textures.length];
161
- PApplet.arrayCopy(images, tempImg, images.length);
162
- tempImg[lastTex] = pg.wrapTexture(tex);
163
- images = tempImg;
164
- }
107
+ texinfoMap = new HashMap<>();
108
+ glyphTexinfos = new TextureInfo[font.getGlyphCount()];
109
+ addAllGlyphsToTexture(pg, font);
110
+ }
165
111
 
166
- // Make sure that the current texture is bound.
167
- tex.bind();
168
112
 
169
- return resize;
170
- }
113
+ public boolean addTexture(PGraphicsOpenGL pg) {
114
+ int w, h;
115
+ boolean resize;
171
116
 
172
- public void begin() {
117
+ w = maxSize;
118
+ if (-1 < lastTex && textures[lastTex].glHeight < maxSize) {
119
+ // The height of the current texture is less than the maximum, this
120
+ // means we can replace it with a larger texture.
121
+ h = PApplet.min(2 * textures[lastTex].glHeight, maxSize);
122
+ resize = true;
123
+ } else {
124
+ h = minSize;
125
+ resize = false;
173
126
  }
174
127
 
175
- public void end() {
176
- for (int i = 0; i < textures.length; i++) {
177
- pgl.disableTexturing(textures[i].glTarget);
178
- }
128
+ Texture tex;
129
+ if (is3D) {
130
+ // Bilinear sampling ensures that the texture doesn't look pixelated
131
+ // either when it is magnified or minified...
132
+ tex = new Texture(pg, w, h,
133
+ new Texture.Parameters(ARGB, Texture.BILINEAR, false));
134
+ } else {
135
+ // ...however, the effect of bilinear sampling is to add some blurriness
136
+ // to the text in its original size. In 2D, we assume that text will be
137
+ // shown at its original size, so linear sampling is chosen instead (which
138
+ // only affects minimized text).
139
+ tex = new Texture(pg, w, h,
140
+ new Texture.Parameters(ARGB, Texture.LINEAR, false));
179
141
  }
180
142
 
181
- public PImage getTexture(TextureInfo info) {
182
- return images[info.texIndex];
143
+ if (textures == null) {
144
+ textures = new Texture[1];
145
+ textures[0] = tex;
146
+ images = new PImage[1];
147
+ images[0] = pg.wrapTexture(tex);
148
+ lastTex = 0;
149
+ } else if (resize) {
150
+ // Replacing old smaller texture with larger one.
151
+ // But first we must copy the contents of the older
152
+ // texture into the new one.
153
+ Texture tex0 = textures[lastTex];
154
+ tex.put(tex0);
155
+ textures[lastTex] = tex;
156
+
157
+ pg.setCache(images[lastTex], tex);
158
+ images[lastTex].width = tex.width;
159
+ images[lastTex].height = tex.height;
160
+ } else {
161
+ // Adding new texture to the list.
162
+ lastTex = textures.length;
163
+ Texture[] tempTex = new Texture[lastTex + 1];
164
+ PApplet.arrayCopy(textures, tempTex, textures.length);
165
+ tempTex[lastTex] = tex;
166
+ textures = tempTex;
167
+
168
+ PImage[] tempImg = new PImage[textures.length];
169
+ PApplet.arrayCopy(images, tempImg, images.length);
170
+ tempImg[lastTex] = pg.wrapTexture(tex);
171
+ images = tempImg;
183
172
  }
184
173
 
185
- // Add all the current glyphs to opengl texture.
186
- public void addAllGlyphsToTexture(PGraphicsOpenGL pg, PFont font) {
187
- // loop over current glyphs.
188
- for (int i = 0; i < font.getGlyphCount(); i++) {
189
- addToTexture(pg, i, font.getGlyph(i));
190
- }
174
+ // Make sure that the current texture is bound.
175
+ tex.bind();
176
+
177
+ return resize;
178
+ }
179
+
180
+
181
+ public void begin() {
182
+ }
183
+
184
+
185
+ public void end() {
186
+ for (Texture texture : textures) {
187
+ pgl.disableTexturing(texture.glTarget);
191
188
  }
189
+ }
192
190
 
193
- public void updateGlyphsTexCoords() {
194
- // loop over current glyphs.
195
- for (int i = 0; i < glyphTexinfos.length; i++) {
196
- TextureInfo tinfo = glyphTexinfos[i];
197
- if (tinfo != null && tinfo.texIndex == lastTex) {
198
- tinfo.updateUV();
199
- }
200
- }
191
+
192
+ public PImage getTexture(TextureInfo info) {
193
+ return images[info.texIndex];
194
+ }
195
+
196
+
197
+ // Add all the current glyphs to opengl texture.
198
+ public void addAllGlyphsToTexture(PGraphicsOpenGL pg, PFont font) {
199
+ // loop over current glyphs.
200
+ for (int i = 0; i < font.getGlyphCount(); i++) {
201
+ addToTexture(pg, i, font.getGlyph(i));
201
202
  }
203
+ }
204
+
202
205
 
203
- public TextureInfo getTexInfo(PFont.Glyph glyph) {
204
- TextureInfo info = texinfoMap.get(glyph);
205
- return info;
206
+ public void updateGlyphsTexCoords() {
207
+ // loop over current glyphs.
208
+ for (TextureInfo tinfo : glyphTexinfos) {
209
+ if (tinfo != null && tinfo.texIndex == lastTex) {
210
+ tinfo.updateUV();
211
+ }
206
212
  }
213
+ }
207
214
 
208
- public TextureInfo addToTexture(PGraphicsOpenGL pg, PFont.Glyph glyph) {
209
- int n = glyphTexinfos.length;
210
- if (n == 0) {
211
- glyphTexinfos = new TextureInfo[1];
212
- }
213
- addToTexture(pg, n, glyph);
214
- return glyphTexinfos[n];
215
+
216
+ public TextureInfo getTexInfo(PFont.Glyph glyph) {
217
+ TextureInfo info = texinfoMap.get(glyph);
218
+ return info;
219
+ }
220
+
221
+
222
+ public TextureInfo addToTexture(PGraphicsOpenGL pg, PFont.Glyph glyph) {
223
+ int n = glyphTexinfos.length;
224
+ if (n == 0) {
225
+ glyphTexinfos = new TextureInfo[1];
215
226
  }
227
+ addToTexture(pg, n, glyph);
228
+ return glyphTexinfos[n];
229
+ }
216
230
 
217
- public boolean contextIsOutdated() {
218
- boolean outdated = false;
219
- for (int i = 0; i < textures.length; i++) {
220
- if (textures[i].contextIsOutdated()) {
221
- outdated = true;
222
- }
223
- }
224
- if (outdated) {
225
- for (int i = 0; i < textures.length; i++) {
226
- textures[i].dispose();
227
- }
228
- }
229
- return outdated;
231
+
232
+ public boolean contextIsOutdated() {
233
+ boolean outdated = false;
234
+ for (Texture texture : textures) {
235
+ if (texture.contextIsOutdated()) {
236
+ outdated = true;
237
+ }
230
238
  }
239
+ if (outdated) {
240
+ for (Texture texture : textures) {
241
+ texture.dispose();
242
+ }
243
+ }
244
+ return outdated;
245
+ }
231
246
 
232
247
  // public void draw() {
233
248
  // Texture tex = textures[lastTex];
@@ -235,125 +250,129 @@ class FontTexture implements PConstants {
235
250
  // tex.glWidth, tex.glHeight,
236
251
  // 0, 0, tex.glWidth, tex.glHeight);
237
252
  // }
238
- // Adds this glyph to the opengl texture in PFont.
239
- protected void addToTexture(PGraphicsOpenGL pg, int idx, PFont.Glyph glyph) {
240
- // We add one pixel to avoid issues when sampling the font texture at
241
- // fractional screen positions. I.e.: the pixel on the screen only contains
242
- // half of the font rectangle, so it would sample half of the color from the
243
- // glyph area in the texture, and the other half from the contiguous pixel.
244
- // If the later contains a portion of the neighbor glyph and the former
245
- // doesn't, this would result in a shaded pixel when the correct output is
246
- // blank. This is a consequence of putting all the glyphs in a common
247
- // texture with bilinear sampling.
248
- int w = 1 + glyph.width + 1;
249
- int h = 1 + glyph.height + 1;
250
-
251
- // Converting the pixels array from the PImage into a valid RGBA array for
252
- // OpenGL.
253
- int[] rgba = new int[w * h];
254
- int t = 0;
255
- int p = 0;
256
- if (PGL.BIG_ENDIAN) {
257
- java.util.Arrays.fill(rgba, 0, w, 0xFFFFFF00); // Set the first row to blank pixels.
258
- t = w;
259
- for (int y = 0; y < glyph.height; y++) {
260
- rgba[t++] = 0xFFFFFF00; // Set the leftmost pixel in this row as blank
261
- for (int x = 0; x < glyph.width; x++) {
262
- rgba[t++] = 0xFFFFFF00 | glyph.image.pixels[p++];
263
- }
264
- rgba[t++] = 0xFFFFFF00; // Set the rightmost pixel in this row as blank
265
- }
266
- java.util.Arrays.fill(rgba, (h - 1) * w, h * w, 0xFFFFFF00); // Set the last row to blank pixels.
267
- } else {
268
- java.util.Arrays.fill(rgba, 0, w, 0x00FFFFFF); // Set the first row to blank pixels.
269
- t = w;
270
- for (int y = 0; y < glyph.height; y++) {
271
- rgba[t++] = 0x00FFFFFF; // Set the leftmost pixel in this row as blank
272
- for (int x = 0; x < glyph.width; x++) {
273
- rgba[t++] = (glyph.image.pixels[p++] << 24) | 0x00FFFFFF;
274
- }
275
- rgba[t++] = 0x00FFFFFF; // Set the rightmost pixel in this row as blank
276
- }
277
- java.util.Arrays.fill(rgba, (h - 1) * w, h * w, 0x00FFFFFF); // Set the last row to blank pixels.
278
- }
279
253
 
280
- // Is there room for this glyph in the current line?
281
- if (offsetX + w > textures[lastTex].glWidth) {
282
- // No room, go to the next line:
283
- offsetX = 0;
284
- offsetY += lineHeight;
254
+
255
+ // Adds this glyph to the opengl texture in PFont.
256
+ protected void addToTexture(PGraphicsOpenGL pg, int idx, PFont.Glyph glyph) {
257
+ // We add one pixel to avoid issues when sampling the font texture at
258
+ // fractional screen positions. I.e.: the pixel on the screen only contains
259
+ // half of the font rectangle, so it would sample half of the color from the
260
+ // glyph area in the texture, and the other half from the contiguous pixel.
261
+ // If the later contains a portion of the neighbor glyph and the former
262
+ // doesn't, this would result in a shaded pixel when the correct output is
263
+ // blank. This is a consequence of putting all the glyphs in a common
264
+ // texture with bilinear sampling.
265
+ int w = 1 + glyph.width + 1;
266
+ int h = 1 + glyph.height + 1;
267
+
268
+ // Converting the pixels array from the PImage into a valid RGBA array for
269
+ // OpenGL.
270
+ int[] rgba = new int[w * h];
271
+ int t = 0;
272
+ int p = 0;
273
+ if (PGL.BIG_ENDIAN) {
274
+ java.util.Arrays.fill(rgba, 0, w, 0xFFFFFF00); // Set the first row to blank pixels.
275
+ t = w;
276
+ for (int y = 0; y < glyph.height; y++) {
277
+ rgba[t++] = 0xFFFFFF00; // Set the leftmost pixel in this row as blank
278
+ for (int x = 0; x < glyph.width; x++) {
279
+ rgba[t++] = 0xFFFFFF00 | glyph.image.pixels[p++];
285
280
  }
286
- lineHeight = Math.max(lineHeight, h);
287
-
288
- boolean resized = false;
289
- if (offsetY + lineHeight > textures[lastTex].glHeight) {
290
- // We run out of space in the current texture, so we add a new texture:
291
- resized = addTexture(pg);
292
- if (resized) {
293
- // Because the current texture has been resized, we need to
294
- // update the UV coordinates of all the glyphs associated to it:
295
- updateGlyphsTexCoords();
296
- } else {
297
- // A new texture has been created. Reseting texture coordinates
298
- // and line.
299
- offsetX = 0;
300
- offsetY = 0;
301
- lineHeight = 0;
302
- }
281
+ rgba[t++] = 0xFFFFFF00; // Set the rightmost pixel in this row as blank
282
+ }
283
+ java.util.Arrays.fill(rgba, (h - 1) * w, h * w, 0xFFFFFF00); // Set the last row to blank pixels.
284
+ } else {
285
+ java.util.Arrays.fill(rgba, 0, w, 0x00FFFFFF); // Set the first row to blank pixels.
286
+ t = w;
287
+ for (int y = 0; y < glyph.height; y++) {
288
+ rgba[t++] = 0x00FFFFFF; // Set the leftmost pixel in this row as blank
289
+ for (int x = 0; x < glyph.width; x++) {
290
+ rgba[t++] = (glyph.image.pixels[p++] << 24) | 0x00FFFFFF;
303
291
  }
292
+ rgba[t++] = 0x00FFFFFF; // Set the rightmost pixel in this row as blank
293
+ }
294
+ java.util.Arrays.fill(rgba, (h - 1) * w, h * w, 0x00FFFFFF); // Set the last row to blank pixels.
295
+ }
304
296
 
305
- TextureInfo tinfo = new TextureInfo(lastTex, offsetX, offsetY, w, h, rgba);
306
- offsetX += w;
297
+ // Is there room for this glyph in the current line?
298
+ if (offsetX + w > textures[lastTex].glWidth) {
299
+ // No room, go to the next line:
300
+ offsetX = 0;
301
+ offsetY += lineHeight;
302
+ }
303
+ lineHeight = Math.max(lineHeight, h);
304
+
305
+ boolean resized = false;
306
+ if (offsetY + lineHeight > textures[lastTex].glHeight) {
307
+ // We run out of space in the current texture, so we add a new texture:
308
+ resized = addTexture(pg);
309
+ if (resized) {
310
+ // Because the current texture has been resized, we need to
311
+ // update the UV coordinates of all the glyphs associated to it:
312
+ updateGlyphsTexCoords();
313
+ } else {
314
+ // A new texture has been created. Reseting texture coordinates
315
+ // and line.
316
+ offsetX = 0;
317
+ offsetY = 0;
318
+ lineHeight = 0;
319
+ }
320
+ }
307
321
 
308
- if (idx == glyphTexinfos.length) {
309
- TextureInfo[] temp = new TextureInfo[glyphTexinfos.length + 1];
310
- System.arraycopy(glyphTexinfos, 0, temp, 0, glyphTexinfos.length);
311
- glyphTexinfos = temp;
312
- }
322
+ TextureInfo tinfo = new TextureInfo(lastTex, offsetX, offsetY, w, h, rgba);
323
+ offsetX += w;
313
324
 
314
- glyphTexinfos[idx] = tinfo;
315
- texinfoMap.put(glyph, tinfo);
325
+ if (idx == glyphTexinfos.length) {
326
+ TextureInfo[] temp = new TextureInfo[glyphTexinfos.length + 1];
327
+ System.arraycopy(glyphTexinfos, 0, temp, 0, glyphTexinfos.length);
328
+ glyphTexinfos = temp;
316
329
  }
317
330
 
318
- class TextureInfo {
331
+ glyphTexinfos[idx] = tinfo;
332
+ texinfoMap.put(glyph, tinfo);
333
+ }
334
+
319
335
 
320
- int texIndex;
321
- int width;
322
- int height;
323
- int[] crop;
324
- float u0, u1;
325
- float v0, v1;
326
- int[] pixels;
336
+ class TextureInfo {
337
+ int texIndex;
338
+ int width;
339
+ int height;
340
+ int[] crop;
341
+ float u0, u1;
342
+ float v0, v1;
343
+ int[] pixels;
327
344
 
328
- TextureInfo(int tidx, int cropX, int cropY, int cropW, int cropH,
345
+ TextureInfo(int tidx, int cropX, int cropY, int cropW, int cropH,
329
346
  int[] pix) {
330
- texIndex = tidx;
331
- crop = new int[4];
332
- // The region of the texture corresponding to the glyph is surrounded by a
333
- // 1-pixel wide border to avoid artifacts due to bilinear sampling. This
334
- // is why the additions and subtractions to the crop values.
335
- crop[0] = cropX + 1;
336
- crop[1] = cropY + 1 + cropH - 2;
337
- crop[2] = cropW - 2;
338
- crop[3] = -cropH + 2;
339
- pixels = pix;
340
- updateUV();
341
- updateTex();
342
- }
347
+ texIndex = tidx;
348
+ crop = new int[4];
349
+ // The region of the texture corresponding to the glyph is surrounded by a
350
+ // 1-pixel wide border to avoid artifacts due to bilinear sampling. This
351
+ // is why the additions and subtractions to the crop values.
352
+ crop[0] = cropX + 1;
353
+ crop[1] = cropY + 1 + cropH - 2;
354
+ crop[2] = cropW - 2;
355
+ crop[3] = -cropH + 2;
356
+ pixels = pix;
357
+ updateUV();
358
+ updateTex();
359
+ }
343
360
 
344
- void updateUV() {
345
- width = textures[texIndex].glWidth;
346
- height = textures[texIndex].glHeight;
347
361
 
348
- u0 = (float) crop[0] / (float) width;
349
- u1 = u0 + (float) crop[2] / (float) width;
350
- v0 = (float) (crop[1] + crop[3]) / (float) height;
351
- v1 = v0 - (float) crop[3] / (float) height;
352
- }
362
+ void updateUV() {
363
+ width = textures[texIndex].glWidth;
364
+ height = textures[texIndex].glHeight;
353
365
 
354
- void updateTex() {
355
- textures[texIndex].setNative(pixels, crop[0] - 1, crop[1] + crop[3] - 1,
356
- crop[2] + 2, -crop[3] + 2);
357
- }
366
+ u0 = (float)crop[0] / (float)width;
367
+ u1 = u0 + (float)crop[2] / (float)width;
368
+ v0 = (float)(crop[1] + crop[3]) / (float)height;
369
+ v1 = v0 - (float)crop[3] / (float)height;
370
+ }
371
+
372
+
373
+ void updateTex() {
374
+ textures[texIndex].setNative(pixels, crop[0] - 1, crop[1] + crop[3] - 1,
375
+ crop[2] + 2, -crop[3] + 2);
358
376
  }
377
+ }
359
378
  }