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.
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