propane 3.4.2-java → 3.5.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.mvn/wrapper/MavenWrapperDownloader.java +1 -1
- data/.travis.yml +1 -1
- data/CHANGELOG.md +5 -1
- data/Gemfile +2 -0
- data/README.md +15 -3
- data/Rakefile +9 -10
- data/bin/propane +3 -1
- data/lib/propane.rb +2 -1
- data/lib/propane/app.rb +2 -1
- data/lib/propane/creators/sketch_class.rb +7 -1
- data/lib/propane/creators/sketch_factory.rb +4 -2
- data/lib/propane/creators/sketch_writer.rb +1 -0
- data/lib/propane/helper_methods.rb +22 -22
- data/lib/propane/helpers/numeric.rb +2 -0
- data/lib/propane/helpers/version_error.rb +1 -0
- data/lib/propane/library.rb +5 -1
- data/lib/propane/library_loader.rb +2 -0
- data/lib/propane/native_folder.rb +10 -9
- data/lib/propane/native_loader.rb +3 -0
- data/lib/propane/runner.rb +11 -5
- data/lib/propane/version.rb +2 -1
- data/library/boids/boids.rb +21 -11
- data/library/color_group/color_group.rb +2 -0
- data/library/control_panel/control_panel.rb +8 -5
- data/library/dxf/dxf.rb +2 -0
- data/library/file_chooser/chooser.rb +10 -9
- data/library/file_chooser/file_chooser.rb +10 -9
- data/library/library_proxy/library_proxy.rb +2 -0
- data/library/net/net.rb +2 -0
- data/library/simplex_noise/simplex_noise.rb +2 -0
- data/library/slider/slider.rb +23 -22
- data/library/vector_utils/vector_utils.rb +4 -0
- data/library/video_event/video_event.rb +2 -0
- data/pom.rb +46 -45
- data/pom.xml +4 -4
- data/propane.gemspec +8 -7
- data/src/main/java/monkstone/ColorUtil.java +1 -3
- data/src/main/java/monkstone/MathToolModule.java +1 -1
- data/src/main/java/monkstone/PropaneLibrary.java +2 -2
- data/src/main/java/monkstone/fastmath/Deglut.java +1 -1
- data/src/main/java/monkstone/filechooser/Chooser.java +1 -1
- data/src/main/java/monkstone/noise/SimplexNoise.java +2 -2
- data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +1 -1
- data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
- data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +1 -1
- data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +1 -1
- data/src/main/java/monkstone/slider/SliderBar.java +1 -1
- data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
- data/src/main/java/monkstone/slider/WheelHandler.java +1 -1
- data/src/main/java/monkstone/vecmath/package-info.java +1 -1
- data/src/main/java/monkstone/vecmath/vec2/Vec2.java +1 -1
- data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -2
- data/src/main/java/monkstone/videoevent/CaptureEvent.java +1 -1
- data/src/main/java/monkstone/videoevent/MovieEvent.java +1 -1
- data/src/main/java/monkstone/videoevent/package-info.java +1 -1
- data/src/main/java/processing/awt/PGraphicsJava2D.java +788 -283
- data/src/main/java/processing/awt/PImageAWT.java +260 -0
- data/src/main/java/processing/awt/PShapeJava2D.java +56 -53
- data/src/main/java/processing/awt/PSurfaceAWT.java +309 -211
- data/src/main/java/processing/awt/ShimAWT.java +580 -0
- data/src/main/java/processing/core/PApplet.java +2877 -2098
- data/src/main/java/processing/core/PConstants.java +477 -447
- data/src/main/java/processing/core/PFont.java +930 -884
- data/src/main/java/processing/core/PGraphics.java +337 -309
- data/src/main/java/processing/core/PImage.java +1689 -1689
- data/src/main/java/processing/core/PMatrix.java +172 -159
- data/src/main/java/processing/core/PMatrix2D.java +456 -410
- data/src/main/java/processing/core/PMatrix3D.java +755 -735
- data/src/main/java/processing/core/PShape.java +2910 -2656
- data/src/main/java/processing/core/PShapeOBJ.java +97 -94
- data/src/main/java/processing/core/PShapeSVG.java +1656 -1462
- data/src/main/java/processing/core/PStyle.java +40 -37
- data/src/main/java/processing/core/PSurface.java +134 -97
- data/src/main/java/processing/core/PSurfaceNone.java +292 -218
- data/src/main/java/processing/core/PVector.java +991 -966
- data/src/main/java/processing/core/ThinkDifferent.java +12 -8
- data/src/main/java/processing/data/DoubleDict.java +756 -710
- data/src/main/java/processing/data/DoubleList.java +749 -696
- data/src/main/java/processing/data/FloatDict.java +748 -702
- data/src/main/java/processing/data/FloatList.java +751 -697
- data/src/main/java/processing/data/IntDict.java +720 -673
- data/src/main/java/processing/data/IntList.java +699 -633
- data/src/main/java/processing/data/JSONArray.java +931 -873
- data/src/main/java/processing/data/JSONObject.java +1262 -1165
- data/src/main/java/processing/data/JSONTokener.java +351 -341
- data/src/main/java/processing/data/LongDict.java +710 -663
- data/src/main/java/processing/data/LongList.java +701 -635
- data/src/main/java/processing/data/Sort.java +37 -41
- data/src/main/java/processing/data/StringDict.java +525 -486
- data/src/main/java/processing/data/StringList.java +626 -580
- data/src/main/java/processing/data/Table.java +3693 -3513
- data/src/main/java/processing/data/TableRow.java +182 -183
- data/src/main/java/processing/data/XML.java +954 -880
- data/src/main/java/processing/event/Event.java +87 -67
- data/src/main/java/processing/event/KeyEvent.java +48 -41
- data/src/main/java/processing/event/MouseEvent.java +87 -113
- data/src/main/java/processing/event/TouchEvent.java +10 -6
- data/src/main/java/processing/javafx/PSurfaceFX.java +26 -0
- data/src/main/java/processing/net/Client.java +20 -20
- data/src/main/java/processing/net/Server.java +9 -9
- data/src/main/java/processing/opengl/FontTexture.java +286 -266
- data/src/main/java/processing/opengl/FrameBuffer.java +390 -376
- data/src/main/java/processing/opengl/LinePath.java +130 -91
- data/src/main/java/processing/opengl/LineStroker.java +593 -582
- data/src/main/java/processing/opengl/PGL.java +645 -579
- data/src/main/java/processing/opengl/PGraphics2D.java +408 -315
- data/src/main/java/processing/opengl/PGraphics3D.java +107 -72
- data/src/main/java/processing/opengl/PGraphicsOpenGL.java +12287 -12030
- data/src/main/java/processing/opengl/PJOGL.java +1743 -1672
- data/src/main/java/processing/opengl/PShader.java +345 -416
- data/src/main/java/processing/opengl/PShapeOpenGL.java +4601 -4543
- data/src/main/java/processing/opengl/PSurfaceJOGL.java +1113 -1029
- data/src/main/java/processing/opengl/Texture.java +1489 -1401
- data/src/main/java/processing/opengl/VertexBuffer.java +57 -55
- data/test/create_test.rb +21 -20
- data/test/deglut_spec_test.rb +4 -2
- data/test/helper_methods_test.rb +49 -20
- data/test/math_tool_test.rb +39 -32
- data/test/native_folder.rb +47 -0
- data/test/respond_to_test.rb +3 -2
- data/test/sketches/key_event.rb +2 -2
- data/test/sketches/library/my_library/my_library.rb +3 -0
- data/test/test_helper.rb +2 -0
- data/test/vecmath_spec_test.rb +35 -22
- data/vendors/Rakefile +28 -22
- metadata +13 -13
- data/src/main/java/processing/opengl/shaders/LightVert-brcm.glsl +0 -154
- data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +0 -154
- data/src/main/java/processing/opengl/shaders/TexLightVert-brcm.glsl +0 -160
- data/src/main/java/processing/opengl/shaders/TexLightVert-vc4.glsl +0 -160
|
@@ -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
|
|
|
@@ -16,9 +18,11 @@
|
|
|
16
18
|
Public License along with this library; if not, write to the
|
|
17
19
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
18
20
|
Boston, MA 02111-1307 USA
|
|
19
|
-
|
|
21
|
+
*/
|
|
22
|
+
|
|
20
23
|
package processing.event;
|
|
21
24
|
|
|
25
|
+
|
|
22
26
|
// PLACEHOLDER CLASS: DO NOT USE. IT HAS NOT EVEN DECIDED WHETHER
|
|
23
27
|
// THIS WILL BE CALLED TOUCHEVENT ONCE IT'S FINISHED.
|
|
24
28
|
|
|
@@ -43,11 +47,11 @@ http://www.w3.org/TR/2011/WD-touch-events-20110913/
|
|
|
43
47
|
Pointer and gesture events (Windows)
|
|
44
48
|
http://msdn.microsoft.com/en-US/library/ie/hh673557.aspx
|
|
45
49
|
|
|
46
|
-
|
|
50
|
+
*/
|
|
47
51
|
public class TouchEvent extends Event {
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
+
public TouchEvent(Object nativeObject, long millis, int action, int modifiers) {
|
|
54
|
+
super(nativeObject, millis, action, modifiers);
|
|
55
|
+
this.flavor = TOUCH;
|
|
56
|
+
}
|
|
53
57
|
}
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
*/
|
|
20
20
|
package processing.javafx;
|
|
21
21
|
|
|
22
|
+
import java.io.File;
|
|
22
23
|
import processing.core.PApplet;
|
|
23
24
|
import processing.core.PImage;
|
|
24
25
|
import processing.core.PSurface;
|
|
@@ -142,4 +143,29 @@ public class PSurfaceFX implements PSurface {
|
|
|
142
143
|
throw new UnsupportedOperationException(message);
|
|
143
144
|
}
|
|
144
145
|
|
|
146
|
+
@Override
|
|
147
|
+
public PImage loadImage(String path, Object... args) {
|
|
148
|
+
throw new UnsupportedOperationException(message);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@Override
|
|
152
|
+
public void selectInput(String prompt, String callback, File file, Object callbackObject) {
|
|
153
|
+
throw new UnsupportedOperationException(message);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@Override
|
|
157
|
+
public void selectOutput(String prompt, String callback, File file, Object callbackObject) {
|
|
158
|
+
throw new UnsupportedOperationException(message);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@Override
|
|
162
|
+
public void selectFolder(String prompt, String callback, File file, Object callbackObject) {
|
|
163
|
+
throw new UnsupportedOperationException(message);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@Override
|
|
167
|
+
public boolean openLink(String url) {
|
|
168
|
+
throw new UnsupportedOperationException(message);
|
|
169
|
+
}
|
|
170
|
+
|
|
145
171
|
}
|
|
@@ -37,7 +37,7 @@ import java.net.*;
|
|
|
37
37
|
* goes wrong with the connection, for example the host is not there or is
|
|
38
38
|
* listening on a different port, an exception is thrown.
|
|
39
39
|
*
|
|
40
|
-
*
|
|
40
|
+
*
|
|
41
41
|
* @webref net
|
|
42
42
|
* @brief The client class is used to create client Objects which connect to a server to exchange data.
|
|
43
43
|
* @instanceName client any variable of type Client
|
|
@@ -108,7 +108,7 @@ public class Client implements Runnable {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
} catch (IOException e) {
|
|
111
|
-
|
|
111
|
+
|
|
112
112
|
dispose();
|
|
113
113
|
}
|
|
114
114
|
}
|
|
@@ -153,7 +153,7 @@ public class Client implements Runnable {
|
|
|
153
153
|
* Disconnects from the server. Use to shut the connection when you're
|
|
154
154
|
* finished with the Client.
|
|
155
155
|
*
|
|
156
|
-
*
|
|
156
|
+
*
|
|
157
157
|
* @webref client:client
|
|
158
158
|
* @brief Disconnects from the server
|
|
159
159
|
* @usage application
|
|
@@ -194,7 +194,7 @@ public class Client implements Runnable {
|
|
|
194
194
|
input = null;
|
|
195
195
|
}
|
|
196
196
|
} catch (Exception e) {
|
|
197
|
-
|
|
197
|
+
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
try {
|
|
@@ -203,7 +203,7 @@ public class Client implements Runnable {
|
|
|
203
203
|
output = null;
|
|
204
204
|
}
|
|
205
205
|
} catch (Exception e) {
|
|
206
|
-
|
|
206
|
+
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
try {
|
|
@@ -212,7 +212,7 @@ public class Client implements Runnable {
|
|
|
212
212
|
socket = null;
|
|
213
213
|
}
|
|
214
214
|
} catch (Exception e) {
|
|
215
|
-
|
|
215
|
+
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
218
|
|
|
@@ -299,7 +299,7 @@ public class Client implements Runnable {
|
|
|
299
299
|
}
|
|
300
300
|
} catch (IOException e) {
|
|
301
301
|
//errorMessage("run", e);
|
|
302
|
-
|
|
302
|
+
|
|
303
303
|
}
|
|
304
304
|
}
|
|
305
305
|
}
|
|
@@ -311,7 +311,7 @@ public class Client implements Runnable {
|
|
|
311
311
|
* Returns true if this client is still active and hasn't run
|
|
312
312
|
* into any trouble.
|
|
313
313
|
*
|
|
314
|
-
*
|
|
314
|
+
*
|
|
315
315
|
* @webref client:client
|
|
316
316
|
* @brief Returns true if this client is still active
|
|
317
317
|
* @usage application
|
|
@@ -326,7 +326,7 @@ public class Client implements Runnable {
|
|
|
326
326
|
*
|
|
327
327
|
* Returns the IP address of the computer to which the Client is attached.
|
|
328
328
|
*
|
|
329
|
-
*
|
|
329
|
+
*
|
|
330
330
|
* @webref client:client
|
|
331
331
|
* @usage application
|
|
332
332
|
* @brief Returns the IP address of the machine as a String
|
|
@@ -345,7 +345,7 @@ public class Client implements Runnable {
|
|
|
345
345
|
* Returns the number of bytes available. When any client has bytes
|
|
346
346
|
* available from the server, it returns the number of bytes.
|
|
347
347
|
*
|
|
348
|
-
*
|
|
348
|
+
*
|
|
349
349
|
* @webref client:client
|
|
350
350
|
* @usage application
|
|
351
351
|
* @brief Returns the number of bytes in the buffer waiting to be read
|
|
@@ -362,7 +362,7 @@ public class Client implements Runnable {
|
|
|
362
362
|
*
|
|
363
363
|
* Empty the buffer, removes all the data stored there.
|
|
364
364
|
*
|
|
365
|
-
*
|
|
365
|
+
*
|
|
366
366
|
* @webref client:client
|
|
367
367
|
* @usage application
|
|
368
368
|
* @brief Clears the buffer
|
|
@@ -382,7 +382,7 @@ public class Client implements Runnable {
|
|
|
382
382
|
* the buffer. Returns -1 if there is no byte, although this should be
|
|
383
383
|
* avoided by first cheacking <b>available()</b> to see if any data is available.
|
|
384
384
|
*
|
|
385
|
-
*
|
|
385
|
+
*
|
|
386
386
|
* @webref client:client
|
|
387
387
|
* @usage application
|
|
388
388
|
* @brief Returns a value from the buffer
|
|
@@ -407,7 +407,7 @@ public class Client implements Runnable {
|
|
|
407
407
|
* Returns the next byte in the buffer as a char. Returns -1 or 0xffff if
|
|
408
408
|
* nothing is there.
|
|
409
409
|
*
|
|
410
|
-
*
|
|
410
|
+
*
|
|
411
411
|
* @webref client:client
|
|
412
412
|
* @usage application
|
|
413
413
|
* @brief Returns the next byte in the buffer as a char
|
|
@@ -431,7 +431,7 @@ public class Client implements Runnable {
|
|
|
431
431
|
* of bytes read. If more bytes are available than can fit into the
|
|
432
432
|
* <b>byteBuffer</b>, only those that fit are read.
|
|
433
433
|
*
|
|
434
|
-
*
|
|
434
|
+
*
|
|
435
435
|
* <h3>Advanced</h3>
|
|
436
436
|
* Return a byte array of anything that's in the serial buffer.
|
|
437
437
|
* Not particularly memory/speed efficient, because it creates
|
|
@@ -531,7 +531,7 @@ public class Client implements Runnable {
|
|
|
531
531
|
* not large enough, -1 is returned and an error is printed to the message
|
|
532
532
|
* area. If nothing is in the buffer, 0 is returned.
|
|
533
533
|
*
|
|
534
|
-
*
|
|
534
|
+
*
|
|
535
535
|
* @webref client:client
|
|
536
536
|
* @usage application
|
|
537
537
|
* @brief Reads from the buffer of bytes up to and including a particular character
|
|
@@ -623,7 +623,7 @@ public class Client implements Runnable {
|
|
|
623
623
|
* representation of your choice (i.e. UTF8 or two-byte Unicode data), and
|
|
624
624
|
* send it as a byte array.
|
|
625
625
|
*
|
|
626
|
-
*
|
|
626
|
+
*
|
|
627
627
|
* @webref client:client
|
|
628
628
|
* @usage application
|
|
629
629
|
* @brief Returns the buffer as a String
|
|
@@ -641,7 +641,7 @@ public class Client implements Runnable {
|
|
|
641
641
|
* Combination of <b>readBytesUntil()</b> and <b>readString()</b>. Returns
|
|
642
642
|
* <b>null</b> if it doesn't find what you're looking for.
|
|
643
643
|
*
|
|
644
|
-
*
|
|
644
|
+
*
|
|
645
645
|
* <h3>Advanced</h3>
|
|
646
646
|
* <p/>
|
|
647
647
|
* If you want to move Unicode data, you can first convert the
|
|
@@ -665,7 +665,7 @@ public class Client implements Runnable {
|
|
|
665
665
|
*
|
|
666
666
|
* Writes data to a server specified when constructing the client.
|
|
667
667
|
*
|
|
668
|
-
*
|
|
668
|
+
*
|
|
669
669
|
* @webref client:client
|
|
670
670
|
* @usage application
|
|
671
671
|
* @brief Writes bytes, chars, ints, bytes[], Strings
|
|
@@ -681,7 +681,7 @@ public class Client implements Runnable {
|
|
|
681
681
|
//e.printStackTrace();
|
|
682
682
|
//dispose();
|
|
683
683
|
//disconnect(e);
|
|
684
|
-
|
|
684
|
+
|
|
685
685
|
stop();
|
|
686
686
|
}
|
|
687
687
|
}
|
|
@@ -696,7 +696,7 @@ public class Client implements Runnable {
|
|
|
696
696
|
//errorMessage("write", e);
|
|
697
697
|
//e.printStackTrace();
|
|
698
698
|
//disconnect(e);
|
|
699
|
-
|
|
699
|
+
|
|
700
700
|
stop();
|
|
701
701
|
}
|
|
702
702
|
}
|
|
@@ -42,7 +42,7 @@ import java.net.*;
|
|
|
42
42
|
* commonly used so be sure to not select one of these. For example, web
|
|
43
43
|
* servers usually use port 80 and POP mail uses port 110.
|
|
44
44
|
*
|
|
45
|
-
*
|
|
45
|
+
*
|
|
46
46
|
* @webref net
|
|
47
47
|
* @usage application
|
|
48
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).
|
|
@@ -119,7 +119,7 @@ public class Server implements Runnable {
|
|
|
119
119
|
*
|
|
120
120
|
* Disconnect a particular client.
|
|
121
121
|
*
|
|
122
|
-
*
|
|
122
|
+
*
|
|
123
123
|
* @brief Disconnect a particular client.
|
|
124
124
|
* @webref server:server
|
|
125
125
|
* @param client the client to disconnect
|
|
@@ -191,7 +191,7 @@ public class Server implements Runnable {
|
|
|
191
191
|
* Returns true if this server is still active and hasn't run
|
|
192
192
|
* into any trouble.
|
|
193
193
|
*
|
|
194
|
-
*
|
|
194
|
+
*
|
|
195
195
|
* @webref server:server
|
|
196
196
|
* @brief Return true if this server is still active.
|
|
197
197
|
*/
|
|
@@ -204,7 +204,7 @@ public class Server implements Runnable {
|
|
|
204
204
|
try {
|
|
205
205
|
return InetAddress.getLocalHost().getHostAddress();
|
|
206
206
|
} catch (UnknownHostException e) {
|
|
207
|
-
|
|
207
|
+
|
|
208
208
|
return null;
|
|
209
209
|
}
|
|
210
210
|
}
|
|
@@ -220,7 +220,7 @@ public class Server implements Runnable {
|
|
|
220
220
|
*
|
|
221
221
|
* Returns the next client in line with a new message.
|
|
222
222
|
*
|
|
223
|
-
*
|
|
223
|
+
*
|
|
224
224
|
* @brief Returns the next client in line with a new message.
|
|
225
225
|
* @webref server
|
|
226
226
|
* @usage application
|
|
@@ -258,7 +258,7 @@ public class Server implements Runnable {
|
|
|
258
258
|
*
|
|
259
259
|
* Disconnects all clients and stops the server.
|
|
260
260
|
*
|
|
261
|
-
*
|
|
261
|
+
*
|
|
262
262
|
* <h3>Advanced</h3>
|
|
263
263
|
* Use this to shut down the server if you finish using it while your applet
|
|
264
264
|
* is still running. Otherwise, it will be automatically be shut down by the
|
|
@@ -290,7 +290,7 @@ public class Server implements Runnable {
|
|
|
290
290
|
server = null;
|
|
291
291
|
}
|
|
292
292
|
} catch (IOException e) {
|
|
293
|
-
|
|
293
|
+
|
|
294
294
|
}
|
|
295
295
|
}
|
|
296
296
|
|
|
@@ -324,7 +324,7 @@ public class Server implements Runnable {
|
|
|
324
324
|
thread = null;
|
|
325
325
|
} catch (IOException e) {
|
|
326
326
|
//errorMessage("run", e);
|
|
327
|
-
|
|
327
|
+
|
|
328
328
|
thread = null;
|
|
329
329
|
}
|
|
330
330
|
}
|
|
@@ -337,7 +337,7 @@ public class Server implements Runnable {
|
|
|
337
337
|
* Writes a value to all the connected clients. It sends bytes out from the
|
|
338
338
|
* Server object.
|
|
339
339
|
*
|
|
340
|
-
*
|
|
340
|
+
*
|
|
341
341
|
* @webref server
|
|
342
342
|
* @brief Writes data to all connected clients
|
|
343
343
|
* @param data data to write
|
|
@@ -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,203 +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
|
|
34
|
-
* Basically, this special class is needed because
|
|
35
|
-
* handled by a separate PImage for each
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
66
|
+
public FontTexture(PGraphicsOpenGL pg, PFont font, boolean is3D) {
|
|
67
|
+
pgl = pg.pgl;
|
|
68
|
+
this.is3D = is3D;
|
|
73
69
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
texture.dispose();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
70
|
+
initTexture(pg, font);
|
|
71
|
+
}
|
|
79
72
|
|
|
80
|
-
protected void initTexture(PGraphicsOpenGL pg, PFont font) {
|
|
81
|
-
lastTex = -1;
|
|
82
73
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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;
|
|
106
|
+
|
|
107
|
+
texinfoMap = new HashMap<>();
|
|
108
|
+
glyphTexinfos = new TextureInfo[font.getGlyphCount()];
|
|
109
|
+
addAllGlyphsToTexture(pg, font);
|
|
110
|
+
}
|
|
134
111
|
|
|
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
|
-
}
|
|
165
112
|
|
|
166
|
-
|
|
167
|
-
|
|
113
|
+
public boolean addTexture(PGraphicsOpenGL pg) {
|
|
114
|
+
int w, h;
|
|
115
|
+
boolean resize;
|
|
168
116
|
|
|
169
|
-
|
|
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;
|
|
170
126
|
}
|
|
171
127
|
|
|
172
|
-
|
|
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));
|
|
173
141
|
}
|
|
174
142
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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;
|
|
179
172
|
}
|
|
180
173
|
|
|
181
|
-
|
|
182
|
-
|
|
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);
|
|
183
188
|
}
|
|
189
|
+
}
|
|
184
190
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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));
|
|
191
202
|
}
|
|
203
|
+
}
|
|
192
204
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
205
|
+
|
|
206
|
+
public void updateGlyphsTexCoords() {
|
|
207
|
+
// loop over current glyphs.
|
|
208
|
+
for (TextureInfo tinfo : glyphTexinfos) {
|
|
209
|
+
if (tinfo != null && tinfo.texIndex == lastTex) {
|
|
210
|
+
tinfo.updateUV();
|
|
199
211
|
}
|
|
200
212
|
}
|
|
213
|
+
}
|
|
201
214
|
|
|
202
|
-
public TextureInfo getTexInfo(PFont.Glyph glyph) {
|
|
203
|
-
TextureInfo info = texinfoMap.get(glyph);
|
|
204
|
-
return info;
|
|
205
|
-
}
|
|
206
215
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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];
|
|
214
226
|
}
|
|
227
|
+
addToTexture(pg, n, glyph);
|
|
228
|
+
return glyphTexinfos[n];
|
|
229
|
+
}
|
|
230
|
+
|
|
215
231
|
|
|
216
|
-
|
|
217
|
-
|
|
232
|
+
public boolean contextIsOutdated() {
|
|
233
|
+
boolean outdated = false;
|
|
234
|
+
for (Texture texture : textures) {
|
|
235
|
+
if (texture.contextIsOutdated()) {
|
|
236
|
+
outdated = true;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (outdated) {
|
|
218
240
|
for (Texture texture : textures) {
|
|
219
|
-
|
|
220
|
-
outdated = true;
|
|
221
|
-
}
|
|
241
|
+
texture.dispose();
|
|
222
242
|
}
|
|
223
|
-
if (outdated) {
|
|
224
|
-
for (Texture texture : textures) {
|
|
225
|
-
texture.dispose();
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
return outdated;
|
|
229
243
|
}
|
|
244
|
+
return outdated;
|
|
245
|
+
}
|
|
230
246
|
|
|
231
247
|
// public void draw() {
|
|
232
248
|
// Texture tex = textures[lastTex];
|
|
@@ -234,125 +250,129 @@ class FontTexture implements PConstants {
|
|
|
234
250
|
// tex.glWidth, tex.glHeight,
|
|
235
251
|
// 0, 0, tex.glWidth, tex.glHeight);
|
|
236
252
|
// }
|
|
237
|
-
// Adds this glyph to the opengl texture in PFont.
|
|
238
|
-
protected void addToTexture(PGraphicsOpenGL pg, int idx, PFont.Glyph glyph) {
|
|
239
|
-
// We add one pixel to avoid issues when sampling the font texture at
|
|
240
|
-
// fractional screen positions. I.e.: the pixel on the screen only contains
|
|
241
|
-
// half of the font rectangle, so it would sample half of the color from the
|
|
242
|
-
// glyph area in the texture, and the other half from the contiguous pixel.
|
|
243
|
-
// If the later contains a portion of the neighbor glyph and the former
|
|
244
|
-
// doesn't, this would result in a shaded pixel when the correct output is
|
|
245
|
-
// blank. This is a consequence of putting all the glyphs in a common
|
|
246
|
-
// texture with bilinear sampling.
|
|
247
|
-
int w = 1 + glyph.width + 1;
|
|
248
|
-
int h = 1 + glyph.height + 1;
|
|
249
|
-
|
|
250
|
-
// Converting the pixels array from the PImage into a valid RGBA array for
|
|
251
|
-
// OpenGL.
|
|
252
|
-
int[] rgba = new int[w * h];
|
|
253
|
-
int t = 0;
|
|
254
|
-
int p = 0;
|
|
255
|
-
if (PGL.BIG_ENDIAN) {
|
|
256
|
-
java.util.Arrays.fill(rgba, 0, w, 0xFFFFFF00); // Set the first row to blank pixels.
|
|
257
|
-
t = w;
|
|
258
|
-
for (int y = 0; y < glyph.height; y++) {
|
|
259
|
-
rgba[t++] = 0xFFFFFF00; // Set the leftmost pixel in this row as blank
|
|
260
|
-
for (int x = 0; x < glyph.width; x++) {
|
|
261
|
-
rgba[t++] = 0xFFFFFF00 | glyph.image.pixels[p++];
|
|
262
|
-
}
|
|
263
|
-
rgba[t++] = 0xFFFFFF00; // Set the rightmost pixel in this row as blank
|
|
264
|
-
}
|
|
265
|
-
java.util.Arrays.fill(rgba, (h - 1) * w, h * w, 0xFFFFFF00); // Set the last row to blank pixels.
|
|
266
|
-
} else {
|
|
267
|
-
java.util.Arrays.fill(rgba, 0, w, 0x00FFFFFF); // Set the first row to blank pixels.
|
|
268
|
-
t = w;
|
|
269
|
-
for (int y = 0; y < glyph.height; y++) {
|
|
270
|
-
rgba[t++] = 0x00FFFFFF; // Set the leftmost pixel in this row as blank
|
|
271
|
-
for (int x = 0; x < glyph.width; x++) {
|
|
272
|
-
rgba[t++] = (glyph.image.pixels[p++] << 24) | 0x00FFFFFF;
|
|
273
|
-
}
|
|
274
|
-
rgba[t++] = 0x00FFFFFF; // Set the rightmost pixel in this row as blank
|
|
275
|
-
}
|
|
276
|
-
java.util.Arrays.fill(rgba, (h - 1) * w, h * w, 0x00FFFFFF); // Set the last row to blank pixels.
|
|
277
|
-
}
|
|
278
253
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
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++];
|
|
284
280
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
} else {
|
|
296
|
-
// A new texture has been created. Reseting texture coordinates
|
|
297
|
-
// and line.
|
|
298
|
-
offsetX = 0;
|
|
299
|
-
offsetY = 0;
|
|
300
|
-
lineHeight = 0;
|
|
301
|
-
}
|
|
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;
|
|
302
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
|
+
}
|
|
303
296
|
|
|
304
|
-
|
|
305
|
-
|
|
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
|
+
}
|
|
306
321
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
System.arraycopy(glyphTexinfos, 0, temp, 0, glyphTexinfos.length);
|
|
310
|
-
glyphTexinfos = temp;
|
|
311
|
-
}
|
|
322
|
+
TextureInfo tinfo = new TextureInfo(lastTex, offsetX, offsetY, w, h, rgba);
|
|
323
|
+
offsetX += w;
|
|
312
324
|
|
|
313
|
-
|
|
314
|
-
|
|
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;
|
|
315
329
|
}
|
|
316
330
|
|
|
317
|
-
|
|
331
|
+
glyphTexinfos[idx] = tinfo;
|
|
332
|
+
texinfoMap.put(glyph, tinfo);
|
|
333
|
+
}
|
|
334
|
+
|
|
318
335
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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;
|
|
326
344
|
|
|
327
|
-
|
|
345
|
+
TextureInfo(int tidx, int cropX, int cropY, int cropW, int cropH,
|
|
328
346
|
int[] pix) {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
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
|
+
}
|
|
342
360
|
|
|
343
|
-
void updateUV() {
|
|
344
|
-
width = textures[texIndex].glWidth;
|
|
345
|
-
height = textures[texIndex].glHeight;
|
|
346
361
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
v1 = v0 - (float) crop[3] / (float) height;
|
|
351
|
-
}
|
|
362
|
+
void updateUV() {
|
|
363
|
+
width = textures[texIndex].glWidth;
|
|
364
|
+
height = textures[texIndex].glHeight;
|
|
352
365
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
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);
|
|
357
376
|
}
|
|
377
|
+
}
|
|
358
378
|
}
|