squib 0.18.0 → 0.19.0a
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/ISSUE_TEMPLATE/bug_report.md +39 -39
- data/.github/ISSUE_TEMPLATE/feature_request.md +22 -22
- data/.github/ISSUE_TEMPLATE/help-wanted.md +13 -13
- data/.github/ISSUE_TEMPLATE/release-todo.md +45 -33
- data/.github/PULL_REQUEST_TEMPLATE.md +13 -13
- data/.github/workflows/tests.yml +22 -22
- data/.gitignore +41 -41
- data/.vscode/settings.json +4 -3
- data/CHANGELOG.md +460 -460
- data/CONTRIBUTING.md +40 -40
- data/Dockerfile +27 -27
- data/Gemfile +2 -2
- data/Guardfile +8 -8
- data/LICENSE.txt +22 -22
- data/README.md +139 -139
- data/Rakefile +51 -51
- data/bin/squib +5 -5
- data/lib/squib/api/settings.rb +21 -21
- data/lib/squib/args/arg_loader.rb +138 -138
- data/lib/squib/args/box.rb +59 -59
- data/lib/squib/args/card_range.rb +34 -34
- data/lib/squib/args/color_validator.rb +7 -7
- data/lib/squib/args/coords.rb +49 -49
- data/lib/squib/args/csv_opts.rb +22 -22
- data/lib/squib/args/dir_validator.rb +11 -11
- data/lib/squib/args/draw.rb +93 -93
- data/lib/squib/args/drop_shadow.rb +39 -39
- data/lib/squib/args/embed_adjust.rb +22 -22
- data/lib/squib/args/embed_key.rb +12 -12
- data/lib/squib/args/hand_special.rb +37 -37
- data/lib/squib/args/import.rb +67 -67
- data/lib/squib/args/input_file.rb +55 -55
- data/lib/squib/args/paint.rb +43 -43
- data/lib/squib/args/paragraph.rb +118 -118
- data/lib/squib/args/save_batch.rb +65 -65
- data/lib/squib/args/scale_box.rb +57 -57
- data/lib/squib/args/sheet.rb +165 -165
- data/lib/squib/args/showcase_special.rb +41 -41
- data/lib/squib/args/sprue_file.rb +44 -44
- data/lib/squib/args/svg_special.rb +37 -37
- data/lib/squib/args/transform.rb +55 -55
- data/lib/squib/args/typographer.rb +115 -115
- data/lib/squib/args/unit_conversion.rb +27 -27
- data/lib/squib/args/xywh_shorthands.rb +50 -50
- data/lib/squib/builtin/layouts/economy.yml +85 -85
- data/lib/squib/builtin/layouts/fantasy.yml +101 -101
- data/lib/squib/builtin/layouts/hand.yml +62 -62
- data/lib/squib/builtin/layouts/party.yml +94 -94
- data/lib/squib/builtin/layouts/playing-card.yml +35 -35
- data/lib/squib/builtin/layouts/tuck_box.yml +46 -46
- data/lib/squib/builtin/projects/advanced/.gitignore +4 -4
- data/lib/squib/builtin/projects/advanced/ABOUT.md +19 -19
- data/lib/squib/builtin/projects/advanced/Gemfile +11 -11
- data/lib/squib/builtin/projects/advanced/Guardfile +21 -21
- data/lib/squib/builtin/projects/advanced/IDEAS.md +22 -22
- data/lib/squib/builtin/projects/advanced/PLAYTESTING.md +26 -26
- data/lib/squib/builtin/projects/advanced/Rakefile +27 -27
- data/lib/squib/builtin/projects/advanced/config.yml +49 -49
- data/lib/squib/builtin/projects/advanced/docs/PNP NOTES.md +3 -3
- data/lib/squib/builtin/projects/advanced/docs/RULES.md +21 -21
- data/lib/squib/builtin/projects/advanced/img/example.svg +60 -60
- data/lib/squib/builtin/projects/advanced/layouts/deck.yml +27 -27
- data/lib/squib/builtin/projects/advanced/src/deck.rb +34 -34
- data/lib/squib/builtin/projects/advanced/src/version.rb +3 -3
- data/lib/squib/builtin/projects/basic/.gitignore +4 -4
- data/lib/squib/builtin/projects/basic/ABOUT.md +19 -19
- data/lib/squib/builtin/projects/basic/Gemfile +3 -3
- data/lib/squib/builtin/projects/basic/IDEAS.md +22 -22
- data/lib/squib/builtin/projects/basic/PLAYTESTING.md +26 -26
- data/lib/squib/builtin/projects/basic/PNP NOTES.md +3 -3
- data/lib/squib/builtin/projects/basic/RULES.md +21 -21
- data/lib/squib/builtin/projects/basic/Rakefile +7 -7
- data/lib/squib/builtin/projects/basic/config.yml +50 -50
- data/lib/squib/builtin/projects/basic/deck.rb +6 -6
- data/lib/squib/builtin/sprues/a4_euro_card.yml +42 -42
- data/lib/squib/builtin/sprues/a4_poker_card_8up.yml +40 -40
- data/lib/squib/builtin/sprues/a4_poker_card_9up.yml +42 -42
- data/lib/squib/builtin/sprues/a4_usa_card.yml +42 -42
- data/lib/squib/builtin/sprues/drivethrucards_1up.yml +10 -10
- data/lib/squib/builtin/sprues/letter_poker_card_9up.yml +25 -25
- data/lib/squib/builtin/sprues/letter_poker_foldable_8up.yml +52 -52
- data/lib/squib/builtin/sprues/printplaygames_18up.yml +68 -68
- data/lib/squib/card.rb +75 -75
- data/lib/squib/commands/cli.rb +39 -39
- data/lib/squib/commands/data/template_option.rb +109 -109
- data/lib/squib/commands/make_sprue.rb +277 -277
- data/lib/squib/commands/new.rb +77 -77
- data/lib/squib/conf.rb +149 -149
- data/lib/squib/constants.rb +17 -17
- data/lib/squib/deck.rb +138 -138
- data/lib/squib/dsl/background.rb +35 -35
- data/lib/squib/dsl/circle.rb +39 -39
- data/lib/squib/dsl/csv.rb +42 -42
- data/lib/squib/dsl/curve.rb +35 -35
- data/lib/squib/dsl/cut_zone.rb +47 -47
- data/lib/squib/dsl/ellipse.rb +37 -37
- data/lib/squib/dsl/grid.rb +35 -35
- data/lib/squib/dsl/groups.rb +54 -54
- data/lib/squib/dsl/hand.rb +42 -42
- data/lib/squib/dsl/line.rb +35 -35
- data/lib/squib/dsl/png.rb +57 -57
- data/lib/squib/dsl/polygon.rb +36 -36
- data/lib/squib/dsl/rect.rb +37 -37
- data/lib/squib/dsl/safe_zone.rb +48 -48
- data/lib/squib/dsl/save.rb +21 -21
- data/lib/squib/dsl/save_pdf.rb +50 -50
- data/lib/squib/dsl/save_png.rb +48 -48
- data/lib/squib/dsl/save_sheet.rb +53 -53
- data/lib/squib/dsl/showcase.rb +43 -43
- data/lib/squib/dsl/star.rb +37 -37
- data/lib/squib/dsl/svg.rb +63 -63
- data/lib/squib/dsl/text.rb +54 -54
- data/lib/squib/dsl/text_embed.rb +79 -79
- data/lib/squib/dsl/triangle.rb +35 -35
- data/lib/squib/dsl/units.rb +37 -37
- data/lib/squib/dsl/xlsx.rb +40 -40
- data/lib/squib/dsl/yaml.rb +40 -40
- data/lib/squib/errors_warnings/warn_unexpected_params.rb +14 -14
- data/lib/squib/graphics/background.rb +14 -14
- data/lib/squib/graphics/cairo_context_wrapper.rb +115 -115
- data/lib/squib/graphics/embedding_utils.rb +28 -28
- data/lib/squib/graphics/gradient_regex.rb +47 -47
- data/lib/squib/graphics/hand.rb +42 -42
- data/lib/squib/graphics/image.rb +123 -123
- data/lib/squib/graphics/save_doc.rb +77 -77
- data/lib/squib/graphics/save_images.rb +91 -91
- data/lib/squib/graphics/save_pdf.rb +90 -90
- data/lib/squib/graphics/save_sprue.rb +231 -231
- data/lib/squib/graphics/shapes.rb +143 -143
- data/lib/squib/graphics/showcase.rb +85 -85
- data/lib/squib/graphics/text.rb +202 -202
- data/lib/squib/import/csv_importer.rb +45 -45
- data/lib/squib/import/data_frame.rb +108 -108
- data/lib/squib/import/quantity_exploder.rb +17 -17
- data/lib/squib/import/xlsx_importer.rb +28 -28
- data/lib/squib/import/yaml_importer.rb +30 -30
- data/lib/squib/layout_parser.rb +155 -155
- data/lib/squib/progress.rb +38 -38
- data/lib/squib/sample_helpers.rb +34 -34
- data/lib/squib/sprues/crop_line.rb +28 -28
- data/lib/squib/sprues/crop_line_dash.rb +35 -35
- data/lib/squib/sprues/invalid_sprue_definition.rb +9 -9
- data/lib/squib/sprues/sprue.rb +208 -208
- data/lib/squib/sprues/sprue_schema.rb +51 -51
- data/lib/squib/system_fonts.rb +16 -16
- data/lib/squib/version.rb +11 -11
- data/lib/squib.rb +35 -35
- data/samples/autoscale_font/_autoscale_font.rb +98 -98
- data/samples/backend/_backend.rb +26 -26
- data/samples/basic.rb +19 -19
- data/samples/build_groups/build_groups.rb +36 -36
- data/samples/colors/_colors.rb +44 -44
- data/samples/colors/_gradients.rb +34 -34
- data/samples/colors/_switch_color.rb +33 -33
- data/samples/config/config_text_markup.rb +20 -20
- data/samples/config/custom_config.rb +18 -18
- data/samples/data/_csv.rb +33 -33
- data/samples/data/_excel.rb +55 -55
- data/samples/data/_yaml.rb +12 -12
- data/samples/hello_world.rb +6 -6
- data/samples/images/_cairo_access.rb +39 -39
- data/samples/images/_images.rb +104 -104
- data/samples/images/_more_load_images.rb +102 -102
- data/samples/images/_placeholders.rb +48 -48
- data/samples/intro/01_hello.rb +8 -8
- data/samples/intro/02_options.rb +14 -14
- data/samples/intro/03_layout.rb +11 -11
- data/samples/intro/04_arrays.rb +15 -15
- data/samples/intro/05_excel.rb +14 -14
- data/samples/layouts/builtin_layouts.rb +97 -97
- data/samples/layouts/layouts.rb +71 -71
- data/samples/project/src/characters.rb +8 -8
- data/samples/project/src/skills.rb +7 -7
- data/samples/proofs/_tgc_proofs.rb +16 -16
- data/samples/ranges/_ranges.rb +64 -64
- data/samples/saves/_hand.rb +23 -23
- data/samples/saves/_portrait_landscape.rb +23 -23
- data/samples/saves/_save_filenames.rb +28 -28
- data/samples/saves/_save_pdf.rb +29 -29
- data/samples/saves/_saves.rb +75 -75
- data/samples/saves/_showcase.rb +25 -25
- data/samples/shadows/_shadow.rb +71 -71
- data/samples/shapes/_draw_shapes.rb +60 -60
- data/samples/shapes/_proofs.rb +22 -22
- data/samples/sprues/_advanced_sprues.rb +25 -25
- data/samples/sprues/_builtin_sprues.rb +22 -22
- data/samples/sprues/_fold_sheet.rb +30 -30
- data/samples/sprues/_hex_tiles.rb +15 -15
- data/samples/sprues/_mints.rb +11 -11
- data/samples/sprues/_negative_coords.rb +6 -6
- data/samples/sprues/_sprue_example.rb +11 -11
- data/samples/system_font_debug/_list_fonts.rb +14 -14
- data/samples/text/_embed_text.rb +128 -128
- data/samples/text/_text.rb +52 -52
- data/samples/text/_text_options.rb +103 -103
- data/samples/text/bug134.rb +14 -14
- data/samples/units/_cells.rb +50 -50
- data/samples/units/_shorthands.rb +48 -48
- data/samples/units/_units.rb +39 -39
- data/squib.gemspec +58 -58
- metadata +21 -21
data/lib/squib/layout_parser.rb
CHANGED
|
@@ -1,155 +1,155 @@
|
|
|
1
|
-
require 'yaml'
|
|
2
|
-
require_relative 'args/xywh_shorthands'
|
|
3
|
-
|
|
4
|
-
module Squib
|
|
5
|
-
# Internal class for handling layouts
|
|
6
|
-
# @api private
|
|
7
|
-
class LayoutParser
|
|
8
|
-
include Args::XYWHShorthands
|
|
9
|
-
|
|
10
|
-
def initialize(dpi = 300, cell_px = 37.5)
|
|
11
|
-
@dpi = dpi
|
|
12
|
-
@cell_px = cell_px
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
# Load the layout file(s), if exists
|
|
16
|
-
# @api private
|
|
17
|
-
def load_layout(files, initial = {})
|
|
18
|
-
layout = initial
|
|
19
|
-
Squib::logger.info { " using layout(s): #{files}" }
|
|
20
|
-
Array(files).each do |file|
|
|
21
|
-
thefile = file
|
|
22
|
-
thefile = builtin(file) unless File.
|
|
23
|
-
if File.
|
|
24
|
-
# note: YAML.load_file returns false on empty file
|
|
25
|
-
yml = layout.merge(YAML.load_file(thefile) || {})
|
|
26
|
-
yml.each do |key, value|
|
|
27
|
-
layout[key] = recurse_extends(yml, key, {})
|
|
28
|
-
end
|
|
29
|
-
else
|
|
30
|
-
Squib::logger.error { "Layout file not found: #{file}. Skipping..." }
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
return layout
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
private
|
|
37
|
-
|
|
38
|
-
# Determine the file path of the built-in layout file
|
|
39
|
-
def builtin(file)
|
|
40
|
-
"#{File.dirname(__FILE__)}/builtin/layouts/#{file}"
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Process the extends recursively
|
|
44
|
-
# :nodoc:
|
|
45
|
-
# @api private
|
|
46
|
-
def recurse_extends(yml, key, visited)
|
|
47
|
-
assert_not_visited(key, visited)
|
|
48
|
-
return yml[key] unless has_extends?(yml, key)
|
|
49
|
-
return yml[key] unless parents_exist?(yml, key)
|
|
50
|
-
visited[key] = key
|
|
51
|
-
parent_keys = [yml[key]['extends']].flatten
|
|
52
|
-
h = {}
|
|
53
|
-
parent_keys.each do |parent_key|
|
|
54
|
-
from_extends = yml[key].merge(recurse_extends(yml, parent_key, visited)) do |key, child_val, parent_val|
|
|
55
|
-
handle_relative_operators(parent_val, child_val)
|
|
56
|
-
end
|
|
57
|
-
h = h.merge(from_extends) do |key, older_sibling, younger_sibling|
|
|
58
|
-
# In general, go with the younger sibling.
|
|
59
|
-
# UNLESS that younger sibling had a relative operator, in which use the
|
|
60
|
-
# (already computed) relative operator applied, which lands in older_sibling
|
|
61
|
-
# See bug 244.
|
|
62
|
-
sibling = younger_sibling
|
|
63
|
-
%w(+= -= *= /=).each do |op|
|
|
64
|
-
sibling = older_sibling if younger_sibling.to_s.strip.start_with? op
|
|
65
|
-
end
|
|
66
|
-
sibling
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
return h
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def handle_relative_operators(parent_val, child_val)
|
|
73
|
-
if uses_operator?(child_val) && !has_digits?(parent_val) && !has_digits?(child_val)
|
|
74
|
-
raise "Layout parse error: can't combine #{parent_val} and #{child_val}"
|
|
75
|
-
end
|
|
76
|
-
if child_val.to_s.strip.start_with?('+=')
|
|
77
|
-
add_parent_child(parent_val, child_val)
|
|
78
|
-
elsif child_val.to_s.strip.start_with?('-=')
|
|
79
|
-
sub_parent_child(parent_val, child_val)
|
|
80
|
-
elsif child_val.to_s.strip.start_with?('*=')
|
|
81
|
-
mul_parent_child(parent_val, child_val)
|
|
82
|
-
elsif child_val.to_s.strip.start_with?('/=')
|
|
83
|
-
div_parent_child(parent_val, child_val)
|
|
84
|
-
else
|
|
85
|
-
child_val # child overrides parent when merging, no +=
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def add_parent_child(parent, child)
|
|
90
|
-
parent_pixels = Args::UnitConversion.parse(parent, @dpi, @cell_px).to_f
|
|
91
|
-
child_pixels = Args::UnitConversion.parse(child.sub('+=', ''), @dpi, @cell_px).to_f
|
|
92
|
-
parent_pixels + child_pixels
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def sub_parent_child(parent, child)
|
|
96
|
-
parent_pixels = Args::UnitConversion.parse(parent, @dpi, @cell_px).to_f
|
|
97
|
-
child_pixels = Args::UnitConversion.parse(child.sub('-=', ''), @dpi, @cell_px).to_f
|
|
98
|
-
parent_pixels - child_pixels
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def mul_parent_child(parent, child)
|
|
102
|
-
parent_pixels = Args::UnitConversion.parse(parent, @dpi, @cell_px).to_f
|
|
103
|
-
child_float = child.sub('*=', '').to_f
|
|
104
|
-
parent_pixels * child_float
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def div_parent_child(parent, child)
|
|
108
|
-
parent_pixels = Args::UnitConversion.parse(parent, @dpi, @cell_px).to_f
|
|
109
|
-
child_float = child.sub('/=', '').to_f
|
|
110
|
-
parent_pixels / child_float
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
# For relative operators, it's difficult for us to handle
|
|
114
|
-
# some of the shorthands - so let's just freak out if you're trying to use
|
|
115
|
-
# relative operators with words, e.g. "middle += 0.5in"
|
|
116
|
-
def has_digits?(arg)
|
|
117
|
-
/.*\d.*/ === arg.to_s
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def uses_operator?(arg)
|
|
121
|
-
/^[+=|\-=|\/=|*=].*/ === arg.to_s
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
# Does this layout entry have an extends field?
|
|
125
|
-
# i.e. is it a base-case or will it need recursion?
|
|
126
|
-
# :nodoc:
|
|
127
|
-
# @api private
|
|
128
|
-
def has_extends?(yml, key)
|
|
129
|
-
!!yml[key] && yml[key].key?('extends')
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
# Checks if we have any absentee parents
|
|
133
|
-
# @api private
|
|
134
|
-
def parents_exist?(yml, key)
|
|
135
|
-
exists = true
|
|
136
|
-
Array(yml[key]['extends']).each do |parent|
|
|
137
|
-
unless yml.key?(parent)
|
|
138
|
-
exists = false unless
|
|
139
|
-
Squib.logger.error "Processing layout: '#{key}' attempts to extend a missing '#{yml[key]['extends']}'"
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
return exists
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
# Safeguard against malformed circular extends
|
|
146
|
-
# :nodoc:
|
|
147
|
-
# @api private
|
|
148
|
-
def assert_not_visited(key, visited)
|
|
149
|
-
if visited.key? key
|
|
150
|
-
raise "Invalid layout: circular extends with '#{key}'"
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
end
|
|
155
|
-
end
|
|
1
|
+
require 'yaml'
|
|
2
|
+
require_relative 'args/xywh_shorthands'
|
|
3
|
+
|
|
4
|
+
module Squib
|
|
5
|
+
# Internal class for handling layouts
|
|
6
|
+
# @api private
|
|
7
|
+
class LayoutParser
|
|
8
|
+
include Args::XYWHShorthands
|
|
9
|
+
|
|
10
|
+
def initialize(dpi = 300, cell_px = 37.5)
|
|
11
|
+
@dpi = dpi
|
|
12
|
+
@cell_px = cell_px
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Load the layout file(s), if exists
|
|
16
|
+
# @api private
|
|
17
|
+
def load_layout(files, initial = {})
|
|
18
|
+
layout = initial
|
|
19
|
+
Squib::logger.info { " using layout(s): #{files}" }
|
|
20
|
+
Array(files).each do |file|
|
|
21
|
+
thefile = file
|
|
22
|
+
thefile = builtin(file) unless File.exist?(file)
|
|
23
|
+
if File.exist? thefile
|
|
24
|
+
# note: YAML.load_file returns false on empty file
|
|
25
|
+
yml = layout.merge(YAML.load_file(thefile) || {})
|
|
26
|
+
yml.each do |key, value|
|
|
27
|
+
layout[key] = recurse_extends(yml, key, {})
|
|
28
|
+
end
|
|
29
|
+
else
|
|
30
|
+
Squib::logger.error { "Layout file not found: #{file}. Skipping..." }
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
return layout
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
# Determine the file path of the built-in layout file
|
|
39
|
+
def builtin(file)
|
|
40
|
+
"#{File.dirname(__FILE__)}/builtin/layouts/#{file}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Process the extends recursively
|
|
44
|
+
# :nodoc:
|
|
45
|
+
# @api private
|
|
46
|
+
def recurse_extends(yml, key, visited)
|
|
47
|
+
assert_not_visited(key, visited)
|
|
48
|
+
return yml[key] unless has_extends?(yml, key)
|
|
49
|
+
return yml[key] unless parents_exist?(yml, key)
|
|
50
|
+
visited[key] = key
|
|
51
|
+
parent_keys = [yml[key]['extends']].flatten
|
|
52
|
+
h = {}
|
|
53
|
+
parent_keys.each do |parent_key|
|
|
54
|
+
from_extends = yml[key].merge(recurse_extends(yml, parent_key, visited)) do |key, child_val, parent_val|
|
|
55
|
+
handle_relative_operators(parent_val, child_val)
|
|
56
|
+
end
|
|
57
|
+
h = h.merge(from_extends) do |key, older_sibling, younger_sibling|
|
|
58
|
+
# In general, go with the younger sibling.
|
|
59
|
+
# UNLESS that younger sibling had a relative operator, in which use the
|
|
60
|
+
# (already computed) relative operator applied, which lands in older_sibling
|
|
61
|
+
# See bug 244.
|
|
62
|
+
sibling = younger_sibling
|
|
63
|
+
%w(+= -= *= /=).each do |op|
|
|
64
|
+
sibling = older_sibling if younger_sibling.to_s.strip.start_with? op
|
|
65
|
+
end
|
|
66
|
+
sibling
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
return h
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def handle_relative_operators(parent_val, child_val)
|
|
73
|
+
if uses_operator?(child_val) && !has_digits?(parent_val) && !has_digits?(child_val)
|
|
74
|
+
raise "Layout parse error: can't combine #{parent_val} and #{child_val}"
|
|
75
|
+
end
|
|
76
|
+
if child_val.to_s.strip.start_with?('+=')
|
|
77
|
+
add_parent_child(parent_val, child_val)
|
|
78
|
+
elsif child_val.to_s.strip.start_with?('-=')
|
|
79
|
+
sub_parent_child(parent_val, child_val)
|
|
80
|
+
elsif child_val.to_s.strip.start_with?('*=')
|
|
81
|
+
mul_parent_child(parent_val, child_val)
|
|
82
|
+
elsif child_val.to_s.strip.start_with?('/=')
|
|
83
|
+
div_parent_child(parent_val, child_val)
|
|
84
|
+
else
|
|
85
|
+
child_val # child overrides parent when merging, no +=
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def add_parent_child(parent, child)
|
|
90
|
+
parent_pixels = Args::UnitConversion.parse(parent, @dpi, @cell_px).to_f
|
|
91
|
+
child_pixels = Args::UnitConversion.parse(child.sub('+=', ''), @dpi, @cell_px).to_f
|
|
92
|
+
parent_pixels + child_pixels
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def sub_parent_child(parent, child)
|
|
96
|
+
parent_pixels = Args::UnitConversion.parse(parent, @dpi, @cell_px).to_f
|
|
97
|
+
child_pixels = Args::UnitConversion.parse(child.sub('-=', ''), @dpi, @cell_px).to_f
|
|
98
|
+
parent_pixels - child_pixels
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def mul_parent_child(parent, child)
|
|
102
|
+
parent_pixels = Args::UnitConversion.parse(parent, @dpi, @cell_px).to_f
|
|
103
|
+
child_float = child.sub('*=', '').to_f
|
|
104
|
+
parent_pixels * child_float
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def div_parent_child(parent, child)
|
|
108
|
+
parent_pixels = Args::UnitConversion.parse(parent, @dpi, @cell_px).to_f
|
|
109
|
+
child_float = child.sub('/=', '').to_f
|
|
110
|
+
parent_pixels / child_float
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# For relative operators, it's difficult for us to handle
|
|
114
|
+
# some of the shorthands - so let's just freak out if you're trying to use
|
|
115
|
+
# relative operators with words, e.g. "middle += 0.5in"
|
|
116
|
+
def has_digits?(arg)
|
|
117
|
+
/.*\d.*/ === arg.to_s
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def uses_operator?(arg)
|
|
121
|
+
/^[+=|\-=|\/=|*=].*/ === arg.to_s
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Does this layout entry have an extends field?
|
|
125
|
+
# i.e. is it a base-case or will it need recursion?
|
|
126
|
+
# :nodoc:
|
|
127
|
+
# @api private
|
|
128
|
+
def has_extends?(yml, key)
|
|
129
|
+
!!yml[key] && yml[key].key?('extends')
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Checks if we have any absentee parents
|
|
133
|
+
# @api private
|
|
134
|
+
def parents_exist?(yml, key)
|
|
135
|
+
exists = true
|
|
136
|
+
Array(yml[key]['extends']).each do |parent|
|
|
137
|
+
unless yml.key?(parent)
|
|
138
|
+
exists = false unless
|
|
139
|
+
Squib.logger.error "Processing layout: '#{key}' attempts to extend a missing '#{yml[key]['extends']}'"
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
return exists
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Safeguard against malformed circular extends
|
|
146
|
+
# :nodoc:
|
|
147
|
+
# @api private
|
|
148
|
+
def assert_not_visited(key, visited)
|
|
149
|
+
if visited.key? key
|
|
150
|
+
raise "Invalid layout: circular extends with '#{key}'"
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
end
|
|
155
|
+
end
|
data/lib/squib/progress.rb
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
require 'ruby-progressbar'
|
|
2
|
-
|
|
3
|
-
module Squib
|
|
4
|
-
|
|
5
|
-
# :nodoc:
|
|
6
|
-
# @api private
|
|
7
|
-
class DoNothing
|
|
8
|
-
def increment
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def finish
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
# A facade that handles (or doesn't) the progress bar on the console
|
|
16
|
-
#
|
|
17
|
-
# :nodoc:
|
|
18
|
-
# @api private
|
|
19
|
-
class Progress
|
|
20
|
-
attr_accessor :enabled
|
|
21
|
-
|
|
22
|
-
def initialize(enabled)
|
|
23
|
-
@enabled = enabled
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def start(title='', total=100, &block)
|
|
27
|
-
if @enabled
|
|
28
|
-
@bar = ProgressBar.create(title: title, total: total, format: '%t <%B> %p%% %a')
|
|
29
|
-
yield(@bar)
|
|
30
|
-
@bar.finish
|
|
31
|
-
else
|
|
32
|
-
yield(Squib::DoNothing.new)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
end
|
|
1
|
+
require 'ruby-progressbar'
|
|
2
|
+
|
|
3
|
+
module Squib
|
|
4
|
+
|
|
5
|
+
# :nodoc:
|
|
6
|
+
# @api private
|
|
7
|
+
class DoNothing
|
|
8
|
+
def increment
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def finish
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# A facade that handles (or doesn't) the progress bar on the console
|
|
16
|
+
#
|
|
17
|
+
# :nodoc:
|
|
18
|
+
# @api private
|
|
19
|
+
class Progress
|
|
20
|
+
attr_accessor :enabled
|
|
21
|
+
|
|
22
|
+
def initialize(enabled)
|
|
23
|
+
@enabled = enabled
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def start(title='', total=100, &block)
|
|
27
|
+
if @enabled
|
|
28
|
+
@bar = ProgressBar.create(title: title, total: total, format: '%t <%B> %p%% %a')
|
|
29
|
+
yield(@bar)
|
|
30
|
+
@bar.finish
|
|
31
|
+
else
|
|
32
|
+
yield(Squib::DoNothing.new)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
end
|
data/lib/squib/sample_helpers.rb
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
module Squib
|
|
2
|
-
|
|
3
|
-
# Some helper methods specifically for samples
|
|
4
|
-
# @api private
|
|
5
|
-
#:nodoc:
|
|
6
|
-
class Deck
|
|
7
|
-
|
|
8
|
-
# Draw graph paper for samples
|
|
9
|
-
def draw_graph_paper(width, height)
|
|
10
|
-
background color: 'white'
|
|
11
|
-
grid width: 50, height: 50, stroke_color: '#659ae9', stroke_width: 1.5
|
|
12
|
-
grid width: 200, height: 200, stroke_color: '#659ae9', stroke_width: 3, x: 50, y: 50
|
|
13
|
-
(50..height).step(200) do |y|
|
|
14
|
-
text str: "y=#{y}", x: 3, y: y - 18, font: 'Open Sans, Sans 10'
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# Define a set of samples on some graph paper
|
|
19
|
-
def sample(str)
|
|
20
|
-
@sample_x ||= 100
|
|
21
|
-
@sample_y ||= 100
|
|
22
|
-
rect x: 460, y: @sample_y - 40, width: 600,
|
|
23
|
-
height: 180, fill_color: '#FFD655', stroke_color: 'black', radius: 15
|
|
24
|
-
text str: str, x: 460, y: @sample_y - 40,
|
|
25
|
-
width: 540, height: 180,
|
|
26
|
-
valign: 'middle', align: 'center',
|
|
27
|
-
font: 'Times New Roman,Serif 8'
|
|
28
|
-
yield @sample_x, @sample_y
|
|
29
|
-
@sample_y += 200
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
end
|
|
1
|
+
module Squib
|
|
2
|
+
|
|
3
|
+
# Some helper methods specifically for samples
|
|
4
|
+
# @api private
|
|
5
|
+
#:nodoc:
|
|
6
|
+
class Deck
|
|
7
|
+
|
|
8
|
+
# Draw graph paper for samples
|
|
9
|
+
def draw_graph_paper(width, height)
|
|
10
|
+
background color: 'white'
|
|
11
|
+
grid width: 50, height: 50, stroke_color: '#659ae9', stroke_width: 1.5
|
|
12
|
+
grid width: 200, height: 200, stroke_color: '#659ae9', stroke_width: 3, x: 50, y: 50
|
|
13
|
+
(50..height).step(200) do |y|
|
|
14
|
+
text str: "y=#{y}", x: 3, y: y - 18, font: 'Open Sans, Sans 10'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Define a set of samples on some graph paper
|
|
19
|
+
def sample(str)
|
|
20
|
+
@sample_x ||= 100
|
|
21
|
+
@sample_y ||= 100
|
|
22
|
+
rect x: 460, y: @sample_y - 40, width: 600,
|
|
23
|
+
height: 180, fill_color: '#FFD655', stroke_color: 'black', radius: 15
|
|
24
|
+
text str: str, x: 460, y: @sample_y - 40,
|
|
25
|
+
width: 540, height: 180,
|
|
26
|
+
valign: 'middle', align: 'center',
|
|
27
|
+
font: 'Times New Roman,Serif 8'
|
|
28
|
+
yield @sample_x, @sample_y
|
|
29
|
+
@sample_y += 200
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
module Squib
|
|
2
|
-
module Sprues
|
|
3
|
-
class CropLine
|
|
4
|
-
attr_reader :x1, :y1, :x2, :y2
|
|
5
|
-
|
|
6
|
-
def initialize(type, position, sheet_width, sheet_height, dpi, cell_px)
|
|
7
|
-
method = "parse_#{type}"
|
|
8
|
-
send method, position, sheet_width, sheet_height, dpi, cell_px
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def parse_horizontal(position, sheet_width, _, dpi, cell_px)
|
|
12
|
-
position = Args::UnitConversion.parse(position, dpi, cell_px)
|
|
13
|
-
@x1 = 0
|
|
14
|
-
@y1 = position
|
|
15
|
-
@x2 = sheet_width
|
|
16
|
-
@y2 = position
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def parse_vertical(position, _, sheet_height, dpi, cell_px)
|
|
20
|
-
position = Args::UnitConversion.parse(position, dpi, cell_px)
|
|
21
|
-
@x1 = position
|
|
22
|
-
@y1 = 0
|
|
23
|
-
@x2 = position
|
|
24
|
-
@y2 = sheet_height
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
1
|
+
module Squib
|
|
2
|
+
module Sprues
|
|
3
|
+
class CropLine
|
|
4
|
+
attr_reader :x1, :y1, :x2, :y2
|
|
5
|
+
|
|
6
|
+
def initialize(type, position, sheet_width, sheet_height, dpi, cell_px)
|
|
7
|
+
method = "parse_#{type}"
|
|
8
|
+
send method, position, sheet_width, sheet_height, dpi, cell_px
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def parse_horizontal(position, sheet_width, _, dpi, cell_px)
|
|
12
|
+
position = Args::UnitConversion.parse(position, dpi, cell_px)
|
|
13
|
+
@x1 = 0
|
|
14
|
+
@y1 = position
|
|
15
|
+
@x2 = sheet_width
|
|
16
|
+
@y2 = position
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def parse_vertical(position, _, sheet_height, dpi, cell_px)
|
|
20
|
+
position = Args::UnitConversion.parse(position, dpi, cell_px)
|
|
21
|
+
@x1 = position
|
|
22
|
+
@y1 = 0
|
|
23
|
+
@x2 = position
|
|
24
|
+
@y2 = sheet_height
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
module Squib
|
|
2
|
-
module Sprues
|
|
3
|
-
class CropLineDash
|
|
4
|
-
VALIDATION_REGEX = /%r{
|
|
5
|
-
^(\d*[.])?\d+(in|cm|mm)
|
|
6
|
-
\s+
|
|
7
|
-
(\d*[.])?\d+(in|cm|mm)$
|
|
8
|
-
}x/
|
|
9
|
-
|
|
10
|
-
attr_reader :pattern
|
|
11
|
-
|
|
12
|
-
def initialize(value, dpi, cell_px)
|
|
13
|
-
if value == :solid
|
|
14
|
-
@pattern = nil
|
|
15
|
-
elsif value == :dotted
|
|
16
|
-
@pattern = [
|
|
17
|
-
Args::UnitConversion.parse('0.2mm', dpi, cell_px),
|
|
18
|
-
Args::UnitConversion.parse('0.5mm', dpi, cell_px)
|
|
19
|
-
]
|
|
20
|
-
elsif value == :dashed
|
|
21
|
-
@pattern = [
|
|
22
|
-
Args::UnitConversion.parse('2mm', dpi, cell_px),
|
|
23
|
-
Args::UnitConversion.parse('2mm', dpi, cell_px)
|
|
24
|
-
]
|
|
25
|
-
elsif value.is_a? String
|
|
26
|
-
@pattern = value.split(' ').map do |val|
|
|
27
|
-
Args::UnitConversion.parse val, dpi, cell_px
|
|
28
|
-
end
|
|
29
|
-
else
|
|
30
|
-
raise ArgumentError, 'Unsupported dash style'
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
1
|
+
module Squib
|
|
2
|
+
module Sprues
|
|
3
|
+
class CropLineDash
|
|
4
|
+
VALIDATION_REGEX = /%r{
|
|
5
|
+
^(\d*[.])?\d+(in|cm|mm)
|
|
6
|
+
\s+
|
|
7
|
+
(\d*[.])?\d+(in|cm|mm)$
|
|
8
|
+
}x/
|
|
9
|
+
|
|
10
|
+
attr_reader :pattern
|
|
11
|
+
|
|
12
|
+
def initialize(value, dpi, cell_px)
|
|
13
|
+
if value == :solid
|
|
14
|
+
@pattern = nil
|
|
15
|
+
elsif value == :dotted
|
|
16
|
+
@pattern = [
|
|
17
|
+
Args::UnitConversion.parse('0.2mm', dpi, cell_px),
|
|
18
|
+
Args::UnitConversion.parse('0.5mm', dpi, cell_px)
|
|
19
|
+
]
|
|
20
|
+
elsif value == :dashed
|
|
21
|
+
@pattern = [
|
|
22
|
+
Args::UnitConversion.parse('2mm', dpi, cell_px),
|
|
23
|
+
Args::UnitConversion.parse('2mm', dpi, cell_px)
|
|
24
|
+
]
|
|
25
|
+
elsif value.is_a? String
|
|
26
|
+
@pattern = value.split(' ').map do |val|
|
|
27
|
+
Args::UnitConversion.parse val, dpi, cell_px
|
|
28
|
+
end
|
|
29
|
+
else
|
|
30
|
+
raise ArgumentError, 'Unsupported dash style'
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
module Squib
|
|
2
|
-
module Sprues
|
|
3
|
-
class InvalidSprueDefinition < StandardError
|
|
4
|
-
def initialize(file, error)
|
|
5
|
-
super("Invalid sprue definition in file: #{file}. #{error.message}")
|
|
6
|
-
end
|
|
7
|
-
end
|
|
8
|
-
end
|
|
9
|
-
end
|
|
1
|
+
module Squib
|
|
2
|
+
module Sprues
|
|
3
|
+
class InvalidSprueDefinition < StandardError
|
|
4
|
+
def initialize(file, error)
|
|
5
|
+
super("Invalid sprue definition in file: #{file}. #{error.message}")
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|