processing 0.4.0 → 0.5.1
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/.github/workflows/{release.yml → release-gem.yml} +21 -21
- data/.github/workflows/tag.yml +35 -0
- data/.github/workflows/test.yml +8 -9
- data/.github/workflows/utils.rb +55 -0
- data/ChangeLog.md +40 -28
- data/LICENSE +1 -1
- data/Rakefile +9 -34
- data/RubyProcessing.podspec +1 -1
- data/VERSION +1 -1
- data/examples/breakout.rb +2 -1
- data/examples/camera.rb +2 -1
- data/examples/clock.rb +3 -1
- data/examples/delay_camera.rb +2 -1
- data/examples/hello.rb +2 -1
- data/examples/image.rb +2 -1
- data/examples/shapes.rb +2 -1
- data/lib/processing/all.rb +20 -0
- data/lib/processing/capture.rb +119 -0
- data/lib/processing/context.rb +471 -0
- data/lib/processing/{module.rb → extension.rb} +3 -3
- data/lib/processing/font.rb +62 -0
- data/lib/processing/graphics.rb +40 -0
- data/lib/processing/graphics_context.rb +1676 -0
- data/lib/processing/image.rb +128 -0
- data/lib/processing/shader.rb +157 -0
- data/lib/processing/touch.rb +28 -0
- data/lib/processing/vector.rb +559 -0
- data/lib/processing.rb +30 -11
- data/lib/rubysketch-processing.rb +2 -1
- data/lib/rubysketch.rb +1 -1
- data/processing.gemspec +12 -6
- data/src/RubyProcessing.mm +1 -1
- data/test/helper.rb +8 -2
- data/test/{processing/test_graphics.rb → test_graphics.rb} +3 -3
- data/test/{processing/test_shader.rb → test_shader.rb} +3 -3
- data/test/{processing/test_utility.rb → test_utility.rb} +3 -3
- data/test/{processing/test_vector.rb → test_vector.rb} +8 -4
- metadata +112 -20
- data/lib/processing/include.rb +0 -25
- data/lib/processing/processing.rb +0 -3211
- data/test/processing/helper.rb +0 -11
@@ -0,0 +1,119 @@
|
|
1
|
+
module Processing
|
2
|
+
|
3
|
+
|
4
|
+
# Camera object.
|
5
|
+
#
|
6
|
+
class Capture
|
7
|
+
|
8
|
+
# Returns a list of available camera device names
|
9
|
+
#
|
10
|
+
# @return [Array] device name list
|
11
|
+
#
|
12
|
+
def self.list()
|
13
|
+
Rays::Camera.device_names
|
14
|
+
end
|
15
|
+
|
16
|
+
# Initialize camera object.
|
17
|
+
#
|
18
|
+
# @overload Capture.new()
|
19
|
+
# @overload Capture.new(cameraName)
|
20
|
+
# @overload Capture.new(requestWidth, requestHeight)
|
21
|
+
# @overload Capture.new(requestWidth, requestHeight, cameraName)
|
22
|
+
#
|
23
|
+
# @param requestWidth [Integer] captured image width
|
24
|
+
# @param requestHeight [Integer] captured image height
|
25
|
+
# @param cameraName [String] camera device name
|
26
|
+
#
|
27
|
+
def initialize(*args)
|
28
|
+
width, height, name =
|
29
|
+
if args.empty?
|
30
|
+
[-1, -1, nil]
|
31
|
+
elsif args[0].kind_of?(String)
|
32
|
+
[-1, -1, args[0]]
|
33
|
+
elsif args[0].kind_of?(Numeric) && args[1].kind_of?(Numeric)
|
34
|
+
[args[0], args[1], args[2]]
|
35
|
+
else
|
36
|
+
raise ArgumentError
|
37
|
+
end
|
38
|
+
@camera = Rays::Camera.new width, height, device_name: name
|
39
|
+
end
|
40
|
+
|
41
|
+
# Start capturing.
|
42
|
+
#
|
43
|
+
# @return [nil] nil
|
44
|
+
#
|
45
|
+
def start()
|
46
|
+
raise "Failed to start capture" unless @camera.start
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
# Stop capturing.
|
51
|
+
#
|
52
|
+
# @return [nil] nil
|
53
|
+
#
|
54
|
+
def stop()
|
55
|
+
@camera.stop
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns is the next captured image available?
|
60
|
+
#
|
61
|
+
# @return [Boolean] true means object has next frame
|
62
|
+
#
|
63
|
+
def available()
|
64
|
+
@camera.active?
|
65
|
+
end
|
66
|
+
|
67
|
+
# Reads next frame image
|
68
|
+
#
|
69
|
+
def read()
|
70
|
+
@camera.image
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns the width of captured image
|
74
|
+
#
|
75
|
+
# @return [Numeric] the width of captured image
|
76
|
+
#
|
77
|
+
def width()
|
78
|
+
@camera.image&.width || 0
|
79
|
+
end
|
80
|
+
|
81
|
+
# Returns the height of captured image
|
82
|
+
#
|
83
|
+
# @return [Numeric] the height of captured image
|
84
|
+
#
|
85
|
+
def height()
|
86
|
+
@camera.image&.height || 0
|
87
|
+
end
|
88
|
+
|
89
|
+
# Applies an image filter.
|
90
|
+
#
|
91
|
+
# overload filter(shader)
|
92
|
+
# overload filter(type)
|
93
|
+
# overload filter(type, param)
|
94
|
+
#
|
95
|
+
# @param shader [Shader] a fragment shader to apply
|
96
|
+
# @param type [THRESHOLD, GRAY, INVERT, BLUR] filter type
|
97
|
+
# @param param [Numeric] a parameter for each filter
|
98
|
+
#
|
99
|
+
def filter(*args)
|
100
|
+
@filter = Shader.createFilter__(*args)
|
101
|
+
end
|
102
|
+
|
103
|
+
# @private
|
104
|
+
def getInternal__()
|
105
|
+
@camera.image || (@dummyImage ||= Rays::Image.new 1, 1)
|
106
|
+
end
|
107
|
+
|
108
|
+
# @private
|
109
|
+
def drawImage__(painter, *args, **states)
|
110
|
+
shader = painter.shader || @filter&.getInternal__
|
111
|
+
painter.push shader: shader, **states do |_|
|
112
|
+
painter.image getInternal__, *args
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
end# Capture
|
117
|
+
|
118
|
+
|
119
|
+
end# Processing
|
@@ -0,0 +1,471 @@
|
|
1
|
+
module Processing
|
2
|
+
|
3
|
+
|
4
|
+
# Processing context
|
5
|
+
#
|
6
|
+
class Context
|
7
|
+
|
8
|
+
include GraphicsContext
|
9
|
+
|
10
|
+
Vector = Processing::Vector
|
11
|
+
Capture = Processing::Capture
|
12
|
+
Graphics = Processing::Graphics
|
13
|
+
Shader = Processing::Shader
|
14
|
+
|
15
|
+
# @private
|
16
|
+
@@context__ = nil
|
17
|
+
|
18
|
+
# @private
|
19
|
+
def self.context__()
|
20
|
+
@@context__
|
21
|
+
end
|
22
|
+
|
23
|
+
# @private
|
24
|
+
def initialize(window)
|
25
|
+
@@context__ = self
|
26
|
+
|
27
|
+
tmpdir__.tap {|dir| FileUtils.rm_r dir.to_s if dir.directory?}
|
28
|
+
|
29
|
+
@window__ = window
|
30
|
+
init__(
|
31
|
+
@window__.canvas_image,
|
32
|
+
@window__.canvas_painter.paint {background 0.8})
|
33
|
+
|
34
|
+
@loop__ = true
|
35
|
+
@redraw__ = false
|
36
|
+
@frameCount__ = 0
|
37
|
+
@key__ = nil
|
38
|
+
@keyCode__ = nil
|
39
|
+
@keysPressed__ = Set.new
|
40
|
+
@pointerPos__ =
|
41
|
+
@pointerPrevPos__ = Rays::Point.new 0
|
42
|
+
@pointersPressed__ = []
|
43
|
+
@touches__ = []
|
44
|
+
@motionGravity__ = createVector 0, 0
|
45
|
+
|
46
|
+
@window__.before_draw = proc {beginDraw__}
|
47
|
+
@window__.after_draw = proc {endDraw__}
|
48
|
+
@window__.update_canvas = proc {|i, p| updateCanvas__ i, p}
|
49
|
+
|
50
|
+
@window__.instance_variable_set :@context, self
|
51
|
+
def @window__.draw_screen(painter)
|
52
|
+
@context.drawImage__ painter
|
53
|
+
end
|
54
|
+
|
55
|
+
drawFrame = -> {
|
56
|
+
begin
|
57
|
+
push
|
58
|
+
@drawBlock__.call if @drawBlock__
|
59
|
+
ensure
|
60
|
+
pop
|
61
|
+
@frameCount__ += 1
|
62
|
+
end
|
63
|
+
}
|
64
|
+
|
65
|
+
@window__.draw = proc do |e|
|
66
|
+
if @loop__ || @redraw__
|
67
|
+
@redraw__ = false
|
68
|
+
drawFrame.call
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
updateKeyStates = -> event, pressed {
|
73
|
+
@key__ = event.chars
|
74
|
+
@keyCode__ = event.key
|
75
|
+
if pressed != nil
|
76
|
+
set, key = @keysPressed__, event.key
|
77
|
+
pressed ? set.add(key) : set.delete(key)
|
78
|
+
end
|
79
|
+
}
|
80
|
+
|
81
|
+
mouseButtonMap = {
|
82
|
+
mouse_left: LEFT,
|
83
|
+
mouse_right: RIGHT,
|
84
|
+
mouse_middle: CENTER
|
85
|
+
}
|
86
|
+
|
87
|
+
updatePointerStates = -> event, pressed = nil {
|
88
|
+
@pointerPrevPos__ = @pointerPos__
|
89
|
+
@pointerPos__ = event.pos.dup
|
90
|
+
@touches__ = event.pointers.map {|p| Touch.new(p.id, *p.pos.to_a)}
|
91
|
+
if pressed != nil
|
92
|
+
array = @pointersPressed__
|
93
|
+
event.types
|
94
|
+
.tap {|types| types.delete :mouse}
|
95
|
+
.map {|type| mouseButtonMap[type] || type}
|
96
|
+
.each {|type| pressed ? array.push(type) : array.delete(type)}
|
97
|
+
end
|
98
|
+
}
|
99
|
+
|
100
|
+
@window__.key_down = proc do |e|
|
101
|
+
updateKeyStates.call e, true
|
102
|
+
@keyPressedBlock__&.call
|
103
|
+
@keyTypedBlock__&.call if @key__ && !@key__.empty?
|
104
|
+
end
|
105
|
+
|
106
|
+
@window__.key_up = proc do |e|
|
107
|
+
updateKeyStates.call e, false
|
108
|
+
@keyReleasedBlock__&.call
|
109
|
+
end
|
110
|
+
|
111
|
+
@window__.pointer_down = proc do |e|
|
112
|
+
updatePointerStates.call e, true
|
113
|
+
@pointerDownStartPos__ = @pointerPos__.dup
|
114
|
+
(@touchStartedBlock__ || @mousePressedBlock__)&.call
|
115
|
+
end
|
116
|
+
|
117
|
+
@window__.pointer_up = proc do |e|
|
118
|
+
updatePointerStates.call e, false
|
119
|
+
(@touchEndedBlock__ || @mouseReleasedBlock__)&.call
|
120
|
+
if startPos = @pointerDownStartPos__
|
121
|
+
@mouseClickedBlock__&.call if (@pointerPos__ - startPos).length < 3
|
122
|
+
@pointerDownStartPos__ = nil
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
@window__.pointer_move = proc do |e|
|
127
|
+
updatePointerStates.call e
|
128
|
+
(@touchMovedBlock__ || @mouseMovedBlock__)&.call
|
129
|
+
end
|
130
|
+
|
131
|
+
@window__.pointer_drag = proc do |e|
|
132
|
+
updatePointerStates.call e
|
133
|
+
(@touchMovedBlock__ || @mouseDraggedBlock__)&.call
|
134
|
+
end
|
135
|
+
|
136
|
+
@window__.motion = proc do |e|
|
137
|
+
@motionGravity__ = createVector(*e.gravity.to_a(3))
|
138
|
+
@motionBlock__&.call
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Defines setup block.
|
143
|
+
#
|
144
|
+
# @return [nil] nil
|
145
|
+
#
|
146
|
+
def setup(&block)
|
147
|
+
@window__.setup = block
|
148
|
+
nil
|
149
|
+
end
|
150
|
+
|
151
|
+
# Defines draw block.
|
152
|
+
#
|
153
|
+
# @return [nil] nil
|
154
|
+
#
|
155
|
+
def draw(&block)
|
156
|
+
@drawBlock__ = block if block
|
157
|
+
nil
|
158
|
+
end
|
159
|
+
|
160
|
+
# @private
|
161
|
+
def hasDrawBlock__()
|
162
|
+
@drawBlock__ != nil
|
163
|
+
end
|
164
|
+
|
165
|
+
# Defines keyPressed block.
|
166
|
+
#
|
167
|
+
# @return [Boolean] is any key pressed or not
|
168
|
+
#
|
169
|
+
def keyPressed(&block)
|
170
|
+
@keyPressedBlock__ = block if block
|
171
|
+
not @keysPressed__.empty?
|
172
|
+
end
|
173
|
+
|
174
|
+
# Defines keyReleased block.
|
175
|
+
#
|
176
|
+
# @return [nil] nil
|
177
|
+
#
|
178
|
+
def keyReleased(&block)
|
179
|
+
@keyReleasedBlock__ = block if block
|
180
|
+
nil
|
181
|
+
end
|
182
|
+
|
183
|
+
# Defines keyTyped block.
|
184
|
+
#
|
185
|
+
# @return [nil] nil
|
186
|
+
#
|
187
|
+
def keyTyped(&block)
|
188
|
+
@keyTypedBlock__ = block if block
|
189
|
+
nil
|
190
|
+
end
|
191
|
+
|
192
|
+
# Defines mousePressed block.
|
193
|
+
#
|
194
|
+
# @return [Boolean] is any mouse button pressed or not
|
195
|
+
#
|
196
|
+
def mousePressed(&block)
|
197
|
+
@mousePressedBlock__ = block if block
|
198
|
+
not @pointersPressed__.empty?
|
199
|
+
end
|
200
|
+
|
201
|
+
# Defines mouseReleased block.
|
202
|
+
#
|
203
|
+
# @return [nil] nil
|
204
|
+
#
|
205
|
+
def mouseReleased(&block)
|
206
|
+
@mouseReleasedBlock__ = block if block
|
207
|
+
nil
|
208
|
+
end
|
209
|
+
|
210
|
+
# Defines mouseMoved block.
|
211
|
+
#
|
212
|
+
# @return [nil] nil
|
213
|
+
#
|
214
|
+
def mouseMoved(&block)
|
215
|
+
@mouseMovedBlock__ = block if block
|
216
|
+
nil
|
217
|
+
end
|
218
|
+
|
219
|
+
# Defines mouseDragged block.
|
220
|
+
#
|
221
|
+
# @return [nil] nil
|
222
|
+
#
|
223
|
+
def mouseDragged(&block)
|
224
|
+
@mouseDraggedBlock__ = block if block
|
225
|
+
nil
|
226
|
+
end
|
227
|
+
|
228
|
+
# Defines mouseClicked block.
|
229
|
+
#
|
230
|
+
# @return [nil] nil
|
231
|
+
#
|
232
|
+
def mouseClicked(&block)
|
233
|
+
@mouseClickedBlock__ = block if block
|
234
|
+
nil
|
235
|
+
end
|
236
|
+
|
237
|
+
# Defines touchStarted block.
|
238
|
+
#
|
239
|
+
# @return [nil] nil
|
240
|
+
#
|
241
|
+
def touchStarted(&block)
|
242
|
+
@touchStartedBlock__ = block if block
|
243
|
+
nil
|
244
|
+
end
|
245
|
+
|
246
|
+
# Defines touchEnded block.
|
247
|
+
#
|
248
|
+
# @return [nil] nil
|
249
|
+
#
|
250
|
+
def touchEnded(&block)
|
251
|
+
@touchEndedBlock__ = block if block
|
252
|
+
nil
|
253
|
+
end
|
254
|
+
|
255
|
+
# Defines touchMoved block.
|
256
|
+
#
|
257
|
+
# @return [nil] nil
|
258
|
+
#
|
259
|
+
def touchMoved(&block)
|
260
|
+
@touchMovedBlock__ = block if block
|
261
|
+
nil
|
262
|
+
end
|
263
|
+
|
264
|
+
# Defines motion block.
|
265
|
+
#
|
266
|
+
# @return [nil] nil
|
267
|
+
#
|
268
|
+
def motion(&block)
|
269
|
+
@motionBlock__ = block if block
|
270
|
+
nil
|
271
|
+
end
|
272
|
+
|
273
|
+
# Changes canvas size.
|
274
|
+
#
|
275
|
+
# @param width [Integer] new width
|
276
|
+
# @param height [Integer] new height
|
277
|
+
# @param pixelDensity [Numeric] new pixel density
|
278
|
+
#
|
279
|
+
# @return [nil] nil
|
280
|
+
#
|
281
|
+
def size(width, height, pixelDensity: self.pixelDensity)
|
282
|
+
resizeCanvas__ :size, width, height, pixelDensity
|
283
|
+
nil
|
284
|
+
end
|
285
|
+
|
286
|
+
# Changes canvas size.
|
287
|
+
#
|
288
|
+
# @param width [Integer] new width
|
289
|
+
# @param height [Integer] new height
|
290
|
+
# @param pixelDensity [Numeric] new pixel density
|
291
|
+
#
|
292
|
+
# @return [nil] nil
|
293
|
+
#
|
294
|
+
def createCanvas(width, height, pixelDensity: self.pixelDensity)
|
295
|
+
resizeCanvas__ :createCanvas, width, height, pixelDensity
|
296
|
+
nil
|
297
|
+
end
|
298
|
+
|
299
|
+
# Changes title of window.
|
300
|
+
#
|
301
|
+
# @param title [String] new title
|
302
|
+
#
|
303
|
+
# @return [nil] nil
|
304
|
+
#
|
305
|
+
def setTitle(title)
|
306
|
+
@window__.title = title
|
307
|
+
nil
|
308
|
+
end
|
309
|
+
|
310
|
+
# Changes and returns canvas pixel density.
|
311
|
+
#
|
312
|
+
# @param density [Numeric] new pixel density
|
313
|
+
#
|
314
|
+
# @return [Numeric] current pixel density
|
315
|
+
#
|
316
|
+
def pixelDensity(density = nil)
|
317
|
+
resizeCanvas__ :pixelDensity, width, height, density if density
|
318
|
+
@painter__.pixel_density
|
319
|
+
end
|
320
|
+
|
321
|
+
# @private
|
322
|
+
def resizeCanvas__(name, width, height, pixelDensity)
|
323
|
+
raise '#{name}() must be called on startup or setup block' if @started__
|
324
|
+
|
325
|
+
@painter__.__send__ :end_paint
|
326
|
+
@window__.resize_canvas width, height, pixelDensity
|
327
|
+
@window__.auto_resize = false
|
328
|
+
ensure
|
329
|
+
@painter__.__send__ :begin_paint
|
330
|
+
end
|
331
|
+
|
332
|
+
# Returns pixel density of display.
|
333
|
+
#
|
334
|
+
# @return [Numeric] pixel density
|
335
|
+
#
|
336
|
+
def displayDensity()
|
337
|
+
@window__.painter.pixel_density
|
338
|
+
end
|
339
|
+
|
340
|
+
# Returns window width.
|
341
|
+
#
|
342
|
+
# @return [Numeric] window width
|
343
|
+
#
|
344
|
+
def windowWidth()
|
345
|
+
@window__.width
|
346
|
+
end
|
347
|
+
|
348
|
+
# Returns window height.
|
349
|
+
#
|
350
|
+
# @return [Numeric] window height
|
351
|
+
#
|
352
|
+
def windowHeight()
|
353
|
+
@window__.height
|
354
|
+
end
|
355
|
+
|
356
|
+
# Returns number of frames since program started.
|
357
|
+
#
|
358
|
+
# @return [Integer] total number of frames
|
359
|
+
#
|
360
|
+
def frameCount()
|
361
|
+
@frameCount__
|
362
|
+
end
|
363
|
+
|
364
|
+
# Returns number of frames per second.
|
365
|
+
#
|
366
|
+
# @return [Float] frames per second
|
367
|
+
#
|
368
|
+
def frameRate()
|
369
|
+
@window__.event.fps
|
370
|
+
end
|
371
|
+
|
372
|
+
# Returns the last key that was pressed or released.
|
373
|
+
#
|
374
|
+
# @return [String] last key
|
375
|
+
#
|
376
|
+
def key()
|
377
|
+
@key__
|
378
|
+
end
|
379
|
+
|
380
|
+
# Returns the last key code that was pressed or released.
|
381
|
+
#
|
382
|
+
# @return [Symbol] last key code
|
383
|
+
#
|
384
|
+
def keyCode()
|
385
|
+
@keyCode__
|
386
|
+
end
|
387
|
+
|
388
|
+
# Returns mouse x position
|
389
|
+
#
|
390
|
+
# @return [Numeric] horizontal position of mouse
|
391
|
+
#
|
392
|
+
def mouseX()
|
393
|
+
@pointerPos__.x
|
394
|
+
end
|
395
|
+
|
396
|
+
# Returns mouse y position
|
397
|
+
#
|
398
|
+
# @return [Numeric] vertical position of mouse
|
399
|
+
#
|
400
|
+
def mouseY()
|
401
|
+
@pointerPos__.y
|
402
|
+
end
|
403
|
+
|
404
|
+
# Returns mouse x position in previous frame
|
405
|
+
#
|
406
|
+
# @return [Numeric] horizontal position of mouse
|
407
|
+
#
|
408
|
+
def pmouseX()
|
409
|
+
@pointerPrevPos__.x
|
410
|
+
end
|
411
|
+
|
412
|
+
# Returns mouse y position in previous frame
|
413
|
+
#
|
414
|
+
# @return [Numeric] vertical position of mouse
|
415
|
+
#
|
416
|
+
def pmouseY()
|
417
|
+
@pointerPrevPos__.y
|
418
|
+
end
|
419
|
+
|
420
|
+
# Returns which mouse button was pressed
|
421
|
+
#
|
422
|
+
# @return [Numeric] LEFT, RIGHT, CENTER or 0
|
423
|
+
#
|
424
|
+
def mouseButton()
|
425
|
+
(@pointersPressed__ & [LEFT, RIGHT, CENTER]).last || 0
|
426
|
+
end
|
427
|
+
|
428
|
+
# Returns array of touches
|
429
|
+
#
|
430
|
+
# @return [Array] Touch objects
|
431
|
+
#
|
432
|
+
def touches()
|
433
|
+
@touches__
|
434
|
+
end
|
435
|
+
|
436
|
+
# Returns vector for real world gravity
|
437
|
+
#
|
438
|
+
# @return [Vector] gravity vector
|
439
|
+
#
|
440
|
+
def motionGravity()
|
441
|
+
@motionGravity__
|
442
|
+
end
|
443
|
+
|
444
|
+
# Enables calling draw block on every frame.
|
445
|
+
#
|
446
|
+
# @return [nil] nil
|
447
|
+
#
|
448
|
+
def loop()
|
449
|
+
@loop__ = true
|
450
|
+
end
|
451
|
+
|
452
|
+
# Disables calling draw block on every frame.
|
453
|
+
#
|
454
|
+
# @return [nil] nil
|
455
|
+
#
|
456
|
+
def noLoop()
|
457
|
+
@loop__ = false
|
458
|
+
end
|
459
|
+
|
460
|
+
# Calls draw block to redraw frame.
|
461
|
+
#
|
462
|
+
# @return [nil] nil
|
463
|
+
#
|
464
|
+
def redraw()
|
465
|
+
@redraw__ = true
|
466
|
+
end
|
467
|
+
|
468
|
+
end# Context
|
469
|
+
|
470
|
+
|
471
|
+
end# Processing
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Processing
|
2
2
|
|
3
3
|
|
4
|
-
module
|
4
|
+
module Extension
|
5
5
|
|
6
6
|
module_function
|
7
7
|
|
@@ -10,14 +10,14 @@ module Processing
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def version()
|
13
|
-
|
13
|
+
File.read(root_dir 'VERSION')[/[\d\.]+/]
|
14
14
|
end
|
15
15
|
|
16
16
|
def root_dir(path = '')
|
17
17
|
File.expand_path "../../#{path}", __dir__
|
18
18
|
end
|
19
19
|
|
20
|
-
end#
|
20
|
+
end# Extension
|
21
21
|
|
22
22
|
|
23
23
|
end# Processing
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Processing
|
2
|
+
|
3
|
+
|
4
|
+
# Font object.
|
5
|
+
#
|
6
|
+
class Font
|
7
|
+
|
8
|
+
# @private
|
9
|
+
def initialize(font)
|
10
|
+
@font = font
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns bounding box.
|
14
|
+
#
|
15
|
+
# @overload textBounds(str)
|
16
|
+
# @overload textBounds(str, x, y)
|
17
|
+
# @overload textBounds(str, x, y, fontSize)
|
18
|
+
#
|
19
|
+
# @param str [String] text to calculate bounding box
|
20
|
+
# @param x [Numeric] horizontal position of bounding box
|
21
|
+
# @param y [Numeric] vertical position of bounding box
|
22
|
+
# @param fontSize [Numeric] font size
|
23
|
+
#
|
24
|
+
# @return [TextBounds] bounding box for text
|
25
|
+
#
|
26
|
+
def textBounds(str, x = 0, y = 0, fontSize = nil)
|
27
|
+
f = fontSize ? Rays::Font.new(@font.name, fontSize) : @font
|
28
|
+
TextBounds.new x, y, x + f.width(str), y + f.height
|
29
|
+
end
|
30
|
+
|
31
|
+
end# Font
|
32
|
+
|
33
|
+
|
34
|
+
# Bounding box for text.
|
35
|
+
#
|
36
|
+
class TextBounds
|
37
|
+
|
38
|
+
# Horizontal position
|
39
|
+
#
|
40
|
+
attr_reader :x
|
41
|
+
|
42
|
+
# Vertical position
|
43
|
+
#
|
44
|
+
attr_reader :y
|
45
|
+
|
46
|
+
# Width of bounding box
|
47
|
+
#
|
48
|
+
attr_reader :w
|
49
|
+
|
50
|
+
# Height of bounding box
|
51
|
+
#
|
52
|
+
attr_reader :h
|
53
|
+
|
54
|
+
# @private
|
55
|
+
def initialize(x, y, w, h)
|
56
|
+
@x, @y, @w, @h = x, y, w, h
|
57
|
+
end
|
58
|
+
|
59
|
+
end# TextBounds
|
60
|
+
|
61
|
+
|
62
|
+
end# Processing
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Processing
|
2
|
+
|
3
|
+
|
4
|
+
# Draws graphics into an offscreen buffer
|
5
|
+
#
|
6
|
+
class Graphics
|
7
|
+
|
8
|
+
include GraphicsContext
|
9
|
+
|
10
|
+
# Initialize graphics object.
|
11
|
+
#
|
12
|
+
def initialize(width, height)
|
13
|
+
image = Rays::Image.new width, height
|
14
|
+
init__ image, image.painter
|
15
|
+
end
|
16
|
+
|
17
|
+
# Start drawing.
|
18
|
+
#
|
19
|
+
def beginDraw(&block)
|
20
|
+
beginDraw__
|
21
|
+
@painter__.__send__ :begin_paint
|
22
|
+
push
|
23
|
+
if block
|
24
|
+
block.call
|
25
|
+
endDraw
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# End drawing.
|
30
|
+
#
|
31
|
+
def endDraw()
|
32
|
+
pop
|
33
|
+
@painter__.__send__ :end_paint
|
34
|
+
endDraw__
|
35
|
+
end
|
36
|
+
|
37
|
+
end# Graphics
|
38
|
+
|
39
|
+
|
40
|
+
end# Processing
|