diff --git a/lib/squib/api/save.rb b/lib/squib/api/save.rb index 0d5fa2c..96f33f6 100644 --- a/lib/squib/api/save.rb +++ b/lib/squib/api/save.rb @@ -1,5 +1,7 @@ -require 'squib/args/save_batch' require 'squib/args/card_range' +require 'squib/args/save_batch' +require 'squib/args/sheet' +require 'squib/args/showcase_special' module Squib class Deck @@ -58,7 +60,7 @@ module Squib # @option opts [Fixnum] scale (0.8) percentage of original width of each (trimmed) card to scale to. Must be between 0.0 and 1.0, but starts looking bad around 0.6. # @option opts [Fixnum] offset (1.1) percentage of the scaled width of each card to shift each offset. e.g. 1.1 is a 10% shift, and 0.95 is overlapping by 5% # @option opts [String, Color] fill_color (:white) backdrop color. Usually black or white. Supports gradients. - # @option opts [Fixnum] reflect_offset (15) the number of pixels between the bottom of the card and the reflection + # @option opts [Fixnum] reflect_offset (15) the number of pixels between the bottom of the card and the reflection. Supports Unit Conversion, see {file:README.md#Units Units}. # @option opts [Fixnum] reflect_strength (0.2) the starting alpha transparency of the reflection (at the top of the card). Percentage between 0 and 1. Looks more realistic at low values since even shiny surfaces lose a lot of light. # @option opts [Fixnum] reflect_percent (0.25) the length of the reflection in percentage of the card. Larger values tend to make the reflection draw just as much attention as the card, which is not good. # @option opts [:left, :right] face (:left) which direction the cards face. Anything but `:right` will face left @@ -67,13 +69,10 @@ module Squib # @return [nil] Returns nothing. # @api public def showcase(opts = {}) - opts = {file: 'showcase.png', fill_color: :white}.merge(opts) - opts = needs(opts,[:range, :margin, :trim, :trim_radius, :creatable_dir, :file_to_save, :face]) - render_showcase(opts[:range], opts[:trim], opts[:trim_radius], - opts[:scale], opts[:offset], opts[:fill_color], - opts[:reflect_offset], opts[:reflect_percent], opts[:reflect_strength], - opts[:margin], opts[:face], - opts[:dir], opts[:file]) + range = Args::CardRange.new(opts[:range], deck_size: size) + showcase = Args::ShowcaseSpecial.new.load!(opts, expand_by: size, layout: layout, dpi: dpi) + sheet = Args::Sheet.new(custom_colors, {file: 'showcase.png'}).load!(opts, expand_by: size, layout: layout, dpi: dpi) + render_showcase(range, sheet, showcase) end # Renders a range of cards fanned out as if in a hand. Saves as PNG. diff --git a/lib/squib/api/shapes.rb b/lib/squib/api/shapes.rb index 9a6e6d9..c82479b 100644 --- a/lib/squib/api/shapes.rb +++ b/lib/squib/api/shapes.rb @@ -212,7 +212,7 @@ module Squib # @option opts radius [Fixnum] (0) the radius from center to corner. Supports Unit conversion. # @option opts stroke_color [String] (:black) the color with which to stroke the line. See {file:README.md#Specifying_Colors___Gradients Specifying Colors & Gradients}. # @option opts stroke_width [Decimal] (2.0) the width of the outside stroke. Supports Unit Conversion, see {file:README.md#Units Units}. - # @option opts stroke_strategy [:fill_first, :stroke_first] (:fill_first) specify whether the stroke is done before (thinner) or after (thicker) filling the shape. + # @option opts stroke_strategy [:fill_first, :stroke_first] (:fill_first) specify whether the stroke is done before (thinner) or after (thicker) filling the shape. # @option opts fill_color [String] ('#0000') the color with which to fill the triangle. See {file:README.md#Specifying_Colors___Gradients Specifying Colors & Gradients} # @option opts dash [String] ('') define a dash pattern for the stroke. Provide a string with space-separated numbers that define the pattern of on-and-off alternating strokes, measured in pixels by defautl. Supports Unit Conversion, see {file:README.md#Units Units} (e.g. `'0.02in 0.02in'`). # @option opts layout [String, Symbol] (nil) entry in the layout to use as defaults for this command. See {file:README.md#Custom_Layouts Custom Layouts} diff --git a/lib/squib/args/dir_validator.rb b/lib/squib/args/dir_validator.rb new file mode 100644 index 0000000..b09d433 --- /dev/null +++ b/lib/squib/args/dir_validator.rb @@ -0,0 +1,16 @@ +module Squib + #@api private + module Args + module DirValidator + + def ensure_dir_created(dir) + unless Dir.exists?(dir) + Squib.logger.warn "Dir '#{dir}' does not exist, creating it." + Dir.mkdir dir + end + return dir + end + + end + end +end diff --git a/lib/squib/args/save_batch.rb b/lib/squib/args/save_batch.rb index 768ae3f..27d3fc2 100644 --- a/lib/squib/args/save_batch.rb +++ b/lib/squib/args/save_batch.rb @@ -1,10 +1,12 @@ require 'squib/args/arg_loader' +require 'squib/args/dir_validator' module Squib # @api private module Args class SaveBatch include ArgLoader + include DirValidator def initialize end @@ -27,11 +29,7 @@ module Squib end def validate_dir(arg, _i) - unless Dir.exists?(arg) - Squib.logger.warn("Dir '#{arg}' does not exist, creating it.") - Dir.mkdir arg - end - return arg + ensure_dir_created(arg) end def validate_rotate(arg, i) diff --git a/lib/squib/args/sheet.rb b/lib/squib/args/sheet.rb new file mode 100644 index 0000000..1a8d73b --- /dev/null +++ b/lib/squib/args/sheet.rb @@ -0,0 +1,50 @@ +require 'cairo' +require 'squib/args/arg_loader' +require 'squib/args/color_validator' +require 'squib/args/dir_validator' + +module Squib + # @api private + module Args + + class Sheet + include ArgLoader + include ColorValidator + include DirValidator + + def initialize(custom_colors = {}, dsl_method_defaults = {}) + @custom_colors = custom_colors + @dsl_method_defaults = dsl_method_defaults + end + + def self.parameters + { dir: '_output', + file: 'sheet.png', + fill_color: :white, + gap: 0, + margin: 75, + trim_radius: 38, + trim: 0, + } + end + + def self.expanding_parameters + [] # none of them + end + + def self.params_with_units + [ :gap, :margin, :trim_radius, :trim ] + end + + def validate_fill_color(arg) + colorify(arg, @custom_colors) + end + + def validate_dir(arg) + ensure_dir_created(arg) + end + + end + + end +end diff --git a/lib/squib/args/showcase_special.rb b/lib/squib/args/showcase_special.rb new file mode 100644 index 0000000..04c26da --- /dev/null +++ b/lib/squib/args/showcase_special.rb @@ -0,0 +1,37 @@ +require 'cairo' +require 'squib/args/arg_loader' + +module Squib + # @api private + module Args + + class ShowcaseSpecial + include ArgLoader + include DirValidator + + def self.parameters + { scale: 0.85, + offset: 1.1, + reflect_offset: 15, + reflect_percent: 0.25, + reflect_strength: 0.2, + face: :left, + } + end + + def self.expanding_parameters + [] # none of them + end + + def self.params_with_units + [ :reflect_offset ] + end + + def face_right? + @face.to_s.strip.downcase == 'right' + end + + end + + end +end diff --git a/lib/squib/graphics/showcase.rb b/lib/squib/graphics/showcase.rb index 491d22e..c7b04b6 100644 --- a/lib/squib/graphics/showcase.rb +++ b/lib/squib/graphics/showcase.rb @@ -11,26 +11,23 @@ module Squib # http://zetcode.com/gui/pygtk/drawingII/ # :nodoc: # @api private - def render_showcase(range, - trim, trim_radius, scale, offset, fill_color, - reflect_offset, reflect_percent, reflect_strength, margin, face_right, - dir, file_to_save) - out_width = range.size * ((@width - 2*trim) * scale * offset) + 2*margin - out_height = reflect_offset + (1.0 + reflect_percent) * (@height - 2*trim) + 2*margin + def render_showcase(range, sheet, showcase) + out_width = range.size * ((@width - 2*sheet.trim) * showcase.scale * showcase.offset) + 2*sheet.margin + out_height = showcase.reflect_offset + (1.0 + showcase.reflect_percent) * (@height - 2*sheet.trim) + 2*sheet.margin out_cc = Cairo::Context.new(Cairo::ImageSurface.new(out_width, out_height)) wrapper = Squib::Graphics::CairoContextWrapper.new(out_cc) - wrapper.set_source_squibcolor(fill_color) + wrapper.set_source_squibcolor(sheet.fill_color) wrapper.paint cards = range.collect { |i| @cards[i] } cards.each_with_index do |card, i| - trimmed = trim_rounded(card.cairo_surface, trim, trim_radius) - reflected = reflect(trimmed, reflect_offset, reflect_percent, reflect_strength) - perspectived = perspective(reflected, scale, face_right) - out_cc.set_source(perspectived, margin + i * perspectived.width * offset, margin) + trimmed = trim_rounded(card.cairo_surface, sheet.trim, sheet.trim_radius) + reflected = reflect(trimmed, showcase.reflect_offset, showcase.reflect_percent, showcase.reflect_strength) + perspectived = perspective(reflected, showcase.scale, showcase.face_right?) + out_cc.set_source(perspectived, sheet.margin + i * perspectived.width * showcase.offset, sheet.margin) out_cc.paint end - out_cc.target.write_to_png("#{dir}/#{file_to_save}") + out_cc.target.write_to_png("#{sheet.dir}/#{sheet.file}") end # :nodoc: @@ -85,4 +82,4 @@ module Squib end end -end \ No newline at end of file +end diff --git a/spec/args/sheet_spec.rb b/spec/args/sheet_spec.rb new file mode 100644 index 0000000..ea0202a --- /dev/null +++ b/spec/args/sheet_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' +require 'squib/args/sheet' + +describe Squib::Args::Sheet do + + context 'dsl overrides' do + subject(:sheet) { Squib::Args::Sheet.new({}, {file: 'foo'}) } + + it 'works when specified' do + sheet.load!({}) # go right to defaults + expect(sheet.file).to eq( 'foo' ) # dsl method default override + end + + end + +end diff --git a/spec/args/showcase_special_spec.rb b/spec/args/showcase_special_spec.rb new file mode 100644 index 0000000..a95db4b --- /dev/null +++ b/spec/args/showcase_special_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' +require 'squib/args/showcase_special' + +describe Squib::Args::ShowcaseSpecial do + subject(:showcase_special) { Squib::Args::ShowcaseSpecial.new } + + context '#face_right?' do + it 'compares face to right' do + opts = { face: 'LEFT ' } + showcase_special.load! opts + expect(showcase_special.face_right?).to be false + end + end + +end diff --git a/spec/data/samples/showcase.rb.txt b/spec/data/samples/showcase.rb.txt index b384923..a437681 100644 --- a/spec/data/samples/showcase.rb.txt +++ b/spec/data/samples/showcase.rb.txt @@ -154,7 +154,7 @@ cairo: rotate([0]) cairo: scale([3.90625, 3.90625]) cairo: render_rsvg_handle([RSVG::Handle, nil]) cairo: restore([]) -cairo: set_source_color([:white]) +cairo: set_source_color(["white"]) cairo: paint([]) cairo: rounded_rectangle([0, 0, 100, 101, 38, 38]) cairo: set_source([MockDouble, 0, 0]) @@ -3029,7 +3029,7 @@ cairo: restore([]) cairo: set_source([MockDouble, 405.0, 75]) cairo: paint([]) surface: write_to_png(["_output/showcase.png"]) -cairo: set_source_color([:black]) +cairo: set_source_color(["black"]) cairo: paint([]) cairo: rounded_rectangle([0, 0, 100, 101, 32, 32]) cairo: set_source([MockDouble, -32, -32])