squib 0.15.0 → 0.16.0.pre.preview2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/tests.yml +22 -0
  3. data/CHANGELOG.md +41 -1
  4. data/Dockerfile +18 -16
  5. data/Guardfile +8 -0
  6. data/README.md +24 -6
  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 +51 -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 +44 -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 +2 -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 +48 -0
  93. data/samples/units/_units.rb +7 -0
  94. data/squib.gemspec +18 -12
  95. metadata +144 -58
  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