forked from arduino/Arduino
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPGraphics.java
5075 lines (4005 loc) · 138 KB
/
PGraphics.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
Copyright (c) 2004-09 Ben Fry and Casey Reas
Copyright (c) 2001-04 Massachusetts Institute of Technology
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.core;
import java.awt.*;
import java.util.HashMap;
/**
* Main graphics and rendering context, as well as the base API implementation for processing "core".
* Use this class if you need to draw into an off-screen graphics buffer.
* A PGraphics object can be constructed with the <b>createGraphics()</b> function.
* The <b>beginDraw()</b> and <b>endDraw()</b> methods (see above example) are necessary to set up the buffer and to finalize it.
* The fields and methods for this class are extensive;
* for a complete list visit the developer's reference: http://dev.processing.org/reference/core/
* =advanced
* Main graphics and rendering context, as well as the base API implementation.
*
* <h2>Subclassing and initializing PGraphics objects</h2>
* Starting in release 0149, subclasses of PGraphics are handled differently.
* The constructor for subclasses takes no parameters, instead a series of
* functions are called by the hosting PApplet to specify its attributes.
* <ul>
* <li>setParent(PApplet) - is called to specify the parent PApplet.
* <li>setPrimary(boolean) - called with true if this PGraphics will be the
* primary drawing surface used by the sketch, or false if not.
* <li>setPath(String) - called when the renderer needs a filename or output
* path, such as with the PDF or DXF renderers.
* <li>setSize(int, int) - this is called last, at which point it's safe for
* the renderer to complete its initialization routine.
* </ul>
* The functions were broken out because of the growing number of parameters
* such as these that might be used by a renderer, yet with the exception of
* setSize(), it's not clear which will be necessary. So while the size could
* be passed in to the constructor instead of a setSize() function, a function
* would still be needed that would notify the renderer that it was time to
* finish its initialization. Thus, setSize() simply does both.
*
* <h2>Know your rights: public vs. private methods</h2>
* Methods that are protected are often subclassed by other renderers, however
* they are not set 'public' because they shouldn't be part of the user-facing
* public API accessible from PApplet. That is, we don't want sketches calling
* textModeCheck() or vertexTexture() directly.
*
* <h2>Handling warnings and exceptions</h2>
* Methods that are unavailable generally show a warning, unless their lack of
* availability will soon cause another exception. For instance, if a method
* like getMatrix() returns null because it is unavailable, an exception will
* be thrown stating that the method is unavailable, rather than waiting for
* the NullPointerException that will occur when the sketch tries to use that
* method. As of release 0149, warnings will only be shown once, and exceptions
* have been changed to warnings where possible.
*
* <h2>Using xxxxImpl() for subclassing smoothness</h2>
* The xxxImpl() methods are generally renderer-specific handling for some
* subset if tasks for a particular function (vague enough for you?) For
* instance, imageImpl() handles drawing an image whose x/y/w/h and u/v coords
* have been specified, and screen placement (independent of imageMode) has
* been determined. There's no point in all renderers implementing the
* <tt>if (imageMode == BLAH)</tt> placement/sizing logic, so that's handled
* by PGraphics, which then calls imageImpl() once all that is figured out.
*
* <h2>His brother PImage</h2>
* PGraphics subclasses PImage so that it can be drawn and manipulated in a
* similar fashion. As such, many methods are inherited from PGraphics,
* though many are unavailable: for instance, resize() is not likely to be
* implemented; the same goes for mask(), depending on the situation.
*
* <h2>What's in PGraphics, what ain't</h2>
* For the benefit of subclasses, as much as possible has been placed inside
* PGraphics. For instance, bezier interpolation code and implementations of
* the strokeCap() method (that simply sets the strokeCap variable) are
* handled here. Features that will vary widely between renderers are located
* inside the subclasses themselves. For instance, all matrix handling code
* is per-renderer: Java 2D uses its own AffineTransform, P2D uses a PMatrix2D,
* and PGraphics3D needs to keep continually update forward and reverse
* transformations. A proper (future) OpenGL implementation will have all its
* matrix madness handled by the card. Lighting also falls under this
* category, however the base material property settings (emissive, specular,
* et al.) are handled in PGraphics because they use the standard colorMode()
* logic. Subclasses should override methods like emissiveFromCalc(), which
* is a point where a valid color has been defined internally, and can be
* applied in some manner based on the calcXxxx values.
*
* <h2>What's in the PGraphics documentation, what ain't</h2>
* Some things are noted here, some things are not. For public API, always
* refer to the <a href="http://processing.org/reference">reference</A>
* on Processing.org for proper explanations. <b>No attempt has been made to
* keep the javadoc up to date or complete.</b> It's an enormous task for
* which we simply do not have the time. That is, it's not something that
* to be done once—it's a matter of keeping the multiple references
* synchronized (to say nothing of the translation issues), while targeting
* them for their separate audiences. Ouch.
*
* We're working right now on synchronizing the two references, so the website reference
* is generated from the javadoc comments. Yay.
*
* @webref rendering
* @instanceName graphics any object of the type PGraphics
* @usage Web & Application
* @see processing.core.PApplet#createGraphics(int, int, String)
*/
public class PGraphics extends PImage implements PConstants {
// ........................................................
// width and height are already inherited from PImage
/// width minus one (useful for many calculations)
protected int width1;
/// height minus one (useful for many calculations)
protected int height1;
/// width * height (useful for many calculations)
public int pixelCount;
/// true if smoothing is enabled (read-only)
public boolean smooth = false;
// ........................................................
/// true if defaults() has been called a first time
protected boolean settingsInited;
/// set to a PGraphics object being used inside a beginRaw/endRaw() block
protected PGraphics raw;
// ........................................................
/** path to the file being saved for this renderer (if any) */
protected String path;
/**
* true if this is the main drawing surface for a particular sketch.
* This would be set to false for an offscreen buffer or if it were
* created any other way than size(). When this is set, the listeners
* are also added to the sketch.
*/
protected boolean primarySurface;
// ........................................................
/**
* Array of hint[] items. These are hacks to get around various
* temporary workarounds inside the environment.
* <p/>
* Note that this array cannot be static, as a hint() may result in a
* runtime change specific to a renderer. For instance, calling
* hint(DISABLE_DEPTH_TEST) has to call glDisable() right away on an
* instance of PGraphicsOpenGL.
* <p/>
* The hints[] array is allocated early on because it might
* be used inside beginDraw(), allocate(), etc.
*/
protected boolean[] hints = new boolean[HINT_COUNT];
////////////////////////////////////////////////////////////
// STYLE PROPERTIES
// Also inherits imageMode() and smooth() (among others) from PImage.
/** The current colorMode */
public int colorMode; // = RGB;
/** Max value for red (or hue) set by colorMode */
public float colorModeX; // = 255;
/** Max value for green (or saturation) set by colorMode */
public float colorModeY; // = 255;
/** Max value for blue (or value) set by colorMode */
public float colorModeZ; // = 255;
/** Max value for alpha set by colorMode */
public float colorModeA; // = 255;
/** True if colors are not in the range 0..1 */
boolean colorModeScale; // = true;
/** True if colorMode(RGB, 255) */
boolean colorModeDefault; // = true;
// ........................................................
// Tint color for images
/**
* True if tint() is enabled (read-only).
*
* Using tint/tintColor seems a better option for naming than
* tintEnabled/tint because the latter seems ugly, even though
* g.tint as the actual color seems a little more intuitive,
* it's just that g.tintEnabled is even more unintuitive.
* Same goes for fill and stroke, et al.
*/
public boolean tint;
/** tint that was last set (read-only) */
public int tintColor;
protected boolean tintAlpha;
protected float tintR, tintG, tintB, tintA;
protected int tintRi, tintGi, tintBi, tintAi;
// ........................................................
// Fill color
/** true if fill() is enabled, (read-only) */
public boolean fill;
/** fill that was last set (read-only) */
public int fillColor = 0xffFFFFFF;
protected boolean fillAlpha;
protected float fillR, fillG, fillB, fillA;
protected int fillRi, fillGi, fillBi, fillAi;
// ........................................................
// Stroke color
/** true if stroke() is enabled, (read-only) */
public boolean stroke;
/** stroke that was last set (read-only) */
public int strokeColor = 0xff000000;
protected boolean strokeAlpha;
protected float strokeR, strokeG, strokeB, strokeA;
protected int strokeRi, strokeGi, strokeBi, strokeAi;
// ........................................................
// Additional stroke properties
static protected final float DEFAULT_STROKE_WEIGHT = 1;
static protected final int DEFAULT_STROKE_JOIN = MITER;
static protected final int DEFAULT_STROKE_CAP = ROUND;
/**
* Last value set by strokeWeight() (read-only). This has a default
* setting, rather than fighting with renderers about whether that
* renderer supports thick lines.
*/
public float strokeWeight = DEFAULT_STROKE_WEIGHT;
/**
* Set by strokeJoin() (read-only). This has a default setting
* so that strokeJoin() need not be called by defaults,
* because subclasses may not implement it (i.e. PGraphicsGL)
*/
public int strokeJoin = DEFAULT_STROKE_JOIN;
/**
* Set by strokeCap() (read-only). This has a default setting
* so that strokeCap() need not be called by defaults,
* because subclasses may not implement it (i.e. PGraphicsGL)
*/
public int strokeCap = DEFAULT_STROKE_CAP;
// ........................................................
// Shape placement properties
// imageMode() is inherited from PImage
/** The current rect mode (read-only) */
public int rectMode;
/** The current ellipse mode (read-only) */
public int ellipseMode;
/** The current shape alignment mode (read-only) */
public int shapeMode;
/** The current image alignment (read-only) */
public int imageMode = CORNER;
// ........................................................
// Text and font properties
/** The current text font (read-only) */
public PFont textFont;
/** The current text align (read-only) */
public int textAlign = LEFT;
/** The current vertical text alignment (read-only) */
public int textAlignY = BASELINE;
/** The current text mode (read-only) */
public int textMode = MODEL;
/** The current text size (read-only) */
public float textSize;
/** The current text leading (read-only) */
public float textLeading;
// ........................................................
// Material properties
// PMaterial material;
// PMaterial[] materialStack;
// int materialStackPointer;
public float ambientR, ambientG, ambientB;
public float specularR, specularG, specularB;
public float emissiveR, emissiveG, emissiveB;
public float shininess;
// Style stack
static final int STYLE_STACK_DEPTH = 64;
PStyle[] styleStack = new PStyle[STYLE_STACK_DEPTH];
int styleStackDepth;
////////////////////////////////////////////////////////////
/** Last background color that was set, zero if an image */
public int backgroundColor = 0xffCCCCCC;
protected boolean backgroundAlpha;
protected float backgroundR, backgroundG, backgroundB, backgroundA;
protected int backgroundRi, backgroundGi, backgroundBi, backgroundAi;
// ........................................................
/**
* Current model-view matrix transformation of the form m[row][column],
* which is a "column vector" (as opposed to "row vector") matrix.
*/
// PMatrix matrix;
// public float m00, m01, m02, m03;
// public float m10, m11, m12, m13;
// public float m20, m21, m22, m23;
// public float m30, m31, m32, m33;
// static final int MATRIX_STACK_DEPTH = 32;
// float[][] matrixStack = new float[MATRIX_STACK_DEPTH][16];
// float[][] matrixInvStack = new float[MATRIX_STACK_DEPTH][16];
// int matrixStackDepth;
static final int MATRIX_STACK_DEPTH = 32;
// ........................................................
/**
* Java AWT Image object associated with this renderer. For P2D and P3D,
* this will be associated with their MemoryImageSource. For PGraphicsJava2D,
* it will be the offscreen drawing buffer.
*/
public Image image;
// ........................................................
// internal color for setting/calculating
protected float calcR, calcG, calcB, calcA;
protected int calcRi, calcGi, calcBi, calcAi;
protected int calcColor;
protected boolean calcAlpha;
/** The last RGB value converted to HSB */
int cacheHsbKey;
/** Result of the last conversion to HSB */
float[] cacheHsbValue = new float[3];
// ........................................................
/**
* Type of shape passed to beginShape(),
* zero if no shape is currently being drawn.
*/
protected int shape;
// vertices
static final int DEFAULT_VERTICES = 512;
protected float vertices[][] =
new float[DEFAULT_VERTICES][VERTEX_FIELD_COUNT];
protected int vertexCount; // total number of vertices
// ........................................................
protected boolean bezierInited = false;
public int bezierDetail = 20;
// used by both curve and bezier, so just init here
protected PMatrix3D bezierBasisMatrix =
new PMatrix3D(-1, 3, -3, 1,
3, -6, 3, 0,
-3, 3, 0, 0,
1, 0, 0, 0);
//protected PMatrix3D bezierForwardMatrix;
protected PMatrix3D bezierDrawMatrix;
// ........................................................
protected boolean curveInited = false;
protected int curveDetail = 20;
public float curveTightness = 0;
// catmull-rom basis matrix, perhaps with optional s parameter
protected PMatrix3D curveBasisMatrix;
protected PMatrix3D curveDrawMatrix;
protected PMatrix3D bezierBasisInverse;
protected PMatrix3D curveToBezierMatrix;
// ........................................................
// spline vertices
protected float curveVertices[][];
protected int curveVertexCount;
// ........................................................
// precalculate sin/cos lookup tables [toxi]
// circle resolution is determined from the actual used radii
// passed to ellipse() method. this will automatically take any
// scale transformations into account too
// [toxi 031031]
// changed table's precision to 0.5 degree steps
// introduced new vars for more flexible code
static final protected float sinLUT[];
static final protected float cosLUT[];
static final protected float SINCOS_PRECISION = 0.5f;
static final protected int SINCOS_LENGTH = (int) (360f / SINCOS_PRECISION);
static {
sinLUT = new float[SINCOS_LENGTH];
cosLUT = new float[SINCOS_LENGTH];
for (int i = 0; i < SINCOS_LENGTH; i++) {
sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION);
cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION);
}
}
// ........................................................
/** The current font if a Java version of it is installed */
//protected Font textFontNative;
/** Metrics for the current native Java font */
//protected FontMetrics textFontNativeMetrics;
/** Last text position, because text often mixed on lines together */
protected float textX, textY, textZ;
/**
* Internal buffer used by the text() functions
* because the String object is slow
*/
protected char[] textBuffer = new char[8 * 1024];
protected char[] textWidthBuffer = new char[8 * 1024];
protected int textBreakCount;
protected int[] textBreakStart;
protected int[] textBreakStop;
// ........................................................
public boolean edge = true;
// ........................................................
/// normal calculated per triangle
static protected final int NORMAL_MODE_AUTO = 0;
/// one normal manually specified per shape
static protected final int NORMAL_MODE_SHAPE = 1;
/// normals specified for each shape vertex
static protected final int NORMAL_MODE_VERTEX = 2;
/// Current mode for normals, one of AUTO, SHAPE, or VERTEX
protected int normalMode;
/// Keep track of how many calls to normal, to determine the mode.
//protected int normalCount;
/** Current normal vector. */
public float normalX, normalY, normalZ;
// ........................................................
/**
* Sets whether texture coordinates passed to
* vertex() calls will be based on coordinates that are
* based on the IMAGE or NORMALIZED.
*/
public int textureMode;
/**
* Current horizontal coordinate for texture, will always
* be between 0 and 1, even if using textureMode(IMAGE).
*/
public float textureU;
/** Current vertical coordinate for texture, see above. */
public float textureV;
/** Current image being used as a texture */
public PImage textureImage;
// ........................................................
// [toxi031031] new & faster sphere code w/ support flexibile resolutions
// will be set by sphereDetail() or 1st call to sphere()
float sphereX[], sphereY[], sphereZ[];
/// Number of U steps (aka "theta") around longitudinally spanning 2*pi
public int sphereDetailU = 0;
/// Number of V steps (aka "phi") along latitudinally top-to-bottom spanning pi
public int sphereDetailV = 0;
//////////////////////////////////////////////////////////////
// INTERNAL
/**
* Constructor for the PGraphics object. Use this to ensure that
* the defaults get set properly. In a subclass, use this(w, h)
* as the first line of a subclass' constructor to properly set
* the internal fields and defaults.
*
*/
public PGraphics() {
}
public void setParent(PApplet parent) { // ignore
this.parent = parent;
}
/**
* Set (or unset) this as the main drawing surface. Meaning that it can
* safely be set to opaque (and given a default gray background), or anything
* else that goes along with that.
*/
public void setPrimary(boolean primary) { // ignore
this.primarySurface = primary;
// base images must be opaque (for performance and general
// headache reasons.. argh, a semi-transparent opengl surface?)
// use createGraphics() if you want a transparent surface.
if (primarySurface) {
format = RGB;
}
}
public void setPath(String path) { // ignore
this.path = path;
}
/**
* The final step in setting up a renderer, set its size of this renderer.
* This was formerly handled by the constructor, but instead it's been broken
* out so that setParent/setPrimary/setPath can be handled differently.
*
* Important that this is ignored by preproc.pl because otherwise it will
* override setSize() in PApplet/Applet/Component, which will 1) not call
* super.setSize(), and 2) will cause the renderer to be resized from the
* event thread (EDT), causing a nasty crash as it collides with the
* animation thread.
*/
public void setSize(int w, int h) { // ignore
width = w;
height = h;
width1 = width - 1;
height1 = height - 1;
allocate();
reapplySettings();
}
/**
* Allocate memory for this renderer. Generally will need to be implemented
* for all renderers.
*/
protected void allocate() { }
/**
* Handle any takedown for this graphics context.
* <p>
* This is called when a sketch is shut down and this renderer was
* specified using the size() command, or inside endRecord() and
* endRaw(), in order to shut things off.
*/
public void dispose() { // ignore
}
//////////////////////////////////////////////////////////////
// FRAME
/**
* Some renderers have requirements re: when they are ready to draw.
*/
public boolean canDraw() { // ignore
return true;
}
/**
* Sets the default properties for a PGraphics object. It should be called before anything is drawn into the object.
* =advanced
* <p/>
* When creating your own PGraphics, you should call this before
* drawing anything.
*
* @webref
* @brief Sets up the rendering context
*/
public void beginDraw() { // ignore
}
/**
* Finalizes the rendering of a PGraphics object so that it can be shown on screen.
* =advanced
* <p/>
* When creating your own PGraphics, you should call this when
* you're finished drawing.
*
* @webref
* @brief Finalizes the renderering context
*/
public void endDraw() { // ignore
}
public void flush() {
// no-op, mostly for P3D to write sorted stuff
}
protected void checkSettings() {
if (!settingsInited) defaultSettings();
}
/**
* Set engine's default values. This has to be called by PApplet,
* somewhere inside setup() or draw() because it talks to the
* graphics buffer, meaning that for subclasses like OpenGL, there
* needs to be a valid graphics context to mess with otherwise
* you'll get some good crashing action.
*
* This is currently called by checkSettings(), during beginDraw().
*/
protected void defaultSettings() { // ignore
// System.out.println("PGraphics.defaultSettings() " + width + " " + height);
noSmooth(); // 0149
colorMode(RGB, 255);
fill(255);
stroke(0);
// other stroke attributes are set in the initializers
// inside the class (see above, strokeWeight = 1 et al)
// init shape stuff
shape = 0;
// init matrices (must do before lights)
//matrixStackDepth = 0;
rectMode(CORNER);
ellipseMode(DIAMETER);
// no current font
textFont = null;
textSize = 12;
textLeading = 14;
textAlign = LEFT;
textMode = MODEL;
// if this fella is associated with an applet, then clear its background.
// if it's been created by someone else through createGraphics,
// they have to call background() themselves, otherwise everything gets
// a gray background (when just a transparent surface or an empty pdf
// is what's desired).
// this background() call is for the Java 2D and OpenGL renderers.
if (primarySurface) {
//System.out.println("main drawing surface bg " + getClass().getName());
background(backgroundColor);
}
settingsInited = true;
// defaultSettings() overlaps reapplySettings(), don't do both
//reapplySettings = false;
}
/**
* Re-apply current settings. Some methods, such as textFont(), require that
* their methods be called (rather than simply setting the textFont variable)
* because they affect the graphics context, or they require parameters from
* the context (e.g. getting native fonts for text).
*
* This will only be called from an allocate(), which is only called from
* size(), which is safely called from inside beginDraw(). And it cannot be
* called before defaultSettings(), so we should be safe.
*/
protected void reapplySettings() {
// System.out.println("attempting reapplySettings()");
if (!settingsInited) return; // if this is the initial setup, no need to reapply
// System.out.println(" doing reapplySettings");
// new Exception().printStackTrace(System.out);
colorMode(colorMode, colorModeX, colorModeY, colorModeZ);
if (fill) {
// PApplet.println(" fill " + PApplet.hex(fillColor));
fill(fillColor);
} else {
noFill();
}
if (stroke) {
stroke(strokeColor);
// The if() statements should be handled inside the functions,
// otherwise an actual reset/revert won't work properly.
//if (strokeWeight != DEFAULT_STROKE_WEIGHT) {
strokeWeight(strokeWeight);
//}
// if (strokeCap != DEFAULT_STROKE_CAP) {
strokeCap(strokeCap);
// }
// if (strokeJoin != DEFAULT_STROKE_JOIN) {
strokeJoin(strokeJoin);
// }
} else {
noStroke();
}
if (tint) {
tint(tintColor);
} else {
noTint();
}
if (smooth) {
smooth();
} else {
// Don't bother setting this, cuz it'll anger P3D.
noSmooth();
}
if (textFont != null) {
// System.out.println(" textFont in reapply is " + textFont);
// textFont() resets the leading, so save it in case it's changed
float saveLeading = textLeading;
textFont(textFont, textSize);
textLeading(saveLeading);
}
textMode(textMode);
textAlign(textAlign, textAlignY);
background(backgroundColor);
//reapplySettings = false;
}
//////////////////////////////////////////////////////////////
// HINTS
/**
* Enable a hint option.
* <P>
* For the most part, hints are temporary api quirks,
* for which a proper api hasn't been properly worked out.
* for instance SMOOTH_IMAGES existed because smooth()
* wasn't yet implemented, but it will soon go away.
* <P>
* They also exist for obscure features in the graphics
* engine, like enabling/disabling single pixel lines
* that ignore the zbuffer, the way they do in alphabot.
* <P>
* Current hint options:
* <UL>
* <LI><TT>DISABLE_DEPTH_TEST</TT> -
* turns off the z-buffer in the P3D or OPENGL renderers.
* </UL>
*/
public void hint(int which) {
if (which > 0) {
hints[which] = true;
} else {
hints[-which] = false;
}
}
//////////////////////////////////////////////////////////////
// VERTEX SHAPES
/**
* Start a new shape of type POLYGON
*/
public void beginShape() {
beginShape(POLYGON);
}
/**
* Start a new shape.
* <P>
* <B>Differences between beginShape() and line() and point() methods.</B>
* <P>
* beginShape() is intended to be more flexible at the expense of being
* a little more complicated to use. it handles more complicated shapes
* that can consist of many connected lines (so you get joins) or lines
* mixed with curves.
* <P>
* The line() and point() command are for the far more common cases
* (particularly for our audience) that simply need to draw a line
* or a point on the screen.
* <P>
* From the code side of things, line() may or may not call beginShape()
* to do the drawing. In the beta code, they do, but in the alpha code,
* they did not. they might be implemented one way or the other depending
* on tradeoffs of runtime efficiency vs. implementation efficiency &mdash
* meaning the speed that things run at vs. the speed it takes me to write
* the code and maintain it. for beta, the latter is most important so
* that's how things are implemented.
*/
public void beginShape(int kind) {
shape = kind;
}
/**
* Sets whether the upcoming vertex is part of an edge.
* Equivalent to glEdgeFlag(), for people familiar with OpenGL.
*/
public void edge(boolean edge) {
this.edge = edge;
}
/**
* Sets the current normal vector. Only applies with 3D rendering
* and inside a beginShape/endShape block.
* <P/>
* This is for drawing three dimensional shapes and surfaces,
* allowing you to specify a vector perpendicular to the surface
* of the shape, which determines how lighting affects it.
* <P/>
* For the most part, PGraphics3D will attempt to automatically
* assign normals to shapes, but since that's imperfect,
* this is a better option when you want more control.
* <P/>
* For people familiar with OpenGL, this function is basically
* identical to glNormal3f().
*/
public void normal(float nx, float ny, float nz) {
normalX = nx;
normalY = ny;
normalZ = nz;
// if drawing a shape and the normal hasn't been set yet,
// then we need to set the normals for each vertex so far
if (shape != 0) {
if (normalMode == NORMAL_MODE_AUTO) {
// either they set the normals, or they don't [0149]
// for (int i = vertex_start; i < vertexCount; i++) {
// vertices[i][NX] = normalX;
// vertices[i][NY] = normalY;
// vertices[i][NZ] = normalZ;
// }
// One normal per begin/end shape
normalMode = NORMAL_MODE_SHAPE;
} else if (normalMode == NORMAL_MODE_SHAPE) {
// a separate normal for each vertex
normalMode = NORMAL_MODE_VERTEX;
}
}
}
/**
* Set texture mode to either to use coordinates based on the IMAGE
* (more intuitive for new users) or NORMALIZED (better for advanced chaps)
*/
public void textureMode(int mode) {
this.textureMode = mode;
}
/**
* Set texture image for current shape.
* Needs to be called between @see beginShape and @see endShape
*
* @param image reference to a PImage object
*/
public void texture(PImage image) {
textureImage = image;
}
protected void vertexCheck() {
if (vertexCount == vertices.length) {
float temp[][] = new float[vertexCount << 1][VERTEX_FIELD_COUNT];
System.arraycopy(vertices, 0, temp, 0, vertexCount);
vertices = temp;
}
}
public void vertex(float x, float y) {
vertexCheck();
float[] vertex = vertices[vertexCount];
curveVertexCount = 0;
vertex[X] = x;
vertex[Y] = y;
vertex[EDGE] = edge ? 1 : 0;
// if (fill) {
// vertex[R] = fillR;
// vertex[G] = fillG;
// vertex[B] = fillB;
// vertex[A] = fillA;
// }
if (fill || textureImage != null) {
if (textureImage == null) {
vertex[R] = fillR;
vertex[G] = fillG;
vertex[B] = fillB;
vertex[A] = fillA;
} else {
if (tint) {
vertex[R] = tintR;
vertex[G] = tintG;
vertex[B] = tintB;
vertex[A] = tintA;
} else {
vertex[R] = 1;
vertex[G] = 1;
vertex[B] = 1;
vertex[A] = 1;
}
}
}
if (stroke) {
vertex[SR] = strokeR;
vertex[SG] = strokeG;
vertex[SB] = strokeB;
vertex[SA] = strokeA;
vertex[SW] = strokeWeight;
}
if (textureImage != null) {
vertex[U] = textureU;