squib 0.15.3 → 0.16.0.pre.preview1

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/tests.yml +22 -0
  3. data/CHANGELOG.md +22 -0
  4. data/Dockerfile +18 -16
  5. data/Guardfile +8 -0
  6. data/README.md +3 -9
  7. data/RELEASE TODO.md +1 -0
  8. data/Rakefile +3 -0
  9. data/lib/squib.rb +3 -1
  10. data/lib/squib/args/arg_loader.rb +109 -106
  11. data/lib/squib/args/box.rb +52 -48
  12. data/lib/squib/args/card_range.rb +26 -24
  13. data/lib/squib/args/color_validator.rb +4 -9
  14. data/lib/squib/args/coords.rb +39 -25
  15. data/lib/squib/args/csv_opts.rb +13 -16
  16. data/lib/squib/args/dir_validator.rb +7 -12
  17. data/lib/squib/args/draw.rb +69 -68
  18. data/lib/squib/args/embed_adjust.rb +12 -15
  19. data/lib/squib/args/embed_key.rb +6 -11
  20. data/lib/squib/args/hand_special.rb +25 -25
  21. data/lib/squib/args/import.rb +54 -27
  22. data/lib/squib/args/input_file.rb +22 -26
  23. data/lib/squib/args/paint.rb +30 -31
  24. data/lib/squib/args/paragraph.rb +95 -93
  25. data/lib/squib/args/save_batch.rb +50 -48
  26. data/lib/squib/args/scale_box.rb +43 -39
  27. data/lib/squib/args/sheet.rb +147 -149
  28. data/lib/squib/args/showcase_special.rb +32 -32
  29. data/lib/squib/args/sprue_file.rb +30 -30
  30. data/lib/squib/args/svg_special.rb +26 -26
  31. data/lib/squib/args/transform.rb +48 -54
  32. data/lib/squib/args/typographer.rb +88 -92
  33. data/lib/squib/args/unit_conversion.rb +6 -8
  34. data/lib/squib/args/xywh_shorthands.rb +56 -0
  35. data/lib/squib/builtin/projects/advanced/config.yml +4 -3
  36. data/lib/squib/builtin/projects/basic/config.yml +4 -3
  37. data/lib/squib/conf.rb +5 -0
  38. data/lib/squib/deck.rb +34 -12
  39. data/lib/squib/dsl/background.rb +35 -0
  40. data/lib/squib/dsl/circle.rb +39 -0
  41. data/lib/squib/dsl/csv.rb +42 -0
  42. data/lib/squib/dsl/curve.rb +35 -0
  43. data/lib/squib/dsl/cut_zone.rb +47 -0
  44. data/lib/squib/dsl/ellipse.rb +37 -0
  45. data/lib/squib/dsl/grid.rb +35 -0
  46. data/lib/squib/{api → dsl}/groups.rb +0 -0
  47. data/lib/squib/dsl/hand.rb +42 -0
  48. data/lib/squib/dsl/line.rb +35 -0
  49. data/lib/squib/dsl/png.rb +56 -0
  50. data/lib/squib/dsl/polygon.rb +36 -0
  51. data/lib/squib/dsl/rect.rb +37 -0
  52. data/lib/squib/dsl/safe_zone.rb +48 -0
  53. data/lib/squib/dsl/save.rb +21 -0
  54. data/lib/squib/dsl/save_pdf.rb +50 -0
  55. data/lib/squib/dsl/save_png.rb +47 -0
  56. data/lib/squib/dsl/save_sheet.rb +53 -0
  57. data/lib/squib/dsl/showcase.rb +43 -0
  58. data/lib/squib/dsl/star.rb +37 -0
  59. data/lib/squib/dsl/svg.rb +62 -0
  60. data/lib/squib/dsl/text.rb +54 -0
  61. data/lib/squib/dsl/text_embed.rb +78 -0
  62. data/lib/squib/dsl/triangle.rb +35 -0
  63. data/lib/squib/{api → dsl}/units.rb +10 -0
  64. data/lib/squib/dsl/xlsx.rb +40 -0
  65. data/lib/squib/dsl/yaml.rb +40 -0
  66. data/lib/squib/errors_warnings/warn_unexpected_params.rb +14 -0
  67. data/lib/squib/graphics/save_images.rb +3 -3
  68. data/lib/squib/graphics/save_sprue.rb +14 -2
  69. data/lib/squib/graphics/text.rb +37 -9
  70. data/lib/squib/import/csv_importer.rb +45 -0
  71. data/lib/squib/import/quantity_exploder.rb +18 -0
  72. data/lib/squib/import/xlsx_importer.rb +28 -0
  73. data/lib/squib/import/yaml_importer.rb +30 -0
  74. data/lib/squib/layout_parser.rb +24 -7
  75. data/lib/squib/sprues/crop_line.rb +6 -6
  76. data/lib/squib/sprues/crop_line_dash.rb +6 -6
  77. data/lib/squib/sprues/sprue.rb +16 -14
  78. data/lib/squib/version.rb +1 -1
  79. data/samples/autoscale_font/_autoscale_font.rb +77 -8
  80. data/samples/colors/_switch_color.rb +2 -2
  81. data/samples/data/_excel.rb +1 -1
  82. data/samples/ranges/_ranges.rb +1 -1
  83. data/samples/saves/_save_filenames.rb +4 -0
  84. data/samples/saves/_save_pdf.rb +1 -1
  85. data/samples/saves/_saves.rb +2 -1
  86. data/samples/shapes/_draw_shapes.rb +2 -2
  87. data/samples/sprues/_builtin_sprues.rb +1 -0
  88. data/samples/sprues/_fold_sheet.rb +4 -1
  89. data/samples/text/_text.rb +6 -1
  90. data/samples/text/_text_options.rb +2 -1
  91. data/samples/units/_cells.rb +51 -0
  92. data/samples/units/_shorthands.rb +49 -0
  93. data/samples/units/_units.rb +7 -0
  94. data/squib.gemspec +11 -5
  95. metadata +120 -33
  96. data/.travis.yml +0 -17
  97. data/appveyor.yml +0 -25
  98. data/lib/squib/api/background.rb +0 -15
  99. data/lib/squib/api/data.rb +0 -137
  100. data/lib/squib/api/image.rb +0 -49
  101. data/lib/squib/api/save.rb +0 -83
  102. data/lib/squib/api/shapes.rb +0 -124
  103. data/lib/squib/api/text.rb +0 -25
  104. data/lib/squib/api/text_embed.rb +0 -71
@@ -5,7 +5,7 @@ module Squib
5
5
  def initialize(deck, tmpl, sheet_args)
6
6
  @deck = deck
7
7
  @tmpl = tmpl
8
- @page_number = 1
8
+ @page_number = 0
9
9
  @sheet_args = sheet_args # might be Args::Sheet or Args::SaveBatch
10
10
  @overlay_lines = @tmpl.crop_lines.select do |line|
11
11
  line['overlay_on_cards']
@@ -39,7 +39,7 @@ module Squib
39
39
  end
40
40
 
41
41
  draw_overlay_above_cards cc
42
- cc.target.finish
42
+ draw_final_page cc # See bug #320
43
43
  end
44
44
  end
45
45
 
@@ -190,6 +190,11 @@ module Squib
190
190
  cc
191
191
  end
192
192
 
193
+ def draw_final_page(cc)
194
+ # PDF doesn't need to create a last page. See bug #320
195
+ cc.target.finish
196
+ end
197
+
193
198
  def full_filename
194
199
  @sheet_args.full_filename
195
200
  end
@@ -211,6 +216,13 @@ module Squib
211
216
  cc
212
217
  end
213
218
 
219
+ # The last page always gets written out for PNGs because they are separate
220
+ # files and don't get "flushed" automatically. See bug #320.
221
+ def draw_final_page(cc)
222
+ draw_page cc
223
+ cc.target.finish
224
+ end
225
+
214
226
  def full_filename
215
227
  @sheet_args.full_filename @page_number
216
228
  end
@@ -76,7 +76,7 @@ module Squib
76
76
 
77
77
  # # :nodoc:
78
78
  # # @api private
79
- def embed_images!(embed, str, layout, valign)
79
+ def embed_images!(embed, str, layout, valign, scale)
80
80
  return [] unless embed.rules.any?
81
81
  layout.markup = str
82
82
  clean_str = layout.text
@@ -84,7 +84,7 @@ module Squib
84
84
  EmbeddingUtils.indices(clean_str, embed.rules.keys).each do |key, ranges|
85
85
  rule = embed.rules[key]
86
86
  ranges.each do |range|
87
- carve = Pango::Rectangle.new(0, 0, compute_carve(rule, range), 0)
87
+ carve = Pango::Rectangle.new(0, 0, compute_carve(rule, range) * scale, 0)
88
88
  att = Pango::AttrShape.new(carve, carve, rule)
89
89
  att.start_index = range.first
90
90
  att.end_index = range.last
@@ -100,7 +100,7 @@ module Squib
100
100
  y = Pango.pixels(layout.index_to_pos(att.start_index).y) +
101
101
  rule[:adjust].dy[@index] +
102
102
  compute_valign(layout, valign, rule[:box].height[@index])
103
- rule[:draw].call(self, x, y)
103
+ rule[:draw].call(self, x, y, scale)
104
104
  cxt.reset_clip
105
105
  [cxt, att, do_path]
106
106
  end
@@ -121,19 +121,46 @@ module Squib
121
121
  end
122
122
  end
123
123
 
124
- # :nodoc:
125
124
  # @api private
126
125
  def text(embed, para, box, trans, draw, dpi)
126
+ font_desc = Pango::FontDescription.new(para.font)
127
+ font_desc.size = para.font_size * Pango::SCALE if para.font_size.is_a? Numeric
128
+ orig_font_size = font_desc.size
129
+
130
+ # If text autoscaling is enabled, find the largest text size (smaller or equal to the set text size) that fits
131
+ if para.ellipsize == :autoscale
132
+ para.ellipsize = Pango::EllipsizeMode::END
133
+ sizes = sizes = (1 .. font_desc.size).to_a.reverse
134
+
135
+ # Dummy render to an area outside the card with decreasing font sizes until text no longer ellipsizes
136
+ max_fitting_size = sizes.bsearch{ |sz|
137
+ font_desc.size = sz
138
+ extents = render_text(embed, para, box, trans, draw, dpi, font_desc, orig_font_size, true)
139
+ !extents[:ellipsized]
140
+ }
141
+
142
+ if max_fitting_size.nil?
143
+ max_fitting_size = sizes.last
144
+ Squib.logger.warn{"Could not autosize for Card \##{@index} as minimum specified size #{max_fitting_size} still ellipsizes."}
145
+ end
146
+ font_desc.size = max_fitting_size
147
+ end
148
+
149
+ render_text(embed, para, box, trans, draw, dpi, font_desc, orig_font_size, false)
150
+ end
151
+
152
+ # :nodoc:
153
+ # @api private
154
+ def render_text(embed, para, box, trans, draw, dpi, font_desc, orig_font_size, dummy_draw)
127
155
  Squib.logger.debug {"Rendering text with: \n#{para} \nat:\n #{box} \ndraw:\n #{draw} \ntransform: #{trans}"}
128
156
  extents = nil
129
157
  use_cairo do |cc|
130
158
  cc.set_source_squibcolor(draw.color)
131
159
  cc.translate(box.x, box.y)
160
+ cc.translate(-10000, -10000) if dummy_draw
132
161
  cc.rotate(trans.angle)
133
162
  cc.move_to(0, 0)
134
163
 
135
- font_desc = Pango::FontDescription.new(para.font)
136
- font_desc.size = para.font_size * Pango::SCALE unless para.font_size.nil?
137
164
  layout = cc.create_pango_layout
138
165
  layout.font_description = font_desc
139
166
  layout.text = para.str.to_s
@@ -152,7 +179,7 @@ module Squib
152
179
  layout.justify = para.justify unless para.justify.nil?
153
180
  layout.spacing = para.spacing unless para.spacing.nil?
154
181
 
155
- embed_images!(embed, para.str, layout, para.valign)
182
+ embed_images!(embed, para.str, layout, para.valign, font_desc.size / orig_font_size.to_f)
156
183
 
157
184
  vertical_start = compute_valign(layout, para.valign, 0)
158
185
  cc.move_to(0, vertical_start)
@@ -164,8 +191,9 @@ module Squib
164
191
  stroke_outline!(cc, layout, draw) if draw.stroke_strategy == :fill_first
165
192
  draw_text_hint(cc, box.x, box.y, layout, para.hint)
166
193
  extents = { width: layout.extents[1].width / Pango::SCALE,
167
- height: layout.extents[1].height / Pango::SCALE }
168
- warn_if_ellipsized layout
194
+ height: layout.extents[1].height / Pango::SCALE,
195
+ ellipsized: layout.ellipsized?}
196
+ warn_if_ellipsized layout unless dummy_draw
169
197
  end
170
198
  return extents
171
199
  end
@@ -0,0 +1,45 @@
1
+ require 'csv'
2
+ require_relative 'quantity_exploder'
3
+
4
+ module Squib::Import
5
+ class CsvImporter
6
+ include Squib::Import::QuantityExploder
7
+ def import_to_dataframe(import, csv_opts, &block)
8
+ data = import.data.nil? ? File.read(import.file) : import.data
9
+ table = CSV.parse(data, **csv_opts.to_hash)
10
+ check_duplicate_csv_headers(table)
11
+ hash = Squib::DataFrame.new
12
+ table.headers.each do |header|
13
+ new_header = header.to_s
14
+ new_header = new_header.strip if import.strip?
15
+ hash[new_header] ||= table[header]
16
+ end
17
+ if import.strip?
18
+ new_hash = Squib::DataFrame.new
19
+ hash.each do |header, col|
20
+ new_hash[header] = col.map do |str|
21
+ str = str.strip if str.respond_to?(:strip)
22
+ str
23
+ end
24
+ end
25
+ hash = new_hash
26
+ end
27
+ unless block.nil?
28
+ hash.each do |header, col|
29
+ col.map! do |val|
30
+ yield(header, val)
31
+ end
32
+ end
33
+ end
34
+ return explode_quantities(hash, import.explode)
35
+ end
36
+
37
+ def check_duplicate_csv_headers(table)
38
+ if table.headers.size != table.headers.uniq.size
39
+ dups = table.headers.select{|e| table.headers.count(e) > 1 }
40
+ Squib.logger.warn "CSV duplicated the following column keys: #{dups.join(',')}"
41
+ end
42
+ end
43
+ end
44
+ end
45
+
@@ -0,0 +1,18 @@
1
+ module Squib
2
+ module Import
3
+ module QuantityExploder
4
+ def explode_quantities(data, qty)
5
+ return data unless data.col? qty.to_s.strip
6
+ qtys = data[qty]
7
+ new_data = Squib::DataFrame.new
8
+ data.each do |col, arr|
9
+ new_data[col] = []
10
+ qtys.each_with_index do |qty, index|
11
+ qty.to_i.times { new_data[col] << arr[index] }
12
+ end
13
+ end
14
+ return new_data
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,28 @@
1
+ require 'roo'
2
+ require_relative 'quantity_exploder'
3
+
4
+ module Squib::Import
5
+ class XlsxImporter
6
+ include Squib::Import::QuantityExploder
7
+ def import_to_dataframe(import, &block)
8
+ s = Roo::Excelx.new(import.file)
9
+ s.default_sheet = s.sheets[import.sheet]
10
+ data = Squib::DataFrame.new
11
+ s.first_column.upto(s.last_column) do |col|
12
+ header = s.cell(s.first_row, col).to_s
13
+ header.strip! if import.strip?
14
+ data[header] = []
15
+ (s.first_row + 1).upto(s.last_row) do |row|
16
+ cell = s.cell(row, col)
17
+ # Roo hack for avoiding unnecessary .0's on whole integers (https://github.com/roo-rb/roo/issues/139)
18
+ cell = s.excelx_value(row, col) if s.excelx_type(row, col) == [:numeric_or_formula, 'General']
19
+ cell.strip! if cell.respond_to?(:strip) && import.strip?
20
+ cell = block.yield(header, cell) unless block.nil?
21
+ data[header] << cell
22
+ end# row
23
+ end# col
24
+ explode_quantities(data, import.explode)
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,30 @@
1
+ require 'yaml'
2
+ require_relative 'data_frame'
3
+ require_relative 'quantity_exploder'
4
+
5
+ module Squib::Import
6
+ class YamlImporter
7
+ include Squib::Import::QuantityExploder
8
+ def import_to_dataframe(import, &block)
9
+ data = import.data.nil? ? File.read(import.file) : import.data
10
+ yml = YAML.load(data)
11
+ data = Squib::DataFrame.new
12
+ # Get a universal list of keys to ensure everything is covered.
13
+ keys = yml.map { |c| c.keys}.flatten.uniq
14
+ keys.each { |k| data[k] = [] } #init arrays
15
+ yml.each do |card|
16
+ # nil value if key isn't set.
17
+ keys.each { |k| data[k] << card[k] }
18
+ end
19
+ unless block.nil?
20
+ data.each do |header, col|
21
+ col.map! do |val|
22
+ block.yield(header, val)
23
+ end
24
+ end
25
+ end
26
+ explode_quantities(data, import.explode)
27
+ end
28
+ end
29
+ end
30
+
@@ -1,12 +1,15 @@
1
1
  require 'yaml'
2
+ require_relative 'args/xywh_shorthands'
2
3
 
3
4
  module Squib
4
5
  # Internal class for handling layouts
5
6
  # @api private
6
7
  class LayoutParser
8
+ include Args::XYWHShorthands
7
9
 
8
- def initialize(dpi = 300)
10
+ def initialize(dpi = 300, cell_px = 37.5)
9
11
  @dpi = dpi
12
+ @cell_px = cell_px
10
13
  end
11
14
 
12
15
  # Load the layout file(s), if exists
@@ -67,6 +70,9 @@ module Squib
67
70
  end
68
71
 
69
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
70
76
  if child_val.to_s.strip.start_with?('+=')
71
77
  add_parent_child(parent_val, child_val)
72
78
  elsif child_val.to_s.strip.start_with?('-=')
@@ -81,29 +87,40 @@ module Squib
81
87
  end
82
88
 
83
89
  def add_parent_child(parent, child)
84
- parent_pixels = Args::UnitConversion.parse(parent, @dpi).to_f
85
- child_pixels = Args::UnitConversion.parse(child.sub('+=', ''), @dpi).to_f
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
86
92
  parent_pixels + child_pixels
87
93
  end
88
94
 
89
95
  def sub_parent_child(parent, child)
90
- parent_pixels = Args::UnitConversion.parse(parent, @dpi).to_f
91
- child_pixels = Args::UnitConversion.parse(child.sub('-=', ''), @dpi).to_f
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
92
98
  parent_pixels - child_pixels
93
99
  end
94
100
 
95
101
  def mul_parent_child(parent, child)
96
- parent_pixels = Args::UnitConversion.parse(parent, @dpi).to_f
102
+ parent_pixels = Args::UnitConversion.parse(parent, @dpi, @cell_px).to_f
97
103
  child_float = child.sub('*=', '').to_f
98
104
  parent_pixels * child_float
99
105
  end
100
106
 
101
107
  def div_parent_child(parent, child)
102
- parent_pixels = Args::UnitConversion.parse(parent, @dpi).to_f
108
+ parent_pixels = Args::UnitConversion.parse(parent, @dpi, @cell_px).to_f
103
109
  child_float = child.sub('/=', '').to_f
104
110
  parent_pixels / child_float
105
111
  end
106
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
+
107
124
  # Does this layout entry have an extends field?
108
125
  # i.e. is it a base-case or will it need recursion?
109
126
  # :nodoc:
@@ -3,21 +3,21 @@ module Squib
3
3
  class CropLine
4
4
  attr_reader :x1, :y1, :x2, :y2
5
5
 
6
- def initialize(type, position, sheet_width, sheet_height, dpi)
6
+ def initialize(type, position, sheet_width, sheet_height, dpi, cell_px)
7
7
  method = "parse_#{type}"
8
- send method, position, sheet_width, sheet_height, dpi
8
+ send method, position, sheet_width, sheet_height, dpi, cell_px
9
9
  end
10
10
 
11
- def parse_horizontal(position, sheet_width, _, dpi)
12
- position = Args::UnitConversion.parse(position, dpi)
11
+ def parse_horizontal(position, sheet_width, _, dpi, cell_px)
12
+ position = Args::UnitConversion.parse(position, dpi, cell_px)
13
13
  @x1 = 0
14
14
  @y1 = position
15
15
  @x2 = sheet_width
16
16
  @y2 = position
17
17
  end
18
18
 
19
- def parse_vertical(position, _, sheet_height, dpi)
20
- position = Args::UnitConversion.parse(position, dpi)
19
+ def parse_vertical(position, _, sheet_height, dpi, cell_px)
20
+ position = Args::UnitConversion.parse(position, dpi, cell_px)
21
21
  @x1 = position
22
22
  @y1 = 0
23
23
  @x2 = position
@@ -9,22 +9,22 @@ module Squib
9
9
 
10
10
  attr_reader :pattern
11
11
 
12
- def initialize(value, dpi)
12
+ def initialize(value, dpi, cell_px)
13
13
  if value == :solid
14
14
  @pattern = nil
15
15
  elsif value == :dotted
16
16
  @pattern = [
17
- Args::UnitConversion.parse('0.2mm', dpi),
18
- Args::UnitConversion.parse('0.5mm', dpi)
17
+ Args::UnitConversion.parse('0.2mm', dpi, cell_px),
18
+ Args::UnitConversion.parse('0.5mm', dpi, cell_px)
19
19
  ]
20
20
  elsif value == :dashed
21
21
  @pattern = [
22
- Args::UnitConversion.parse('2mm', dpi),
23
- Args::UnitConversion.parse('2mm', dpi)
22
+ Args::UnitConversion.parse('2mm', dpi, cell_px),
23
+ Args::UnitConversion.parse('2mm', dpi, cell_px)
24
24
  ]
25
25
  elsif value.is_a? String
26
26
  @pattern = value.split(' ').map do |val|
27
- Args::UnitConversion.parse val, dpi
27
+ Args::UnitConversion.parse val, dpi, cell_px
28
28
  end
29
29
  else
30
30
  raise ArgumentError, 'Unsupported dash style'
@@ -18,6 +18,7 @@ module Squib
18
18
  'card_width' => nil,
19
19
  'card_height' => nil,
20
20
  'dpi' => 300,
21
+ 'cell_px' => 37.5,
21
22
  'position_reference' => :topleft,
22
23
  'rotate' => 0.0,
23
24
  'crop_line' => {
@@ -32,16 +33,17 @@ module Squib
32
33
 
33
34
  attr_reader :dpi
34
35
 
35
- def initialize(template_hash, dpi)
36
+ def initialize(template_hash, dpi, cell_px)
36
37
  @template_hash = template_hash
37
38
  @dpi = dpi
39
+ @cell_px = cell_px
38
40
  @crop_line_default = @template_hash['crop_line'].select do |k, _|
39
41
  %w[style width color].include? k
40
42
  end
41
43
  end
42
44
 
43
45
  # Load the template definition file
44
- def self.load(file, dpi)
46
+ def self.load(file, dpi, cell_px)
45
47
  yaml = {}
46
48
  thefile = file if File.exist?(file) # use custom first
47
49
  thefile = builtin(file) if File.exist?(builtin(file)) # then builtin
@@ -62,23 +64,23 @@ module Squib
62
64
  rescue ClassyHash::SchemaViolationError => e
63
65
  raise Sprues::InvalidSprueDefinition.new(thefile, e)
64
66
  end
65
- Sprue.new new_hash, dpi
67
+ Sprue.new new_hash, dpi, cell_px
66
68
  end
67
69
 
68
70
  def sheet_width
69
- Args::UnitConversion.parse @template_hash['sheet_width'], @dpi
71
+ Args::UnitConversion.parse @template_hash['sheet_width'], @dpi, @cell_px
70
72
  end
71
73
 
72
74
  def sheet_height
73
- Args::UnitConversion.parse @template_hash['sheet_height'], @dpi
75
+ Args::UnitConversion.parse @template_hash['sheet_height'], @dpi, @cell_px
74
76
  end
75
77
 
76
78
  def card_width
77
- Args::UnitConversion.parse @template_hash['card_width'], @dpi
79
+ Args::UnitConversion.parse @template_hash['card_width'], @dpi, @cell_px
78
80
  end
79
81
 
80
82
  def card_height
81
- Args::UnitConversion.parse @template_hash['card_height'], @dpi
83
+ Args::UnitConversion.parse @template_hash['card_height'], @dpi, @cell_px
82
84
  end
83
85
 
84
86
  def card_default_rotation
@@ -113,8 +115,8 @@ module Squib
113
115
  # NOTE: There's a baseline of 0.25mm that we can 100% make sure that we
114
116
  # can overlap really thin lines on the PDF
115
117
  crop_line_width = [
116
- Args::UnitConversion.parse(@template_hash['crop_line']['width'], @dpi),
117
- Args::UnitConversion.parse('0.25mm', @dpi)
118
+ Args::UnitConversion.parse(@template_hash['crop_line']['width'], @dpi, @cell_px),
119
+ Args::UnitConversion.parse('0.25mm', @dpi, @cell_px)
118
120
  ].max
119
121
 
120
122
  parsed_cards = cards
@@ -149,12 +151,12 @@ module Squib
149
151
  # Parse crop line definitions from template.
150
152
  def parse_crop_line(line)
151
153
  new_line = @crop_line_default.merge line
152
- new_line['width'] = Args::UnitConversion.parse(new_line['width'], @dpi)
154
+ new_line['width'] = Args::UnitConversion.parse(new_line['width'], @dpi, @cell_px)
153
155
  new_line['color'] = colorify new_line['color']
154
156
  new_line['style_desc'] = new_line['style']
155
- new_line['style'] = Sprues::CropLineDash.new(new_line['style'], @dpi)
157
+ new_line['style'] = Sprues::CropLineDash.new(new_line['style'], @dpi, @cell_px)
156
158
  new_line['line'] = Sprues::CropLine.new(
157
- new_line['type'], new_line['position'], sheet_width, sheet_height, @dpi
159
+ new_line['type'], new_line['position'], sheet_width, sheet_height, @dpi, @cell_px
158
160
  )
159
161
  new_line
160
162
  end
@@ -163,8 +165,8 @@ module Squib
163
165
  def parse_card(card)
164
166
  new_card = card.clone
165
167
 
166
- x = Args::UnitConversion.parse(card['x'], @dpi)
167
- y = Args::UnitConversion.parse(card['y'], @dpi)
168
+ x = Args::UnitConversion.parse(card['x'], @dpi, @cell_px)
169
+ y = Args::UnitConversion.parse(card['y'], @dpi, @cell_px)
168
170
  if @template_hash['position_reference'] == :center
169
171
  # Normalize it to a top-left positional reference
170
172
  x -= card_width / 2