Employing the new args refactoring on all shapes

This commit is contained in:
Andy Meneely
2015-06-11 16:16:08 -04:00
parent 8a7841d64f
commit c5e00f1877
26 changed files with 505 additions and 189 deletions
+48 -57
View File
@@ -1,5 +1,10 @@
require 'squib/args/box'
require 'squib/args/draw'
require 'squib/args/card_range'
require 'squib/args/tri'
require 'squib/args/bezier'
require 'squib/args/polygon'
require 'squib/args/transform'
module Squib
class Deck
@@ -28,13 +33,10 @@ module Squib
# @return [nil] intended to be void
# @api public
def rect(opts = {})
opts = needs(opts, [:range, :rect_radius, :x_radius, :y_radius,
:fill_color, :stroke_color, :stroke_width, :layout])
box = Args::Box.new(self).load!(opts, expand_by: size, layout: layout, dpi: dpi)
draw = Args::Draw.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
opts[:range].each do |i|
@cards[i].rect(box[i], draw[i])
end
range = Args::CardRange.new(opts[:range], deck_size: size)
box = Args::Box.new(self).load!(opts, expand_by: size, layout: layout, dpi: dpi)
draw = Args::Draw.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
range.each { |i| @cards[i].rect(box[i], draw[i]) }
end
# Draw a circle centered at the given coordinates
@@ -51,17 +53,16 @@ module Squib
# @option opts fill_color [String] ('#0000') the color with which to fill the rectangle. See {file:README.md#Specifying_Colors___Gradients Specifying Colors & Gradients}.
# @option opts stroke_color [String] (:black) the color with which to stroke the outside of the rectangle. 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 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}
# @return [nil] intended to be void
# @api public
def circle(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|
@cards[i].circle(opts[:x][i], opts[:y][i], opts[:radius][i],
opts[:fill_color][i], opts[:stroke_color][i], opts[:stroke_width][i])
end
range = Args::CardRange.new(opts[:range], deck_size: size)
opts = {radius: 100}.merge(opts) # overriding the non-system default
box = Args::Box.new(self).load!(opts, expand_by: size, layout: layout, dpi: dpi)
draw = Args::Draw.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
range.each { |i| @cards[i].circle(box[i], draw[i]) }
end
# Draw an ellipse
@@ -79,17 +80,15 @@ module Squib
# @option opts fill_color [String] ('#0000') the color with which to fill the rectangle. See {file:README.md#Specifying_Colors___Gradients Specifying Colors & Gradients}
# @option opts stroke_color [String] (:black) the color with which to stroke the outside of the rectangle. {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 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}
# @return [nil] intended to be void
# @api public
def ellipse(opts = {})
opts = needs(opts, [:range, :x, :y, :width, :height,
:fill_color, :stroke_color, :stroke_width, :layout])
opts[:range].each do |i|
@cards[i].ellipse(opts[:x][i], opts[:y][i], opts[:width][i], opts[:height][i],
opts[:fill_color][i], opts[:stroke_color][i],
opts[:stroke_width][i])
end
range = Args::CardRange.new(opts[:range], deck_size: size)
draw = Args::Draw.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
box = Args::Box.new(self).load!(opts, expand_by: size, layout: layout, dpi: dpi)
range.each { |i| @cards[i].ellipse(box[i], draw[i]) }
end
# Draw a triangle using the given coordinates
@@ -109,19 +108,15 @@ module Squib
# @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 stroke_color [String] (:black) the color with which to stroke the outside of the triangle. 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 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}
# @return [nil] intended to be void
# @api public
def triangle(opts = {})
opts = needs(opts, [:range, :x1, :y1, :x2, :y2, :x3, :y3, :layout,
:fill_color, :stroke_color, :stroke_width])
opts[:range].each do |i|
@cards[i].triangle(opts[:x1][i], opts[:y1][i],
opts[:x2][i], opts[:y2][i],
opts[:x3][i], opts[:y3][i],
opts[:fill_color][i], opts[:stroke_color][i],
opts[:stroke_width][i])
end
range = Args::CardRange.new(opts[:range], deck_size: size)
draw = Args::Draw.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
tri = Args::Tri.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
range.each { |i| @cards[i].triangle(tri[i], draw[i]) }
end
# Draw a line using the given coordinates
@@ -136,16 +131,16 @@ module Squib
# @option opts y2 [Integer] (50) the y-coordinate to place. Supports Unit Conversion, see {file:README.md#Units Units}.
# @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 cap [String] ('butt') how the end of the line is drawn. Options are "square", "butt", and "round"
# @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}
# @return [nil] intended to be void
# @api public
def line(opts = {})
opts = needs(opts, [:range, :x1, :y1, :x2, :y2, :layout,
:stroke_color, :stroke_width])
opts[:range].each do |i|
@cards[i].line(opts[:x1][i], opts[:y1][i], opts[:x2][i], opts[:y2][i],
opts[:stroke_color][i], opts[:stroke_width][i])
end
range = Args::CardRange.new(opts[:range], deck_size: size)
draw = Args::Draw.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
bezier = Args::Bezier.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
range.each { |i| @cards[i].line(bezier[i], draw[i]) }
end
# Draw a curve using the given coordinates
@@ -163,18 +158,15 @@ module Squib
# @option opts stroke_width [Decimal] (2.0) the width of the outside stroke. Supports Unit Conversion, see {file:README.md#Units Units}.
# @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 cap [String] ('butt') how the end of the line is drawn. Options are "square", "butt", and "round"
# @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}
# @return [nil] intended to be void
# @api public
def curve(opts = {})
opts = needs(opts, [:range, :x1, :y1, :cx1, :cy1, :x2, :y2, :cx2, :cy2,
:layout, :fill_color, :stroke_color, :stroke_width])
range = Args::CardRange.new(opts[:range], deck_size: size)
draw = Args::Draw.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
opts[:range].each do |i|
@cards[i].curve(opts[:x1][i], opts[:y1][i], opts[:cx1][i], opts[:cy1][i],
opts[:x2][i], opts[:y2][i], opts[:cx2][i], opts[:cy2][i],
draw[i])
end
bezier = Args::Bezier.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
range.each { |i| @cards[i].curve(bezier[i], draw[i]) }
end
# Draw a star at the given x,y
@@ -191,18 +183,16 @@ module Squib
# @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 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}
# @return [nil] intended to be void
# @api public
def star(opts = {})
opts = needs(opts, [:range, :x, :y, :n, :angle, :inner_radius, :outer_radius,
:layout, :fill_color, :stroke_color, :stroke_width])
opts[:range].each do |i|
@cards[i].star(opts[:x][i], opts[:y][i], opts[:n][i], opts[:angle][i],
opts[:inner_radius][i], opts[:outer_radius][i],
opts[:fill_color][i], opts[:stroke_color][i],
opts[:stroke_width][i])
end
range = Args::CardRange.new(opts[:range], deck_size: size)
draw = Args::Draw.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
poly = Args::Polygon.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
trans = Args::Transform.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
range.each { |i| @cards[i].star(poly[i], trans[i], draw[i]) }
end
# Draw a regular polygon at the given x,y
@@ -215,19 +205,20 @@ module Squib
# @option opts y [Fixnum] (0) the y-coordinate of the center. Supports Unit Conversion, see {file:README.md#Units Units}.
# @option opts n [Integer] (5) the number of points on the star
# @option opts angle [Fixnum] (0) the angle at which to rotate
# @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 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}
# @return [nil] intended to be void
# @api public
def polygon(opts = {})
opts = needs(opts, [:range, :x, :y, :n, :circle_radius, :angle, :layout, :fill_color, :stroke_color, :stroke_width])
opts[:range].each do |i|
@cards[i].polygon(opts[:x][i], opts[:y][i], opts[:n][i], opts[:angle][i], opts[:radius][i],
opts[:fill_color][i], opts[:stroke_color][i],
opts[:stroke_width][i])
end
range = Args::CardRange.new(opts[:range], deck_size: size)
draw = Args::Draw.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
poly = Args::Polygon.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
trans = Args::Transform.new.load!(opts, expand_by: size, layout: layout, dpi: dpi)
range.each { |i| @cards[i].polygon(poly[i], trans[i], draw[i]) }
end
end
+2 -2
View File
@@ -65,7 +65,7 @@ module Squib
val = instance_variable_get(attribute)
if val.respond_to? :each
new_val = val.map.with_index do |v, i|
v ||= layout[layout_args[i]][param] unless layout_args[i].nil?
v ||= layout[layout_args[i].to_s][param] unless layout_args[i].nil?
v ||= default
end
instance_variable_set(attribute, new_val)
@@ -78,7 +78,7 @@ module Squib
# For each parameter/attribute foo we try to invoke a validate_foo
def validate
self.class.parameters.each do |param, default|
method = "validate_#{param}"
method = "validate_#{param}"
if self.respond_to? method
attribute = "@#{param}"
val = instance_variable_get(attribute)
+28
View File
@@ -0,0 +1,28 @@
require 'squib/args/arg_loader'
module Squib
# @api private
module Args
class Bezier
include ArgLoader
def self.parameters
{ x1: 100, y1: 100,
cx1: 0 , cy1: 0,
x2: 150, y2: 150,
cx2: 0 , cy2: 0}
end
def self.expanding_parameters
parameters.keys # all of them
end
def self.params_with_units
parameters.keys # all of them
end
end
end
end
+28
View File
@@ -0,0 +1,28 @@
module Squib
# @api private
module Args
class CardRange
include Enumerable
def initialize(input, deck_size: 1)
@range = validate(input, deck_size)
end
# Hook into enumerable by delegating to @range
def each(&block)
@range.each { |i| block.call(i) }
end
private
def validate(input, deck_size)
input ||= :all # default
input = 0..(deck_size - 1) if input == :all
input = (input.to_i)..(input.to_i) if input.respond_to? :to_i
raise ArgumentError.new("#{input} must be Enumerable (i.e. respond_to :each).") unless input.respond_to? :each
raise ArgumentError.new("#{input} is outside of deck range of 0..#{deck_size-1}") if input.max > (deck_size - 1)
input
end
end
end
end
+26
View File
@@ -0,0 +1,26 @@
require 'squib/args/arg_loader'
module Squib
# @api private
module Args
class Polygon
include ArgLoader
def self.parameters
{ x: 0, y: 0, n: 5,
radius: 100, inner_radius: 50, outer_radius: 100}
end
def self.expanding_parameters
parameters.keys # all of them
end
def self.params_with_units
parameters.keys # all of them
end
end
end
end
+25
View File
@@ -0,0 +1,25 @@
require 'squib/args/arg_loader'
module Squib
# @api private
module Args
class Transform
include ArgLoader
def self.parameters
{ angle: 0 }
end
def self.expanding_parameters
parameters.keys # all of them
end
def self.params_with_units
parameters.keys # all of them
end
end
end
end
+27
View File
@@ -0,0 +1,27 @@
require 'squib/args/arg_loader'
module Squib
# @api private
module Args
class Tri
include ArgLoader
def self.parameters
{ x1: 100, y1: 100,
x2: 150, y2: 150,
x3: 100, y3: 150 }
end
def self.expanding_parameters
parameters.keys # all of them
end
def self.params_with_units
parameters.keys # all of them
end
end
end
end
+13 -9
View File
@@ -52,19 +52,23 @@ module Squib
# Convenience method for a common task
# @api private
def fill_n_stroke(fill_color, stroke_color, stroke_width,
line_join = 0, line_cap = Cairo::LINE_CAP_BUTT,
dash = [])
set_source_squibcolor(fill_color)
def fill_n_stroke(draw)
set_source_squibcolor draw.fill_color
fill_preserve
set_source_squibcolor(stroke_color)
set_line_width(stroke_width)
set_line_join(line_join)
set_line_cap(line_cap)
set_dash(dash)
set_source_squibcolor draw.stroke_color
set_line_width draw.stroke_width
set_line_join draw.join
set_line_cap draw.cap
set_dash draw.dash
stroke
end
def rotate_about(x, y, angle)
translate(x, y)
rotate(angle)
translate(-x, -y)
end
end
end
end
+38 -34
View File
@@ -7,17 +7,18 @@ module Squib
def rect(box, draw)
use_cairo do |cc|
cc.rounded_rectangle(box.x, box.y, box.width, box.height, box.x_radius, box.y_radius)
cc.fill_n_stroke(draw.fill_color, draw.stroke_color, draw.stroke_width, draw.join, draw.cap, draw.dash)
cc.fill_n_stroke(draw)
end
end
# :nodoc:
# @api private
def circle(x, y, radius, fill_color, stroke_color, stroke_width)
def circle(box, draw)
x, y, r = box.x, box.y, box.radius
use_cairo do |cc|
cc.move_to(x + radius, y)
cc.circle(x, y, radius)
cc.fill_n_stroke(fill_color, stroke_color, stroke_width)
cc.move_to(x + r, y)
cc.circle(x, y, r)
cc.fill_n_stroke(draw)
end
end
@@ -26,7 +27,8 @@ module Squib
# of the rectangle. Control points are at 1/4 and 3/4 of the side.
# :nodoc:
# @api private
def ellipse(x, y, w, h, fill_color, stroke_color, stroke_width)
def ellipse(box, draw)
x, y, w, h = box.x, box.y, box.width, box.height
use_cairo do |cc|
cc.move_to(x, y + 0.5*h) # start west
cc.curve_to(x, y + 0.25*h, # west to north
@@ -41,67 +43,68 @@ module Squib
cc.curve_to(x + 0.25*w, y + h, # south to west
x, y + 0.75*h,
x, y + 0.5*h)
cc.fill_n_stroke(fill_color, stroke_color, stroke_width)
cc.fill_n_stroke(draw)
end
end
# :nodoc:
# @api private
def triangle(x1, y1, x2, y2, x3, y3, fill_color, stroke_color, stroke_width)
def triangle(tri, draw)
use_cairo do |cc|
cc.triangle(x1, y1, x2, y2, x3, y3)
cc.fill_n_stroke(fill_color, stroke_color, stroke_width)
cc.triangle(tri.x1, tri.y1, tri.x2, tri.y2, tri.x3, tri.y3)
cc.fill_n_stroke(draw)
end
end
# :nodoc:
# @api private
def line(x1, y1, x2, y2, stroke_color, stroke_width)
def line(coord, draw)
use_cairo do |cc|
cc.move_to(x1, y1)
cc.line_to(x2, y2)
cc.set_source_squibcolor(stroke_color)
cc.set_line_width(stroke_width)
cc.stroke
cc.move_to(coord.x1, coord.y1)
cc.line_to(coord.x2, coord.y2)
cc.fill_n_stroke(draw)
end
end
# :nodoc:
# @api private
def curve(x1, y1, cx1, cy1, x2, y2, cx2, cy2, draw)
def curve(bez, draw)
x1, y1, cx1, cy1 = bez.x1, bez.y1, bez.cx1, bez.cy1
cx2, cy2, x2, y2 = bez.cx2, bez.cy2, bez.x2, bez.y2
use_cairo do |cc|
cc.move_to(x1, y1)
cc.curve_to(cx1, cy1, cx2, cy2, x2, y2)
cc.fill_n_stroke(draw.fill_color, draw.stroke_color, draw.stroke_width, draw.join, draw.cap)
cc.fill_n_stroke(draw)
end
end
# :nodoc:
# @api private
def star(x, y, n, angle, inner_radius, outer_radius, fill_color, stroke_color, stroke_width)
def star(poly, trans, draw)
x, y, n = poly.x, poly.y, poly.n
inner_radius, outer_radius = poly.inner_radius, poly.outer_radius
use_cairo do |cc|
cc.translate(x, y)
cc.rotate(angle)
cc.translate(-x, -y)
cc.move_to(x + outer_radius, y) #i = 0, so cos(0)=1 and sin(0)=0
theta = Math::PI / n.to_f # i.e. (2*pi) / (2*n)
0.upto(2 * n) do |i|
radius = i.even? ? outer_radius : inner_radius
cc.line_to(x + radius * Math::cos(i * theta),
y + radius * Math::sin(i * theta))
poly.instance_eval do
cc.rotate_about(x, y, trans.angle)
cc.move_to(x + outer_radius, y) #i = 0, so cos(0)=1 and sin(0)=0
theta = Math::PI / n.to_f # i.e. (2*pi) / (2*n)
0.upto(2 * n) do |i|
radius = i.even? ? outer_radius : inner_radius
cc.line_to(x + radius * Math::cos(i * theta),
y + radius * Math::sin(i * theta))
end
end
cc.close_path
cc.fill_n_stroke(fill_color, stroke_color, stroke_width)
cc.fill_n_stroke(draw)
end
end
# :nodoc:
# @api private
def polygon(x, y, n, angle, radius, fill_color, stroke_color, stroke_width)
def polygon(poly, trans, draw)
x, y, n, radius = poly.x, poly.y, poly.n, poly.radius
use_cairo do |cc|
cc.translate(x, y)
cc.rotate(angle)
cc.translate(-x, -y)
cc.rotate_about(x, y, trans.angle)
cc.move_to(x + radius, y) # i = 0, so cos(0)=1 and sin(0)=0
theta = (2 * Math::PI) / n.to_f
0.upto(n) do |i|
@@ -109,9 +112,10 @@ module Squib
y + radius * Math::sin(i * theta))
end
cc.close_path
cc.fill_n_stroke(fill_color, stroke_color, stroke_width)
cc.fill_n_stroke(draw)
end
end
end
end