fretboards 0.1.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/fretboards_render +8 -0
- data/lib/fretboards/fretboard.rb +10 -8
- data/lib/fretboards/fretboard_collection.rb +7 -4
- data/lib/fretboards/renderer/svg.rb +37 -33
- data/lib/fretboards/version.rb +1 -1
- data/test/test_fretboard.rb +24 -17
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90adc54d636c181a05f9a6ba3ba4705c3778cb4dd827165b0fe03b330c126f3e
|
4
|
+
data.tar.gz: e92bcfd36a655f3ef0839be73390625960ebe0e1be9f933634bc2202467dbead
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c94ffd1f79ad6c4b50a25e4d275b5413f8b68537fee21d5f3ea258a41eaa20c616361a5837e37849a994cfe9aadd56aba0f753f4b292be66c7d2b55f78a8cfee
|
7
|
+
data.tar.gz: e33c2aedbe85f7c85119f9f8a87bd5e794bc7c5f27c491be41b86bbab1b787baf151ca4f21566b87b103bd341f04b110c03763f51a4d598e8f662e0e90e8505a
|
data/bin/fretboards_render
CHANGED
@@ -18,6 +18,7 @@ Options:
|
|
18
18
|
--width=<width> Width of the fretboard [default: 108].
|
19
19
|
--height=<height> Height of the fretboard [default: 180].
|
20
20
|
--fret-count=<fret-count> Number of frets [default: 4].
|
21
|
+
--offset=<offset> Offset of the fretboard [default: 0].
|
21
22
|
--title=<title> Title of the fretboard [default: ].
|
22
23
|
-h --help Show this screen.
|
23
24
|
--version Show version.
|
@@ -84,5 +85,12 @@ fret_count = arguments['--fret-count'].to_i
|
|
84
85
|
fb = Fretboards::Fretboard.new(:tuning => tuning)
|
85
86
|
fb.title = title unless title.empty?
|
86
87
|
fb.terse(terse)
|
88
|
+
|
89
|
+
if arguments['--offset']
|
90
|
+
fb.set_offset(arguments['--offset'].to_i)
|
91
|
+
end
|
92
|
+
|
93
|
+
|
87
94
|
renderer = Fretboards::Renderer::Svg.new(width: width, height: height, fret_count: fret_count)
|
95
|
+
|
88
96
|
puts renderer.render(fb)
|
data/lib/fretboards/fretboard.rb
CHANGED
@@ -75,12 +75,12 @@ module Fretboards
|
|
75
75
|
@offset = n
|
76
76
|
self
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
def set_label_offset(n)
|
80
80
|
@label_offset = n
|
81
81
|
self
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
|
85
85
|
def mark(s, f = nil, settings = {})
|
86
86
|
if !s.is_a? Hash
|
@@ -196,15 +196,17 @@ module Fretboards
|
|
196
196
|
if marks.empty?
|
197
197
|
[1, size]
|
198
198
|
else
|
199
|
-
min = marks.inject { |sum, i| i[:fret] < sum[:fret] ? i : sum }[:fret]
|
199
|
+
min = marks.inject { |sum, i| (i[:fret] < sum[:fret]) ? i : sum }[:fret]
|
200
200
|
max = marks.inject { |sum, i| i[:fret] > sum[:fret] ? i : sum }[:fret]
|
201
201
|
if size >= max
|
202
202
|
[1, size]
|
203
203
|
else
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
204
|
+
if offset > 0
|
205
|
+
[ offset, offset + size - 1 ]
|
206
|
+
else
|
207
|
+
min = 1 if min == 0
|
208
|
+
[min, max]
|
209
|
+
end
|
208
210
|
end
|
209
211
|
end
|
210
212
|
end
|
@@ -213,4 +215,4 @@ module Fretboards
|
|
213
215
|
|
214
216
|
|
215
217
|
end
|
216
|
-
end
|
218
|
+
end
|
@@ -10,7 +10,7 @@ module Fretboards
|
|
10
10
|
@tuning = %w{ g' c' e' a' }
|
11
11
|
@table = "default"
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def set_tuning(a)
|
15
15
|
@tuning = a
|
16
16
|
end
|
@@ -20,14 +20,14 @@ module Fretboards
|
|
20
20
|
@col << fb
|
21
21
|
fb
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def define(title, a, attrs = {})
|
25
25
|
form_add(title, a, { :title => title }.merge(attrs))
|
26
26
|
end
|
27
27
|
|
28
28
|
def use(title)
|
29
29
|
raise "#{title} form not available" unless @forms[title]
|
30
|
-
@forms[title]
|
30
|
+
@forms[title]
|
31
31
|
end
|
32
32
|
|
33
33
|
|
@@ -45,6 +45,9 @@ module Fretboards
|
|
45
45
|
fb = Fretboard.new(:tuning => @tuning)
|
46
46
|
fb.terse(dots, attrs)
|
47
47
|
end
|
48
|
+
if attrs[:offset]
|
49
|
+
fb.set_offset(attrs[:offset])
|
50
|
+
end
|
48
51
|
fb
|
49
52
|
end
|
50
53
|
|
@@ -71,4 +74,4 @@ module Fretboards
|
|
71
74
|
|
72
75
|
end
|
73
76
|
|
74
|
-
end
|
77
|
+
end
|
@@ -4,7 +4,7 @@ require "fretboards/ext/hash"
|
|
4
4
|
module Fretboards
|
5
5
|
module Renderer
|
6
6
|
class Svg < Base
|
7
|
-
|
7
|
+
|
8
8
|
def initialize(opts = {})
|
9
9
|
# TODO configuration should merge recursively
|
10
10
|
@opts = {
|
@@ -48,7 +48,7 @@ module Fretboards
|
|
48
48
|
:open_margin_bottom => 4,
|
49
49
|
}.deep_merge(opts)
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
def render(fb)
|
53
53
|
@fb = fb
|
54
54
|
require "builder"
|
@@ -75,7 +75,7 @@ module Fretboards
|
|
75
75
|
# @svg
|
76
76
|
# xml
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
def landscape_attributes
|
80
80
|
if @opts[:landscape]
|
81
81
|
{
|
@@ -85,23 +85,23 @@ module Fretboards
|
|
85
85
|
{}
|
86
86
|
end
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
def string_attrs
|
90
90
|
@opts[:string_attrs]
|
91
91
|
end
|
92
|
-
|
92
|
+
|
93
93
|
def fret_attrs
|
94
94
|
@opts[:fret_attrs]
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
97
|
def nut_attrs
|
98
98
|
@opts[:nut_attrs]
|
99
99
|
end
|
100
|
-
|
100
|
+
|
101
101
|
def string_spacing
|
102
102
|
(@opts[:width] - @opts[:padding_left] - @opts[:padding_right]) / ((@fb.string_count - 1).to_f)
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
def draw_strings(svg)
|
106
106
|
(0..@fb.string_count-1).each do |sn|
|
107
107
|
# x = @opts[:padding_left] + sn * string_spacing(fb)
|
@@ -109,24 +109,24 @@ module Fretboards
|
|
109
109
|
y1 = @opts[:padding_top]
|
110
110
|
y2 = @opts[:height] - @opts[:padding_bottom]
|
111
111
|
attrs = string_attrs.merge(:x1 => x, :x2 => x, :y1 => y1, :y2 => y2, :class => 'string')
|
112
|
-
if (!@opts[:string_widths].empty?)
|
112
|
+
if (!@opts[:string_widths].empty?)
|
113
113
|
attrs = attrs.merge({ :"stroke-width" => @opts[:string_widths][sn] })
|
114
114
|
end
|
115
115
|
svg.line(attrs)
|
116
116
|
end
|
117
117
|
end
|
118
|
-
|
118
|
+
|
119
119
|
def draw_title(svg)
|
120
120
|
# TODO calculate ideal gap
|
121
|
-
gap = @opts[:title_attrs][:"font-size"]
|
121
|
+
gap = @opts[:title_attrs][:"font-size"]
|
122
122
|
svg.text(@fb.title, { :x => @opts[:width] * 0.5 + ((@opts[:padding_left] - @opts[:padding_right])*0.5), :y => @opts[:padding_top] - gap, :class => 'title' }.merge(@opts[:title_attrs]))
|
123
123
|
end
|
124
|
-
|
124
|
+
|
125
125
|
def get_string_x(sn)
|
126
126
|
sn = @fb.string_number_to_index(sn)
|
127
127
|
@opts[:padding_left] + sn * string_spacing
|
128
128
|
end
|
129
|
-
|
129
|
+
|
130
130
|
def draw_frets(svg)
|
131
131
|
fret_range = @fb.fret_range(@opts[:fret_count])
|
132
132
|
total_frets = fret_range.last - fret_range.first + 1
|
@@ -141,17 +141,21 @@ module Fretboards
|
|
141
141
|
draw_fret(svg, n+1)
|
142
142
|
end
|
143
143
|
end
|
144
|
-
|
144
|
+
|
145
145
|
def draw_labels(svg)
|
146
146
|
fret_range = @fb.fret_range(@opts[:fret_count])
|
147
147
|
if fret_range.first > 1
|
148
148
|
y = get_dot_position(0, fret_range.first + @fb.label_offset)[1] + @opts[:label_attrs][:"font-size"] * 0.4
|
149
|
-
x =
|
149
|
+
x = if !@opts[:label_attrs][:'x-offset'].nil?
|
150
|
+
@opts[:padding_left] - @opts[:label_attrs][:'x-offset']
|
151
|
+
else
|
152
|
+
@opts[:padding_left] - @opts[:label_attrs][:"font-size"] * 1.25
|
153
|
+
end
|
150
154
|
# TODO allow rotating
|
151
155
|
svg.text(fret_range.first + @fb.label_offset, { :y => y, :x => x, :class => 'label' }.merge(@opts[:label_attrs]))
|
152
156
|
end
|
153
157
|
end
|
154
|
-
|
158
|
+
|
155
159
|
def draw_fret(svg, n)
|
156
160
|
y = get_fret_y(n)
|
157
161
|
if @opts[:rectangular_frets]
|
@@ -160,14 +164,14 @@ module Fretboards
|
|
160
164
|
svg.line(fret_attrs.merge(:x1 => @opts[:padding_left], :x2 => @opts[:width] - @opts[:padding_right], :y1 => y, :y2 => y, :class => 'fret'))
|
161
165
|
end
|
162
166
|
end
|
163
|
-
|
167
|
+
|
164
168
|
def draw_nut(svg)
|
165
169
|
y = @opts[:padding_top] - @opts[:nut_attrs][:"stroke-width"] * 0.5
|
166
170
|
extra_first = 0 # @opts[:string_widths][0] * 0.5
|
167
171
|
extra_last = 0 # @opts[:string_widths].last * 0.5
|
168
172
|
svg.line(nut_attrs.merge(:x1 => @opts[:padding_left] - extra_first, :x2 => @opts[:width] - @opts[:padding_right] + extra_last, :y1 => y, :y2 => y, :class => 'nut'))
|
169
173
|
end
|
170
|
-
|
174
|
+
|
171
175
|
def get_fret_y(fret_number)
|
172
176
|
fret_range = @fb.fret_range(@opts[:fret_count])
|
173
177
|
avail = @opts[:height] - @opts[:padding_top] - @opts[:padding_bottom] - @opts[:string_ext_bottom]
|
@@ -184,7 +188,7 @@ module Fretboards
|
|
184
188
|
end
|
185
189
|
y
|
186
190
|
end
|
187
|
-
|
191
|
+
|
188
192
|
def get_first_fret_size(gaps, factor, avail)
|
189
193
|
sum = 0
|
190
194
|
(0..gaps-1).each do |t|
|
@@ -192,8 +196,8 @@ module Fretboards
|
|
192
196
|
end
|
193
197
|
avail.to_f/sum.to_f
|
194
198
|
end
|
195
|
-
|
196
|
-
|
199
|
+
|
200
|
+
|
197
201
|
def draw_marks(svg)
|
198
202
|
@fb.marks.each do |m|
|
199
203
|
if m[:fret] == 0
|
@@ -209,13 +213,13 @@ module Fretboards
|
|
209
213
|
end
|
210
214
|
end
|
211
215
|
end
|
212
|
-
|
216
|
+
|
213
217
|
def draw_blue_note_symbol(svg, x, y, m)
|
214
218
|
svg.rect(:x => x - 4, :y => y - 4, :width => 8, :height => 8, :fill => "#000", :stroke => "", :transform => "rotate(-45 #{x} #{y})")
|
215
219
|
# svg.circle(:cx => x, :cy => y, :r => 3, :fill => "blue")
|
216
220
|
end
|
217
|
-
|
218
|
-
|
221
|
+
|
222
|
+
|
219
223
|
def draw_dot(svg, x, y, m)
|
220
224
|
cnames = %w[dot]
|
221
225
|
cnames << "dot-#{m[:symbol]}" if m[:symbol]
|
@@ -223,7 +227,7 @@ module Fretboards
|
|
223
227
|
attrs = attrs.merge(@opts[(m[:symbol].to_s + "_symbol_attrs").to_sym]) if (m[:symbol] && @opts[(m[:symbol].to_s + "_symbol_attrs").to_sym])
|
224
228
|
svg.circle(attrs)
|
225
229
|
end
|
226
|
-
|
230
|
+
|
227
231
|
def get_dot_position(string, fret)
|
228
232
|
fret_range = @fb.fret_range(@opts[:fret_count])
|
229
233
|
diff = fret_range.first == 1 ? 0 : fret_range.first - 1
|
@@ -232,7 +236,7 @@ module Fretboards
|
|
232
236
|
y = 0.5 * (get_fret_y(fret - 1) + get_fret_y(fret))
|
233
237
|
[x, y]
|
234
238
|
end
|
235
|
-
|
239
|
+
|
236
240
|
def draw_in_dots(svg, name)
|
237
241
|
# TODO allow rotating dot text on rotated fretboards
|
238
242
|
sym = name.to_sym
|
@@ -250,7 +254,7 @@ module Fretboards
|
|
250
254
|
end
|
251
255
|
end
|
252
256
|
end
|
253
|
-
|
257
|
+
|
254
258
|
def draw_in_bottom(svg, name)
|
255
259
|
# TODO allow rotating bottom text on rotated fretboards
|
256
260
|
sym = name.to_sym
|
@@ -264,7 +268,7 @@ module Fretboards
|
|
264
268
|
end
|
265
269
|
end
|
266
270
|
end
|
267
|
-
|
271
|
+
|
268
272
|
def draw_open(svg, m)
|
269
273
|
margin_bottom = @opts[:open_margin_bottom]
|
270
274
|
y = @opts[:padding_top] - @opts[:open_attrs][:r] - @opts[:nut_attrs][:"stroke-width"] - margin_bottom
|
@@ -274,7 +278,7 @@ module Fretboards
|
|
274
278
|
attrs = attrs.merge(@opts[symbol_attrs]) if (m[:symbol] && @opts[symbol_attrs])
|
275
279
|
svg.circle(attrs)
|
276
280
|
end
|
277
|
-
|
281
|
+
|
278
282
|
def draw_mutes(svg)
|
279
283
|
margin_bottom = @opts[:open_margin_bottom]
|
280
284
|
cy = @opts[:padding_top] - @opts[:open_attrs][:r] - @opts[:nut_attrs][:"stroke-width"] - margin_bottom
|
@@ -286,7 +290,7 @@ module Fretboards
|
|
286
290
|
# svg.text("x", { :x => cx, :y => cy })
|
287
291
|
end
|
288
292
|
end
|
289
|
-
|
293
|
+
|
290
294
|
def draw_barres(svg)
|
291
295
|
barre_attrs = @opts[:barre_attrs]
|
292
296
|
@fb.barres.each do |b|
|
@@ -297,8 +301,8 @@ module Fretboards
|
|
297
301
|
svg.rect({:y => y, :x => x, :width => w, :class => :barre}.merge(barre_attrs))
|
298
302
|
end
|
299
303
|
end
|
300
|
-
|
301
|
-
|
304
|
+
|
305
|
+
|
302
306
|
end
|
303
307
|
end
|
304
|
-
end
|
308
|
+
end
|
data/lib/fretboards/version.rb
CHANGED
data/test/test_fretboard.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'test/unit'
|
2
|
+
$:<< File.dirname(__FILE__) + '/../lib'
|
2
3
|
require 'fretboards'
|
3
|
-
|
4
4
|
include Fretboards
|
5
5
|
|
6
6
|
# TODO write useful tests
|
7
7
|
class FretboardTest < Test::Unit::TestCase
|
8
|
-
|
8
|
+
|
9
9
|
def test_string_count
|
10
10
|
uke = Fretboard.new()
|
11
11
|
assert_equal(4, uke.string_count)
|
@@ -13,71 +13,71 @@ class FretboardTest < Test::Unit::TestCase
|
|
13
13
|
guit = Fretboard.new(:tuning => Fretboards::Tuning::GUITAR)
|
14
14
|
assert_equal(6, guit.string_count)
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
def test_mark
|
18
18
|
fb = Fretboard.new
|
19
19
|
fb.mark :string => 1, :fret => 5
|
20
20
|
assert_equal([{:string => 1, :fret => 5}], fb.marks)
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def test_barre
|
24
24
|
fb = Fretboard.new(:tuning => %w{ g' c' e' a' })
|
25
25
|
fb.barre 1
|
26
26
|
assert_equal([{:fret => 1, :from => 4, :to => 1 }], fb.barres)
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def test_mute
|
30
30
|
fb = Fretboard.new
|
31
31
|
fb.mute(1)
|
32
32
|
assert_equal([1], fb.mutes)
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def test_open
|
36
36
|
fb = Fretboard.new
|
37
37
|
fb.open(1)
|
38
38
|
assert_equal([{:string => 1, :fret => 0}], fb.marks)
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
def test_terse_full
|
42
42
|
fb = Fretboard.new
|
43
43
|
fb.terse %w{ 1/4-3(5) }
|
44
44
|
assert_equal([{:string => 4, :finger => 3, :function => "5", :fret => 1}], fb.marks)
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
def test_terse_minimal
|
48
48
|
fb = Fretboard.new
|
49
49
|
fb.terse %w{ 1 }
|
50
50
|
assert_equal([{ :string => 4, :fret => 1 } ], fb.marks)
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
def test_terse_barre
|
54
54
|
fb = Fretboard.new
|
55
55
|
fb.terse %w{ 3 1[ 1] 0 }
|
56
56
|
assert_equal([{:fret => 1, :from => 3, :to => 2 }], fb.barres)
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
def test_terse_unfinished_barre
|
60
60
|
fb = Fretboard.new
|
61
61
|
fb.terse %w{ 3 1[ 1 1 }
|
62
62
|
assert_equal([{:fret => 1, :from => 3, :to => 1 }], fb.barres)
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
def test_terse_symbols
|
66
66
|
# puts "symbols"
|
67
67
|
fb = Fretboard.new
|
68
68
|
fb.terse %w{ 3! }
|
69
69
|
assert_equal(:root, fb.marks.first[:symbol])
|
70
|
-
|
70
|
+
|
71
71
|
fb = Fretboard.new
|
72
72
|
fb.terse %w{ 3? }
|
73
73
|
assert_equal(:phantom, fb.marks.first[:symbol])
|
74
|
-
|
74
|
+
|
75
75
|
fb = Fretboard.new
|
76
76
|
fb.terse %w{ 3!? }
|
77
77
|
assert_equal(:phantom_root, fb.marks.first[:symbol])
|
78
|
-
|
78
|
+
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
def test_fret_range
|
82
82
|
fb = Fretboard.new
|
83
83
|
fb.terse %w{ 0 0 0 3 }
|
@@ -89,5 +89,12 @@ class FretboardTest < Test::Unit::TestCase
|
|
89
89
|
fb.terse %w{ 7 6 5 9 }
|
90
90
|
assert_equal([5, 9], fb.fret_range)
|
91
91
|
end
|
92
|
-
|
93
|
-
|
92
|
+
|
93
|
+
def test_fret_range_with_offset
|
94
|
+
fb = Fretboard.new
|
95
|
+
fb.terse %w{ 0 5 7 7 }
|
96
|
+
fb.set_offset 5
|
97
|
+
assert_equal([5, 8], fb.fret_range)
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fretboards
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Choan Galvez
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-11-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: builder
|