sprues: polishing up the feature
Lots of examples, some better checking, lots of documentation, sanity tests. Lots of little stuff.dev
|
|
@ -12,15 +12,33 @@ A `sprue <https://en.wikipedia.org/wiki/Sprue_(manufacturing)>`_ is a Squib feat
|
|||
|
||||
Without using a sprue, the :doc:`/dsl/save_sheet` and :doc:`/dsl/save_sheet` will simply lay out your cards one after another with the gap and margins you specify.
|
||||
|
||||
Like Layouts, Squib comes with a library of built-in sprues that you can use. You can make a sprue yourself, or you can generate one from the command line.
|
||||
.. warning::
|
||||
|
||||
Sprues don't currently support the `trim` and `trim_radius` options. `Stay tuned <https://github.com/andymeneely/squib/issues/235>`_
|
||||
|
||||
Using a Sprue
|
||||
-------------
|
||||
|
||||
The easiest way to get started is to use our library of built-in sprues for various default paper sizes and card sizes. See :ref:`list-of-sprues` below.
|
||||
|
||||
Sprues are specified in Yaml, just like layouts. To use a built-in sprue, just specify the name and Squib will use that::
|
||||
|
||||
save_sheet sprue: 'letter_poker_card_9up.yml'
|
||||
|
||||
Here's a full example `from here <https://github.com/andymeneely/squib/tree/master/samples/sprues/_sprue_example.rb>`_:
|
||||
|
||||
.. literalinclude:: ../samples/sprues/_sprue_example.rb
|
||||
:linenos:
|
||||
|
||||
Make Your Own Sprue
|
||||
-------------------
|
||||
|
||||
Need a special one? You can make a sprue file yourself following the :ref:`sprue-format` below, or you can generate one from the command line.
|
||||
|
||||
.. note::
|
||||
|
||||
Would someone else find your sprue useful? Contribute one!! This is an easy way to help out the Squib community.
|
||||
|
||||
Make Your Own Sprue on Command Line
|
||||
-----------------------------------
|
||||
|
||||
Squib comes with a handy little command-line interface that will generate a sprue file based on your own parameters. Of course, you can edit the sprue file once you're done to fix any quirks you like.
|
||||
|
||||
Here's an example run::
|
||||
|
|
@ -99,6 +117,7 @@ Of course, a Squib sprue is just a YAML file with a specific structure. Here's a
|
|||
- type: :horizontal
|
||||
position: 10.625in
|
||||
|
||||
.. _sprue-format:
|
||||
|
||||
Sprue Format
|
||||
------------
|
||||
|
|
@ -115,15 +134,15 @@ sheet_height
|
|||
Width of the sheet, supports :doc:`/units`.
|
||||
|
||||
card_width
|
||||
Intended width of the card. Sprues will allow any size of card, but if the size of the incoming card does not match this size then a warning will be printed to stdout. Supports :doc:`/units`.
|
||||
Intended width of the card. Sprues will allow any size of card. Squib will check for potential overlaps, and will warn you if the deck card width is greater than the Sprue's expected card width (this option). If there is overlap detected Squib will send out a warning to stdout. Supports :doc:`/units`.
|
||||
|
||||
card_height
|
||||
Intended height of the card. Sprues will allow any size of card, but if the size of the incoming card does not match this size then a warning will be printed to stdout. Supports :doc:`/units`.
|
||||
Intended height of the card. Sprues will allow any size of card. Squib will check for potential overlaps, and will warn you if the deck card height is greater than the Sprue's expected card height (this option). If there is overlap detected Squib will send out a warning to stdout. Supports :doc:`/units`.
|
||||
|
||||
position_reference
|
||||
Default: ``topleft``
|
||||
Default: ``:topleft``
|
||||
|
||||
Can be ``topleft`` or ``center``. Are the ``card`` coordinates refer to the top-left of the card, or the middle of the card?
|
||||
Can be ``:topleft`` or ``:center``. Are the ``card`` coordinates refer to the top-left of the card, or the middle of the card? (Don't forget that colon!)
|
||||
|
||||
cards
|
||||
^^^^^
|
||||
|
|
@ -169,20 +188,10 @@ type
|
|||
position
|
||||
The x-position or y-position of the crop line (depending on ``type``)
|
||||
|
||||
.. _list-of-sprues:
|
||||
|
||||
Front-to-Back Printing
|
||||
----------------------
|
||||
|
||||
While Squib does not natively support card "fronts" and "backs" (`yet <https://github.com/andymeneely/squib/issues/93>`_), you can use sprues and the ``range`` option (see :doc:`/ranges`).
|
||||
|
||||
Consider this sample:
|
||||
|
||||
.. warning::
|
||||
|
||||
To be written
|
||||
|
||||
Built-in Sprues
|
||||
---------------
|
||||
List of Built-in Sprues
|
||||
-----------------------
|
||||
|
||||
Here's a list of built-in sprues that come with Squib. You can get the original YAML files `on GitHub here <https://github.com/andymeneely/squib/tree/master/lib/squib/builtin/sprues>`_.
|
||||
|
||||
|
|
@ -191,5 +200,37 @@ a4_euro_card.yml
|
|||
|
||||
.. raw:: html
|
||||
|
||||
<img src="sprues/sprue_a4_euro_card.yml_01.png"
|
||||
<img src="sprues/sprue_a4_euro_card.yml_01_expected.png"
|
||||
class="figure" width=550>
|
||||
|
||||
a4_poker_card_8up.yml
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
.. raw:: html
|
||||
|
||||
<img src="sprues/sprue_a4_poker_card_8up.yml_01_expected.png"
|
||||
class="figure" width=550>
|
||||
|
||||
a4_usa_card.yml
|
||||
^^^^^^^^^^^^^^^
|
||||
.. raw:: html
|
||||
|
||||
<img src="sprues/sprue_a4_usa_card.yml_01_expected.png"
|
||||
class="figure" width=550>
|
||||
|
||||
letter_poker_card_9up.yml
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
.. raw:: html
|
||||
|
||||
<img src="sprues/sprue_letter_poker_card_9up.yml_01_expected.png"
|
||||
class="figure" width=550>
|
||||
|
||||
letter_poker_foldable_8up.yml
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. literalinclude:: ../samples/sprues/_fold_sheet.rb
|
||||
:linenos:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<img src="sprues/foldable_01_expected.png"
|
||||
class="figure" width=550>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
sheet_width: 8.5in
|
||||
sheet_height: 11in
|
||||
card_width: 2.5in
|
||||
card_height: 3.5in
|
||||
position_reference: :center
|
||||
cards:
|
||||
- x: 1.75in
|
||||
y: 2.000in
|
||||
- x: 4.250in
|
||||
y: 2.000in
|
||||
- x: 6.750in
|
||||
y: 2.000in
|
||||
- x: 1.75in
|
||||
y: 5.500in
|
||||
- x: 4.250in
|
||||
y: 5.500in
|
||||
- x: 6.750in
|
||||
y: 5.500in
|
||||
- x: 1.75in
|
||||
y: 9.000in
|
||||
- x: 4.250in
|
||||
y: 9.000in
|
||||
- x: 6.750in
|
||||
y: 9.000in
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
---
|
||||
sheet_width: 11in
|
||||
sheet_height: 8.5in
|
||||
card_width: 2.5in
|
||||
card_height: 3.5in
|
||||
cards:
|
||||
- x: 0.35in
|
||||
y: 0.225in
|
||||
- x: 0.35in
|
||||
y: 4.800in
|
||||
rotate: :turnaround
|
||||
- x: 2.95in
|
||||
y: 0.225in
|
||||
- x: 2.95in
|
||||
y: 4.800in
|
||||
rotate: :turnaround
|
||||
- x: 5.55in
|
||||
y: 0.225in
|
||||
- x: 5.55in
|
||||
y: 4.800in
|
||||
rotate: :turnaround
|
||||
- x: 8.15in
|
||||
y: 0.225in
|
||||
- x: 8.15in
|
||||
y: 4.800in
|
||||
rotate: :turnaround
|
||||
crop_line:
|
||||
lines:
|
||||
- type: :vertical
|
||||
position: 0.35in
|
||||
- type: :vertical
|
||||
position: 2.85in
|
||||
- type: :vertical
|
||||
position: 2.95in
|
||||
- type: :vertical
|
||||
position: 5.45in
|
||||
- type: :vertical
|
||||
position: 5.55in
|
||||
- type: :vertical
|
||||
position: 8.05in
|
||||
- type: :vertical
|
||||
position: 8.15in
|
||||
- type: :vertical
|
||||
position: 10.65in
|
||||
- type: :horizontal
|
||||
position: 0.225in
|
||||
- type: :horizontal
|
||||
position: 3.725in
|
||||
- type: :horizontal
|
||||
position: 3.825in
|
||||
- type: :horizontal
|
||||
position: 7.325in
|
||||
|
|
@ -15,6 +15,8 @@ module Squib
|
|||
|
||||
def render_sheet(range)
|
||||
cc = init_cc
|
||||
cc.set_source_color(:white) # white backdrop TODO make option
|
||||
cc.paint
|
||||
card_set = @tmpl.cards
|
||||
per_sheet = card_set.size
|
||||
default_angle = @tmpl.card_default_rotation
|
||||
|
|
@ -26,7 +28,7 @@ module Squib
|
|||
|
||||
track_progress(range) do |bar|
|
||||
range.each do |i|
|
||||
next_page_if_needed(cc, i, per_sheet)
|
||||
cc = next_page_if_needed(cc, i, per_sheet)
|
||||
|
||||
card = @deck.cards[i]
|
||||
slot = card_set[i % per_sheet]
|
||||
|
|
@ -45,7 +47,7 @@ module Squib
|
|||
end
|
||||
|
||||
draw_overlay_above_cards cc
|
||||
draw_page cc
|
||||
cc = draw_page cc
|
||||
cc.target.finish
|
||||
end
|
||||
end
|
||||
|
|
@ -68,12 +70,13 @@ module Squib
|
|||
private
|
||||
|
||||
def next_page_if_needed(cc, i, per_sheet)
|
||||
return unless (i != 0) && (i % per_sheet).zero?
|
||||
return cc unless (i != 0) && (i % per_sheet).zero?
|
||||
|
||||
draw_overlay_above_cards cc
|
||||
cc = draw_page cc
|
||||
draw_overlay_below_cards cc
|
||||
@page_number += 1
|
||||
cc
|
||||
end
|
||||
|
||||
def track_progress(range)
|
||||
|
|
@ -129,8 +132,8 @@ module Squib
|
|||
|
||||
def check_card_orientation
|
||||
clockwise = 1.5 * Math::PI
|
||||
# Simple detection
|
||||
if @deck.width == @tmpl.card_width && @deck.height == @tmpl.card_height
|
||||
if @deck.width <= @tmpl.card_width &&
|
||||
@deck.height <= @tmpl.card_height
|
||||
return 0
|
||||
elsif (
|
||||
@deck.width == @tmpl.card_height &&
|
||||
|
|
@ -141,20 +144,11 @@ module Squib
|
|||
return clockwise
|
||||
end
|
||||
|
||||
# If the card dimensions doesn't match, warns the user...
|
||||
Squib.logger.warn {
|
||||
'Card size does not match the template\'s expected card size. '\
|
||||
'Card size is larger than sprue\'s expected card size. '\
|
||||
'Cards may overlap.'
|
||||
}
|
||||
|
||||
# ... but still try to auto-orient the cards anyway
|
||||
is_tmpl_card_landscape = @tmpl.card_width > @tmpl.card_height
|
||||
is_deck_card_landscape = @deck.width > @deck.height
|
||||
if is_tmpl_card_landscape == is_deck_card_landscape
|
||||
clockwise
|
||||
else
|
||||
0
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
def draw_rotated_card(cc, card, x, y, angle)
|
||||
|
|
@ -201,6 +195,8 @@ module Squib
|
|||
|
||||
def draw_page(cc)
|
||||
cc.show_page
|
||||
cc.set_source_color(:white) # white backdrop TODO make option
|
||||
cc.paint
|
||||
cc
|
||||
end
|
||||
|
||||
|
|
@ -209,7 +205,7 @@ module Squib
|
|||
end
|
||||
end
|
||||
|
||||
# Templated sheet renderer in PDF format.
|
||||
# Templated sheet renderer in PNG format.
|
||||
class SaveSpruePNG < SaveSprue
|
||||
def init_cc
|
||||
surface = Cairo::ImageSurface.new @tmpl.sheet_width, @tmpl.sheet_height
|
||||
|
|
@ -219,6 +215,9 @@ module Squib
|
|||
def draw_page(cc)
|
||||
cc.target.write_to_png(full_filename)
|
||||
init_cc
|
||||
cc.set_source_color(:white) # white backdrop TODO make option
|
||||
cc.paint
|
||||
cc
|
||||
end
|
||||
|
||||
def full_filename
|
||||
|
|
|
|||
|
|
@ -136,10 +136,10 @@ module Squib
|
|||
font_desc.size = para.font_size * Pango::SCALE unless para.font_size.nil?
|
||||
layout = cc.create_pango_layout
|
||||
layout.font_description = font_desc
|
||||
layout.text = para.str
|
||||
layout.text = para.str.to_s
|
||||
if para.markup
|
||||
para.str = @deck.typographer.process(layout.text)
|
||||
layout.markup = para.str
|
||||
layout.markup = para.str.to_s
|
||||
end
|
||||
|
||||
set_font_rendering_opts!(layout)
|
||||
|
|
|
|||
|
|
@ -43,20 +43,21 @@ module Squib
|
|||
# Load the template definition file
|
||||
def self.load(file, dpi)
|
||||
yaml = {}
|
||||
thefile = File.exist?(file) ? file : builtin(file)
|
||||
thefile = file if File.exist?(file) # use custom first
|
||||
thefile = builtin(file) if File.exist?(builtin(file)) # then builtin
|
||||
unless File.exist?(thefile)
|
||||
Squib::logger.error("Sprue not found: #{file}. Falling back to defaults.")
|
||||
end
|
||||
yaml = YAML.load_file(thefile) || {} if File.exist? thefile
|
||||
|
||||
# Bake the default values into our template
|
||||
# Bake the default values into our sprue
|
||||
new_hash = DEFAULTS.merge(yaml)
|
||||
new_hash['crop_line'] = DEFAULTS['crop_line'].merge(
|
||||
new_hash['crop_line']
|
||||
)
|
||||
|
||||
# Create a new template file
|
||||
new_hash['crop_line'] = DEFAULTS['crop_line'].
|
||||
merge(new_hash['crop_line'])
|
||||
warn_unrecognized(yaml)
|
||||
|
||||
# Validate
|
||||
begin
|
||||
require 'benchmark'
|
||||
ClassyHash.validate(new_hash, Sprues::SCHEMA)
|
||||
rescue ClassyHash::SchemaViolationError => e
|
||||
raise Sprues::InvalidSprueDefinition.new(thefile, e)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
require 'squib'
|
||||
|
||||
Squib::Deck.new(cards: 8) do
|
||||
Squib::Deck.new(width: '50mm', height: '70mm', cards: 9) do
|
||||
background color: :white
|
||||
rect stroke_width: 5, stroke_dash: '7 7'
|
||||
text str: %w(First Second Third Fourth Fifth Sixth Seventh Eighth),
|
||||
rect stroke_width: 5, stroke_color: :red
|
||||
text str: (0..9).map{ |i| "Card! #{i}\n50x77mm" },
|
||||
font: 'Sans 96', align: :center, valign: :middle,
|
||||
height: :deck, width: :deck
|
||||
|
||||
%w(
|
||||
a4_euro_card.yml
|
||||
a4_poker_card_8up.yml
|
||||
a4_euro_card.yml
|
||||
a4_poker_card_9up.yml
|
||||
a4_usa_card.yml
|
||||
letter_poker_card_9up.yml
|
||||
).each do |builtin|
|
||||
save_sheet sprue: builtin, prefix: "sprue_#{builtin}_", dir: '.'
|
||||
save_sheet sprue: builtin, prefix: "sprue_#{builtin}_"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,11 +1,27 @@
|
|||
require 'squib'
|
||||
|
||||
Squib::Deck.new(width: '63mm', height: '88mm', cards: 8) do
|
||||
rect fill_color: :gray
|
||||
text(
|
||||
str: %w[Front_1 Front_2 Front_3 Front_4 Back_1 Back_2 Back_3 Back_4],
|
||||
x: '3mm', y: '3mm'
|
||||
)
|
||||
save_pdf file: 'fold_sheet.pdf',
|
||||
sprue: 'my_sprues/fold_sheet.yml'
|
||||
# Note that this sample has no bleed - you might want to have bleed
|
||||
# but tighter than usual: 0.1 instead of 0.125in since this sprue is
|
||||
# crowded horizontally on US letter
|
||||
Squib::Deck.new(width: '2.5in', height: '3.5in', cards: 8) do
|
||||
background color: :white
|
||||
rect stroke_width: 5, stroke_color: :red
|
||||
# Note that we are interleaving strings
|
||||
# This could be used as a secondary Squib script that loads
|
||||
# Squib-generated individual images
|
||||
strings = [
|
||||
"Front 1",
|
||||
"Back 1",
|
||||
"Front 2",
|
||||
"Back 2",
|
||||
"Front 3",
|
||||
"Back 3",
|
||||
"Front 4",
|
||||
"Back 4",
|
||||
]
|
||||
|
||||
text str: strings,font: 'Sans 96', align: :center, valign: :middle,
|
||||
height: :deck, width: :deck
|
||||
save_sheet prefix: 'foldable_',
|
||||
sprue: 'letter_poker_foldable_8up.yml'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
require 'squib'
|
||||
|
||||
Squib::Deck.new(cards: 9) do
|
||||
background color: :white
|
||||
rect stroke_width: 5, stroke_color: :red
|
||||
text str: (0..9).map{ |i| "Card #{i}\n2.5x3.5in" },
|
||||
font: 'Sans 96', align: :center, valign: :middle,
|
||||
height: :deck, width: :deck
|
||||
save_sheet sprue: 'letter_poker_card_9up.yml',
|
||||
prefix: "sprue_example_"
|
||||
end
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
require 'squib'
|
||||
|
||||
Squib::Deck.new(width: '63mm', height: '88mm', cards: 9) do
|
||||
text(
|
||||
str: %w[One Two Three Four Five Six Seven Eight Nine], x: '3mm', y: '3mm'
|
||||
)
|
||||
save_pdf file: 'use_package_tmpl.pdf',
|
||||
sprue: 'a4_poker_card_9up.yml'
|
||||
end
|
||||
|
After Width: | Height: | Size: 59 KiB |
|
|
@ -1,57 +0,0 @@
|
|||
---
|
||||
sheet_width: 297mm
|
||||
sheet_height: 210mm
|
||||
card_width: 63.0mm
|
||||
card_height: 88.0mm
|
||||
cards:
|
||||
- x: 16.5mm
|
||||
y: 13.0mm
|
||||
- x: 83.5mm
|
||||
y: 13.0mm
|
||||
- x: 150.5mm
|
||||
y: 13.0mm
|
||||
- x: 217.5mm
|
||||
y: 13.0mm
|
||||
- x: 16.5mm
|
||||
y: 109.0mm
|
||||
rotate: :turnaround
|
||||
- x: 83.5mm
|
||||
y: 109.0mm
|
||||
rotate: :turnaround
|
||||
- x: 150.5mm
|
||||
y: 109.0mm
|
||||
rotate: :turnaround
|
||||
- x: 217.5mm
|
||||
y: 109.0mm
|
||||
rotate: :turnaround
|
||||
crop_line:
|
||||
lines:
|
||||
- type: :vertical
|
||||
position: 16.5mm
|
||||
- type: :vertical
|
||||
position: 79.5mm
|
||||
- type: :vertical
|
||||
position: 83.5mm
|
||||
- type: :vertical
|
||||
position: 146.5mm
|
||||
- type: :vertical
|
||||
position: 150.5mm
|
||||
- type: :vertical
|
||||
position: 213.5mm
|
||||
- type: :vertical
|
||||
position: 217.5mm
|
||||
- type: :vertical
|
||||
position: 280.5mm
|
||||
- type: :horizontal
|
||||
position: 13.0mm
|
||||
- type: :horizontal
|
||||
position: 101.0mm
|
||||
- type: :horizontal
|
||||
position: 109.0mm
|
||||
- type: :horizontal
|
||||
position: 197.0mm
|
||||
- type: :horizontal
|
||||
position: 105.0mm
|
||||
style: :dashed
|
||||
color: :red
|
||||
overlay_on_cards: true
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
---
|
||||
sheet_width: 8.5in
|
||||
sheet_height: 11in
|
||||
card_width: 2.5in
|
||||
card_height: 3.5in
|
||||
cards:
|
||||
- x: 0.5in
|
||||
y: 0.125in
|
||||
- x: 3.0in
|
||||
y: 0.125in
|
||||
- x: 5.5in
|
||||
y: 0.125in
|
||||
- x: 0.5in
|
||||
y: 3.625in
|
||||
- x: 3.0in
|
||||
y: 3.625in
|
||||
- x: 5.5in
|
||||
y: 3.625in
|
||||
- x: 0.5in
|
||||
y: 7.125in
|
||||
- x: 3.0in
|
||||
y: 7.125in
|
||||
- x: 5.5in
|
||||
y: 7.125in
|
||||
crop_line:
|
||||
lines:
|
||||
- type: :vertical
|
||||
position: 0.5in
|
||||
- type: :vertical
|
||||
position: 3.0in
|
||||
- type: :vertical
|
||||
position: 5.5in
|
||||
- type: :vertical
|
||||
position: 8.0in
|
||||
- type: :horizontal
|
||||
position: 0.125in
|
||||
- type: :horizontal
|
||||
position: 3.625in
|
||||
- type: :horizontal
|
||||
position: 7.125in
|
||||
- type: :horizontal
|
||||
position: 10.625in
|
||||
|
After Width: | Height: | Size: 254 KiB |
|
After Width: | Height: | Size: 229 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 244 KiB |
|
After Width: | Height: | Size: 249 KiB |
|
After Width: | Height: | Size: 74 KiB |