Browse Source

woof this was a big change but ok

Add cell_px everywhere we have dpi

This might be smelly. Sorry, Mr. Fowler and Prof. Frens...
dev
Andy Meneely 5 years ago
parent
commit
93a0d56eda
  1. 5
      docs/config.rst
  2. 17
      lib/squib/args/arg_loader.rb
  3. 2
      lib/squib/args/draw.rb
  4. 2
      lib/squib/args/sheet.rb
  5. 12
      lib/squib/args/xywh_shorthands.rb
  6. 5
      lib/squib/conf.rb
  7. 9
      lib/squib/deck.rb
  8. 2
      lib/squib/dsl/cut_zone.rb
  9. 2
      lib/squib/dsl/safe_zone.rb
  10. 2
      lib/squib/dsl/save_pdf.rb
  11. 2
      lib/squib/dsl/save_sheet.rb
  12. 19
      lib/squib/layout_parser.rb
  13. 12
      lib/squib/sprues/crop_line.rb
  14. 12
      lib/squib/sprues/crop_line_dash.rb
  15. 30
      lib/squib/sprues/sprue.rb
  16. 8
      samples/units/_cells.rb
  17. 2
      samples/units/cell_config.yml
  18. 5
      spec/args/box_spec.rb
  19. 2
      spec/args/draw_spec.rb
  20. 20
      spec/sprue_spec.rb

5
docs/config.rst

@ -101,6 +101,11 @@ smart_quotes
When ``markup: true``, the ``text`` method will convert quotes. With ``smart_quotes: false``, explicit replacements like em-dashes and en-dashes will be replaced but not smart quotes.
cell_px
default: ``37.5``
The number of pixels that the "cell" custom unit is set to. See :doc:`/units`
Options are available as methods
--------------------------------

17
lib/squib/args/arg_loader.rb

@ -9,16 +9,21 @@ module Squib::Args::ArgLoader
# wrapper for compatibility
def extract!(args, deck)
@deck = deck
load!(args, expand_by: deck.size, layout: deck.layout, dpi: deck.dpi)
load!(args,
expand_by: deck.size,
layout: deck.layout,
dpi: deck.dpi,
cell_px: deck.cell_px)
end
# Main class invoked by the client (i.e. dsl/ methods)
def load!(args, expand_by: 1, layout: {}, dpi: 300)
def load!(args, expand_by: 1, layout: {}, dpi: 300, cell_px: 37.5)
@dpi = dpi
@cell_px = cell_px
args[:layout] = prep_layout_args(args[:layout], expand_by: expand_by)
expand_and_set_and_defaultify(args: args, by: expand_by, layout: layout)
validate
convert_units dpi: dpi
convert_units dpi: dpi, cell_px: cell_px
self
end
@ -107,15 +112,15 @@ module Squib::Args::ArgLoader
end
# Convert units
def convert_units(dpi: 300)
def convert_units(dpi: 300, cell_px: 37.5)
self.class.params_with_units.each do |p|
p_str = "@#{p}"
p_val = instance_variable_get(p_str)
if p_val.respond_to? :each
arr = p_val.map { |x| Squib::Args::UnitConversion.parse(x, dpi) }
arr = p_val.map { |x| Squib::Args::UnitConversion.parse(x, dpi, cell_px) }
instance_variable_set p_str, arr
else
instance_variable_set p_str, Squib::Args::UnitConversion.parse(p_val, dpi)
instance_variable_set p_str, Squib::Args::UnitConversion.parse(p_val, dpi, cell_px)
end
end
self

2
lib/squib/args/draw.rb

@ -61,7 +61,7 @@ module Squib::Args
def validate_dash(arg, _i)
arg.to_s.split.collect do |x|
UnitConversion.parse(x, @dpi).to_f
UnitConversion.parse(x, @dpi, @cell_px).to_f
end
end

2
lib/squib/args/sheet.rb

@ -58,7 +58,7 @@ module Squib::Args
def validate_crop_stroke_dash(arg)
arg.to_s.split.collect do |x|
UnitConversion.parse(x, @deck.dpi).to_f
UnitConversion.parse(x, @deck.dpi, @deck.cell_px).to_f
end
end

12
lib/squib/args/xywh_shorthands.rb

@ -24,27 +24,27 @@ module Squib
dimension
when WIDTH_MINUS_REGEX # e.g. width - 1.5in
n = arg_s.sub WIDTH_MINUS_REGEX, ''
n = UnitConversion.parse(n)
n = UnitConversion.parse(n, deck.dpi, deck.cell_px)
deck.width - n
when HEIGHT_MINUS_REGEX # e.g. height - 1.5in
n = arg_s.sub HEIGHT_MINUS_REGEX, ''
n = UnitConversion.parse(n)
n = UnitConversion.parse(n, deck.dpi, deck.cell_px)
deck.height - n
when WIDTH_DIV_REGEX # e.g. width / 3
n = arg_s.sub WIDTH_DIV_REGEX, ''
n = UnitConversion.parse(n).to_f
n = UnitConversion.parse(n, deck.dpi, deck.cell_px).to_f
deck.width / n
when HEIGHT_DIV_REGEX # e.g. height / 3
n = arg_s.sub HEIGHT_DIV_REGEX, ''
n = UnitConversion.parse(n).to_f
n = UnitConversion.parse(n, deck.dpi, deck.cell_px).to_f
deck.height / n
when MIDDLE_PLUS_REGEX # e.g. middle + 1.5in
n = arg_s.sub MIDDLE_PLUS_REGEX, ''
n = UnitConversion.parse(n)
n = UnitConversion.parse(n, deck.dpi, deck.cell_px)
dimension / 2.0 + n
when MIDDLE_MINUS_REGEX # e.g. middle - 1.5in
n = arg_s.sub MIDDLE_MINUS_REGEX, ''
n = UnitConversion.parse(n)
n = UnitConversion.parse(n, deck.dpi, deck.cell_px)
dimension / 2.0 - n
else
arg

5
lib/squib/conf.rb

@ -17,6 +17,7 @@ module Squib
DEFAULTS = {
'antialias' => 'best',
'backend' => 'memory',
'cell_px' => 37.5,
'count_format' => '%02d',
'custom_colors' => {},
'dir' => '_output',
@ -89,6 +90,10 @@ module Squib
@typographer
end
def cell_px
@config_hash['cell_px'].to_f
end
def dir
@config_hash['dir']
end

9
lib/squib/deck.rb

@ -33,7 +33,7 @@ module Squib
:img_dir, :prefix, :text_hint, :typographer
# :nodoc:
# @api private
attr_reader :layout, :conf, :dpi, :font
attr_reader :layout, :conf, :dpi, :font, :cell_px
#
# deck.size is really just @cards.size
@ -63,12 +63,13 @@ module Squib
@font = DEFAULT_FONT
@cards = []
@conf = Conf.load(config)
@cell_px = @conf.cell_px
@progress_bar = Progress.new(@conf.progress_bars) # FIXME this is evil. Using something different with @ and non-@
show_info(config, layout)
@width = Args::UnitConversion.parse width, dpi
@height = Args::UnitConversion.parse height, dpi
@width = Args::UnitConversion.parse width, dpi, @cell_px
@height = Args::UnitConversion.parse height, dpi, @cell_px
cards.times{ |i| @cards << Squib::Card.new(self, @width, @height, i) }
@layout = LayoutParser.new(dpi).load_layout(layout)
@layout = LayoutParser.new(dpi, @cell_px).load_layout(layout)
enable_groups_from_env!
if block_given?
instance_eval(&block) # here we go. wheeeee!

2
lib/squib/dsl/cut_zone.rb

@ -34,7 +34,7 @@ module Squib
stroke_width: 2.0,
}
new_opts = cut_defaults.merge(opts)
margin = Args::UnitConversion.parse new_opts[:margin]
margin = Args::UnitConversion.parse new_opts[:margin], @deck.dpi, @deck.cell_px
new_opts[:x] = margin
new_opts[:y] = margin
new_opts[:width] = deck.width - (2 * margin)

2
lib/squib/dsl/safe_zone.rb

@ -35,7 +35,7 @@ module Squib
dash: '3 3',
}
new_opts = safe_defaults.merge(opts)
margin = Args::UnitConversion.parse new_opts[:margin]
margin = Args::UnitConversion.parse new_opts[:margin], @deck.dpi, @deck.cell_px
new_opts[:x] = margin
new_opts[:y] = margin
new_opts[:width] = deck.width - (2 * margin)

2
lib/squib/dsl/save_pdf.rb

@ -40,7 +40,7 @@ module Squib
if sprue_file.sprue.nil?
Graphics::SavePDF.new(deck).render_pdf(range, sheet)
else
tmpl = Sprue.load sprue_file.sprue, deck.dpi
tmpl = Sprue.load sprue_file.sprue, deck.dpi, deck.cell_px
Graphics::SaveSpruePDF.new(deck, tmpl, sheet).render_sheet(range)
end

2
lib/squib/dsl/save_sheet.rb

@ -43,7 +43,7 @@ module Squib
if sprue_file.sprue.nil?
deck.render_sheet(range, batch, sheet)
else
tmpl = Sprue.load sprue_file.sprue, deck.dpi
tmpl = Sprue.load sprue_file.sprue, deck.dpi, deck.cell_px
Graphics::SaveSpruePNG.new(deck, tmpl, sheet).render_sheet(range)
end

19
lib/squib/layout_parser.rb

@ -7,8 +7,9 @@ module Squib
class LayoutParser
include Args::XYWHShorthands
def initialize(dpi = 300)
def initialize(dpi = 300, cell_px = 37.5)
@dpi = dpi
@cell_px = cell_px
end
# Load the layout file(s), if exists
@ -86,31 +87,31 @@ module Squib
end
def add_parent_child(parent, child)
parent_pixels = Args::UnitConversion.parse(parent, @dpi).to_f
child_pixels = Args::UnitConversion.parse(child.sub('+=', ''), @dpi).to_f
parent_pixels = Args::UnitConversion.parse(parent, @dpi, @cell_px).to_f
child_pixels = Args::UnitConversion.parse(child.sub('+=', ''), @dpi, @cell_px).to_f
parent_pixels + child_pixels
end
def sub_parent_child(parent, child)
parent_pixels = Args::UnitConversion.parse(parent, @dpi).to_f
child_pixels = Args::UnitConversion.parse(child.sub('-=', ''), @dpi).to_f
parent_pixels = Args::UnitConversion.parse(parent, @dpi, @cell_px).to_f
child_pixels = Args::UnitConversion.parse(child.sub('-=', ''), @dpi, @cell_px).to_f
parent_pixels - child_pixels
end
def mul_parent_child(parent, child)
parent_pixels = Args::UnitConversion.parse(parent, @dpi).to_f
parent_pixels = Args::UnitConversion.parse(parent, @dpi, @cell_px).to_f
child_float = child.sub('*=', '').to_f
parent_pixels * child_float
end
def div_parent_child(parent, child)
parent_pixels = Args::UnitConversion.parse(parent, @dpi).to_f
parent_pixels = Args::UnitConversion.parse(parent, @dpi, @cell_px).to_f
child_float = child.sub('/=', '').to_f
parent_pixels / child_float
end
# For relative operators, it's difficult for us to handle
# some of the shorthands - so let's just freak out if you're trying to use
# For relative operators, it's difficult for us to handle
# some of the shorthands - so let's just freak out if you're trying to use
# relative operators with words, e.g. "middle += 0.5in"
def has_digits?(arg)
/.*\d.*/ === arg.to_s

12
lib/squib/sprues/crop_line.rb

@ -3,21 +3,21 @@ module Squib
class CropLine
attr_reader :x1, :y1, :x2, :y2
def initialize(type, position, sheet_width, sheet_height, dpi)
def initialize(type, position, sheet_width, sheet_height, dpi, cell_px)
method = "parse_#{type}"
send method, position, sheet_width, sheet_height, dpi
send method, position, sheet_width, sheet_height, dpi, cell_px
end
def parse_horizontal(position, sheet_width, _, dpi)
position = Args::UnitConversion.parse(position, dpi)
def parse_horizontal(position, sheet_width, _, dpi, cell_px)
position = Args::UnitConversion.parse(position, dpi, cell_px)
@x1 = 0
@y1 = position
@x2 = sheet_width
@y2 = position
end
def parse_vertical(position, _, sheet_height, dpi)
position = Args::UnitConversion.parse(position, dpi)
def parse_vertical(position, _, sheet_height, dpi, cell_px)
position = Args::UnitConversion.parse(position, dpi, cell_px)
@x1 = position
@y1 = 0
@x2 = position

12
lib/squib/sprues/crop_line_dash.rb

@ -9,22 +9,22 @@ module Squib
attr_reader :pattern
def initialize(value, dpi)
def initialize(value, dpi, cell_px)
if value == :solid
@pattern = nil
elsif value == :dotted
@pattern = [
Args::UnitConversion.parse('0.2mm', dpi),
Args::UnitConversion.parse('0.5mm', dpi)
Args::UnitConversion.parse('0.2mm', dpi, cell_px),
Args::UnitConversion.parse('0.5mm', dpi, cell_px)
]
elsif value == :dashed
@pattern = [
Args::UnitConversion.parse('2mm', dpi),
Args::UnitConversion.parse('2mm', dpi)
Args::UnitConversion.parse('2mm', dpi, cell_px),
Args::UnitConversion.parse('2mm', dpi, cell_px)
]
elsif value.is_a? String
@pattern = value.split(' ').map do |val|
Args::UnitConversion.parse val, dpi
Args::UnitConversion.parse val, dpi, cell_px
end
else
raise ArgumentError, 'Unsupported dash style'

30
lib/squib/sprues/sprue.rb

@ -18,6 +18,7 @@ module Squib
'card_width' => nil,
'card_height' => nil,
'dpi' => 300,
'cell_px' => 37.5,
'position_reference' => :topleft,
'rotate' => 0.0,
'crop_line' => {
@ -32,16 +33,17 @@ module Squib
attr_reader :dpi
def initialize(template_hash, dpi)
def initialize(template_hash, dpi, cell_px)
@template_hash = template_hash
@dpi = dpi
@cell_px = cell_px
@crop_line_default = @template_hash['crop_line'].select do |k, _|
%w[style width color].include? k
end
end
# Load the template definition file
def self.load(file, dpi)
def self.load(file, dpi, cell_px)
yaml = {}
thefile = file if File.exist?(file) # use custom first
thefile = builtin(file) if File.exist?(builtin(file)) # then builtin
@ -62,23 +64,23 @@ module Squib
rescue ClassyHash::SchemaViolationError => e
raise Sprues::InvalidSprueDefinition.new(thefile, e)
end
Sprue.new new_hash, dpi
Sprue.new new_hash, dpi, cell_px
end
def sheet_width
Args::UnitConversion.parse @template_hash['sheet_width'], @dpi
Args::UnitConversion.parse @template_hash['sheet_width'], @dpi, @cell_px
end
def sheet_height
Args::UnitConversion.parse @template_hash['sheet_height'], @dpi
Args::UnitConversion.parse @template_hash['sheet_height'], @dpi, @cell_px
end
def card_width
Args::UnitConversion.parse @template_hash['card_width'], @dpi
Args::UnitConversion.parse @template_hash['card_width'], @dpi, @cell_px
end
def card_height
Args::UnitConversion.parse @template_hash['card_height'], @dpi
Args::UnitConversion.parse @template_hash['card_height'], @dpi, @cell_px
end
def card_default_rotation
@ -113,8 +115,8 @@ module Squib
# NOTE: There's a baseline of 0.25mm that we can 100% make sure that we
# can overlap really thin lines on the PDF
crop_line_width = [
Args::UnitConversion.parse(@template_hash['crop_line']['width'], @dpi),
Args::UnitConversion.parse('0.25mm', @dpi)
Args::UnitConversion.parse(@template_hash['crop_line']['width'], @dpi, @cell_px),
Args::UnitConversion.parse('0.25mm', @dpi, @cell_px)
].max
parsed_cards = cards
@ -149,12 +151,12 @@ module Squib
# Parse crop line definitions from template.
def parse_crop_line(line)
new_line = @crop_line_default.merge line
new_line['width'] = Args::UnitConversion.parse(new_line['width'], @dpi)
new_line['width'] = Args::UnitConversion.parse(new_line['width'], @dpi, @cell_px)
new_line['color'] = colorify new_line['color']
new_line['style_desc'] = new_line['style']
new_line['style'] = Sprues::CropLineDash.new(new_line['style'], @dpi)
new_line['style'] = Sprues::CropLineDash.new(new_line['style'], @dpi, @cell_px)
new_line['line'] = Sprues::CropLine.new(
new_line['type'], new_line['position'], sheet_width, sheet_height, @dpi
new_line['type'], new_line['position'], sheet_width, sheet_height, @dpi, @cell_px
)
new_line
end
@ -163,8 +165,8 @@ module Squib
def parse_card(card)
new_card = card.clone
x = Args::UnitConversion.parse(card['x'], @dpi)
y = Args::UnitConversion.parse(card['y'], @dpi)
x = Args::UnitConversion.parse(card['x'], @dpi, @cell_px)
y = Args::UnitConversion.parse(card['y'], @dpi, @cell_px)
if @template_hash['position_reference'] == :center
# Normalize it to a top-left positional reference
x -= card_width / 2

8
samples/units/_cells.rb

@ -43,3 +43,11 @@ Squib::Deck.new(width: '1.5in', height: '1.5in') do
save_png prefix: 'cells_'
end
# You can customize this with the cell_px configuration option
Squib::Deck.new(width: 100, height: 100, config: 'cell_config.yml') do
background color: :white
rect x: '1c', y: '1c', width: '1c', height: '1c', fill_color: :purple
save_png prefix: 'custom_cell_'
end

2
samples/units/cell_config.yml

@ -0,0 +1,2 @@
# Defaults to 37.5, but we'll go with 50 for this example
cell_px: 50

5
spec/args/box_spec.rb

@ -55,7 +55,8 @@ describe Squib::Args::Box do
context 'layouts' do
let(:deck_of_2) do
OpenStruct.new(width: 123, height: 456, size: 2, layout: {
OpenStruct.new(width: 123, height: 456, size: 2,
dpi: 300, cell_px: 37.5, layout: {
'attack' => { 'x' => 50 },
'defend' => { 'x' => 60 },
})
@ -100,7 +101,7 @@ describe Squib::Args::Box do
end
context 'unit conversion' do
let(:deck_of_2) { OpenStruct.new(width: 123, height: 456, size: 2, dpi: 300) }
let(:deck_of_2) { OpenStruct.new(width: 123, height: 456, size: 2, dpi: 300, cell_px: 37.5) }
it 'converts units on all args' do
args = { x: ['1in', '2in'], y: 300, width: '1in', height: '1in' }

2
spec/args/draw_spec.rb

@ -50,7 +50,7 @@ describe Squib::Args::Draw do
it 'does unit conversion on dash options' do
args = { dash: '3in 4in 5in' }
draw.load!(args)
draw.load!(args, dpi: 300)
expect(draw).to have_attributes(dash: [[900, 1200, 1500]])
end

20
spec/sprue_spec.rb

@ -3,7 +3,7 @@ require 'squib/sprues/sprue'
describe Squib::Sprue do
it 'loads a sprue' do
tmpl = Squib::Sprue.load(sprue_file('basic.yml'), 100)
tmpl = Squib::Sprue.load(sprue_file('basic.yml'), 100, 37.5)
expect(tmpl.sheet_width).to eq(850)
expect(tmpl.sheet_height).to eq(1100)
expect(tmpl.card_width).to eq(250)
@ -23,7 +23,7 @@ describe Squib::Sprue do
end
it 'loads from the default templates if none exists' do
tmpl = Squib::Sprue.load('a4_poker_card_9up.yml', 100)
tmpl = Squib::Sprue.load('a4_poker_card_9up.yml', 100, 37.5)
expect(tmpl.sheet_width).to eq(826.7716527)
expect(tmpl.sheet_height).to eq(1169.2913373899999)
expect(tmpl.card_width).to eq(248.03149580999997)
@ -84,7 +84,7 @@ describe Squib::Sprue do
end
it 'loads a template with the coordinates specifying the middle of cards' do
tmpl = Squib::Sprue.load(sprue_file('card_center_coord.yml'), 100)
tmpl = Squib::Sprue.load(sprue_file('card_center_coord.yml'), 100, 37.5)
expect(tmpl.sheet_width).to eq(850)
expect(tmpl.sheet_height).to eq(1100)
expect(tmpl.card_width).to eq(200)
@ -101,7 +101,7 @@ describe Squib::Sprue do
end
it 'loads a template with customized crop lines' do
tmpl = Squib::Sprue.load(sprue_file('custom_crop_lines.yml'), 100)
tmpl = Squib::Sprue.load(sprue_file('custom_crop_lines.yml'), 100, 37.5)
expect(tmpl.sheet_width).to eq(850)
expect(tmpl.sheet_height).to eq(1100)
expect(tmpl.card_width).to eq(200)
@ -137,7 +137,7 @@ describe Squib::Sprue do
end
it 'loads a template with rotated cards' do
tmpl = Squib::Sprue.load(sprue_file('card_rotation.yml'), 100)
tmpl = Squib::Sprue.load(sprue_file('card_rotation.yml'), 100, 37.5)
expect(tmpl.sheet_width).to eq(850)
expect(tmpl.sheet_height).to eq(1100)
expect(tmpl.card_width).to eq(250)
@ -151,7 +151,7 @@ describe Squib::Sprue do
end
it 'loads a template with flipped cards' do
tmpl = Squib::Sprue.load(sprue_file('card_flip.yml'), 100)
tmpl = Squib::Sprue.load(sprue_file('card_flip.yml'), 100, 37.5)
expect(tmpl.cards.length).to eq(3)
expect(tmpl.cards.map { |card| card['flip_vertical'] })
.to eq( [false, true, false] )
@ -161,7 +161,7 @@ describe Squib::Sprue do
it 'fails when sheet_width is not defined' do
expect do
Squib::Sprue.load(sprue_file('fail_no_sheet_width.yml'), 100)
Squib::Sprue.load(sprue_file('fail_no_sheet_width.yml'), 100, 37.5)
end.to raise_error(
Squib::Sprues::InvalidSprueDefinition,
include('"sheet_width" is not a String matching /^(\d*[.])?\d+(in|cm|mm)$/')
@ -170,7 +170,7 @@ describe Squib::Sprue do
it 'fails when sheet_height is not defined' do
expect do
Squib::Sprue.load(sprue_file('fail_no_sheet_height.yml'), 100)
Squib::Sprue.load(sprue_file('fail_no_sheet_height.yml'), 100, 37.5)
end.to raise_error(
Squib::Sprues::InvalidSprueDefinition,
include('"sheet_height" is not a String matching /^(\d*[.])?\d+(in|cm|mm)$/')
@ -179,7 +179,7 @@ describe Squib::Sprue do
it 'fails when card_width is not defined' do
expect do
Squib::Sprue.load(sprue_file('fail_no_card_width.yml'), 100)
Squib::Sprue.load(sprue_file('fail_no_card_width.yml'), 100, 37.5)
end.to raise_error(
Squib::Sprues::InvalidSprueDefinition,
include('"card_width" is not a String matching /^(\d*[.])?\d+(in|cm|mm)$/')
@ -188,7 +188,7 @@ describe Squib::Sprue do
it 'fails when card_height is not defined' do
expect do
Squib::Sprue.load(sprue_file('fail_no_card_height.yml'), 100)
Squib::Sprue.load(sprue_file('fail_no_card_height.yml'), 100, 37.5)
end.to raise_error(
Squib::Sprues::InvalidSprueDefinition,
include('"card_height" is not a String matching /^(\d*[.])?\d+(in|cm|mm)$/')

Loading…
Cancel
Save