Image rotation support for png and svg commands
With unit tests and other refactoringsdev
parent
bb1befc22b
commit
d4f0105785
|
|
@ -15,14 +15,16 @@ module Squib
|
|||
# @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}. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
|
||||
# @option opts alpha [Decimal] (1.0) the alpha-transparency percentage used to blend this image. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
|
||||
# @option opts blend [:none, :multiply, :screen, :overlay, :darken, :lighten, :color_dodge, :color_burn, :hard_light, :soft_light, :difference, :exclusion, :hsl_hue, :hsl_saturation, :hsl_color, :hsl_luminosity] (:none) the composite blend operator used when applying this image. See Blend Modes at http://cairographics.org/operators. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
|
||||
# @option opts angle [FixNum] (0) Rotation of the in radians. Note that this rotates around the upper-left corner, making the placement of x-y coordinates slightly tricky. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
|
||||
# @return [nil] Returns nil
|
||||
# @api public
|
||||
def png(opts = {})
|
||||
opts = needs(opts, [:range, :files, :x, :y, :alpha, :layout, :blend])
|
||||
opts = needs(opts, [:range, :files, :x, :y, :alpha, :layout, :blend, :angle])
|
||||
Dir.chdir(@img_dir) do
|
||||
@progress_bar.start('Loading PNG(s)', opts[:range].size) do |bar|
|
||||
opts[:range].each do |i|
|
||||
@cards[i].png(opts[:file][i], opts[:x][i], opts[:y][i], opts[:alpha][i], opts[:blend][i])
|
||||
@cards[i].png(opts[:file][i], opts[:x][i], opts[:y][i],
|
||||
opts[:alpha][i], opts[:blend][i], opts[:angle][i])
|
||||
bar.increment
|
||||
end
|
||||
end
|
||||
|
|
@ -46,16 +48,17 @@ module Squib
|
|||
# @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}. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
|
||||
# @option opts alpha [Decimal] (1.0) the alpha-transparency percentage used to blend this image. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
|
||||
# @option opts blend [:none, :multiply, :screen, :overlay, :darken, :lighten, :color_dodge, :color_burn, :hard_light, :soft_light, :difference, :exclusion, :hsl_hue, :hsl_saturation, :hsl_color, :hsl_luminosity] (:none) the composite blend operator used when applying this image. See Blend Modes at http://cairographics.org/operators. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
|
||||
# @option opts angle [FixNum] (0) Rotation of the in radians. Note that this rotates around the upper-left corner, making the placement of x-y coordinates slightly tricky. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
|
||||
# @return [nil] Returns nil
|
||||
# @api public
|
||||
def svg(opts = {})
|
||||
p = needs(opts,[:range, :files, :svgid, :force_svgid, :x, :y, :width, :height, :layout, :alpha, :blend])
|
||||
p = needs(opts,[:range, :files, :svgid, :force_svgid, :x, :y, :width, :height, :layout, :alpha, :blend, :angle])
|
||||
Dir.chdir(@img_dir) do
|
||||
@progress_bar.start('Loading SVG(s)', p[:range].size) do |bar|
|
||||
p[:range].each do |i|
|
||||
unless p[:force_id][i] && p[:id][i].to_s.empty?
|
||||
@cards[i].svg(p[:file][i], p[:id][i], p[:x][i], p[:y][i],
|
||||
p[:width][i], p[:height][i], p[:alpha][i], p[:blend][i])
|
||||
p[:width][i], p[:height][i], p[:alpha][i], p[:blend][i], p[:angle][i])
|
||||
end
|
||||
bar.increment
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,10 +14,14 @@ module Squib
|
|||
|
||||
# :nodoc:
|
||||
# @api private
|
||||
def png(file, x, y, alpha, blend)
|
||||
def png(file, x, y, alpha, blend, angle)
|
||||
Squib.logger.debug {"Rendering: #{file} @#{x},#{y} #{width}x#{height}, alpha: #{alpha}, blend: #{blend}, angle: #{angle}"}
|
||||
return if file.nil? or file.eql? ''
|
||||
png = Squib.cache_load_image(file)
|
||||
use_cairo do |cc|
|
||||
cc.translate(x, y)
|
||||
cc.rotate(angle)
|
||||
cc.translate(-1 * x, -1 * y)
|
||||
cc.set_source(png, x, y)
|
||||
cc.operator = blend unless blend == :none
|
||||
cc.paint(alpha)
|
||||
|
|
@ -26,8 +30,8 @@ module Squib
|
|||
|
||||
# :nodoc:
|
||||
# @api private
|
||||
def svg(file, id, x, y, width, height, alpha, blend)
|
||||
Squib.logger.debug {"Rendering: #{file}, #{id} #{x}, #{y}, #{width}, #{height}, #{alpha}, #{blend}"}
|
||||
def svg(file, id, x, y, width, height, alpha, blend, angle)
|
||||
Squib.logger.debug {"Rendering: #{file}, id: #{id} @#{x},#{y} #{width}x#{height}, alpha: #{alpha}, blend: #{blend}, angle: #{angle}"}
|
||||
return if file.nil? or file.eql? ''
|
||||
svg = RSVG::Handle.new_from_file(file)
|
||||
width = svg.width if width == :native
|
||||
|
|
@ -37,6 +41,9 @@ module Squib
|
|||
tmp_cc.scale(width.to_f / svg.width.to_f, height.to_f / svg.height.to_f)
|
||||
tmp_cc.render_rsvg_handle(svg, id)
|
||||
use_cairo do |cc|
|
||||
cc.translate(x, y)
|
||||
cc.rotate(angle)
|
||||
cc.translate(-1 * x, -1 * y)
|
||||
cc.set_source(tmp, x, y)
|
||||
cc.operator = blend unless blend == :none
|
||||
cc.paint(alpha)
|
||||
|
|
|
|||
|
|
@ -25,5 +25,10 @@ Squib::Deck.new(width: 825, height: 1125, cards: 1) do
|
|||
png file: 'ball.png', x: 50, y: 700
|
||||
png file: 'grit.png', x: 70, y: 750, blend: :color_burn, alpha: 0.75
|
||||
|
||||
# Images can be rotated around their upper-left corner
|
||||
png file: 'shiny-purse.png', x: 300, y: 700, angle: 0.0 # default (no rotate)
|
||||
png file: 'shiny-purse.png', x: 300, y: 800, angle: Math::PI / 4
|
||||
svg file: 'spanner.svg', x: 300, y: 900, angle: Math::PI / 2 - 0.1
|
||||
|
||||
save prefix: 'load_images_', format: :png
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
require 'spec_helper'
|
||||
require 'squib'
|
||||
|
||||
describe Squib::Card do
|
||||
|
||||
before(:each) do
|
||||
@deck = double(Squib::Deck)
|
||||
@context = double(Cairo::Context)
|
||||
@svg = double(RSVG::Handle)
|
||||
allow(Cairo::Context).to receive(:new).and_return(@context)
|
||||
allow(Cairo::ImageSurface).to receive(:from_png).and_return(nil)
|
||||
allow(Cairo::ImageSurface).to receive(:new).and_return(nil)
|
||||
allow(RSVG::Handle).to receive(:new_from_file).and_return(@svg)
|
||||
end
|
||||
|
||||
context '#png' do
|
||||
it 'makes all the expected calls on a smoke test' do
|
||||
expect(@context).to receive(:save).once
|
||||
expect(@context).to receive(:translate).with(-37, -38).once
|
||||
expect(@context).to receive(:rotate).with(0.0).once
|
||||
expect(@context).to receive(:translate).with(37, 38).once
|
||||
expect(@context).to receive(:set_source).with(nil, 37, 38).once
|
||||
expect(@context).to receive(:paint).with(0.9).once
|
||||
expect(@context).to receive(:restore).once
|
||||
|
||||
card = Squib::Card.new(@deck, 100, 150)
|
||||
# png(file, x, y, alpha, blend, angle)
|
||||
card.png('foo.png', 37, 38, 0.9, :none, 0.0)
|
||||
end
|
||||
|
||||
it 'sets blend when needed' do
|
||||
@context.as_null_object
|
||||
expect(@context).to receive(:operator=).with(:overlay).once
|
||||
|
||||
card = Squib::Card.new(@deck, 100, 150)
|
||||
card.png('foo.png', 37, 38, 0.9, :overlay, 0.0)
|
||||
end
|
||||
end
|
||||
|
||||
context '#svg' do
|
||||
it 'makes all the expected calls on a smoke test' do
|
||||
expect(@svg).to receive(:width).and_return(100).twice
|
||||
expect(@svg).to receive(:height).and_return(100).twice
|
||||
expect(@context).to receive(:save).once
|
||||
expect(@context).to receive(:translate).with(-37, -38).once
|
||||
expect(@context).to receive(:rotate).with(0.0).once
|
||||
expect(@context).to receive(:translate).with(37, 38).once
|
||||
expect(@context).to receive(:scale).with(1.0, 1.0).once
|
||||
expect(@context).to receive(:render_rsvg_handle).with(@svg, 'id').once
|
||||
expect(@context).to receive(:set_source).with(nil, 37, 38).once
|
||||
expect(@context).to receive(:paint).with(0.9).once
|
||||
expect(@context).to receive(:restore).once
|
||||
|
||||
card = Squib::Card.new(@deck, 100, 150)
|
||||
# svg(file, id, x, y, width, height, alpha, blend, angle)
|
||||
card.svg('foo.png', 'id', 37, 38, :native, :native, 0.9, :none, 0.0)
|
||||
end
|
||||
|
||||
it 'sets blend when needed' do
|
||||
@context.as_null_object
|
||||
@svg.as_null_object
|
||||
expect(@context).to receive(:operator=).with(:overlay).once
|
||||
|
||||
card = Squib::Card.new(@deck, 100, 150)
|
||||
card.svg('foo.png', nil, 37, 38, :native, :native, 0.9, :overlay, 0.0)
|
||||
end
|
||||
|
||||
it 'sets width & height when needed' do
|
||||
@context.as_null_object
|
||||
expect(@svg).to receive(:width).and_return(100).once
|
||||
expect(@svg).to receive(:height).and_return(100).once
|
||||
expect(@context).to receive(:scale).with(2.0, 3.0).once
|
||||
|
||||
card = Squib::Card.new(@deck, 100, 150)
|
||||
card.svg('foo.png', nil, 37, 38, 200, 300, 0.9, :none, 0.0)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
Loading…
Reference in New Issue