6 changed files with 97 additions and 56 deletions
@ -1 +1,41 @@
|
||||
hand.rb |
||||
module Squib |
||||
class Deck |
||||
|
||||
# Draw cards in a fan. |
||||
# @api private |
||||
def render_hand(range, radius, angle_range, trim, trim_radius, margin, |
||||
fill_color, dir, file) |
||||
cards = range.collect { |i| @cards[i] } |
||||
center_x = width / 2.0 |
||||
center_y = radius + height |
||||
out_size = 3.0 * center_y |
||||
angle_delta = (angle_range.last - angle_range.first) / cards.size |
||||
cxt = Cairo::Context.new(Cairo::RecordingSurface.new(0, 0, out_size, out_size)) |
||||
cxt.translate(out_size / 2.0, out_size / 2.0) |
||||
cxt.rotate(angle_range.first) |
||||
cxt.translate(-width, -width) |
||||
cards.each_with_index do |card, i| |
||||
cxt.translate(center_x, center_y) |
||||
cxt.rotate(angle_delta) |
||||
cxt.translate(-center_x, -center_y) |
||||
card.use_cairo do |card_cxt| |
||||
cxt.rounded_rectangle(trim, trim, |
||||
width - (2 * trim), height - (2 * trim), |
||||
trim_radius, trim_radius) |
||||
cxt.clip |
||||
cxt.set_source(card_cxt.target) |
||||
cxt.paint |
||||
cxt.reset_clip |
||||
end |
||||
end |
||||
x, y, w, h = cxt.target.ink_extents # I love Ruby assignment ;) |
||||
png_cxt = Cairo::Context.new(Cairo::ImageSurface.new(w + 2*margin, h + 2*margin)) |
||||
png_cxt.set_source_color(fill_color) |
||||
png_cxt.paint |
||||
png_cxt.translate(-x + margin, -y + margin) |
||||
png_cxt.set_source(cxt.target) |
||||
png_cxt.paint |
||||
png_cxt.target.write_to_png("#{dir}/#{file}") |
||||
end |
||||
end |
||||
end |
||||
|
||||
@ -1,45 +1,21 @@
|
||||
require 'squib' |
||||
|
||||
# Built-in layouts are easy to use and extend |
||||
Squib::Deck.new(cards: 8, layout: 'playing-card.yml') do |
||||
background color: :white |
||||
background color: :cyan |
||||
rect x: 37, y: 37, width: 750, height: 1050, fill_color: :black, radius: 25 |
||||
rect x: 75, y: 75, width: 675, height: 975, fill_color: :white, radius: 20 |
||||
text str: ('A'..'H').to_a, layout: :bonus_ul, font: 'Sans bold 100' |
||||
# hand range: :all, |
||||
# center_x: :auto, center_y: :auto, |
||||
# angle_start: 0, angle_end: Math::PI, |
||||
# width: :auto, height: :auto |
||||
# save_png prefix: 'hand_' |
||||
# |
||||
# Here's the hacky version |
||||
# So much hardcoded magic to get this to work. Math is hard. |
||||
# Idea: getting the final image surface extents is hard math for me. Maybe |
||||
# just put it on a recording surface, then get the extents. |
||||
# Can't seem to create unbounded surfaces in rcairo, so just make it |
||||
# massively large enough. Paint the recording surface with proper margins |
||||
# at the end |
||||
cxt = Cairo::Context.new(Cairo::ImageSurface.new(2 * 1.3 * height, 2 * 1.3 * height)) |
||||
cxt.translate( 1.3 * height , 1.3 * height) |
||||
cxt.rotate(Math::PI / -4.0) |
||||
cxt.translate( -1.3 * height, -1.3 * height) |
||||
cxt.translate(500, 500) # I don't even know why I need this |
||||
angle = (Math::PI / 2.0) / cards.size |
||||
radius_x, radius_y = 0 + (width / 2.0), 1.3 * height |
||||
each_with_index do |card, i| |
||||
cxt.translate(radius_x, radius_y) |
||||
cxt.rotate(angle) |
||||
cxt.translate(-radius_x, -radius_y) |
||||
card.use_cairo do |card_cxt| |
||||
cxt.rounded_rectangle(37, 37, 825-75, 1125-75, 25, 25) |
||||
cxt.clip |
||||
cxt.set_source(card_cxt.target) |
||||
cxt.paint |
||||
cxt.reset_clip |
||||
end |
||||
end |
||||
text str: ('A'..'Z').to_a, layout: :bonus_ul, font: 'Sans bold 100' |
||||
|
||||
cxt.target.write_to_png('_output/hand.png') |
||||
# Defaults are sensible |
||||
hand #saves to _output/hand.png |
||||
|
||||
# Here's a prettier version: |
||||
# - Each card is trimmed with rounded corners |
||||
# - Zero radius means cards rotate about the bottom of the card |
||||
# - Cards are shown in reverse order |
||||
hand trim: 37.5, trim_radius: 25, |
||||
radius: 0, |
||||
range: 7.downto(0), |
||||
file: 'hand_pretty.png' |
||||
end |
||||
|
||||
|
||||
Loading…
Reference in new issue