pixelflow_canvas 0.4.1 → 0.4.3
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/lib/pixelflow_canvas/version.rb +1 -1
- data/lib/pixelflow_canvas/vga_palette.rb +50 -0
- data/lib/pixelflow_canvas.rb +219 -112
- data/test-anaglyph.rb +15 -0
- data/test-draw.rb +26 -0
- data/test-sirds.rb +37 -0
- data/test-turtle.rb +14 -0
- data/test.rb +36 -0
- metadata +23 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03bac01ad660c83aac3bb58e8b9dc009f07d99d773ebf3e4c9c77106c9016a08
|
4
|
+
data.tar.gz: 810c59ec0266aec7f5b4b20b7b411fe5e7c4383db0dd0c1614e0fc1446ae5ffc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f4d69987a229d3c369acaab172efb8d39a189ed739b0e21f5078de233b612eff4b8daaf9d85eea46a8b9c5020aafdc528fd3e6cca2f5618ca3d87e5328f1b41
|
7
|
+
data.tar.gz: 921f5a582cd70c7024e502feae11dbd2eed01eb59fa6487bc9534913b859125d8d0fe6a13665bf389184137a6f9f2b563be266832002e5fa88c772b5e5476b6f
|
@@ -0,0 +1,50 @@
|
|
1
|
+
VGA_PALETTE = [
|
2
|
+
0x00,0x00,0x00,0x00,0x00,0xaa,0x00,0xaa,0x00,0x00,0xaa,0xaa,0xaa,0x00,0x00,0xaa,
|
3
|
+
0x00,0xaa,0xaa,0x55,0x00,0xaa,0xaa,0xaa,0x55,0x55,0x55,0x55,0x55,0xff,0x55,0xff,
|
4
|
+
0x55,0x55,0xff,0xff,0xff,0x55,0x55,0xff,0x55,0xff,0xff,0xff,0x55,0xff,0xff,0xff,
|
5
|
+
0x00,0x00,0x00,0x14,0x14,0x14,0x20,0x20,0x20,0x2c,0x2c,0x2c,0x38,0x38,0x38,0x45,
|
6
|
+
0x45,0x45,0x51,0x51,0x51,0x61,0x61,0x61,0x71,0x71,0x71,0x82,0x82,0x82,0x92,0x92,
|
7
|
+
0x92,0xa2,0xa2,0xa2,0xb6,0xb6,0xb6,0xcb,0xcb,0xcb,0xe3,0xe3,0xe3,0xff,0xff,0xff,
|
8
|
+
0x00,0x00,0xff,0x41,0x00,0xff,0x7d,0x00,0xff,0xbe,0x00,0xff,0xff,0x00,0xff,0xff,
|
9
|
+
0x00,0xbe,0xff,0x00,0x7d,0xff,0x00,0x41,0xff,0x00,0x00,0xff,0x41,0x00,0xff,0x7d,
|
10
|
+
0x00,0xff,0xbe,0x00,0xff,0xff,0x00,0xbe,0xff,0x00,0x7d,0xff,0x00,0x41,0xff,0x00,
|
11
|
+
0x00,0xff,0x00,0x00,0xff,0x41,0x00,0xff,0x7d,0x00,0xff,0xbe,0x00,0xff,0xff,0x00,
|
12
|
+
0xbe,0xff,0x00,0x7d,0xff,0x00,0x41,0xff,0x7d,0x7d,0xff,0x9e,0x7d,0xff,0xbe,0x7d,
|
13
|
+
0xff,0xdf,0x7d,0xff,0xff,0x7d,0xff,0xff,0x7d,0xdf,0xff,0x7d,0xbe,0xff,0x7d,0x9e,
|
14
|
+
0xff,0x7d,0x7d,0xff,0x9e,0x7d,0xff,0xbe,0x7d,0xff,0xdf,0x7d,0xff,0xff,0x7d,0xdf,
|
15
|
+
0xff,0x7d,0xbe,0xff,0x7d,0x9e,0xff,0x7d,0x7d,0xff,0x7d,0x7d,0xff,0x9e,0x7d,0xff,
|
16
|
+
0xbe,0x7d,0xff,0xdf,0x7d,0xff,0xff,0x7d,0xdf,0xff,0x7d,0xbe,0xff,0x7d,0x9e,0xff,
|
17
|
+
0xb6,0xb6,0xff,0xc7,0xb6,0xff,0xdb,0xb6,0xff,0xeb,0xb6,0xff,0xff,0xb6,0xff,0xff,
|
18
|
+
0xb6,0xeb,0xff,0xb6,0xdb,0xff,0xb6,0xc7,0xff,0xb6,0xb6,0xff,0xc7,0xb6,0xff,0xdb,
|
19
|
+
0xb6,0xff,0xeb,0xb6,0xff,0xff,0xb6,0xeb,0xff,0xb6,0xdb,0xff,0xb6,0xc7,0xff,0xb6,
|
20
|
+
0xb6,0xff,0xb6,0xb6,0xff,0xc7,0xb6,0xff,0xdb,0xb6,0xff,0xeb,0xb6,0xff,0xff,0xb6,
|
21
|
+
0xeb,0xff,0xb6,0xdb,0xff,0xb6,0xc7,0xff,0x00,0x00,0x71,0x1c,0x00,0x71,0x38,0x00,
|
22
|
+
0x71,0x55,0x00,0x71,0x71,0x00,0x71,0x71,0x00,0x55,0x71,0x00,0x38,0x71,0x00,0x1c,
|
23
|
+
0x71,0x00,0x00,0x71,0x1c,0x00,0x71,0x38,0x00,0x71,0x55,0x00,0x71,0x71,0x00,0x55,
|
24
|
+
0x71,0x00,0x38,0x71,0x00,0x1c,0x71,0x00,0x00,0x71,0x00,0x00,0x71,0x1c,0x00,0x71,
|
25
|
+
0x38,0x00,0x71,0x55,0x00,0x71,0x71,0x00,0x55,0x71,0x00,0x38,0x71,0x00,0x1c,0x71,
|
26
|
+
0x38,0x38,0x71,0x45,0x38,0x71,0x55,0x38,0x71,0x61,0x38,0x71,0x71,0x38,0x71,0x71,
|
27
|
+
0x38,0x61,0x71,0x38,0x55,0x71,0x38,0x45,0x71,0x38,0x38,0x71,0x45,0x38,0x71,0x55,
|
28
|
+
0x38,0x71,0x61,0x38,0x71,0x71,0x38,0x61,0x71,0x38,0x55,0x71,0x38,0x45,0x71,0x38,
|
29
|
+
0x38,0x71,0x38,0x38,0x71,0x45,0x38,0x71,0x55,0x38,0x71,0x61,0x38,0x71,0x71,0x38,
|
30
|
+
0x61,0x71,0x38,0x55,0x71,0x38,0x45,0x71,0x51,0x51,0x71,0x59,0x51,0x71,0x61,0x51,
|
31
|
+
0x71,0x69,0x51,0x71,0x71,0x51,0x71,0x71,0x51,0x69,0x71,0x51,0x61,0x71,0x51,0x59,
|
32
|
+
0x71,0x51,0x51,0x71,0x59,0x51,0x71,0x61,0x51,0x71,0x69,0x51,0x71,0x71,0x51,0x69,
|
33
|
+
0x71,0x51,0x61,0x71,0x51,0x59,0x71,0x51,0x51,0x71,0x51,0x51,0x71,0x59,0x51,0x71,
|
34
|
+
0x61,0x51,0x71,0x69,0x51,0x71,0x71,0x51,0x69,0x71,0x51,0x61,0x71,0x51,0x59,0x71,
|
35
|
+
0x00,0x00,0x41,0x10,0x00,0x41,0x20,0x00,0x41,0x30,0x00,0x41,0x41,0x00,0x41,0x41,
|
36
|
+
0x00,0x30,0x41,0x00,0x20,0x41,0x00,0x10,0x41,0x00,0x00,0x41,0x10,0x00,0x41,0x20,
|
37
|
+
0x00,0x41,0x30,0x00,0x41,0x41,0x00,0x30,0x41,0x00,0x20,0x41,0x00,0x10,0x41,0x00,
|
38
|
+
0x00,0x41,0x00,0x00,0x41,0x10,0x00,0x41,0x20,0x00,0x41,0x30,0x00,0x41,0x41,0x00,
|
39
|
+
0x30,0x41,0x00,0x20,0x41,0x00,0x10,0x41,0x20,0x20,0x41,0x28,0x20,0x41,0x30,0x20,
|
40
|
+
0x41,0x38,0x20,0x41,0x41,0x20,0x41,0x41,0x20,0x38,0x41,0x20,0x30,0x41,0x20,0x28,
|
41
|
+
0x41,0x20,0x20,0x41,0x28,0x20,0x41,0x30,0x20,0x41,0x38,0x20,0x41,0x41,0x20,0x38,
|
42
|
+
0x41,0x20,0x30,0x41,0x20,0x28,0x41,0x20,0x20,0x41,0x20,0x20,0x41,0x28,0x20,0x41,
|
43
|
+
0x30,0x20,0x41,0x38,0x20,0x41,0x41,0x20,0x38,0x41,0x20,0x30,0x41,0x20,0x28,0x41,
|
44
|
+
0x2c,0x2c,0x41,0x30,0x2c,0x41,0x34,0x2c,0x41,0x3c,0x2c,0x41,0x41,0x2c,0x41,0x41,
|
45
|
+
0x2c,0x3c,0x41,0x2c,0x34,0x41,0x2c,0x30,0x41,0x2c,0x2c,0x41,0x30,0x2c,0x41,0x34,
|
46
|
+
0x2c,0x41,0x3c,0x2c,0x41,0x41,0x2c,0x3c,0x41,0x2c,0x34,0x41,0x2c,0x30,0x41,0x2c,
|
47
|
+
0x2c,0x41,0x2c,0x2c,0x41,0x30,0x2c,0x41,0x34,0x2c,0x41,0x3c,0x2c,0x41,0x41,0x2c,
|
48
|
+
0x3c,0x41,0x2c,0x34,0x41,0x2c,0x30,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
49
|
+
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
50
|
+
]
|
data/lib/pixelflow_canvas.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "pixelflow_canvas/version"
|
4
|
+
require_relative "pixelflow_canvas/vga_palette.rb"
|
5
|
+
require 'chunky_png'
|
4
6
|
require 'socket'
|
5
7
|
require 'time'
|
6
8
|
|
@@ -18,36 +20,35 @@ module Pixelflow
|
|
18
20
|
:direct => 0,
|
19
21
|
:buffered => 1
|
20
22
|
}
|
23
|
+
COMPOSE_MODES = {
|
24
|
+
:over => 0,
|
25
|
+
:add => 1,
|
26
|
+
:subtract => 2
|
27
|
+
}
|
28
|
+
INTERPOLATION_MODES = {
|
29
|
+
:nearest => 0,
|
30
|
+
:bilinear => 1,
|
31
|
+
}
|
21
32
|
def initialize(width, height, color_mode = nil)
|
22
33
|
@width = 320
|
23
34
|
@height = 180
|
24
35
|
@x = 0
|
25
36
|
@y = 0
|
37
|
+
@r = color_mode == :palette ? 15 : 255
|
38
|
+
@g = color_mode == :palette ? 0 : 255
|
39
|
+
@b = color_mode == :palette ? 0 : 255
|
26
40
|
@color_mode = :rgb
|
27
41
|
@advance_mode = :right
|
28
42
|
@draw_mode = :direct
|
29
|
-
@
|
43
|
+
@compose_mode = :over
|
44
|
+
@palette = VGA_PALETTE.dup
|
30
45
|
@socket = TCPSocket.new('127.0.0.1', 19223)
|
31
46
|
set_size(width, height)
|
32
47
|
set_color_mode(color_mode) if color_mode
|
33
48
|
@last_timestamp = Time.now.to_f
|
34
49
|
end
|
35
50
|
|
36
|
-
|
37
|
-
yield(self)
|
38
|
-
end
|
39
|
-
|
40
|
-
def recreate_screen()
|
41
|
-
@screen = [0] * @width * @height * (@color_mode == :rgb ? 3 : 1)
|
42
|
-
end
|
43
|
-
|
44
|
-
def set_draw_mode(mode)
|
45
|
-
unless DRAW_MODES.keys.include?(mode)
|
46
|
-
raise "Invalid draw mode: #{mode}"
|
47
|
-
end
|
48
|
-
@draw_mode = mode
|
49
|
-
recreate_screen()
|
50
|
-
end
|
51
|
+
attr_reader :width, :height
|
51
52
|
|
52
53
|
def set_size(width, height)
|
53
54
|
@x = 0
|
@@ -59,25 +60,24 @@ module Pixelflow
|
|
59
60
|
@socket.flush
|
60
61
|
end
|
61
62
|
|
63
|
+
def recreate_screen()
|
64
|
+
@screen = [0] * @width * @height * (@color_mode == :rgb ? 3 : 1)
|
65
|
+
end
|
66
|
+
|
62
67
|
def set_color_mode(mode)
|
63
68
|
unless COLOR_MODES.keys.include?(mode)
|
64
69
|
raise "Invalid color mode: #{mode}"
|
65
70
|
end
|
66
71
|
@color_mode = mode
|
72
|
+
if mode == :palette
|
73
|
+
@palette = VGA_PALETTE.dup
|
74
|
+
end
|
67
75
|
recreate_screen()
|
68
76
|
@socket.write([2, COLOR_MODES[@color_mode]].pack('CC'))
|
69
77
|
@socket.flush
|
70
78
|
end
|
71
79
|
|
72
|
-
def
|
73
|
-
i = i % 256
|
74
|
-
r = (r % 256) << 2
|
75
|
-
g = (g % 256) << 2
|
76
|
-
b = (b % 256) << 2
|
77
|
-
@socket.write([3, i, r, g, b].pack('CCCCC'))
|
78
|
-
end
|
79
|
-
|
80
|
-
def set_advance(mode)
|
80
|
+
def set_advance_mode(mode)
|
81
81
|
unless ADVANCE_MODES.keys.include?(mode)
|
82
82
|
raise "Invalid advance mode: #{mode}"
|
83
83
|
end
|
@@ -86,11 +86,91 @@ module Pixelflow
|
|
86
86
|
@socket.flush
|
87
87
|
end
|
88
88
|
|
89
|
+
def set_draw_mode(mode)
|
90
|
+
unless DRAW_MODES.keys.include?(mode)
|
91
|
+
raise "Invalid draw mode: #{mode}"
|
92
|
+
end
|
93
|
+
@draw_mode = mode
|
94
|
+
end
|
95
|
+
|
96
|
+
def set_compose_mode(mode)
|
97
|
+
unless COMPOSE_MODES.keys.include?(mode)
|
98
|
+
raise "Invalid compose mode: #{mode}"
|
99
|
+
end
|
100
|
+
if mode != :over && @color_mode != :rgb
|
101
|
+
raise "Cannot switch compose mode to #{mode} in palette color mode!"
|
102
|
+
end
|
103
|
+
@compose_mode = mode
|
104
|
+
end
|
105
|
+
|
106
|
+
def set_interpolation_mode(mode)
|
107
|
+
unless INTERPOLATION_MODES.keys.include?(mode)
|
108
|
+
raise "Invalid interpolation mode: #{mode}"
|
109
|
+
end
|
110
|
+
@socket.write([8, INTERPOLATION_MODES[mode]].pack('CC'))
|
111
|
+
@socket.flush
|
112
|
+
end
|
113
|
+
|
114
|
+
def flip()
|
115
|
+
if @draw_mode == :buffered
|
116
|
+
@socket.write([7].pack('C'))
|
117
|
+
@socket.write(@screen.pack('C*'))
|
118
|
+
@socket.flush
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def ensure_max_fps(fps)
|
123
|
+
fps1 = 1.0 / fps
|
124
|
+
t = Time.now.to_f
|
125
|
+
dt = t - @last_timestamp
|
126
|
+
sleep(fps1 - dt) if dt < fps1
|
127
|
+
@last_timestamp = t
|
128
|
+
end
|
129
|
+
|
130
|
+
def save_as_png(path)
|
131
|
+
if @color_mode == :rgb
|
132
|
+
image = ChunkyPNG::Image.from_rgb_stream(@width, @height, @screen.pack('C*'))
|
133
|
+
image.save(path)
|
134
|
+
else
|
135
|
+
buffer = [0] * @width * @height * 3
|
136
|
+
offset = 0
|
137
|
+
source = 0
|
138
|
+
(0...@height).each do |y|
|
139
|
+
(0...@width).each do |x|
|
140
|
+
i = @screen[source]
|
141
|
+
buffer[offset + 0] = @palette[i + 0]
|
142
|
+
buffer[offset + 1] = @palette[i + 1]
|
143
|
+
buffer[offset + 2] = @palette[i + 2]
|
144
|
+
source += 1
|
145
|
+
offset += 3
|
146
|
+
end
|
147
|
+
end
|
148
|
+
image = ChunkyPNG::Image.from_rgb_stream(@width, @height, buffer.pack('C*'))
|
149
|
+
image.save(path)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def set_color(r, g = 0, b = 0)
|
154
|
+
@r = r
|
155
|
+
@g = g
|
156
|
+
@b = b
|
157
|
+
end
|
158
|
+
|
159
|
+
def set_palette(i, r, g, b)
|
160
|
+
i = i.to_i.clamp(0, 255)
|
161
|
+
r = r.to_i.clamp(0, 255)
|
162
|
+
g = g.to_i.clamp(0, 255)
|
163
|
+
b = b.to_i.clamp(0, 255)
|
164
|
+
@palette[i * 3 + 0] = r
|
165
|
+
@palette[i * 3 + 1] = g
|
166
|
+
@palette[i * 3 + 2] = b
|
167
|
+
@socket.write([3, i, r, g, b].pack('CCCCC'))
|
168
|
+
@socket.flush
|
169
|
+
end
|
170
|
+
|
89
171
|
def move_to(x, y)
|
90
|
-
|
91
|
-
|
92
|
-
x1 = x1.to_i
|
93
|
-
y1 = y1.to_i
|
172
|
+
x = x.to_i
|
173
|
+
y = y.to_i
|
94
174
|
return if x < 0 || x >= @width || y < 0 || y >= @height
|
95
175
|
@x = x
|
96
176
|
@y = y
|
@@ -101,7 +181,10 @@ module Pixelflow
|
|
101
181
|
@socket.flush
|
102
182
|
end
|
103
183
|
|
104
|
-
def set_pixel(x, y, r, g =
|
184
|
+
def set_pixel(x, y, r = nil, g = nil, b = nil)
|
185
|
+
r ||= @r
|
186
|
+
g ||= @g
|
187
|
+
b ||= @b
|
105
188
|
x0 = x0.to_i
|
106
189
|
y0 = y0.to_i
|
107
190
|
x1 = x1.to_i
|
@@ -112,6 +195,14 @@ module Pixelflow
|
|
112
195
|
end
|
113
196
|
if @color_mode == :rgb
|
114
197
|
offset = (@y * @width + @x) * 3
|
198
|
+
if @compose_mode == :add
|
199
|
+
r += @screen[offset + 0]
|
200
|
+
g += @screen[offset + 1]
|
201
|
+
b += @screen[offset + 2]
|
202
|
+
r = 255 if r > 255
|
203
|
+
g = 255 if g > 255
|
204
|
+
b = 255 if b > 255
|
205
|
+
end
|
115
206
|
@screen[offset + 0] = r
|
116
207
|
@screen[offset + 1] = g
|
117
208
|
@screen[offset + 2] = b
|
@@ -155,52 +246,36 @@ module Pixelflow
|
|
155
246
|
end
|
156
247
|
end
|
157
248
|
|
158
|
-
def
|
159
|
-
if @draw_mode == :buffered
|
160
|
-
@socket.write([7].pack('C'))
|
161
|
-
@socket.write(@screen.pack('C*'))
|
162
|
-
@socket.flush
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
def ensure_max_fps(fps)
|
167
|
-
fps1 = 1.0 / fps
|
168
|
-
t = Time.now.to_f
|
169
|
-
dt = t - @last_timestamp
|
170
|
-
sleep(fps1 - dt) if dt < fps1
|
171
|
-
@last_timestamp = t
|
172
|
-
end
|
173
|
-
|
174
|
-
def draw_rect(x0, y0, x1, y1, color)
|
249
|
+
def draw_rect(x0, y0, x1, y1)
|
175
250
|
x0 = x0.to_i
|
176
251
|
y0 = y0.to_i
|
177
252
|
x1 = x1.to_i
|
178
253
|
y1 = y1.to_i
|
179
254
|
(x0..x1).each do |x|
|
180
|
-
set_pixel(x, y0
|
255
|
+
set_pixel(x, y0)
|
181
256
|
end
|
182
257
|
(x0..x1).each do |x|
|
183
|
-
set_pixel(x, y1
|
258
|
+
set_pixel(x, y1)
|
184
259
|
end
|
185
260
|
(y0+1..y1-1).each do |y|
|
186
|
-
set_pixel(x0, y
|
187
|
-
set_pixel(x1, y
|
261
|
+
set_pixel(x0, y)
|
262
|
+
set_pixel(x1, y)
|
188
263
|
end
|
189
264
|
end
|
190
265
|
|
191
|
-
def fill_rect(x0, y0, x1, y1
|
266
|
+
def fill_rect(x0, y0, x1, y1)
|
192
267
|
x0 = x0.to_i
|
193
268
|
y0 = y0.to_i
|
194
269
|
x1 = x1.to_i
|
195
270
|
y1 = y1.to_i
|
196
271
|
(y0..y1).each do |y|
|
197
272
|
(x0..x1).each do |x|
|
198
|
-
set_pixel(x, y
|
273
|
+
set_pixel(x, y)
|
199
274
|
end
|
200
275
|
end
|
201
276
|
end
|
202
277
|
|
203
|
-
def draw_line(x0, y0, x1, y1
|
278
|
+
def draw_line(x0, y0, x1, y1)
|
204
279
|
x0 = x0.to_i
|
205
280
|
y0 = y0.to_i
|
206
281
|
x1 = x1.to_i
|
@@ -211,7 +286,7 @@ module Pixelflow
|
|
211
286
|
sy = y0 < y1 ? 1 : -1
|
212
287
|
err = dx - dy
|
213
288
|
loop do
|
214
|
-
set_pixel(x0, y0
|
289
|
+
set_pixel(x0, y0)
|
215
290
|
break if x0 == x1 && y0 == y1
|
216
291
|
e2 = 2 * err
|
217
292
|
if e2 > -dy
|
@@ -225,19 +300,19 @@ module Pixelflow
|
|
225
300
|
end
|
226
301
|
end
|
227
302
|
|
228
|
-
def draw_circle(x, y,
|
303
|
+
def draw_circle(x, y, r)
|
229
304
|
x = x.to_i
|
230
305
|
y = y.to_i
|
231
|
-
|
232
|
-
f = 1 -
|
306
|
+
r = r.to_i
|
307
|
+
f = 1 - r
|
233
308
|
ddF_x = 1
|
234
|
-
ddF_y = -2 *
|
309
|
+
ddF_y = -2 * r
|
235
310
|
xx = 0
|
236
|
-
yy =
|
237
|
-
set_pixel(x, y +
|
238
|
-
set_pixel(x, y -
|
239
|
-
set_pixel(x +
|
240
|
-
set_pixel(x -
|
311
|
+
yy = r
|
312
|
+
set_pixel(x, y + r)
|
313
|
+
set_pixel(x, y - r)
|
314
|
+
set_pixel(x + r, y)
|
315
|
+
set_pixel(x - r, y)
|
241
316
|
while xx < yy
|
242
317
|
if f >= 0
|
243
318
|
yy -= 1
|
@@ -247,18 +322,18 @@ module Pixelflow
|
|
247
322
|
xx += 1
|
248
323
|
ddF_x += 2
|
249
324
|
f += ddF_x
|
250
|
-
set_pixel(x + xx, y + yy
|
251
|
-
set_pixel(x - xx, y + yy
|
252
|
-
set_pixel(x + xx, y - yy
|
253
|
-
set_pixel(x - xx, y - yy
|
254
|
-
set_pixel(x + yy, y + xx
|
255
|
-
set_pixel(x - yy, y + xx
|
256
|
-
set_pixel(x + yy, y - xx
|
257
|
-
set_pixel(x - yy, y - xx
|
325
|
+
set_pixel(x + xx, y + yy)
|
326
|
+
set_pixel(x - xx, y + yy)
|
327
|
+
set_pixel(x + xx, y - yy)
|
328
|
+
set_pixel(x - xx, y - yy)
|
329
|
+
set_pixel(x + yy, y + xx)
|
330
|
+
set_pixel(x - yy, y + xx)
|
331
|
+
set_pixel(x + yy, y - xx)
|
332
|
+
set_pixel(x - yy, y - xx)
|
258
333
|
end
|
259
334
|
end
|
260
335
|
|
261
|
-
def fill_circle(x, y, r
|
336
|
+
def fill_circle(x, y, r)
|
262
337
|
x = x.to_i
|
263
338
|
y = y.to_i
|
264
339
|
r = r.to_i
|
@@ -268,7 +343,7 @@ module Pixelflow
|
|
268
343
|
xx = 0
|
269
344
|
yy = r
|
270
345
|
(y - r..y + r).each do |i|
|
271
|
-
set_pixel(x, i
|
346
|
+
set_pixel(x, i)
|
272
347
|
end
|
273
348
|
while xx < yy
|
274
349
|
if f >= 0
|
@@ -280,33 +355,33 @@ module Pixelflow
|
|
280
355
|
ddF_x += 2
|
281
356
|
f += ddF_x
|
282
357
|
(y - yy..y + yy).each do |i|
|
283
|
-
set_pixel(x + xx, i
|
284
|
-
set_pixel(x - xx, i
|
358
|
+
set_pixel(x + xx, i)
|
359
|
+
set_pixel(x - xx, i)
|
285
360
|
end
|
286
361
|
(y - xx..y + xx).each do |i|
|
287
|
-
set_pixel(x + yy, i
|
288
|
-
set_pixel(x - yy, i
|
362
|
+
set_pixel(x + yy, i)
|
363
|
+
set_pixel(x - yy, i)
|
289
364
|
end
|
290
365
|
end
|
291
366
|
end
|
292
367
|
|
293
|
-
def draw_ellipse(x, y,
|
368
|
+
def draw_ellipse(x, y, ra, rb)
|
294
369
|
x = x.to_i
|
295
370
|
y = y.to_i
|
296
|
-
|
297
|
-
|
298
|
-
a2 =
|
299
|
-
b2 =
|
371
|
+
ra = ra.to_i
|
372
|
+
rb = rb.to_i
|
373
|
+
a2 = ra * ra
|
374
|
+
b2 = rb * rb
|
300
375
|
fa2 = 4 * a2
|
301
376
|
fb2 = 4 * b2
|
302
377
|
x0 = 0
|
303
378
|
y0 = b
|
304
|
-
sigma = 2 * b2 + a2 * (1 - 2 *
|
379
|
+
sigma = 2 * b2 + a2 * (1 - 2 * rb)
|
305
380
|
while b2 * x0 <= a2 * y0
|
306
|
-
set_pixel(x + x0, y + y0
|
307
|
-
set_pixel(x - x0, y + y0
|
308
|
-
set_pixel(x + x0, y - y0
|
309
|
-
set_pixel(x - x0, y - y0
|
381
|
+
set_pixel(x + x0, y + y0)
|
382
|
+
set_pixel(x - x0, y + y0)
|
383
|
+
set_pixel(x + x0, y - y0)
|
384
|
+
set_pixel(x - x0, y - y0)
|
310
385
|
if sigma >= 0
|
311
386
|
sigma += fa2 * (1 - y0)
|
312
387
|
y0 -= 1
|
@@ -316,12 +391,12 @@ module Pixelflow
|
|
316
391
|
end
|
317
392
|
x0 = a
|
318
393
|
y0 = 0
|
319
|
-
sigma = 2 * a2 + b2 * (1 - 2 *
|
394
|
+
sigma = 2 * a2 + b2 * (1 - 2 * ra)
|
320
395
|
while a2 * y0 <= b2 * x0
|
321
|
-
set_pixel(x + x0, y + y0
|
322
|
-
set_pixel(x - x0, y + y0
|
323
|
-
set_pixel(x + x0, y - y0
|
324
|
-
set_pixel(x - x0, y - y0
|
396
|
+
set_pixel(x + x0, y + y0)
|
397
|
+
set_pixel(x - x0, y + y0)
|
398
|
+
set_pixel(x + x0, y - y0)
|
399
|
+
set_pixel(x - x0, y - y0)
|
325
400
|
if sigma >= 0
|
326
401
|
sigma += fb2 * (1 - x0)
|
327
402
|
x0 -= 1
|
@@ -331,22 +406,22 @@ module Pixelflow
|
|
331
406
|
end
|
332
407
|
end
|
333
408
|
|
334
|
-
def fill_ellipse(x, y,
|
409
|
+
def fill_ellipse(x, y, ra, rb)
|
335
410
|
x = x.to_i
|
336
411
|
y = y.to_i
|
337
|
-
|
338
|
-
|
339
|
-
a2 =
|
340
|
-
b2 =
|
412
|
+
ra = ra.to_i
|
413
|
+
rb = rb.to_i
|
414
|
+
a2 = ra * ra
|
415
|
+
b2 = rb * rb
|
341
416
|
fa2 = 4 * a2
|
342
417
|
fb2 = 4 * b2
|
343
418
|
x0 = 0
|
344
419
|
y0 = b
|
345
|
-
sigma = 2 * b2 + a2 * (1 - 2 *
|
420
|
+
sigma = 2 * b2 + a2 * (1 - 2 * rb)
|
346
421
|
while b2 * x0 <= a2 * y0
|
347
422
|
(x - x0..x + x0).each do |i|
|
348
|
-
set_pixel(i, y + y0
|
349
|
-
set_pixel(i, y - y0
|
423
|
+
set_pixel(i, y + y0)
|
424
|
+
set_pixel(i, y - y0)
|
350
425
|
end
|
351
426
|
if sigma >= 0
|
352
427
|
sigma += fa2 * (1 - y0)
|
@@ -357,11 +432,11 @@ module Pixelflow
|
|
357
432
|
end
|
358
433
|
x0 = a
|
359
434
|
y0 = 0
|
360
|
-
sigma = 2 * a2 + b2 * (1 - 2 *
|
435
|
+
sigma = 2 * a2 + b2 * (1 - 2 * ra)
|
361
436
|
while a2 * y0 <= b2 * x0
|
362
437
|
(x - x0..x + x0).each do |i|
|
363
|
-
set_pixel(i, y + y0
|
364
|
-
set_pixel(i, y - y0
|
438
|
+
set_pixel(i, y + y0)
|
439
|
+
set_pixel(i, y - y0)
|
365
440
|
end
|
366
441
|
if sigma >= 0
|
367
442
|
sigma += fb2 * (1 - x0)
|
@@ -372,7 +447,7 @@ module Pixelflow
|
|
372
447
|
end
|
373
448
|
end
|
374
449
|
|
375
|
-
def draw_quadratic_bezier(x0, y0, x1, y1, x2, y2,
|
450
|
+
def draw_quadratic_bezier(x0, y0, x1, y1, x2, y2, steps = 100)
|
376
451
|
steps = steps.to_i
|
377
452
|
xp = nil
|
378
453
|
yp = nil
|
@@ -381,14 +456,14 @@ module Pixelflow
|
|
381
456
|
x = (1 - t) ** 2 * x0 + 2 * (1 - t) * t * x1 + t ** 2 * x2
|
382
457
|
y = (1 - t) ** 2 * y0 + 2 * (1 - t) * t * y1 + t ** 2 * y2
|
383
458
|
if xp && yp
|
384
|
-
draw_line(xp.to_i, yp.to_i, x.to_i, y.to_i
|
459
|
+
draw_line(xp.to_i, yp.to_i, x.to_i, y.to_i)
|
385
460
|
end
|
386
461
|
xp = x
|
387
462
|
yp = y
|
388
463
|
end
|
389
464
|
end
|
390
465
|
|
391
|
-
def draw_cubic_bezier(x0, y0, x1, y1, x2, y2, x3, y3,
|
466
|
+
def draw_cubic_bezier(x0, y0, x1, y1, x2, y2, x3, y3, steps = 100)
|
392
467
|
steps = steps.to_i
|
393
468
|
xp = nil
|
394
469
|
yp = nil
|
@@ -397,17 +472,49 @@ module Pixelflow
|
|
397
472
|
x = (1 - t) ** 3 * x0 + 3 * (1 - t) ** 2 * t * x1 + 3 * (1 - t) * t ** 2 * x2 + t ** 3 * x3
|
398
473
|
y = (1 - t) ** 3 * y0 + 3 * (1 - t) ** 2 * t * y1 + 3 * (1 - t) * t ** 2 * y2 + t ** 3 * y3
|
399
474
|
if xp && yp
|
400
|
-
draw_line(xp.to_i, yp.to_i, x.to_i, y.to_i
|
475
|
+
draw_line(xp.to_i, yp.to_i, x.to_i, y.to_i)
|
401
476
|
end
|
402
477
|
xp = x
|
403
478
|
yp = y
|
404
479
|
end
|
405
480
|
end
|
406
481
|
|
407
|
-
def draw_triangle(x0, y0, x1, y1, x2, y2
|
408
|
-
draw_line(x0, y0, x1, y1
|
409
|
-
draw_line(x1, y1, x2, y2
|
410
|
-
draw_line(x2, y2, x0, y0
|
482
|
+
def draw_triangle(x0, y0, x1, y1, x2, y2)
|
483
|
+
draw_line(x0, y0, x1, y1)
|
484
|
+
draw_line(x1, y1, x2, y2)
|
485
|
+
draw_line(x2, y2, x0, y0)
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
class Turtle
|
490
|
+
def initialize(canvas)
|
491
|
+
@canvas = canvas
|
492
|
+
@x = canvas.width / 2.0
|
493
|
+
@y = canvas.height / 2.0
|
494
|
+
@phi = 270.0
|
495
|
+
@pen_down = true
|
496
|
+
end
|
497
|
+
|
498
|
+
attr_accessor :x, :y, :phi, :color, :pen_down
|
499
|
+
|
500
|
+
def forward(l)
|
501
|
+
nx = @x + Math.cos(@phi * Math::PI / 180.0) * l
|
502
|
+
ny = @y + Math.sin(@phi * Math::PI / 180.0) * l
|
503
|
+
@canvas.draw_line(@x, @y, nx, ny) if @pen_down
|
504
|
+
@x = nx
|
505
|
+
@y = ny
|
506
|
+
end
|
507
|
+
|
508
|
+
def set_color(r = 0, g = nil, b = nil)
|
509
|
+
@canvas.set_color(r, g, b)
|
510
|
+
end
|
511
|
+
|
512
|
+
def turn_left(phi)
|
513
|
+
@phi -= phi
|
514
|
+
end
|
515
|
+
|
516
|
+
def turn_right(phi)
|
517
|
+
@phi += phi
|
411
518
|
end
|
412
519
|
end
|
413
520
|
end
|
data/test-anaglyph.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require './lib/pixelflow_canvas.rb'
|
2
|
+
|
3
|
+
width = 256
|
4
|
+
height = 256
|
5
|
+
|
6
|
+
canvas = Pixelflow::Canvas.new(width, height, :rgb)
|
7
|
+
canvas.set_compose_mode(:add)
|
8
|
+
|
9
|
+
canvas.set_color(255, 0, 0)
|
10
|
+
canvas.draw_line(10, 10, 100, 200)
|
11
|
+
|
12
|
+
canvas.set_color(0, 255, 0)
|
13
|
+
canvas.draw_line(20, 10, 90, 200)
|
14
|
+
|
15
|
+
canvas.save_as_png('anaglyph.png')
|
data/test-draw.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require './lib/pixelflow_canvas.rb'
|
2
|
+
|
3
|
+
width = 256
|
4
|
+
height = 256
|
5
|
+
|
6
|
+
canvas = Pixelflow::Canvas.new(width, height, :palette)
|
7
|
+
canvas.set_interpolation_mode(:bilinear)
|
8
|
+
turtle = Pixelflow::Turtle.new(canvas)
|
9
|
+
turtle.set_color(13)
|
10
|
+
|
11
|
+
def draw(canvas, x0, y0, x1, y1, x2, y2, level)
|
12
|
+
canvas.draw_triangle(x0, y0, x1, y1, x2, y2)
|
13
|
+
mx0 = (x0 + x1) / 2
|
14
|
+
my0 = (y0 + y1) / 2
|
15
|
+
mx1 = (x1 + x2) / 2
|
16
|
+
my1 = (y1 + y2) / 2
|
17
|
+
mx2 = (x2 + x0) / 2
|
18
|
+
my2 = (y2 + y0) / 2
|
19
|
+
if level > 0
|
20
|
+
draw(canvas, x0, y0, mx0, my0, mx2, my2, level - 1)
|
21
|
+
draw(canvas, x1, y1, mx1, my1, mx0, my0, level - 1)
|
22
|
+
draw(canvas, x2, y2, mx2, my2, mx1, my1, level - 1)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
draw(canvas, 128, 10, 10, 186, 246, 246, 5)
|
data/test-sirds.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require './lib/pixelflow_canvas.rb'
|
2
|
+
|
3
|
+
def depth(x, y)
|
4
|
+
r = (x - 128) ** 2 + (y - 128) ** 2
|
5
|
+
return 10 if r < 5000
|
6
|
+
r * 0.001
|
7
|
+
end
|
8
|
+
|
9
|
+
width = 256
|
10
|
+
height = 256
|
11
|
+
|
12
|
+
canvas = Pixelflow::Canvas.new(width, height, :palette)
|
13
|
+
(0...64).each { |i| canvas.set_palette(i, i * 4, i * 4, i * 4) }
|
14
|
+
(0...height).each do |y|
|
15
|
+
(0...48).each do |x|
|
16
|
+
canvas.set_pixel(x, y, rand(64))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
(0...height).each do |y|
|
20
|
+
sx = 0
|
21
|
+
dx = 48
|
22
|
+
while dx < width
|
23
|
+
c = canvas.get_pixel(sx, y)
|
24
|
+
canvas.set_pixel(dx, y, c)
|
25
|
+
dx += 1
|
26
|
+
sx = dx - 48 + depth(dx - 24, y)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# (0...height).each do |y|
|
31
|
+
# (0...width).each do |x|
|
32
|
+
# d = depth(x, y)
|
33
|
+
# canvas.set_pixel(x, y, d)
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
|
37
|
+
canvas.save_as_png('sirds.png')
|
data/test-turtle.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require './lib/pixelflow_canvas.rb'
|
2
|
+
|
3
|
+
width = 256
|
4
|
+
height = 256
|
5
|
+
|
6
|
+
canvas = Pixelflow::Canvas.new(width, height, :palette)
|
7
|
+
turtle = Pixelflow::Turtle.new(canvas)
|
8
|
+
turtle.set_color(13)
|
9
|
+
|
10
|
+
turtle.forward(10)
|
11
|
+
turtle.turn_right(90)
|
12
|
+
turtle.forward(10)
|
13
|
+
turtle.turn_right(90)
|
14
|
+
turtle.forward(10)
|
data/test.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require './lib/pixelflow_canvas.rb'
|
2
|
+
|
3
|
+
def depth(x, y)
|
4
|
+
r = (x - 128) ** 2 + (y - 128) ** 2
|
5
|
+
return 10 if r < 5000
|
6
|
+
r * 0.001
|
7
|
+
end
|
8
|
+
|
9
|
+
width = 256
|
10
|
+
height = 256
|
11
|
+
|
12
|
+
canvas = Pixelflow::Canvas.new(width, height, :palette)
|
13
|
+
(0...64).each { |i| canvas.set_palette(i, i, i, i) }
|
14
|
+
(0...height).each do |y|
|
15
|
+
(0...48).each do |x|
|
16
|
+
canvas.set_pixel(x, y, rand(64))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
(0...height).each do |y|
|
20
|
+
sx = 0
|
21
|
+
dx = 48
|
22
|
+
while dx < width
|
23
|
+
c = canvas.get_pixel(sx, y)
|
24
|
+
canvas.set_pixel(dx, y, c)
|
25
|
+
dx += 1
|
26
|
+
sx = dx - 48 + depth(dx - 24, y)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# (0...height).each do |y|
|
31
|
+
# (0...width).each do |x|
|
32
|
+
# d = depth(x, y)
|
33
|
+
# canvas.set_pixel(x, y, d)
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pixelflow_canvas
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Specht
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-10-
|
12
|
-
dependencies:
|
11
|
+
date: 2024-10-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: chunky_png
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.4.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.4.0
|
13
27
|
description: Use a virtual CRT for old school graphics programming, in VS Code, from
|
14
28
|
Ruby.
|
15
29
|
email:
|
@@ -23,7 +37,13 @@ files:
|
|
23
37
|
- Rakefile
|
24
38
|
- lib/pixelflow_canvas.rb
|
25
39
|
- lib/pixelflow_canvas/version.rb
|
40
|
+
- lib/pixelflow_canvas/vga_palette.rb
|
26
41
|
- sig/pixelflow_canvas.rbs
|
42
|
+
- test-anaglyph.rb
|
43
|
+
- test-draw.rb
|
44
|
+
- test-sirds.rb
|
45
|
+
- test-turtle.rb
|
46
|
+
- test.rb
|
27
47
|
homepage: https://github.com/specht/pixelflow_canvas_ruby
|
28
48
|
licenses:
|
29
49
|
- GPL-3.0-only
|