processing 0.5.30 → 0.5.32

Sign up to get free protection for your applications and to get access to all the features.
@@ -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