processing 0.5.30 → 0.5.32

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.
@@ -45,15 +45,16 @@ module Processing
45
45
  #
46
46
  DEGREES = :degrees
47
47
 
48
- # Mode for rectMode(), ellipseMode() and imageMode().
48
+ # Mode for rectMode(), ellipseMode(), imageMode(), and shapeMode().
49
49
  #
50
50
  CORNER = :corner
51
51
 
52
- # Mode for rectMode(), ellipseMode() and imageMode().
52
+ # Mode for rectMode(), ellipseMode(), imageMode(), and shapeMode().
53
53
  #
54
54
  CORNERS = :corners
55
55
 
56
- # Mode for rectMode(), ellipseMode(), imageMode() and textAlign().
56
+ # Mode for rectMode(), ellipseMode(), imageMode(), shapeMode(),
57
+ # and textAlign().
57
58
  #
58
59
  CENTER = :center
59
60
 
@@ -128,6 +129,18 @@ module Processing
128
129
  # Mode for textAlign().
129
130
  BASELINE = :baseline
130
131
 
132
+ # Mode for textureMode().
133
+ IMAGE = :image
134
+
135
+ # Mode for textureMode().
136
+ NORMAL = :normal
137
+
138
+ # Mode for textureWrap().
139
+ CLAMP = :clamp
140
+
141
+ # Mode for textureWrap().
142
+ REPEAT = :repeat
143
+
131
144
  # Filter type for filter()
132
145
  THRESHOLD = :threshold
133
146
 
@@ -140,6 +153,57 @@ module Processing
140
153
  # Filter type for filter()
141
154
  BLUR = :blur
142
155
 
156
+ # Shape mode for createShape()
157
+ LINE = :line
158
+
159
+ # Shape mode for createShape()
160
+ RECT = :rect
161
+
162
+ # Shape mode for createShape()
163
+ ELLIPSE = :ellipse
164
+
165
+ # Shape mode for createShape()
166
+ ARC = :arc
167
+
168
+ # Shape mode for createShape()
169
+ TRIANGLE = :triangle
170
+
171
+ # Shape mode for createShape()
172
+ QUAD = :quad
173
+
174
+ # Shape mode for createShape()
175
+ GROUP = :group
176
+
177
+ # Shape mode for beginShape()
178
+ POINTS = :points
179
+
180
+ # Shape mode for beginShape()
181
+ LINES = :lines
182
+
183
+ # Shape mode for beginShape()
184
+ TRIANGLES = :triangles
185
+
186
+ # Shape mode for beginShape()
187
+ TRIANGLE_FAN = :triangle_fan
188
+
189
+ # Shape mode for beginShape()
190
+ TRIANGLE_STRIP = :triangle_strip
191
+
192
+ # Shape mode for beginShape()
193
+ QUADS = :quads
194
+
195
+ # Shape mode for beginShape()
196
+ QUAD_STRIP = :quad_strip
197
+
198
+ # Shape mode for beginShape()
199
+ TESS = :tess
200
+
201
+ # OPEN flag for endShape()
202
+ OPEN = :open
203
+
204
+ # CLOSE flag for endShape()
205
+ CLOSE = :close
206
+
143
207
  # Key codes.
144
208
  ENTER = :enter
145
209
  SPACE = :space
@@ -195,6 +259,12 @@ module Processing
195
259
  # @private
196
260
  RAD2DEG__ = 180.0 / Math::PI
197
261
 
262
+ # @private
263
+ FONT_SIZE_DEFAULT__ = 12
264
+
265
+ # @private
266
+ FONT_SIZE_MAX__ = 256
267
+
198
268
  # @private
199
269
  def init__(image, painter)
200
270
  @drawing__ = false
@@ -206,14 +276,16 @@ module Processing
206
276
  @rectMode__ = nil
207
277
  @ellipseMode__ = nil
208
278
  @imageMode__ = nil
279
+ @shapeMode__ = nil
209
280
  @blendMode__ = nil
210
281
  @textAlignH__ = nil
211
282
  @textAlignV__ = nil
283
+ @textFont__ = nil
212
284
  @tint__ = nil
213
285
  @filter__ = nil
286
+ @pixels__ = nil
214
287
  @matrixStack__ = []
215
288
  @styleStack__ = []
216
- @fontCache__ = {}
217
289
 
218
290
  updateCanvas__ image, painter
219
291
 
@@ -222,10 +294,14 @@ module Processing
222
294
  rectMode CORNER
223
295
  ellipseMode CENTER
224
296
  imageMode CORNER
297
+ shapeMode CORNER
225
298
  blendMode BLEND
226
299
  strokeCap ROUND
227
300
  strokeJoin MITER
228
301
  textAlign LEFT
302
+ textFont createFont(nil, nil)
303
+ textureMode IMAGE
304
+ textureWrap CLAMP
229
305
 
230
306
  fill 255
231
307
  stroke 0
@@ -235,7 +311,9 @@ module Processing
235
311
 
236
312
  # @private
237
313
  def updateCanvas__(image, painter)
238
- @image__, @painter__ = image, painter
314
+ @image__, @painter__ = image, painter
315
+ @painter__.miter_limit = 10
316
+ @painter__.stroke_outset = 0.5
239
317
  end
240
318
 
241
319
  # @private
@@ -257,7 +335,7 @@ module Processing
257
335
  # @return [Numeric] width
258
336
  #
259
337
  def width()
260
- @image__.width
338
+ getInternal__.width
261
339
  end
262
340
 
263
341
  # Returns the height of the graphics object.
@@ -265,7 +343,7 @@ module Processing
265
343
  # @return [Numeric] height
266
344
  #
267
345
  def height()
268
- @image__.height
346
+ getInternal__.height
269
347
  end
270
348
 
271
349
  # Returns the width of the graphics object in pixels.
@@ -387,17 +465,21 @@ module Processing
387
465
 
388
466
  # @private
389
467
  private def toRGBA__(*args)
390
- a, b, c, d = args
468
+ a, b = args
391
469
  return parseColor__(a, b || alphaMax__) if a.kind_of?(String)
470
+ toRaysColor__(*args).to_a
471
+ end
392
472
 
473
+ # @private
474
+ def toRaysColor__(*args)
475
+ a, b, c, d = args
393
476
  rgba = case args.size
394
477
  when 1, 2 then [a, a, a, b || alphaMax__]
395
478
  when 3, 4 then [a, b, c, d || alphaMax__]
396
479
  else raise ArgumentError
397
480
  end
398
- rgba = rgba.map.with_index {|value, i| value / @colorMaxes__[i]}
399
- color = @hsbColor__ ? Rays::Color.hsv(*rgba) : Rays::Color.new(*rgba)
400
- color.to_a
481
+ rgba = rgba.map.with_index {|value, i| value / @colorMaxes__[i]}
482
+ @hsbColor__ ? Rays::Color.hsv(*rgba) : Rays::Color.new(*rgba)
401
483
  end
402
484
 
403
485
  # @private
@@ -434,7 +516,7 @@ module Processing
434
516
  end
435
517
 
436
518
  # @private
437
- def toAngle__(angle)
519
+ def toDegrees__(angle)
438
520
  angle * @angleScale__
439
521
  end
440
522
 
@@ -460,8 +542,8 @@ module Processing
460
542
  #
461
543
  # CORNER -> rect(left, top, width, height)
462
544
  # CORNERS -> rect(left, top, right, bottom)
463
- # CENTER -> rect(center_x, center_y, width, height)
464
- # RADIUS -> rect(center_x, center_y, radius_h, radius_v)
545
+ # CENTER -> rect(centerX, centerY, width, height)
546
+ # RADIUS -> rect(centerX, centerY, radiusH, radiusV)
465
547
  #
466
548
  # @param mode [CORNER, CORNERS, CENTER, RADIUS]
467
549
  #
@@ -475,8 +557,8 @@ module Processing
475
557
  #
476
558
  # CORNER -> ellipse(left, top, width, height)
477
559
  # CORNERS -> ellipse(left, top, right, bottom)
478
- # CENTER -> ellipse(center_x, center_y, width, height)
479
- # RADIUS -> ellipse(center_x, center_y, radius_h, radius_v)
560
+ # CENTER -> ellipse(centerX, centerY, width, height)
561
+ # RADIUS -> ellipse(centerX, centerY, radiusH, radiusV)
480
562
  #
481
563
  # @param mode [CORNER, CORNERS, CENTER, RADIUS]
482
564
  #
@@ -490,7 +572,7 @@ module Processing
490
572
  #
491
573
  # CORNER -> image(img, left, top, width, height)
492
574
  # CORNERS -> image(img, left, top, right, bottom)
493
- # CENTER -> image(img, center_x, center_y, width, height)
575
+ # CENTER -> image(img, centerX, centerY, width, height)
494
576
  #
495
577
  # @param mode [CORNER, CORNERS, CENTER]
496
578
  #
@@ -500,6 +582,20 @@ module Processing
500
582
  @imageMode__ = mode
501
583
  end
502
584
 
585
+ # Sets shape mode. Default is CORNER.
586
+ #
587
+ # CORNER -> shape(shp, left, top, width, height)
588
+ # CORNERS -> shape(shp, left, top, right, bottom)
589
+ # CENTER -> shape(shp, centerX, centerY, width, height)
590
+ #
591
+ # @param mode [CORNER, CORNERS, CENTER]
592
+ #
593
+ # @return [nil] nil
594
+ #
595
+ def shapeMode(mode)
596
+ @shapeMode__ = mode
597
+ end
598
+
503
599
  # @private
504
600
  private def toXYWH__(mode, a, b, c, d)
505
601
  case mode
@@ -548,6 +644,11 @@ module Processing
548
644
  nil
549
645
  end
550
646
 
647
+ # @private
648
+ def getFill__()
649
+ @painter__.fill
650
+ end
651
+
551
652
  # Disables filling.
552
653
  #
553
654
  # @return [nil] nil
@@ -653,6 +754,11 @@ module Processing
653
754
  @tint__ = nil
654
755
  end
655
756
 
757
+ # @private
758
+ def getTint__()
759
+ @tint__ ? toRGBA__(*@tint__) : 1
760
+ end
761
+
656
762
  # Limits the drawable rectangle.
657
763
  #
658
764
  # The parameters a, b, c, and d are determined by rectMode().
@@ -679,7 +785,9 @@ module Processing
679
785
  nil
680
786
  end
681
787
 
682
- # Sets font.
788
+ # Sets text font.
789
+ #
790
+ # (Passing a font name as the first parameter is deprecated)
683
791
  #
684
792
  # @overload textFont(font)
685
793
  # @overload textFont(name)
@@ -690,11 +798,18 @@ module Processing
690
798
  # @param name [String] font name
691
799
  # @param size [Numeric] font size (max 256)
692
800
  #
693
- # @return [Font] current font
801
+ # @return [nil] nil
694
802
  #
695
- def textFont(font = nil, size = nil)
696
- setFont__ font, size if font || size
697
- Font.new @painter__.font
803
+ def textFont(font, size = nil)
804
+ size = FONT_SIZE_MAX__ if size && size > FONT_SIZE_MAX__
805
+ if font.nil? || font.kind_of?(String)
806
+ font = createFont font, size
807
+ elsif size
808
+ font.setSize__ size
809
+ end
810
+ @textFont__ = font
811
+ @painter__.font = font.getInternal__
812
+ nil
698
813
  end
699
814
 
700
815
  # Sets text size.
@@ -704,8 +819,7 @@ module Processing
704
819
  # @return [nil] nil
705
820
  #
706
821
  def textSize(size)
707
- setFont__ nil, size
708
- nil
822
+ textFont @textFont__, size
709
823
  end
710
824
 
711
825
  def textWidth(str)
@@ -725,16 +839,46 @@ module Processing
725
839
  @textAlignV__ = vertical
726
840
  end
727
841
 
842
+ def texture(image)
843
+ @painter__.texture image&.getInternal__
844
+ nil
845
+ end
846
+
728
847
  # @private
729
- def setFont__(fontOrName, size)
730
- name = case fontOrName
731
- when Font then fontOrName.name
732
- else fontOrName || @painter__.font.name
733
- end
734
- size ||= @painter__.font.size
735
- size = 256 if size > 256
736
- font = @fontCache__[[name, size]] ||= Rays::Font.new name, size
737
- @painter__.font = font
848
+ def drawWithTexture__(&block)
849
+ if @painter__.texture
850
+ @painter__.push fill: getTint__, &block
851
+ else
852
+ block.call
853
+ end
854
+ end
855
+
856
+ # Sets the coordinate space for texture mapping.
857
+ #
858
+ # @param mode [IMAGE, NORMAL] image coordinate, or normalized coordinate
859
+ #
860
+ # @return [nil] nil
861
+ #
862
+ # @see https://processing.org/reference/textureMode_.html
863
+ # @see https://p5js.org/reference/#/p5/textureMode
864
+ #
865
+ def textureMode(mode)
866
+ @painter__.texcoord_mode = mode
867
+ nil
868
+ end
869
+
870
+ # Sets the texture wrapping mode.
871
+ #
872
+ # @param wrap [CLAMP, REPEAT] how texutres behave when go outside of the range
873
+ #
874
+ # @return [nil] nil
875
+ #
876
+ # @see https://processing.org/reference/textureWrap_.html
877
+ # @see https://p5js.org/reference/#/p5/textureWrap
878
+ #
879
+ def textureWrap(wrap)
880
+ @painter__.texcoord_wrap = wrap
881
+ nil
738
882
  end
739
883
 
740
884
  # Sets shader.
@@ -924,9 +1068,8 @@ module Processing
924
1068
  def arc(a, b, c, d, start, stop)
925
1069
  assertDrawing__
926
1070
  x, y, w, h = toXYWH__ @ellipseMode__, a, b, c, d
927
- start = toAngle__(-start)
928
- stop = toAngle__(-stop)
929
- @painter__.ellipse x, y, w, h, from: start, to: stop
1071
+ from, to = toDegrees__(-start), toDegrees__(-stop)
1072
+ @painter__.ellipse x, y, w, h, from: from, to: to
930
1073
  nil
931
1074
  end
932
1075
 
@@ -1087,13 +1230,196 @@ module Processing
1087
1230
  def image(img, a, b, c = nil, d = nil)
1088
1231
  assertDrawing__
1089
1232
  x, y, w, h = toXYWH__ @imageMode__, a, b, c || img.width, d || img.height
1090
- tint = @tint__ ? toRGBA__(*@tint__) : 1
1091
- img.drawImage__ @painter__, x, y, w, h, fill: tint, stroke: :none
1233
+ img.drawImage__ @painter__, x, y, w, h, fill: getTint__, stroke: :none
1092
1234
  nil
1093
1235
  end
1094
1236
 
1095
1237
  alias drawImage image
1096
1238
 
1239
+ # Draws a shape.
1240
+ #
1241
+ # The parameters a, b, c, and d are determined by shapeMode().
1242
+ #
1243
+ # @overload shape(img, a, b)
1244
+ # @overload shape(img, a, b, c, d)
1245
+ #
1246
+ # @param shp [Shape] shape to draw
1247
+ # @param a [Numeric] horizontal position of the shape, by default
1248
+ # @param b [Numeric] vertical position of the shape, by default
1249
+ # @param c [Numeric] width of the shape, by default
1250
+ # @param d [Numeric] height of the shape, by default
1251
+ #
1252
+ # @return [nil] nil
1253
+ #
1254
+ def shape(shp, a = 0, b = 0, c = nil, d = nil)
1255
+ assertDrawing__
1256
+ return nil unless shp.isVisible
1257
+
1258
+ drawWithTexture__ do |_|
1259
+ if c || d || @shapeMode__ != CORNER
1260
+ x, y, w, h = toXYWH__ @shapeMode__, a, b, c || shp.width, d || shp.height
1261
+ shp.draw__ @painter__, x, y, w, h
1262
+ else
1263
+ shp.draw__ @painter__, a, b
1264
+ end
1265
+ end
1266
+ nil
1267
+ end
1268
+
1269
+ alias drawShape shape
1270
+
1271
+ # Begins drawing complex shapes.
1272
+ #
1273
+ # @param type [POINTS, LINES, TRIANGLES, TRIANGLE_FAN, TRIANGLE_STRIP, QUADS, QUAD_STRIP, TESS]
1274
+ #
1275
+ # @return [nil] nil
1276
+ #
1277
+ # @example
1278
+ # # Draws polygon
1279
+ # beginShape
1280
+ # vertex 10, 10
1281
+ # vertex 10, 50
1282
+ # vertex 50, 50
1283
+ # vertex 90, 10
1284
+ # endShape CLOSE
1285
+ #
1286
+ # # Draws triangles
1287
+ # beginShape TRIANGLES
1288
+ # vertex 10, 10
1289
+ # vertex 10, 50
1290
+ # vertex 50, 50
1291
+ # endShape
1292
+ #
1293
+ # @see https://processing.org/reference/beginShape_.html
1294
+ #
1295
+ def beginShape(type = nil)
1296
+ raise "beginShape() cannot be called twice" if @drawingShape__
1297
+ @drawingShape__ = createShape
1298
+ @drawingShape__.beginShape type
1299
+ end
1300
+
1301
+ # Ends drawing complex shapes.
1302
+ #
1303
+ # @overload endShape()
1304
+ # @overload endShape(CLOSE)
1305
+ #
1306
+ # @param mode [CLOSE] Use CLOSE to create looped polygon
1307
+ #
1308
+ # @return [nil] nil
1309
+ #
1310
+ # @see https://processing.org/reference/endShape_.html
1311
+ #
1312
+ def endShape(mode = nil)
1313
+ s = @drawingShape__ or raise "endShape() must be called after beginShape()"
1314
+ s.endShape mode
1315
+ shape s
1316
+ @drawingShape__ = nil
1317
+ nil
1318
+ end
1319
+
1320
+ # Begins drawing a hole inside shape.
1321
+ #
1322
+ # @return [nil] nil
1323
+ #
1324
+ # @example
1325
+ # beginShape
1326
+ # vertex 10, 10
1327
+ # vertex 10, 50
1328
+ # vertex 50, 50
1329
+ # vertex 90, 10
1330
+ # beginContour
1331
+ # vertex 20, 20
1332
+ # vertex 30, 20
1333
+ # vertex 30, 30
1334
+ # vertex 20, 30
1335
+ # endContour
1336
+ # endShape CLOSE
1337
+ #
1338
+ # @see https://processing.org/reference/beginContour_.html
1339
+ # @see https://p5js.org/reference/#/p5/beginContour
1340
+ #
1341
+ def beginContour()
1342
+ (@drawingShape__ or raise "beginContour() must be called after beginShape()")
1343
+ .beginContour
1344
+ end
1345
+
1346
+ # Ends drawing a hole.
1347
+ #
1348
+ # @return [nil] nil
1349
+ #
1350
+ # @see https://processing.org/reference/endContour_.html
1351
+ # @see https://p5js.org/reference/#/p5/endContour
1352
+ #
1353
+ def endContour()
1354
+ (@drawingShape__ or raise "endContour() must be called after beginShape()")
1355
+ .endContour
1356
+ end
1357
+
1358
+ # Append vertex for shape polygon.
1359
+ #
1360
+ # @overload vertex(x, y)
1361
+ # @overload vertex(x, y, u, v)
1362
+ #
1363
+ # @param x [Numeric] x position of vertex
1364
+ # @param y [Numeric] y position of vertex
1365
+ # @param u [Numeric] u texture coordinate of vertex
1366
+ # @param v [Numeric] v texture coordinate of vertex
1367
+ #
1368
+ # @return [nil] nil
1369
+ #
1370
+ # @see https://processing.org/reference/vertex_.html
1371
+ # @see https://p5js.org/reference/#/p5/vertex
1372
+ #
1373
+ def vertex(x, y, u = nil, v = nil)
1374
+ (@drawingShape__ or raise "vertex() must be called after beginShape()")
1375
+ .vertex x, y, u, v
1376
+ end
1377
+
1378
+ # Append curve vertex for shape polygon.
1379
+ #
1380
+ # @param x [Numeric] x position of vertex
1381
+ # @param y [Numeric] y position of vertex
1382
+ #
1383
+ # @return [nil] nil
1384
+ #
1385
+ # @see https://processing.org/reference/curveVertex_.html
1386
+ # @see https://p5js.org/reference/#/p5/curveVertex
1387
+ #
1388
+ def curveVertex(x, y)
1389
+ (@drawingShape__ or raise "curveVertex() must be called after beginShape()")
1390
+ .curveVertex x, y
1391
+ end
1392
+
1393
+ # Append bezier vertex for shape polygon.
1394
+ #
1395
+ # @param x [Numeric] x position of vertex
1396
+ # @param y [Numeric] y position of vertex
1397
+ #
1398
+ # @return [nil] nil
1399
+ #
1400
+ # @see https://processing.org/reference/bezierVertex_.html
1401
+ # @see https://p5js.org/reference/#/p5/bezierVertex
1402
+ #
1403
+ def bezierVertex(x2, y2, x3, y3, x4, y4)
1404
+ (@drawingShape__ or raise "bezierVertex() must be called after beginShape()")
1405
+ .bezierVertex x2, y2, x3, y3, x4, y4
1406
+ end
1407
+
1408
+ # Append quadratic vertex for shape polygon.
1409
+ #
1410
+ # @param x [Numeric] x position of vertex
1411
+ # @param y [Numeric] y position of vertex
1412
+ #
1413
+ # @return [nil] nil
1414
+ #
1415
+ # @see https://processing.org/reference/quadraticVertex_.html
1416
+ # @see https://p5js.org/reference/#/p5/quadraticVertex
1417
+ #
1418
+ def quadraticVertex(cx, cy, x3, y3)
1419
+ (@drawingShape__ or raise "quadraticVertex() must be called after beginShape()")
1420
+ .quadraticVertex cx, cy, x3, y3
1421
+ end
1422
+
1097
1423
  # Copies image.
1098
1424
  #
1099
1425
  # @overload copy(sx, sy, sw, sh, dx, dy, dw, dh)
@@ -1135,11 +1461,34 @@ module Processing
1135
1461
  #
1136
1462
  def blend(img = nil, sx, sy, sw, sh, dx, dy, dw, dh, mode)
1137
1463
  assertDrawing__
1138
- tint = @tint__ ? toRGBA__(*@tint__) : 1
1139
- img ||= self
1140
- img.drawImage__(
1464
+ (img || self).drawImage__(
1141
1465
  @painter__, sx, sy, sw, sh, dx, dy, dw, dh,
1142
- fill: tint, stroke: :none, blend_mode: mode)
1466
+ fill: getTint__, stroke: :none, blend_mode: mode)
1467
+ end
1468
+
1469
+ # Loads all pixels to the 'pixels' array.
1470
+ #
1471
+ # @return [nil] nil
1472
+ #
1473
+ def loadPixels()
1474
+ @pixels__ = getInternal__.pixels
1475
+ end
1476
+
1477
+ # Update the image pixels with the 'pixels' array.
1478
+ #
1479
+ # @return [nil] nil
1480
+ #
1481
+ def updatePixels()
1482
+ return unless @pixels__
1483
+ getInternal__.pixels = @pixels__
1484
+ @pixels__ = nil
1485
+ end
1486
+
1487
+ # An array of all pixels.
1488
+ # Call loadPixels() before accessing the array.
1489
+ #
1490
+ def pixels()
1491
+ @pixels__
1143
1492
  end
1144
1493
 
1145
1494
  # Saves screen image to file.
@@ -1149,7 +1498,7 @@ module Processing
1149
1498
  # @return [nil] nil
1150
1499
  #
1151
1500
  def save(filename)
1152
- @window__.canvas_image.save filename
1501
+ getInternal__.save filename
1153
1502
  nil
1154
1503
  end
1155
1504
 
@@ -1181,9 +1530,9 @@ module Processing
1181
1530
  #
1182
1531
  # @return [nil] nil
1183
1532
  #
1184
- def scale(x, y)
1533
+ def scale(x, y = nil, z = 1)
1185
1534
  assertDrawing__
1186
- @painter__.scale x, y
1535
+ @painter__.scale x, (y || x), z
1187
1536
  nil
1188
1537
  end
1189
1538
 
@@ -1195,7 +1544,7 @@ module Processing
1195
1544
  #
1196
1545
  def rotate(angle)
1197
1546
  assertDrawing__
1198
- @painter__.rotate toAngle__ angle
1547
+ @painter__.rotate toDegrees__ angle
1199
1548
  nil
1200
1549
  end
1201
1550
 
@@ -1247,6 +1596,9 @@ module Processing
1247
1596
  @painter__.clip,
1248
1597
  @painter__.blend_mode,
1249
1598
  @painter__.font,
1599
+ @painter__.texture,
1600
+ @painter__.texcoord_mode,
1601
+ @painter__.texcoord_wrap,
1250
1602
  @painter__.shader,
1251
1603
  @hsbColor__,
1252
1604
  @colorMaxes__,
@@ -1254,8 +1606,10 @@ module Processing
1254
1606
  @rectMode__,
1255
1607
  @ellipseMode__,
1256
1608
  @imageMode__,
1609
+ @shapeMode__,
1257
1610
  @textAlignH__,
1258
1611
  @textAlignV__,
1612
+ @textFont__,
1259
1613
  @tint__,
1260
1614
  ]
1261
1615
  block.call if block
@@ -1278,6 +1632,9 @@ module Processing
1278
1632
  @painter__.clip,
1279
1633
  @painter__.blend_mode,
1280
1634
  @painter__.font,
1635
+ @painter__.texture,
1636
+ @painter__.texcoord_mode,
1637
+ @painter__.texcoord_wrap,
1281
1638
  @painter__.shader,
1282
1639
  @hsbColor__,
1283
1640
  @colorMaxes__,
@@ -1285,9 +1642,12 @@ module Processing
1285
1642
  @rectMode__,
1286
1643
  @ellipseMode__,
1287
1644
  @imageMode__,
1645
+ @shapeMode__,
1288
1646
  @textAlignH__,
1289
1647
  @textAlignV__,
1648
+ @textFont__,
1290
1649
  @tint__ = @styleStack__.pop
1650
+ @textFont__.setSize__ @painter__.font.size
1291
1651
  nil
1292
1652
  end
1293
1653
 
@@ -1699,7 +2059,7 @@ module Processing
1699
2059
  rand (low || 0).to_f...(high || 1).to_f
1700
2060
  end
1701
2061
 
1702
- # Creates a new vector.
2062
+ # Creates a new vector object.
1703
2063
  #
1704
2064
  # @overload createVector()
1705
2065
  # @overload createVector(x, y)
@@ -1715,7 +2075,17 @@ module Processing
1715
2075
  Vector.new(*args, context: self)
1716
2076
  end
1717
2077
 
1718
- # Creates a new image.
2078
+ # Creates a new font object.
2079
+ #
2080
+ # @param name [String] font name
2081
+ # @param size [Numeric] font size (max 256)
2082
+ #
2083
+ def createFont(name, size)
2084
+ size = FONT_SIZE_MAX__ if size && size > FONT_SIZE_MAX__
2085
+ Font.new Rays::Font.new(name, size || FONT_SIZE_DEFAULT__)
2086
+ end
2087
+
2088
+ # Creates a new image object.
1719
2089
  #
1720
2090
  # @overload createImage(w, h)
1721
2091
  # @overload createImage(w, h, format)
@@ -1732,6 +2102,67 @@ module Processing
1732
2102
  Image.new Rays::Image.new(w, h, colorspace).paint {background 0, 0}
1733
2103
  end
1734
2104
 
2105
+ # Creates a new shape object.
2106
+ #
2107
+ # @overload createShape()
2108
+ # @overload createShape(LINE, x1, y1, x2, y2)
2109
+ # @overload createShape(RECT, a, b, c, d)
2110
+ # @overload createShape(ELLIPSE, a, b, c, d)
2111
+ # @overload createShape(ARC, a, b, c, d, start, stop)
2112
+ # @overload createShape(TRIANGLE, x1, y1, x2, y2, x3, y3)
2113
+ # @overload createShape(QUAD, x1, y1, x2, y2, x3, y3, x4, y4)
2114
+ # @overload createShape(GROUP)
2115
+ #
2116
+ # @param kind [LINE, RECT, ELLIPSE, ARC, TRIANGLE, QUAD, GROUP]
2117
+ #
2118
+ def createShape(kind = nil, *args)
2119
+ case kind
2120
+ when LINE then createLineShape__( *args)
2121
+ when RECT then createRectShape__( *args)
2122
+ when ELLIPSE then createEllipseShape__( *args)
2123
+ when ARC then createArcShape__( *args)
2124
+ when TRIANGLE then createTriangleShape__(*args)
2125
+ when QUAD then createQuadShape__( *args)
2126
+ when GROUP then Shape.new nil, [], context: self
2127
+ when nil then Shape.new context: self
2128
+ else raise ArgumentError, "Unknown shape kind '#{kind}'"
2129
+ end
2130
+ end
2131
+
2132
+ # @private
2133
+ private def createLineShape__(x1, y1, x2, y2)
2134
+ Shape.new Rays::Polygon.line(x1, y1, x2, y2), context: self
2135
+ end
2136
+
2137
+ # @private
2138
+ private def createRectShape__(a, b, c, d)
2139
+ x, y, w, h = toXYWH__ @rectMode__, a, b, c, d
2140
+ Shape.new Rays::Polygon.rect(x, y, w, h), context: self
2141
+ end
2142
+
2143
+ # @private
2144
+ private def createEllipseShape__(a, b, c, d)
2145
+ x, y, w, h = toXYWH__ @ellipseMode__, a, b, c, d
2146
+ Shape.new Rays::Polygon.ellipse(x, y, w, h), context: self
2147
+ end
2148
+
2149
+ # @private
2150
+ private def createArcShape__(a, b, c, d, start, stop)
2151
+ x, y, w, h = toXYWH__ @ellipseMode__, a, b, c, d
2152
+ from, to = toDegrees__(-start), toDegrees__(-stop)
2153
+ Shape.new Rays::Polygon.ellipse(x, y, w, h, from: from, to: to), context: self
2154
+ end
2155
+
2156
+ # @private
2157
+ private def createTriangleShape__(x1, y1, x2, y2, x3, y3)
2158
+ Shape.new Rays::Polygon.new(x1, y1, x2, y2, x3, y3, loop: true), context: self
2159
+ end
2160
+
2161
+ # @private
2162
+ private def createQuadShape__(x1, y1, x2, y2, x3, y3, x4, y4)
2163
+ Shape.new Rays::Polygon.quads(x1, y1, x2, y2, x3, y3, x4, y4), context: self
2164
+ end
2165
+
1735
2166
  # Creates a new off-screen graphics context object.
1736
2167
  #
1737
2168
  # @param width [Numeric] width of graphics image
@@ -1790,6 +2221,23 @@ module Processing
1790
2221
  Capture.new(*args)
1791
2222
  end
1792
2223
 
2224
+ # Loads font from file.
2225
+ #
2226
+ # @param filename [String] file name to load font file
2227
+ #
2228
+ # @return [Font] loaded font object
2229
+ #
2230
+ # @see https://processing.org/reference/loadFont_.html
2231
+ # @see https://p5js.org/reference/#/p5/loadFont
2232
+ #
2233
+ def loadFont(filename)
2234
+ ext = File.extname filename
2235
+ raise "unsupported font type -- '#{ext}'" unless ext =~ /^\.?(ttf|otf)$/i
2236
+
2237
+ filename = httpGet__ filename, ext if filename =~ %r|^https?://|
2238
+ Font.new Rays::Font.load p filename
2239
+ end
2240
+
1793
2241
  # Loads image.
1794
2242
  #
1795
2243
  # @param filename [String] file name to load image
@@ -1797,11 +2245,39 @@ module Processing
1797
2245
  #
1798
2246
  # @return [Image] loaded image object
1799
2247
  #
2248
+ # @see https://processing.org/reference/loadImage_.html
2249
+ # @see https://p5js.org/reference/#/p5/loadImage
2250
+ #
1800
2251
  def loadImage(filename, extension = nil)
1801
- filename = getImage__ filename, extension if filename =~ %r|^https?://|
2252
+ ext = extension || File.extname(filename)
2253
+ raise "unsupported image type -- '#{ext}'" unless ext =~ /^\.?(png|jpg|gif)$/i
2254
+
2255
+ filename = httpGet__ filename, ext if filename =~ %r|^https?://|
1802
2256
  Image.new Rays::Image.load filename
1803
2257
  end
1804
2258
 
2259
+ # Loads image on a new thread.
2260
+ # When the image is loading, its width and height will be 0.
2261
+ # If an error occurs while loading the image, its width and height wil be -1.
2262
+ #
2263
+ # @param filename [String] file name to load image
2264
+ # @param extension [String] type of image to load (ex. 'png')
2265
+ #
2266
+ # @return [Image] loading image object
2267
+ #
2268
+ # @see https://processing.org/reference/requestImage_.html
2269
+ #
2270
+ def requestImage(filename, extension = nil)
2271
+ img = Image.new nil
2272
+ Thread.new filename, extension do |fn, ext|
2273
+ loaded = loadImage(fn, ext) or raise
2274
+ img.setInternal__ loaded.getInternal__
2275
+ rescue
2276
+ img.setInternal__ nil, true
2277
+ end
2278
+ img
2279
+ end
2280
+
1805
2281
  # Loads shader file.
1806
2282
  #
1807
2283
  # @overload loadShader(fragPath)
@@ -1817,10 +2293,7 @@ module Processing
1817
2293
  end
1818
2294
 
1819
2295
  # @private
1820
- private def getImage__(uri, ext)
1821
- ext ||= File.extname uri
1822
- raise "unsupported image type -- #{ext}" unless ext =~ /^\.?(png|jpg|gif)$/i
1823
-
2296
+ private def httpGet__(uri, ext)
1824
2297
  tmpdir = tmpdir__
1825
2298
  path = tmpdir + Digest::SHA1.hexdigest(uri)
1826
2299
  path = path.sub_ext ext