lib/squib/graphics/save_images.rb in squib-0.16.0 vs lib/squib/graphics/save_images.rb in squib-0.17.0
- old
+ new
@@ -1,52 +1,91 @@
+require_relative 'cairo_context_wrapper'
+
module Squib
class Card
# :nodoc:
# @api private
- def save_png(batch)
- surface = if preprocess_save?(batch)
+ def save_png(batch, shadow)
+ surface = if preprocess_save?(batch, shadow)
w, h = compute_dimensions(batch.rotate, batch.trim)
- preprocessed_save(w, h, batch)
+ preprocessed_save(w, h, batch, shadow)
else
@cairo_surface
end
write_png(surface, index, batch)
end
# :nodoc:
# @api private
- def preprocess_save?(batch)
- batch.rotate != false || batch.trim > 0
+ def preprocess_save?(batch, shadow)
+ batch.rotate != false || batch.trim > 0 || !(shadow.shadow_radius.nil?)
end
def compute_dimensions(rotate, trim)
if rotate
[ @height - 2 * trim, @width - 2 * trim ]
else
[ @width - 2 * trim, @height - 2 * trim ]
end
end
- def preprocessed_save(width, height, batch)
- new_cc = Cairo::Context.new(Cairo::ImageSurface.new(width, height))
+ def preprocessed_save(w, h, batch, shadow)
+ new_cc = Cairo::Context.new(Cairo::ImageSurface.new(w, h))
trim_radius = batch.trim_radius
if batch.rotate != false
- new_cc.translate(width * 0.5, height * 0.5)
- new_cc.rotate(batch.angle)
- new_cc.translate(height * -0.5, width * -0.5)
- new_cc.rounded_rectangle(0, 0, height, width, trim_radius, trim_radius)
+ new_cc.translate w * 0.5, h * 0.5
+ new_cc.rotate batch.angle
+ new_cc.translate h * -0.5, w * -0.5
+ new_cc.rounded_rectangle(0, 0, h, w, trim_radius, trim_radius)
else
- new_cc.rounded_rectangle(0, 0, width, height, trim_radius, trim_radius)
+ new_cc.rounded_rectangle(0, 0, w, h, trim_radius, trim_radius)
end
new_cc.clip
new_cc.set_source(@cairo_surface, -batch.trim, -batch.trim)
new_cc.paint
+ new_cc.reset_clip
+ new_cc = drop_shadow(new_cc, shadow, batch) unless shadow.shadow_radius.nil?
return new_cc.target
end
+ # pseudo-blur behave weirdly with a radius of 0 - wrapping
+ def blur(cc, r, &block)
+ if r == 0
+ yield(block)
+ else
+ cc.pseudo_blur(r, &block)
+ end
+ end
+
+ def drop_shadow(cc, s, batch)
+ off_x = s.shadow_offset_x
+ off_y = s.shadow_offset_y
+ s_trim = s.shadow_trim
+ s_rad = s.shadow_radius
+ new_w = cc.target.width + off_x + 3 * s_rad - (2 * s_trim)
+ new_h = cc.target.height + off_y + 3 * s_rad - (2 * s_trim)
+ new_cc = Squib::Graphics::CairoContextWrapper.new(
+ Cairo::Context.new(Cairo::ImageSurface.new(new_w, new_h)))
+ blur(new_cc, s_rad) do
+ # fill in with shadow color
+ new_cc.set_source_squibcolor s.shadow_color
+ new_cc.rectangle 0, 0, new_cc.target.width, new_cc.target.height
+ new_cc.fill
+ # then, paint but blend with :dest_in to get a shadow-shaped drawing
+ new_cc.set_source cc.target, s_rad + off_x, s_rad + off_y
+ new_cc.operator = :dest_in # see https://www.cairographics.org/operators/
+ new_cc.paint
+ end
+ new_cc.set_source cc.target, s_rad, s_rad
+ new_cc.operator = :over
+ new_cc.paint
+ return new_cc
+ end
+
def write_png(surface, i, b)
- surface.write_to_png("#{b.dir}/#{b.prefix}#{b.count_format % i}#{b.suffix}.png")
+ filename = "#{b.dir}/#{b.prefix}#{b.count_format % i}#{b.suffix}.png"
+ surface.write_to_png filename
end
end
end