squib 0.18.0 → 0.19.0a

Sign up to get free protection for your applications and to get access to all the features.
Files changed (202) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +39 -39
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +22 -22
  4. data/.github/ISSUE_TEMPLATE/help-wanted.md +13 -13
  5. data/.github/ISSUE_TEMPLATE/release-todo.md +45 -33
  6. data/.github/PULL_REQUEST_TEMPLATE.md +13 -13
  7. data/.github/workflows/tests.yml +22 -22
  8. data/.gitignore +41 -41
  9. data/.vscode/settings.json +4 -3
  10. data/CHANGELOG.md +460 -460
  11. data/CONTRIBUTING.md +40 -40
  12. data/Dockerfile +27 -27
  13. data/Gemfile +2 -2
  14. data/Guardfile +8 -8
  15. data/LICENSE.txt +22 -22
  16. data/README.md +139 -139
  17. data/Rakefile +51 -51
  18. data/bin/squib +5 -5
  19. data/lib/squib/api/settings.rb +21 -21
  20. data/lib/squib/args/arg_loader.rb +138 -138
  21. data/lib/squib/args/box.rb +59 -59
  22. data/lib/squib/args/card_range.rb +34 -34
  23. data/lib/squib/args/color_validator.rb +7 -7
  24. data/lib/squib/args/coords.rb +49 -49
  25. data/lib/squib/args/csv_opts.rb +22 -22
  26. data/lib/squib/args/dir_validator.rb +11 -11
  27. data/lib/squib/args/draw.rb +93 -93
  28. data/lib/squib/args/drop_shadow.rb +39 -39
  29. data/lib/squib/args/embed_adjust.rb +22 -22
  30. data/lib/squib/args/embed_key.rb +12 -12
  31. data/lib/squib/args/hand_special.rb +37 -37
  32. data/lib/squib/args/import.rb +67 -67
  33. data/lib/squib/args/input_file.rb +55 -55
  34. data/lib/squib/args/paint.rb +43 -43
  35. data/lib/squib/args/paragraph.rb +118 -118
  36. data/lib/squib/args/save_batch.rb +65 -65
  37. data/lib/squib/args/scale_box.rb +57 -57
  38. data/lib/squib/args/sheet.rb +165 -165
  39. data/lib/squib/args/showcase_special.rb +41 -41
  40. data/lib/squib/args/sprue_file.rb +44 -44
  41. data/lib/squib/args/svg_special.rb +37 -37
  42. data/lib/squib/args/transform.rb +55 -55
  43. data/lib/squib/args/typographer.rb +115 -115
  44. data/lib/squib/args/unit_conversion.rb +27 -27
  45. data/lib/squib/args/xywh_shorthands.rb +50 -50
  46. data/lib/squib/builtin/layouts/economy.yml +85 -85
  47. data/lib/squib/builtin/layouts/fantasy.yml +101 -101
  48. data/lib/squib/builtin/layouts/hand.yml +62 -62
  49. data/lib/squib/builtin/layouts/party.yml +94 -94
  50. data/lib/squib/builtin/layouts/playing-card.yml +35 -35
  51. data/lib/squib/builtin/layouts/tuck_box.yml +46 -46
  52. data/lib/squib/builtin/projects/advanced/.gitignore +4 -4
  53. data/lib/squib/builtin/projects/advanced/ABOUT.md +19 -19
  54. data/lib/squib/builtin/projects/advanced/Gemfile +11 -11
  55. data/lib/squib/builtin/projects/advanced/Guardfile +21 -21
  56. data/lib/squib/builtin/projects/advanced/IDEAS.md +22 -22
  57. data/lib/squib/builtin/projects/advanced/PLAYTESTING.md +26 -26
  58. data/lib/squib/builtin/projects/advanced/Rakefile +27 -27
  59. data/lib/squib/builtin/projects/advanced/config.yml +49 -49
  60. data/lib/squib/builtin/projects/advanced/docs/PNP NOTES.md +3 -3
  61. data/lib/squib/builtin/projects/advanced/docs/RULES.md +21 -21
  62. data/lib/squib/builtin/projects/advanced/img/example.svg +60 -60
  63. data/lib/squib/builtin/projects/advanced/layouts/deck.yml +27 -27
  64. data/lib/squib/builtin/projects/advanced/src/deck.rb +34 -34
  65. data/lib/squib/builtin/projects/advanced/src/version.rb +3 -3
  66. data/lib/squib/builtin/projects/basic/.gitignore +4 -4
  67. data/lib/squib/builtin/projects/basic/ABOUT.md +19 -19
  68. data/lib/squib/builtin/projects/basic/Gemfile +3 -3
  69. data/lib/squib/builtin/projects/basic/IDEAS.md +22 -22
  70. data/lib/squib/builtin/projects/basic/PLAYTESTING.md +26 -26
  71. data/lib/squib/builtin/projects/basic/PNP NOTES.md +3 -3
  72. data/lib/squib/builtin/projects/basic/RULES.md +21 -21
  73. data/lib/squib/builtin/projects/basic/Rakefile +7 -7
  74. data/lib/squib/builtin/projects/basic/config.yml +50 -50
  75. data/lib/squib/builtin/projects/basic/deck.rb +6 -6
  76. data/lib/squib/builtin/sprues/a4_euro_card.yml +42 -42
  77. data/lib/squib/builtin/sprues/a4_poker_card_8up.yml +40 -40
  78. data/lib/squib/builtin/sprues/a4_poker_card_9up.yml +42 -42
  79. data/lib/squib/builtin/sprues/a4_usa_card.yml +42 -42
  80. data/lib/squib/builtin/sprues/drivethrucards_1up.yml +10 -10
  81. data/lib/squib/builtin/sprues/letter_poker_card_9up.yml +25 -25
  82. data/lib/squib/builtin/sprues/letter_poker_foldable_8up.yml +52 -52
  83. data/lib/squib/builtin/sprues/printplaygames_18up.yml +68 -68
  84. data/lib/squib/card.rb +75 -75
  85. data/lib/squib/commands/cli.rb +39 -39
  86. data/lib/squib/commands/data/template_option.rb +109 -109
  87. data/lib/squib/commands/make_sprue.rb +277 -277
  88. data/lib/squib/commands/new.rb +77 -77
  89. data/lib/squib/conf.rb +149 -149
  90. data/lib/squib/constants.rb +17 -17
  91. data/lib/squib/deck.rb +138 -138
  92. data/lib/squib/dsl/background.rb +35 -35
  93. data/lib/squib/dsl/circle.rb +39 -39
  94. data/lib/squib/dsl/csv.rb +42 -42
  95. data/lib/squib/dsl/curve.rb +35 -35
  96. data/lib/squib/dsl/cut_zone.rb +47 -47
  97. data/lib/squib/dsl/ellipse.rb +37 -37
  98. data/lib/squib/dsl/grid.rb +35 -35
  99. data/lib/squib/dsl/groups.rb +54 -54
  100. data/lib/squib/dsl/hand.rb +42 -42
  101. data/lib/squib/dsl/line.rb +35 -35
  102. data/lib/squib/dsl/png.rb +57 -57
  103. data/lib/squib/dsl/polygon.rb +36 -36
  104. data/lib/squib/dsl/rect.rb +37 -37
  105. data/lib/squib/dsl/safe_zone.rb +48 -48
  106. data/lib/squib/dsl/save.rb +21 -21
  107. data/lib/squib/dsl/save_pdf.rb +50 -50
  108. data/lib/squib/dsl/save_png.rb +48 -48
  109. data/lib/squib/dsl/save_sheet.rb +53 -53
  110. data/lib/squib/dsl/showcase.rb +43 -43
  111. data/lib/squib/dsl/star.rb +37 -37
  112. data/lib/squib/dsl/svg.rb +63 -63
  113. data/lib/squib/dsl/text.rb +54 -54
  114. data/lib/squib/dsl/text_embed.rb +79 -79
  115. data/lib/squib/dsl/triangle.rb +35 -35
  116. data/lib/squib/dsl/units.rb +37 -37
  117. data/lib/squib/dsl/xlsx.rb +40 -40
  118. data/lib/squib/dsl/yaml.rb +40 -40
  119. data/lib/squib/errors_warnings/warn_unexpected_params.rb +14 -14
  120. data/lib/squib/graphics/background.rb +14 -14
  121. data/lib/squib/graphics/cairo_context_wrapper.rb +115 -115
  122. data/lib/squib/graphics/embedding_utils.rb +28 -28
  123. data/lib/squib/graphics/gradient_regex.rb +47 -47
  124. data/lib/squib/graphics/hand.rb +42 -42
  125. data/lib/squib/graphics/image.rb +123 -123
  126. data/lib/squib/graphics/save_doc.rb +77 -77
  127. data/lib/squib/graphics/save_images.rb +91 -91
  128. data/lib/squib/graphics/save_pdf.rb +90 -90
  129. data/lib/squib/graphics/save_sprue.rb +231 -231
  130. data/lib/squib/graphics/shapes.rb +143 -143
  131. data/lib/squib/graphics/showcase.rb +85 -85
  132. data/lib/squib/graphics/text.rb +202 -202
  133. data/lib/squib/import/csv_importer.rb +45 -45
  134. data/lib/squib/import/data_frame.rb +108 -108
  135. data/lib/squib/import/quantity_exploder.rb +17 -17
  136. data/lib/squib/import/xlsx_importer.rb +28 -28
  137. data/lib/squib/import/yaml_importer.rb +30 -30
  138. data/lib/squib/layout_parser.rb +155 -155
  139. data/lib/squib/progress.rb +38 -38
  140. data/lib/squib/sample_helpers.rb +34 -34
  141. data/lib/squib/sprues/crop_line.rb +28 -28
  142. data/lib/squib/sprues/crop_line_dash.rb +35 -35
  143. data/lib/squib/sprues/invalid_sprue_definition.rb +9 -9
  144. data/lib/squib/sprues/sprue.rb +208 -208
  145. data/lib/squib/sprues/sprue_schema.rb +51 -51
  146. data/lib/squib/system_fonts.rb +16 -16
  147. data/lib/squib/version.rb +11 -11
  148. data/lib/squib.rb +35 -35
  149. data/samples/autoscale_font/_autoscale_font.rb +98 -98
  150. data/samples/backend/_backend.rb +26 -26
  151. data/samples/basic.rb +19 -19
  152. data/samples/build_groups/build_groups.rb +36 -36
  153. data/samples/colors/_colors.rb +44 -44
  154. data/samples/colors/_gradients.rb +34 -34
  155. data/samples/colors/_switch_color.rb +33 -33
  156. data/samples/config/config_text_markup.rb +20 -20
  157. data/samples/config/custom_config.rb +18 -18
  158. data/samples/data/_csv.rb +33 -33
  159. data/samples/data/_excel.rb +55 -55
  160. data/samples/data/_yaml.rb +12 -12
  161. data/samples/hello_world.rb +6 -6
  162. data/samples/images/_cairo_access.rb +39 -39
  163. data/samples/images/_images.rb +104 -104
  164. data/samples/images/_more_load_images.rb +102 -102
  165. data/samples/images/_placeholders.rb +48 -48
  166. data/samples/intro/01_hello.rb +8 -8
  167. data/samples/intro/02_options.rb +14 -14
  168. data/samples/intro/03_layout.rb +11 -11
  169. data/samples/intro/04_arrays.rb +15 -15
  170. data/samples/intro/05_excel.rb +14 -14
  171. data/samples/layouts/builtin_layouts.rb +97 -97
  172. data/samples/layouts/layouts.rb +71 -71
  173. data/samples/project/src/characters.rb +8 -8
  174. data/samples/project/src/skills.rb +7 -7
  175. data/samples/proofs/_tgc_proofs.rb +16 -16
  176. data/samples/ranges/_ranges.rb +64 -64
  177. data/samples/saves/_hand.rb +23 -23
  178. data/samples/saves/_portrait_landscape.rb +23 -23
  179. data/samples/saves/_save_filenames.rb +28 -28
  180. data/samples/saves/_save_pdf.rb +29 -29
  181. data/samples/saves/_saves.rb +75 -75
  182. data/samples/saves/_showcase.rb +25 -25
  183. data/samples/shadows/_shadow.rb +71 -71
  184. data/samples/shapes/_draw_shapes.rb +60 -60
  185. data/samples/shapes/_proofs.rb +22 -22
  186. data/samples/sprues/_advanced_sprues.rb +25 -25
  187. data/samples/sprues/_builtin_sprues.rb +22 -22
  188. data/samples/sprues/_fold_sheet.rb +30 -30
  189. data/samples/sprues/_hex_tiles.rb +15 -15
  190. data/samples/sprues/_mints.rb +11 -11
  191. data/samples/sprues/_negative_coords.rb +6 -6
  192. data/samples/sprues/_sprue_example.rb +11 -11
  193. data/samples/system_font_debug/_list_fonts.rb +14 -14
  194. data/samples/text/_embed_text.rb +128 -128
  195. data/samples/text/_text.rb +52 -52
  196. data/samples/text/_text_options.rb +103 -103
  197. data/samples/text/bug134.rb +14 -14
  198. data/samples/units/_cells.rb +50 -50
  199. data/samples/units/_shorthands.rb +48 -48
  200. data/samples/units/_units.rb +39 -39
  201. data/squib.gemspec +58 -58
  202. metadata +21 -21
@@ -1,208 +1,208 @@
1
- require 'yaml'
2
- require 'classy_hash'
3
- require_relative '../args/color_validator'
4
- require_relative '../args/unit_conversion'
5
- require_relative 'crop_line'
6
- require_relative 'crop_line_dash'
7
- require_relative 'invalid_sprue_definition'
8
- require_relative 'sprue_schema'
9
-
10
- module Squib
11
- class Sprue
12
- include Args::ColorValidator
13
-
14
- # Defaults are set for poker sized deck on a A4 sheet, with no cards
15
- DEFAULTS = {
16
- 'sheet_width' => nil,
17
- 'sheet_height' => nil,
18
- 'card_width' => nil,
19
- 'card_height' => nil,
20
- 'dpi' => 300,
21
- 'cell_px' => 37.5,
22
- 'position_reference' => :topleft,
23
- 'rotate' => 0.0,
24
- 'crop_line' => {
25
- 'style' => :solid,
26
- 'width' => '0.02mm',
27
- 'color' => :black,
28
- 'overlay' => :on_margin,
29
- 'lines' => []
30
- },
31
- 'cards' => []
32
- }.freeze
33
-
34
- attr_reader :dpi
35
-
36
- def initialize(template_hash, dpi, cell_px)
37
- @template_hash = template_hash
38
- @dpi = dpi
39
- @cell_px = cell_px
40
- @crop_line_default = @template_hash['crop_line'].select do |k, _|
41
- %w[style width color].include? k
42
- end
43
- end
44
-
45
- # Load the template definition file
46
- def self.load(file, dpi, cell_px)
47
- yaml = {}
48
- thefile = file if File.exist?(file) # use custom first
49
- thefile = builtin(file) if File.exist?(builtin(file)) # then builtin
50
- unless File.exist?(thefile)
51
- Squib::logger.error("Sprue not found: #{file}. Falling back to defaults.")
52
- end
53
- yaml = YAML.load_file(thefile) || {} if File.exist? thefile
54
- # Bake the default values into our sprue
55
- new_hash = DEFAULTS.merge(yaml)
56
- new_hash['crop_line'] = DEFAULTS['crop_line'].
57
- merge(new_hash['crop_line'])
58
- warn_unrecognized(yaml)
59
-
60
- # Validate
61
- begin
62
- require 'benchmark'
63
- ClassyHash.validate(new_hash, Sprues::SCHEMA)
64
- rescue ClassyHash::SchemaViolationError => e
65
- raise Sprues::InvalidSprueDefinition.new(thefile, e)
66
- end
67
- Sprue.new new_hash, dpi, cell_px
68
- end
69
-
70
- def sheet_width
71
- Args::UnitConversion.parse @template_hash['sheet_width'], @dpi, @cell_px
72
- end
73
-
74
- def sheet_height
75
- Args::UnitConversion.parse @template_hash['sheet_height'], @dpi, @cell_px
76
- end
77
-
78
- def card_width
79
- Args::UnitConversion.parse @template_hash['card_width'], @dpi, @cell_px
80
- end
81
-
82
- def card_height
83
- Args::UnitConversion.parse @template_hash['card_height'], @dpi, @cell_px
84
- end
85
-
86
- def card_default_rotation
87
- parse_rotate_param @template_hash['rotate']
88
- end
89
-
90
- def crop_line_overlay
91
- @template_hash['crop_line']['overlay']
92
- end
93
-
94
- def crop_lines
95
- lines = @template_hash['crop_line']['lines'].map(
96
- &method(:parse_crop_line)
97
- )
98
- if block_given?
99
- lines.each { |v| yield v }
100
- else
101
- lines
102
- end
103
- end
104
-
105
- def cards
106
- parsed_cards = @template_hash['cards'].map(&method(:parse_card))
107
- if block_given?
108
- parsed_cards.each { |v| yield v }
109
- else
110
- parsed_cards
111
- end
112
- end
113
-
114
- def margin
115
- # NOTE: There's a baseline of 0.25mm that we can 100% make sure that we
116
- # can overlap really thin lines on the PDF
117
- crop_line_width = [
118
- Args::UnitConversion.parse(@template_hash['crop_line']['width'], @dpi, @cell_px),
119
- Args::UnitConversion.parse('0.25mm', @dpi, @cell_px)
120
- ].max
121
-
122
- parsed_cards = cards
123
- left, right = parsed_cards.minmax { |a, b| a['x'] <=> b['x'] }
124
- top, bottom = parsed_cards.minmax { |a, b| a['y'] <=> b['y'] }
125
-
126
- {
127
- left: left['x'] - crop_line_width,
128
- right: right['x'] + card_width + crop_line_width,
129
- top: top['y'] - crop_line_width,
130
- bottom: bottom['y'] + card_height + crop_line_width
131
- }
132
- end
133
-
134
- # Warn unrecognized options in the template sheet
135
- def self.warn_unrecognized(yaml)
136
- unrec = yaml.keys - DEFAULTS.keys
137
- return unless unrec.any?
138
-
139
- Squib.logger.warn(
140
- "Unrecognized configuration option(s): #{unrec.join(',')}"
141
- )
142
- end
143
-
144
- private
145
-
146
- # Return path for built-in sheet templates
147
- def self.builtin(file)
148
- "#{File.dirname(__FILE__)}/../builtin/sprues/#{file}"
149
- end
150
-
151
- # Parse crop line definitions from template.
152
- def parse_crop_line(line)
153
- new_line = @crop_line_default.merge line
154
- new_line['width'] = Args::UnitConversion.parse(new_line['width'], @dpi, @cell_px)
155
- new_line['color'] = colorify new_line['color']
156
- new_line['style_desc'] = new_line['style']
157
- new_line['style'] = Sprues::CropLineDash.new(new_line['style'], @dpi, @cell_px)
158
- new_line['line'] = Sprues::CropLine.new(
159
- new_line['type'], new_line['position'], sheet_width, sheet_height, @dpi, @cell_px
160
- )
161
- new_line
162
- end
163
-
164
- # Parse card definitions from template.
165
- def parse_card(card)
166
- new_card = card.clone
167
-
168
- x = Args::UnitConversion.parse(card['x'], @dpi, @cell_px)
169
- y = Args::UnitConversion.parse(card['y'], @dpi, @cell_px)
170
- if @template_hash['position_reference'] == :center
171
- # Normalize it to a top-left positional reference
172
- x -= card_width / 2
173
- y -= card_height / 2
174
- end
175
-
176
- new_card['x'] = x
177
- new_card['y'] = y
178
- new_card['rotate'] = parse_rotate_param(
179
- card['rotate'] ? card['rotate'] : @template_hash['rotate'])
180
- new_card['flip_vertical'] = card['flip_vertical'] == true
181
- new_card['flip_horizontal'] = card['flip_horizontal'] == true
182
- new_card
183
- end
184
-
185
- def parse_rotate_param(val)
186
- if val == :clockwise
187
- 0.5 * Math::PI
188
- elsif val == :counterclockwise
189
- 1.5 * Math::PI
190
- elsif val == :turnaround
191
- Math::PI
192
- elsif val.is_a? String
193
- if val.end_with? 'deg'
194
- val.gsub(/deg$/, '').to_f / 180 * Math::PI
195
- elsif val.end_with? 'rad'
196
- val.gsub(/rad$/, '').to_f
197
- else
198
- val.to_f
199
- end
200
- elsif val.nil?
201
- 0.0
202
- else
203
- val.to_f
204
- end
205
- end
206
-
207
- end
208
- end
1
+ require 'yaml'
2
+ require 'classy_hash'
3
+ require_relative '../args/color_validator'
4
+ require_relative '../args/unit_conversion'
5
+ require_relative 'crop_line'
6
+ require_relative 'crop_line_dash'
7
+ require_relative 'invalid_sprue_definition'
8
+ require_relative 'sprue_schema'
9
+
10
+ module Squib
11
+ class Sprue
12
+ include Args::ColorValidator
13
+
14
+ # Defaults are set for poker sized deck on a A4 sheet, with no cards
15
+ DEFAULTS = {
16
+ 'sheet_width' => nil,
17
+ 'sheet_height' => nil,
18
+ 'card_width' => nil,
19
+ 'card_height' => nil,
20
+ 'dpi' => 300,
21
+ 'cell_px' => 37.5,
22
+ 'position_reference' => :topleft,
23
+ 'rotate' => 0.0,
24
+ 'crop_line' => {
25
+ 'style' => :solid,
26
+ 'width' => '0.02mm',
27
+ 'color' => :black,
28
+ 'overlay' => :on_margin,
29
+ 'lines' => []
30
+ },
31
+ 'cards' => []
32
+ }.freeze
33
+
34
+ attr_reader :dpi
35
+
36
+ def initialize(template_hash, dpi, cell_px)
37
+ @template_hash = template_hash
38
+ @dpi = dpi
39
+ @cell_px = cell_px
40
+ @crop_line_default = @template_hash['crop_line'].select do |k, _|
41
+ %w[style width color].include? k
42
+ end
43
+ end
44
+
45
+ # Load the template definition file
46
+ def self.load(file, dpi, cell_px)
47
+ yaml = {}
48
+ thefile = file if File.exist?(file) # use custom first
49
+ thefile = builtin(file) if File.exist?(builtin(file)) # then builtin
50
+ unless File.exist?(thefile)
51
+ Squib::logger.error("Sprue not found: #{file}. Falling back to defaults.")
52
+ end
53
+ yaml = YAML.load_file(thefile) || {} if File.exist? thefile
54
+ # Bake the default values into our sprue
55
+ new_hash = DEFAULTS.merge(yaml)
56
+ new_hash['crop_line'] = DEFAULTS['crop_line'].
57
+ merge(new_hash['crop_line'])
58
+ warn_unrecognized(yaml)
59
+
60
+ # Validate
61
+ begin
62
+ require 'benchmark'
63
+ ClassyHash.validate(new_hash, Sprues::SCHEMA)
64
+ rescue ClassyHash::SchemaViolationError => e
65
+ raise Sprues::InvalidSprueDefinition.new(thefile, e)
66
+ end
67
+ Sprue.new new_hash, dpi, cell_px
68
+ end
69
+
70
+ def sheet_width
71
+ Args::UnitConversion.parse @template_hash['sheet_width'], @dpi, @cell_px
72
+ end
73
+
74
+ def sheet_height
75
+ Args::UnitConversion.parse @template_hash['sheet_height'], @dpi, @cell_px
76
+ end
77
+
78
+ def card_width
79
+ Args::UnitConversion.parse @template_hash['card_width'], @dpi, @cell_px
80
+ end
81
+
82
+ def card_height
83
+ Args::UnitConversion.parse @template_hash['card_height'], @dpi, @cell_px
84
+ end
85
+
86
+ def card_default_rotation
87
+ parse_rotate_param @template_hash['rotate']
88
+ end
89
+
90
+ def crop_line_overlay
91
+ @template_hash['crop_line']['overlay']
92
+ end
93
+
94
+ def crop_lines
95
+ lines = @template_hash['crop_line']['lines'].map(
96
+ &method(:parse_crop_line)
97
+ )
98
+ if block_given?
99
+ lines.each { |v| yield v }
100
+ else
101
+ lines
102
+ end
103
+ end
104
+
105
+ def cards
106
+ parsed_cards = @template_hash['cards'].map(&method(:parse_card))
107
+ if block_given?
108
+ parsed_cards.each { |v| yield v }
109
+ else
110
+ parsed_cards
111
+ end
112
+ end
113
+
114
+ def margin
115
+ # NOTE: There's a baseline of 0.25mm that we can 100% make sure that we
116
+ # can overlap really thin lines on the PDF
117
+ crop_line_width = [
118
+ Args::UnitConversion.parse(@template_hash['crop_line']['width'], @dpi, @cell_px),
119
+ Args::UnitConversion.parse('0.25mm', @dpi, @cell_px)
120
+ ].max
121
+
122
+ parsed_cards = cards
123
+ left, right = parsed_cards.minmax { |a, b| a['x'] <=> b['x'] }
124
+ top, bottom = parsed_cards.minmax { |a, b| a['y'] <=> b['y'] }
125
+
126
+ {
127
+ left: left['x'] - crop_line_width,
128
+ right: right['x'] + card_width + crop_line_width,
129
+ top: top['y'] - crop_line_width,
130
+ bottom: bottom['y'] + card_height + crop_line_width
131
+ }
132
+ end
133
+
134
+ # Warn unrecognized options in the template sheet
135
+ def self.warn_unrecognized(yaml)
136
+ unrec = yaml.keys - DEFAULTS.keys
137
+ return unless unrec.any?
138
+
139
+ Squib.logger.warn(
140
+ "Unrecognized configuration option(s): #{unrec.join(',')}"
141
+ )
142
+ end
143
+
144
+ private
145
+
146
+ # Return path for built-in sheet templates
147
+ def self.builtin(file)
148
+ "#{File.dirname(__FILE__)}/../builtin/sprues/#{file}"
149
+ end
150
+
151
+ # Parse crop line definitions from template.
152
+ def parse_crop_line(line)
153
+ new_line = @crop_line_default.merge line
154
+ new_line['width'] = Args::UnitConversion.parse(new_line['width'], @dpi, @cell_px)
155
+ new_line['color'] = colorify new_line['color']
156
+ new_line['style_desc'] = new_line['style']
157
+ new_line['style'] = Sprues::CropLineDash.new(new_line['style'], @dpi, @cell_px)
158
+ new_line['line'] = Sprues::CropLine.new(
159
+ new_line['type'], new_line['position'], sheet_width, sheet_height, @dpi, @cell_px
160
+ )
161
+ new_line
162
+ end
163
+
164
+ # Parse card definitions from template.
165
+ def parse_card(card)
166
+ new_card = card.clone
167
+
168
+ x = Args::UnitConversion.parse(card['x'], @dpi, @cell_px)
169
+ y = Args::UnitConversion.parse(card['y'], @dpi, @cell_px)
170
+ if @template_hash['position_reference'] == :center
171
+ # Normalize it to a top-left positional reference
172
+ x -= card_width / 2
173
+ y -= card_height / 2
174
+ end
175
+
176
+ new_card['x'] = x
177
+ new_card['y'] = y
178
+ new_card['rotate'] = parse_rotate_param(
179
+ card['rotate'] ? card['rotate'] : @template_hash['rotate'])
180
+ new_card['flip_vertical'] = card['flip_vertical'] == true
181
+ new_card['flip_horizontal'] = card['flip_horizontal'] == true
182
+ new_card
183
+ end
184
+
185
+ def parse_rotate_param(val)
186
+ if val == :clockwise
187
+ 0.5 * Math::PI
188
+ elsif val == :counterclockwise
189
+ 1.5 * Math::PI
190
+ elsif val == :turnaround
191
+ Math::PI
192
+ elsif val.is_a? String
193
+ if val.end_with? 'deg'
194
+ val.gsub(/deg$/, '').to_f / 180 * Math::PI
195
+ elsif val.end_with? 'rad'
196
+ val.gsub(/rad$/, '').to_f
197
+ else
198
+ val.to_f
199
+ end
200
+ elsif val.nil?
201
+ 0.0
202
+ else
203
+ val.to_f
204
+ end
205
+ end
206
+
207
+ end
208
+ end
@@ -1,51 +1,51 @@
1
- module Squib
2
- module Sprues
3
- UNIT_REGEX = /^(\d*[.])?\d+(in|cm|mm)$/
4
- COORD_REGEX = /^\-?(\d*[.])?\d+(in|cm|mm)$/
5
- ROTATE_REGEX = /^\-?(\d*[.])?\d+(deg|rad)?$/
6
- SCHEMA = {
7
- 'sheet_width' => UNIT_REGEX,
8
- 'sheet_height' => UNIT_REGEX,
9
- 'card_width' => UNIT_REGEX,
10
- 'card_height' => UNIT_REGEX,
11
- 'position_reference' => ClassyHash::G.enum(:topleft, :center),
12
- 'rotate' => [
13
- :optional, Numeric,
14
- ClassyHash::G.enum(:clockwise, :counterclockwise, :turnaround),
15
- ROTATE_REGEX
16
- ],
17
- 'crop_line' => {
18
- 'style' => [
19
- ClassyHash::G.enum(:solid, :dotted, :dashed),
20
- Sprues::CropLineDash::VALIDATION_REGEX
21
- ],
22
- 'width' => UNIT_REGEX,
23
- 'color' => [String, Symbol],
24
- 'overlay' => ClassyHash::G.enum(
25
- :on_margin, :overlay_on_cards, :beneath_cards
26
- ),
27
- 'lines' => [[{
28
- 'type' => ClassyHash::G.enum(:horizontal, :vertical),
29
- 'position' => UNIT_REGEX,
30
- 'style' => [
31
- :optional, ClassyHash::G.enum(:solid, :dotted, :dashed)
32
- ],
33
- 'width' => [:optional, UNIT_REGEX],
34
- 'color' => [:optional, String, Symbol],
35
- 'overlay_on_cards' => [:optional, TrueClass]
36
- }]]
37
- },
38
- 'cards' => [[{
39
- 'x' => COORD_REGEX,
40
- 'y' => COORD_REGEX,
41
- 'rotate' => [
42
- :optional, Numeric,
43
- ClassyHash::G.enum(:clockwise, :counterclockwise, :turnaround),
44
- ROTATE_REGEX
45
- ],
46
- 'flip_vertical' => [ :optional, FalseClass ],
47
- 'flip_horizontal' => [ :optional, FalseClass ],
48
- }]]
49
- }.freeze
50
- end
51
- end
1
+ module Squib
2
+ module Sprues
3
+ UNIT_REGEX = /^(\d*[.])?\d+(in|cm|mm)$/
4
+ COORD_REGEX = /^\-?(\d*[.])?\d+(in|cm|mm)$/
5
+ ROTATE_REGEX = /^\-?(\d*[.])?\d+(deg|rad)?$/
6
+ SCHEMA = {
7
+ 'sheet_width' => UNIT_REGEX,
8
+ 'sheet_height' => UNIT_REGEX,
9
+ 'card_width' => UNIT_REGEX,
10
+ 'card_height' => UNIT_REGEX,
11
+ 'position_reference' => ClassyHash::G.enum(:topleft, :center),
12
+ 'rotate' => [
13
+ :optional, Numeric,
14
+ ClassyHash::G.enum(:clockwise, :counterclockwise, :turnaround),
15
+ ROTATE_REGEX
16
+ ],
17
+ 'crop_line' => {
18
+ 'style' => [
19
+ ClassyHash::G.enum(:solid, :dotted, :dashed),
20
+ Sprues::CropLineDash::VALIDATION_REGEX
21
+ ],
22
+ 'width' => UNIT_REGEX,
23
+ 'color' => [String, Symbol],
24
+ 'overlay' => ClassyHash::G.enum(
25
+ :on_margin, :overlay_on_cards, :beneath_cards
26
+ ),
27
+ 'lines' => [[{
28
+ 'type' => ClassyHash::G.enum(:horizontal, :vertical),
29
+ 'position' => UNIT_REGEX,
30
+ 'style' => [
31
+ :optional, ClassyHash::G.enum(:solid, :dotted, :dashed)
32
+ ],
33
+ 'width' => [:optional, UNIT_REGEX],
34
+ 'color' => [:optional, String, Symbol],
35
+ 'overlay_on_cards' => [:optional, TrueClass]
36
+ }]]
37
+ },
38
+ 'cards' => [[{
39
+ 'x' => COORD_REGEX,
40
+ 'y' => COORD_REGEX,
41
+ 'rotate' => [
42
+ :optional, Numeric,
43
+ ClassyHash::G.enum(:clockwise, :counterclockwise, :turnaround),
44
+ ROTATE_REGEX
45
+ ],
46
+ 'flip_vertical' => [ :optional, FalseClass ],
47
+ 'flip_horizontal' => [ :optional, FalseClass ],
48
+ }]]
49
+ }.freeze
50
+ end
51
+ end
@@ -1,17 +1,17 @@
1
- require 'pango'
2
- module Squib
3
-
4
- # List all system fonts that Cairo/Pango can see
5
- # Wow this call was convoluted...
6
- # Returns array of strings with the names of fonts
7
- module_function def system_fonts
8
- cc = Cairo::Context.new(Cairo::ImageSurface.new(0,0)) # empty image
9
- cc.create_pango_layout.context.families.map {|f| f.name }
10
- end
11
-
12
- # Prints out the system fonts in sorted order
13
- module_function def print_system_fonts
14
- puts "== DEBUG: Squib knows about these fonts =="
15
- puts system_fonts.sort
16
- end
1
+ require 'pango'
2
+ module Squib
3
+
4
+ # List all system fonts that Cairo/Pango can see
5
+ # Wow this call was convoluted...
6
+ # Returns array of strings with the names of fonts
7
+ module_function def system_fonts
8
+ cc = Cairo::Context.new(Cairo::ImageSurface.new(0,0)) # empty image
9
+ cc.create_pango_layout.context.families.map {|f| f.name }
10
+ end
11
+
12
+ # Prints out the system fonts in sorted order
13
+ module_function def print_system_fonts
14
+ puts "== DEBUG: Squib knows about these fonts =="
15
+ puts system_fonts.sort
16
+ end
17
17
  end
data/lib/squib/version.rb CHANGED
@@ -1,11 +1,11 @@
1
- module Squib
2
-
3
- # The next version to be released.
4
- # Uses semantic versioning: http://semver.org/
5
- #
6
- # Most of the time this is in the alpha of the next release.
7
- # e.g. v0.0.5a is on its way to becoming v0.0.5
8
- #
9
- VERSION = '0.18.0'
10
- end
11
-
1
+ module Squib
2
+
3
+ # The next version to be released.
4
+ # Uses semantic versioning: http://semver.org/
5
+ #
6
+ # Most of the time this is in the alpha of the next release.
7
+ # e.g. v0.0.5a is on its way to becoming v0.0.5
8
+ #
9
+ VERSION = '0.19.0a'
10
+ end
11
+
data/lib/squib.rb CHANGED
@@ -1,35 +1,35 @@
1
- autoload :Cairo, 'cairo'
2
- autoload :Pango, 'pango'
3
- autoload :Rsvg, 'rsvg2'
4
- require 'logger'
5
- require 'rainbow/refinement'
6
- require_relative 'squib/version'
7
- require_relative 'squib/commands/cli'
8
- require_relative 'squib/deck'
9
- require_relative 'squib/card'
10
- require_relative 'squib/system_fonts'
11
-
12
- module Squib
13
- using Rainbow # we can colorize strings now!
14
-
15
- # Access the internal logger that Squib uses. By default, Squib configure the logger to the WARN level
16
- # Use this to suppress or increase output levels.
17
- # @example
18
- # Squib.logger.level = Logger::DEBUG #show waaaay more information than you probably need, unless you're a dev
19
- # Squib.logger.level = Logger::ERROR #basically turns it off
20
- #
21
- # @return [Logger] the ruby logger
22
- # @api public
23
- def logger
24
- if @logger.nil?
25
- @logger = Logger.new($stdout)
26
- @logger.level = Logger::WARN
27
- @logger.formatter = proc do |severity, datetime, m_progname, msg|
28
- "[#{datetime.strftime('%F %H:%M:%S')} #{severity.red}] #{msg}\n"
29
- end
30
- end
31
- @logger
32
- end
33
- module_function :logger
34
-
35
- end
1
+ autoload :Cairo, 'cairo'
2
+ autoload :Pango, 'pango'
3
+ autoload :Rsvg, 'rsvg2'
4
+ require 'logger'
5
+ require 'rainbow/refinement'
6
+ require_relative 'squib/version'
7
+ require_relative 'squib/commands/cli'
8
+ require_relative 'squib/deck'
9
+ require_relative 'squib/card'
10
+ require_relative 'squib/system_fonts'
11
+
12
+ module Squib
13
+ using Rainbow # we can colorize strings now!
14
+
15
+ # Access the internal logger that Squib uses. By default, Squib configure the logger to the WARN level
16
+ # Use this to suppress or increase output levels.
17
+ # @example
18
+ # Squib.logger.level = Logger::DEBUG #show waaaay more information than you probably need, unless you're a dev
19
+ # Squib.logger.level = Logger::ERROR #basically turns it off
20
+ #
21
+ # @return [Logger] the ruby logger
22
+ # @api public
23
+ def logger
24
+ if @logger.nil?
25
+ @logger = Logger.new($stdout)
26
+ @logger.level = Logger::WARN
27
+ @logger.formatter = proc do |severity, datetime, m_progname, msg|
28
+ "[#{datetime.strftime('%F %H:%M:%S')} #{severity.red}] #{msg}\n"
29
+ end
30
+ end
31
+ @logger
32
+ end
33
+ module_function :logger
34
+
35
+ end