Implemented sheet command
This commit is contained in:
@@ -50,7 +50,7 @@ module Squib
|
||||
# @return [nil] intended to be void
|
||||
# @api public
|
||||
def circle(opts = {})
|
||||
opts = {radius: 100}.merge(opts)
|
||||
opts = {radius: 100}.merge(opts) # overriding the non-system default
|
||||
opts = needs(opts, [:range, :x, :y, :circle_radius, :layout,
|
||||
:fill_color, :stroke_color, :stroke_width])
|
||||
opts[:range].each do |i|
|
||||
|
||||
@@ -8,6 +8,7 @@ module Squib
|
||||
:angle => 0,
|
||||
:blend => :none,
|
||||
:color => :black,
|
||||
:columns => 1,
|
||||
:default_font => 'Arial 36',
|
||||
:dir => '_output',
|
||||
:ellipsize => :end,
|
||||
@@ -27,6 +28,7 @@ module Squib
|
||||
:progress_bar => false,
|
||||
:range => :all,
|
||||
:rotate => false,
|
||||
:rows => :infinite,
|
||||
:sheet => 0,
|
||||
:spacing => 0,
|
||||
:str => '',
|
||||
@@ -62,7 +64,7 @@ module Squib
|
||||
# These are parameters that are intended to be "expanded" across
|
||||
# range if they are singletons.
|
||||
#
|
||||
# For example, using a different font for each card, using one `text`
|
||||
# For example: using a different font for each card, using one `text` command
|
||||
#
|
||||
# key: the internal name of the param (e.g. :files)
|
||||
# value: the user-facing API key (e.g. file: 'abc.png')
|
||||
|
||||
@@ -40,6 +40,63 @@ module Squib
|
||||
end
|
||||
end
|
||||
|
||||
# Lays out the cards in range and renders a stitched PNG sheet
|
||||
#
|
||||
# @example
|
||||
# save_png_sheet prefix: 'sheet_', margin: 75, gap: 5, trim: 37
|
||||
#
|
||||
# @option opts [Enumerable] range (:all) the range of cards over which this will be rendered. See {file:README.md#Specifying_Ranges Specifying Ranges}
|
||||
# @option opts colulmns [Integer] (1) the number of columns in the grid
|
||||
# @option opts rows [Integer] (:infinite) the number of rows in the grid. When set to :infinite, the sheet scales to the rows needed. If there are more cards than rows*columns, new sheets are started.
|
||||
# @option opts [String] prefix (card_) the prefix of the file name(s)
|
||||
# @option opts dir [String] (_output) the directory to save to. Created if it doesn't exist.
|
||||
# @option opts margin [Integer] (0) the margin around the outside of the page
|
||||
# @option opts gap [Integer] (0) the space in pixels between the cards
|
||||
# @option opts trim [Integer] (0) the space around the edge of each card to trim (e.g. to cut off the bleed margin for print-and-play)
|
||||
# @return [nil]
|
||||
# @api public
|
||||
def save_sheet(opts = {})
|
||||
opts = {margin: 0}.merge(opts) # overriding the non-system default
|
||||
p = needs(opts, [:range, :prefix, :creatable_dir, :margin, :gap, :trim, :rows, :columns])
|
||||
# EXTRACT METHOD HERE
|
||||
sheet_width = (p[:columns] * (@width + 2 * p[:gap] - 2 * p[:trim])) + (2 * p[:margin])
|
||||
sheet_height = (p[:rows] * (@height + 2 * p[:gap] - 2 * p[:trim])) + (2 * p[:margin])
|
||||
cc = Cairo::Context.new(Cairo::ImageSurface.new(sheet_width, sheet_height))
|
||||
num_this_sheet = 0
|
||||
sheet_num = 0
|
||||
x, y = p[:margin], p[:margin]
|
||||
@progress_bar.start("Saving PNG sheet to #{p[:dir]}/#{p[:prefix]}_*", @cards.size + 1) do |bar|
|
||||
p[:range].each do |i|
|
||||
if num_this_sheet >= (p[:columns] * p[:rows]) # new sheet
|
||||
cc.target.write_to_png("#{p[:dir]}/#{p[:prefix]}#{sheet_num}.png")
|
||||
new_sheet = false
|
||||
num_this_sheet = 0
|
||||
sheet_num += 1
|
||||
x, y = p[:margin], p[:margin]
|
||||
cc = Cairo::Context.new(Cairo::ImageSurface.new(sheet_width, sheet_height))
|
||||
end
|
||||
surface = trim(@cards[i].cairo_surface, p[:trim], @width, @height)
|
||||
cc.set_source(surface, x, y)
|
||||
cc.paint
|
||||
bar.increment
|
||||
num_this_sheet += 1
|
||||
x += surface.width + p[:gap]
|
||||
if num_this_sheet % p[:columns] == 0 # new row
|
||||
x = p[:margin]
|
||||
y += surface.height + p[:gap]
|
||||
end
|
||||
bar.increment
|
||||
end
|
||||
cc.target.write_to_png("#{p[:dir]}/#{p[:prefix]}#{sheet_num}.png")
|
||||
end
|
||||
end
|
||||
|
||||
# Return a new Cairo::ImageSurface that is trimmed from the original
|
||||
#
|
||||
# @param surface The surface to trim
|
||||
# @param trim The number of pixels around the edge to trim
|
||||
# @width width The width of the surface prior to the trim
|
||||
# @height height The height of the surface prior to the trim
|
||||
# :nodoc:
|
||||
# @api private
|
||||
def trim(surface, trim, width, height)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
require 'squib/constants'
|
||||
require 'squib/api/units'
|
||||
|
||||
module Squib
|
||||
# :nodoc:
|
||||
@@ -28,6 +27,7 @@ module Squib
|
||||
opts = svgidify(opts) if params.include? :svgid
|
||||
opts = formatify(opts) if params.include? :formats
|
||||
opts = rotateify(opts) if params.include? :rotate
|
||||
opts = rowify(opts) if params.include? :rows
|
||||
opts = convert_units(opts, params)
|
||||
opts
|
||||
end
|
||||
@@ -192,7 +192,7 @@ module Squib
|
||||
end
|
||||
module_function :rotateify
|
||||
|
||||
@@INCHES_IN_CM = 0.393700787
|
||||
@@INCHES_IN_CM = 0.393700787
|
||||
# Convert units
|
||||
# :nodoc:
|
||||
# @api private
|
||||
@@ -214,5 +214,19 @@ module Squib
|
||||
end
|
||||
module_function :convert_units
|
||||
|
||||
# Handles expanding rows. If the "rows" does not respond to to_i (e.g. :infinite),
|
||||
# then compute what we need based on number of cards and number of columns.
|
||||
# :nodoc:
|
||||
# @api private
|
||||
def rowify(opts)
|
||||
unless opts[:rows].respond_to? :to_i
|
||||
raise "Columns must be an integer" unless opts[:columns].respond_to? :to_i
|
||||
opts[:rows] = (@cards.size / opts[:columns].to_i).ceil
|
||||
end
|
||||
opts
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user