@ -0,0 +1,2 @@ |
|||||||
|
*.png |
||||||
|
!card_00_expected.png |
||||||
@ -0,0 +1,29 @@ |
|||||||
|
require 'squib' |
||||||
|
|
||||||
|
# Here's an example of being able to scale a font |
||||||
|
# based on the length of individual string. |
||||||
|
# Handy for making minor font scales to fill text boxes. |
||||||
|
def autoscale(str_array) |
||||||
|
str_array.map do | str | |
||||||
|
case str.length |
||||||
|
when 0..15 |
||||||
|
32 |
||||||
|
when 16..20 |
||||||
|
18 |
||||||
|
else |
||||||
|
12 |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
Squib::Deck.new(width: 300, height: 100, cards: 3) do |
||||||
|
background color: :white |
||||||
|
rect |
||||||
|
title = ['Short & Big', |
||||||
|
'Medium Length & Size', |
||||||
|
'Super duper long string here, therefore a smaller font.'] |
||||||
|
text str: title, font: 'Arial', font_size: autoscale(title), |
||||||
|
x: 10, y:10, align: :center, width: 280, ellipsize: false, hint: :red |
||||||
|
|
||||||
|
save_sheet dir: '.', columns: 3 |
||||||
|
end |
||||||
|
After Width: | Height: | Size: 5.2 KiB |
@ -0,0 +1,5 @@ |
|||||||
|
# To configure for using SVG as our backend, we need to set this option |
||||||
|
# This will create a series of SVG files that get updated with Squib command |
||||||
|
backend: svg |
||||||
|
# They are auto-saved with this background |
||||||
|
prefix: backend_vectors_ |
||||||
@ -0,0 +1,33 @@ |
|||||||
|
require 'squib' |
||||||
|
|
||||||
|
# Our SVGs are auto-saved after each step using the configuration parameters |
||||||
|
Squib::Deck.new(cards: 2, config: '_backend-config.yml') do |
||||||
|
|
||||||
|
# These are all supported by the SVG backend |
||||||
|
background color: :gray |
||||||
|
text str: 'Hello, world!', y: 500, width: 825, font: 'Sans bold 72', align: :center |
||||||
|
rect x: 38, y: 38, width: 750, height: 1050, x_radius: 38, y_radius: 38 |
||||||
|
circle x: 100, y: 400, radius: 25 |
||||||
|
triangle x1: 100, y1: 425, x2: 125, y2: 475, x3: 75, y3: 475 |
||||||
|
line x1: 100, y1: 620, x2: 720, y2: 620, stroke_width: 15.0 |
||||||
|
svg file: 'spanner.svg', x: 100, y: 75 |
||||||
|
png file: 'shiny-purse.png', x: 250, y: 75 # raster can still be used too |
||||||
|
png file: 'shiny-purse.png', x: 250, y: 250, mask: :red # still renders as raster |
||||||
|
# We can still rasterize whenever we want |
||||||
|
save_png prefix: 'backend_' |
||||||
|
|
||||||
|
# And our PDFs will be vectorized . |
||||||
|
save_pdf file: 'backend_vectorized.pdf', gap: 5 |
||||||
|
|
||||||
|
# This one is a known issue. Masking an SVG onto an SVG backend is still buggy. |
||||||
|
# svg file: 'glass-heart.svg', x: 100, y: 200, width: 100, height: 100, mask: :sangria |
||||||
|
|
||||||
|
# This one is, unfortunately, not possible with svg back ends |
||||||
|
# Cairo lacks a perspective transform (currently), so we have to |
||||||
|
# use a striping method, which assumes raster. Fortunately, Cairo |
||||||
|
# has perspective transforms on its roadmap, |
||||||
|
# so perhaps this can be done someday with all vectors. |
||||||
|
# |
||||||
|
# showcase file: 'showcase.png', fill_color: 'white' |
||||||
|
|
||||||
|
end |
||||||
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
@ -0,0 +1,37 @@ |
|||||||
|
require 'squib' |
||||||
|
|
||||||
|
Squib::Deck.new(width: 825, height: 1125, cards: 1) do |
||||||
|
background color: :white |
||||||
|
|
||||||
|
y = 0 |
||||||
|
text color: '#f00', str: '3-hex', x: 50, y: y += 50 |
||||||
|
text color: '#f00', str: '3-hex (alpha)', x: 50, y: y += 50 |
||||||
|
text color: '#ff0000', str: '6-hex', x: 50, y: y += 50 |
||||||
|
text color: '#ff000099', str: '8-hex(alpha)', x: 50, y: y += 50 |
||||||
|
text color: '#ffff00000000', str: '12-hex', x: 50, y: y += 50 |
||||||
|
text color: '#ffff000000009999', str: '12-hex (alpha)', x: 50, y: y += 50 |
||||||
|
text color: :burnt_orange, str: 'Symbols of constants too', x: 50, y: y += 50 |
||||||
|
text color: '(0,0)(400,0) blue@0.0 red@1.0', str: 'Linear gradients!', x: 50, y: y += 50 |
||||||
|
text color: '(200,500,10)(200,500,100) blue@0.0 red@1.0', str: 'Radial gradients!', x: 50, y: y += 50 |
||||||
|
# see gradients.rb sample for more on gradients |
||||||
|
|
||||||
|
save_png prefix: 'colors_' |
||||||
|
end |
||||||
|
|
||||||
|
# This script generates a table of the built-in constants |
||||||
|
Squib::Deck.new(width: 3000, height: 1500) do |
||||||
|
colors = (Cairo::Color.constants - %i(HEX_RE Base RGB CMYK HSV X11)) |
||||||
|
colors.sort_by! {|c| Cairo::Color.parse(c).to_s} |
||||||
|
x, y, w, h = 0, 0, 300, 50 |
||||||
|
colors.each_with_index do |color, i| |
||||||
|
rect x: x, y: y, width: w, height: h, fill_color: color |
||||||
|
text str: color.to_s, x: x + 5, y: y + 13, font: 'Sans Bold 16', |
||||||
|
color: (Cairo::Color.parse(color).to_hsv.v > 0.9) ? '#000' : '#fff' |
||||||
|
y += h |
||||||
|
if y > @height |
||||||
|
x += w |
||||||
|
y = 0 |
||||||
|
end |
||||||
|
end |
||||||
|
save_png prefix: 'color_constants_' |
||||||
|
end |
||||||
@ -0,0 +1,34 @@ |
|||||||
|
require 'squib' |
||||||
|
|
||||||
|
Squib::Deck.new do |
||||||
|
# Just about anywhere Squib takes in a color it can also take in a gradient too |
||||||
|
# The x-y coordinates on the card itself, |
||||||
|
# and then color stops are defined between 0 and 1 |
||||||
|
background color: '(0,0)(0,1125) #ccc@0.0 #111@1.0' |
||||||
|
line stroke_color: '(0,0)(825,0) #111@1.0 #ccc@0.0', |
||||||
|
x1: 0, y1: 600, x2: 825, y2: 600, |
||||||
|
stroke_width: 15 |
||||||
|
|
||||||
|
# Radial gradients look like this |
||||||
|
circle fill_color: '(425,400,2)(425,400,120) #ccc@0.0 #111@1.0', |
||||||
|
x: 415, y: 415, radius: 100, stroke_color: '#0000' |
||||||
|
triangle fill_color: '(650,400,2)(650,400,120) #ccc@0.0 #111@1.0', |
||||||
|
stroke_color: '#0000', |
||||||
|
x1: 650, y1: 360, |
||||||
|
x2: 550, y2: 500, |
||||||
|
x3: 750, y3: 500 |
||||||
|
|
||||||
|
# Gradients are also good for beveling effects: |
||||||
|
rect fill_color: '(0,200)(0,600) #111@0.0 #ccc@1.0', |
||||||
|
x: 30, y: 350, width: 150, height: 150, |
||||||
|
radius: 15, stroke_color: '#0000' |
||||||
|
rect fill_color: '(0,200)(0,600) #111@1.0 #ccc@0.0', |
||||||
|
x: 40, y: 360, width: 130, height: 130, |
||||||
|
radius: 15, stroke_color: '#0000' |
||||||
|
|
||||||
|
# Alpha transparency can be used too |
||||||
|
text str: 'Hello, world!', x: 75, y: 700, font: 'Sans Bold 72', |
||||||
|
color: '(0,0)(825,0) #000f@0.0 #0000@1.0' |
||||||
|
|
||||||
|
save_png prefix: 'gradient_' |
||||||
|
end |
||||||
|
After Width: | Height: | Size: 346 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 30 KiB |
@ -0,0 +1,33 @@ |
|||||||
|
require 'squib' |
||||||
|
|
||||||
|
Squib::Deck.new(cards: 2) do |
||||||
|
background color: :white |
||||||
|
|
||||||
|
# Outputs a hash of arrays with the header names as keys |
||||||
|
data = csv file: 'sample.csv' |
||||||
|
text str: data['Type'], x: 250, y: 55, font: 'Arial 54' |
||||||
|
text str: data['Level'], x: 65, y: 65, font: 'Arial 72' |
||||||
|
|
||||||
|
save format: :png, prefix: 'sample_csv_' |
||||||
|
|
||||||
|
# You can also specify the sheet, starting at 0 |
||||||
|
data = xlsx file: 'sample.xlsx', sheet: 2 |
||||||
|
end |
||||||
|
|
||||||
|
# CSV is also a Squib-module-level function, so this also works: |
||||||
|
data = Squib.csv file: 'quantity_explosion.csv' # 2 rows... |
||||||
|
num_cards = data['Name'].size # ...but 4 cards! |
||||||
|
|
||||||
|
Squib::Deck.new(cards: num_cards) do |
||||||
|
background color: :white |
||||||
|
rect # card border |
||||||
|
text str: data['Name'], font: 'Arial 54' |
||||||
|
save_sheet prefix: 'sample_csv_qty_', columns: 4 |
||||||
|
end |
||||||
|
|
||||||
|
# Additionally, CSV supports inline data specifically |
||||||
|
data = Squib.csv data: <<-EOCSV |
||||||
|
Name,Cost |
||||||
|
Knight,3 |
||||||
|
Orc,1 |
||||||
|
EOCSV |
||||||
@ -0,0 +1,55 @@ |
|||||||
|
require 'squib' |
||||||
|
|
||||||
|
Squib::Deck.new(cards: 3) do |
||||||
|
background color: :white |
||||||
|
|
||||||
|
# Reads the first sheet by default (sheet 0) |
||||||
|
# Outputs a hash of arrays with the header names as keys |
||||||
|
data = xlsx file: 'sample.xlsx' |
||||||
|
|
||||||
|
text str: data['Name'], x: 250, y: 55, font: 'Arial 54' |
||||||
|
text str: data['Level'], x: 65, y: 65, font: 'Arial 72' |
||||||
|
text str: data['Description'], x: 65, y: 600, font: 'Arial 36' |
||||||
|
|
||||||
|
save format: :png, prefix: 'sample_excel_' # save to individual pngs |
||||||
|
end |
||||||
|
|
||||||
|
# xlsx is also a Squib-module-level function, so this also works: |
||||||
|
data = Squib.xlsx file: 'explode_quantities.xlsx' # 2 rows... |
||||||
|
num_cards = data['Name'].size # ...but 4 cards! |
||||||
|
|
||||||
|
Squib::Deck.new(cards: num_cards) do |
||||||
|
background color: :white |
||||||
|
rect # card border |
||||||
|
text str: data['Name'], font: 'Arial 54' |
||||||
|
save_sheet prefix: 'sample_xlsx_qty_', columns: 4 |
||||||
|
end |
||||||
|
|
||||||
|
|
||||||
|
# Here's another example, a bit more realistic. Here's what's going on: |
||||||
|
# * We call xlsx from Squib directly - BEFORE Squib::Deck creation. This |
||||||
|
# allows us to infer the number of cards based on the size of the "Name" |
||||||
|
# field |
||||||
|
# * We make use of quantity explosion. Fields named "Qty" or "Quantity" |
||||||
|
# (any capitalization), or any other in the "qty_header" get expanded by the |
||||||
|
# number given |
||||||
|
# * We also make sure that trailing and leading whitespace is stripped |
||||||
|
# from each value. This is the default behavior in Squib, but the options |
||||||
|
# are here just to make sure. |
||||||
|
|
||||||
|
resource_data = Squib.xlsx(file: 'sample.xlsx', sheet: 2, strip: true) do |header, value| |
||||||
|
case header |
||||||
|
when 'Cost' |
||||||
|
"$#{value}k" # e.g. "3" becomes "$3k" |
||||||
|
else |
||||||
|
value # always return the original value if you didn't do anything to it |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
Squib::Deck.new(cards: resource_data['Name'].size) do |
||||||
|
background color: :white |
||||||
|
rect width: :deck, height: :deck |
||||||
|
text str: resource_data['Name'], align: :center, width: :deck, hint: 'red' |
||||||
|
text str: resource_data['Cost'], align: :right, width: :deck, hint: 'red' |
||||||
|
save_sheet prefix: 'sample_excel_resources_' # save to a whole sheet |
||||||
|
end |
||||||
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,7 @@ |
|||||||
|
*.png |
||||||
|
!ball.png |
||||||
|
!grit.png |
||||||
|
!sprites.png |
||||||
|
!with-alpha.png |
||||||
|
!_images_00_expected.png |
||||||
|
!shiny-purse.png |
||||||
@ -0,0 +1,104 @@ |
|||||||
|
require 'squib' |
||||||
|
require 'squib/sample_helpers' |
||||||
|
|
||||||
|
Squib::Deck.new(width: 1000, height: 3000) do |
||||||
|
draw_graph_paper width, height |
||||||
|
|
||||||
|
sample "This a PNG.\nNo scaling is done by default." do |x, y| |
||||||
|
png file: 'angler-fish.png', x: x, y: y |
||||||
|
end |
||||||
|
|
||||||
|
sample 'PNGs can be upscaled, but they will emit an antialias warning (unless you turn it off in the config.yml)' do |x,y| |
||||||
|
png file: 'angler-fish.png', x: x, y: y, width: 150, height: 150 |
||||||
|
end |
||||||
|
|
||||||
|
sample 'SVGs can be loaded from a file (left) or from straight XML (right). They can also be scaled to any size.' do |x,y| |
||||||
|
svg file: 'robot-golem.svg', x: x, y: y, width: 100, height: 100 |
||||||
|
svg data: File.read('robot-golem.svg'), width: 100, height: 100, |
||||||
|
x: x + 200, y: y |
||||||
|
end |
||||||
|
|
||||||
|
sample 'PNG and SVG can be auto-scaled by one side and setting the other to :scale' do |x,y| |
||||||
|
svg file: 'robot-golem.svg', x: x, y: y, width: 50, height: :scale |
||||||
|
svg file: 'robot-golem.svg', x: x + 50, y: y, width: :scale, height: 50 |
||||||
|
|
||||||
|
png file: 'angler-fish.png', x: x + 200, y: y, width: 50, height: :scale |
||||||
|
png file: 'angler-fish.png', x: x + 250, y: y, width: :scale, height: 50 |
||||||
|
end |
||||||
|
|
||||||
|
sample 'PNGs can be cropped. To work from sprite sheets, you can set crop coordinates to PNG images. Rounded corners supported too.' do |x,y| |
||||||
|
png file: 'sprites.png', x: x - 50, y: y - 50 # entire sprite sheet |
||||||
|
rect x: x - 50, y: y - 50, width: 100, height: 100, # draw the crop line |
||||||
|
radius: 15, dash: '3 3', stroke_color: 'red', stroke_width: 3 |
||||||
|
text str: '➜', font: 'Sans Bold 36', x: x + 150, y: y - 35 |
||||||
|
png file: 'sprites.png', x: x + 200, y: y - 50, # just the robot golem image |
||||||
|
crop_x: 0, crop_y: 0, crop_corner_radius: 15, |
||||||
|
crop_width: 100, crop_height: 100 |
||||||
|
|
||||||
|
png file: 'sprites.png', x: x - 50, y: y + 50 # entire sprite sheet again |
||||||
|
rect x: x + 14, y: y + 50, width: 65, height: 65, # highlight the crop |
||||||
|
radius: 25, dash: '3 3', stroke_color: 'red', stroke_width: 3 |
||||||
|
text str: '➜', font: 'Sans Bold 36', x: x + 150, y: y + 50 |
||||||
|
png file: 'sprites.png', x: x + 225, y: y + 50, # just the drakkar ship image, rotated |
||||||
|
crop_x: 64, crop_y: 0, crop_corner_x_radius: 25, crop_corner_y_radius: 25, |
||||||
|
crop_width: 64, crop_height: 64, angle: Math::PI / 6 |
||||||
|
end |
||||||
|
|
||||||
|
sample 'SVGs can be cropped too.' do |x,y| |
||||||
|
svg file: 'robot-golem.svg', x: x, y: y, width: 100, height: 100, |
||||||
|
crop_x: 40, crop_y: 0, crop_width: 50, crop_height: 50 |
||||||
|
end |
||||||
|
|
||||||
|
sample 'Images can be flipped about their center.' do |x,y| |
||||||
|
png file: 'angler-fish.png', x: x, y: y, flip_vertical: true, flip_horizontal: true |
||||||
|
svg file: 'robot-golem.svg', x: x + 200, y: y, width: 100, height: 100, |
||||||
|
flip_horizontal: true |
||||||
|
end |
||||||
|
|
||||||
|
sample 'SVG can be limited to rendering to a single object if the SVG ID is set. If you look in this SVG file, the black backdrop has ID #backdrop.' do |x,y| |
||||||
|
svg file: 'robot-golem.svg', id: 'backdrop', x: x, y: y, width: 100, height: 100 |
||||||
|
end |
||||||
|
|
||||||
|
sample "The SVG force_id option allows use of an ID only when specified, and render nothing if empty. Useful for multiple icons in one SVG file.\nThis should show nothing." do |x,y| |
||||||
|
svg file: 'robot-golem.svg', x: x, y: y, |
||||||
|
force_id: true, id: '' # <-- the important parts |
||||||
|
end |
||||||
|
|
||||||
|
sample 'NOTE! If you render a single object in an SVG, its placement is still relative to the SVG document.' do |x,y| |
||||||
|
svg file: 'offset.svg', x: x, y: y |
||||||
|
rect x: x, y: y, width: 100, height: 100, dash: '3 1', stroke_color: 'red', stroke_width: 3 |
||||||
|
|
||||||
|
svg file: 'offset.svg', id: 'thing', x: x + 200, y: y, width: 100, height: 100 |
||||||
|
rect x: x + 200, y: y, width: 100, height: 100, dash: '3 1', stroke_color: 'red', stroke_width: 3 |
||||||
|
end |
||||||
|
|
||||||
|
sample 'PNGs can be blended onto each other with 15 different blending operators. Alpha transparency supported too. See http://cairographics.org/operators' do |x,y| |
||||||
|
png file: 'ball.png', x: x, y: y |
||||||
|
png file: 'grit.png', x: x + 20, y: y + 20, blend: :color_burn, alpha: 0.75 |
||||||
|
end |
||||||
|
|
||||||
|
sample 'Rotation is around the upper-left corner of the image. Unit is radians.' do |x,y| |
||||||
|
rect x: x, y: y, width: 100, height: 100, stroke_width: 3, dash: '3 3', stroke_color: :red |
||||||
|
png x: x, y: y, width: 100, height: 100, angle: Math::PI / 4, file: 'angler-fish.png' |
||||||
|
|
||||||
|
rect x: x + 250, y: y, width: 100, height: 100, stroke_width: 3, dash: '3 3', stroke_color: :red |
||||||
|
svg x: x + 250, y: y, width: 100, height: 100, file: 'robot-golem.svg', |
||||||
|
angle: Math::PI / 2 - 0.2 |
||||||
|
end |
||||||
|
|
||||||
|
sample 'SVGs and PNGs can be used as masks for colors instead of being directly rendered.' do |x,y| |
||||||
|
svg mask: '#00ff00', file: 'glass-heart.svg', x: x - 50, y: y - 50, width: 200, height: 200 |
||||||
|
svg mask: '(0,0)(500,0) #eee@0.0 #111@1.0', file: 'glass-heart.svg', x: x + 150, y: y - 50, width: 200, height: 200 |
||||||
|
end |
||||||
|
|
||||||
|
sample 'PNG masks are based on the alpha channel. Gradient coordinates are relative to the card.' do |x,y| |
||||||
|
png file: 'with-alpha.png', x: x - 50, y: y |
||||||
|
png file: 'with-alpha.png', mask: :magenta, x: x + 50, y: y |
||||||
|
|
||||||
|
mask = "(#{x+150+75}, #{y+75}, 0)(#{x+150+75}, #{y+75}, 100) #f00@0.0 #000@1.0" |
||||||
|
png file: 'with-alpha.png', mask: mask, x: x + 150, y: y, width: 150, height: :scale |
||||||
|
end |
||||||
|
|
||||||
|
|
||||||
|
save_png prefix: '_images_', dir: '.' |
||||||
|
end |
||||||
|
After Width: | Height: | Size: 312 KiB |
@ -0,0 +1,99 @@ |
|||||||
|
require 'squib' |
||||||
|
|
||||||
|
Squib::Deck.new(width: 825, height: 1125, cards: 1, config: 'load_images_config.yml') do |
||||||
|
background color: '#0b7c8e' |
||||||
|
rect x: 38, y: 38, width: 750, height: 1050, x_radius: 38, y_radius: 38 |
||||||
|
|
||||||
|
png file: 'shiny-purse.png', x: 620, y: 75 # no scaling is done by default |
||||||
|
svg file: 'spanner.svg', x: 620, y: 218 |
||||||
|
|
||||||
|
# Can be scaled if width and height are set |
||||||
|
svg file: 'spanner.svg', x: 50, y: 50, width: 250, height: 250 |
||||||
|
png file: 'shiny-purse.png', x: 305, y: 50, width: 250, height: 250 |
||||||
|
# ...but PNGs will warn if it's an upscale, unless you disable them in config.yml |
||||||
|
|
||||||
|
# Can be scaled using just width or height, if one of them is set to :scale |
||||||
|
svg file: 'spanner.svg', x: 200, y: 350, width: 35, height: :scale |
||||||
|
svg file: 'spanner.svg', x: 200, y: 390, width: :scale, height: 35 |
||||||
|
png file: 'shiny-purse.png', x: 240, y: 350, width: 35, height: :scale |
||||||
|
png file: 'shiny-purse.png', x: 240, y: 390, width: :scale, height: 35 |
||||||
|
|
||||||
|
# You can also crop the loaded images, so you can work from a sprite sheet |
||||||
|
png file: 'sprites.png', x: 300, y: 350 # entire sprite sheet |
||||||
|
png file: 'sprites.png', x: 300, y: 425, # just the robot golem image |
||||||
|
crop_x: 0, crop_y: 0, crop_corner_radius: 10, |
||||||
|
crop_width: 64, crop_height: 64 |
||||||
|
png file: 'sprites.png', x: 400, y: 425, # just the drakkar ship image |
||||||
|
crop_x: 64, crop_y: 0, crop_corner_x_radius: 25, crop_corner_y_radius: 25, |
||||||
|
crop_width: 64, crop_height: 64 |
||||||
|
png file: 'sprites.png', x: 500, y: 415, # just the drakkar ship image, rotated |
||||||
|
crop_x: 64, crop_y: 0, crop_corner_x_radius: 25, crop_corner_y_radius: 25, |
||||||
|
crop_width: 64, crop_height: 64, angle: Math::PI / 6 |
||||||
|
|
||||||
|
# Cropping also works on SVGs too |
||||||
|
svg file: 'spanner.svg', x: 300, y: 500, width: 64, height: 64, |
||||||
|
crop_x: 32, crop_y: 32, crop_width: 32, crop_height:32 |
||||||
|
|
||||||
|
# We can flip our images too |
||||||
|
png file: 'sprites.png', x: 300, y: 535, flip_vertical: true, flip_horizontal: true |
||||||
|
svg file: 'spanner.svg', x: 300, y: 615, width: 64, height: 64, |
||||||
|
flip_vertical: true, flip_horizontal: true |
||||||
|
|
||||||
|
# We can also limit our rendering to a single object, if the SVG ID is set |
||||||
|
svg file: 'spanner.svg', id: '#backdrop', x: 50, y: 350, width: 75, height: 75 |
||||||
|
# Squib prepends a #-sign if one is not specified |
||||||
|
svg file: 'spanner.svg', id: 'backdrop', x: 50, y: 450, width: 125, height: 125 |
||||||
|
|
||||||
|
# We can also load SVGs as a string of XML |
||||||
|
svg data: File.read('spanner.svg'), x: 50, y: 600, width: 75, height: 75 |
||||||
|
|
||||||
|
# The svg data field works nicely with modifying the SVG XML on-the-fly. |
||||||
|
# To run this one, do `gem install game_icons` and uncomment the following |
||||||
|
# |
||||||
|
# require 'game_icons' |
||||||
|
# svg data: GameIcons.get('angler-fish').recolor(fg: '#ccc', bg: '#333').string, |
||||||
|
# x: 150, y: 600, width: 75, height: 75 |
||||||
|
# |
||||||
|
# More examples at https://github.com/andymeneely/game_icons |
||||||
|
# (or `gem install game_icons`) to get & manipulate art from game-icons.net |
||||||
|
# Nokogiri (already included in Squib) is also great for XML manipulation. |
||||||
|
|
||||||
|
# WARNING! If you choose to use the SVG ID, the x-y coordinates are still |
||||||
|
# relative to the SVG page. See this example in an SVG editor |
||||||
|
svg file: 'offset.svg', id: 'thing', x: 0, y: 0, width: 600, height: 600 |
||||||
|
|
||||||
|
# Over 15 different blending operators are supported. |
||||||
|
# See http://cairographics.org/operators |
||||||
|
# Alpha transparency too |
||||||
|
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 |
||||||
|
|
||||||
|
# Images can also be used as masks instead of being directly painted. |
||||||
|
# This is particularly useful for switching directly over to black-and-white for printing |
||||||
|
# Or, if you want the same image to be used but with different colors/gradients |
||||||
|
svg mask: '#00ff00', |
||||||
|
file: 'glass-heart.svg', |
||||||
|
x: 500, y: 600, width: 200, height: 200 |
||||||
|
svg mask: '(0,0)(0,500) #ccc@0.0 #333@1.0', |
||||||
|
file: 'glass-heart.svg', |
||||||
|
x: 500, y: 800, width: 200, height: 200 |
||||||
|
|
||||||
|
# Masks are based on the alpha channel, so this is just a magenta square |
||||||
|
png mask: :magenta, file: 'shiny-purse.png', |
||||||
|
x: 650, y: 950 |
||||||
|
|
||||||
|
# Note that this method does nothing, even though it would normally fill up |
||||||
|
# the card. force_id: true looks to the id field to be non-empty to render. |
||||||
|
# This is useful if you have multiple different icons in one SVG file, |
||||||
|
# but sometimes want to use none. |
||||||
|
# e.g. id: [:attack, :defend, nil] |
||||||
|
svg file: 'spanner.svg', width: :deck, height: :deck, |
||||||
|
force_id: true, id: '' # <-- the important part |
||||||
|
|
||||||
|
save prefix: 'load_images_', format: :png |
||||||
|
end |
||||||
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 9.9 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,9 @@ |
|||||||
|
require 'squib' |
||||||
|
|
||||||
|
Squib::Deck.new cards: 1 do |
||||||
|
background color: 'pink' |
||||||
|
rect |
||||||
|
text str: 'Draw two cards.' |
||||||
|
save_png prefix: 'part1_', dir: '.' |
||||||
|
end |
||||||
|
|
||||||
@ -0,0 +1,15 @@ |
|||||||
|
require 'squib' |
||||||
|
|
||||||
|
Squib::Deck.new cards: 1 do |
||||||
|
background color: '#252322' |
||||||
|
rect fill_color: '#0B3736', |
||||||
|
x: 38, y: 38, width: 750, height: 1050, radius: 38 |
||||||
|
text str: 'Robot Golem', font: 'True Crimes, Sans 72', |
||||||
|
align: :center, x: 75, width: :deck, color: '#DFDFE1', y: 90 |
||||||
|
svg file: 'auto-repair.svg', x: 75, y: 75, width: 100, height: :scale |
||||||
|
svg file: 'robot-golem.svg', x: 75, y: 300, width: 675, height: :scale |
||||||
|
text str: 'Draw two cards', font: 'Serif 36', |
||||||
|
align: :center, width: :deck, color: '#DFDFE1', y: 1000 |
||||||
|
save_png prefix: 'part2_', dir: '.' |
||||||
|
end |
||||||
|
|
||||||
@ -0,0 +1,12 @@ |
|||||||
|
require 'squib' |
||||||
|
|
||||||
|
Squib::Deck.new cards: 1, layout: 'part3_layout.yml' do |
||||||
|
background color: '#252322' |
||||||
|
rect layout: 'backdrop' |
||||||
|
text str: 'Robot Golem', layout: 'title' |
||||||
|
svg layout: 'drone' |
||||||
|
svg file: 'robot-golem.svg', layout: 'art' |
||||||
|
text str: 'Draw two cards.', layout: 'power' |
||||||
|
save_png prefix: 'part3_', dir: '.' |
||||||
|
end |
||||||
|
|
||||||
@ -0,0 +1,16 @@ |
|||||||
|
require 'squib' |
||||||
|
|
||||||
|
Squib::Deck.new cards: 2, layout: 'part3_layout.yml' do |
||||||
|
background color: '#252322' |
||||||
|
rect layout: 'backdrop' |
||||||
|
text str: ['Robot Golem', 'Ninja'], |
||||||
|
layout: 'title' |
||||||
|
svg layout: ['drone', 'human'] |
||||||
|
svg file: ['robot-golem.svg','ninja-mask.svg'], |
||||||
|
layout: 'art' |
||||||
|
text str: ['Draw two cards', |
||||||
|
'Use the power of another player'], |
||||||
|
layout: 'power' |
||||||
|
save_png prefix: 'part4_', dir: '.' |
||||||
|
end |
||||||
|
|
||||||
@ -0,0 +1,15 @@ |
|||||||
|
require 'squib' |
||||||
|
|
||||||
|
Squib::Deck.new cards: 4, layout: 'part3_layout.yml' do |
||||||
|
background color: '#252322' |
||||||
|
rect layout: 'backdrop' |
||||||
|
data = xlsx file: 'data.xlsx' |
||||||
|
text str: data['name'], layout: 'title' |
||||||
|
svg layout: data['class'] |
||||||
|
svg file: data['art'], layout: 'art' |
||||||
|
text str: data['power'], layout: 'power' |
||||||
|
save_png prefix: 'part5_', dir: '.' |
||||||
|
hand file: 'part5_hand.png', dir: '.', trim_radius: 38 |
||||||
|
showcase file: 'part5_showcase.png', dir: '.' |
||||||
|
end |
||||||
|
|
||||||
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 61 KiB |
@ -0,0 +1,34 @@ |
|||||||
|
backdrop: |
||||||
|
fill_color: '#0B3736' |
||||||
|
x: 38 |
||||||
|
y: 38 |
||||||
|
radius: 38 |
||||||
|
width: 750 |
||||||
|
height: 1050 |
||||||
|
title: |
||||||
|
font: 'True Crimes, Sans 72' |
||||||
|
align: center |
||||||
|
color: '#DFDFE1' |
||||||
|
x: 75 |
||||||
|
y: 90 |
||||||
|
width: 825 |
||||||
|
drone: |
||||||
|
file: auto-repair.svg |
||||||
|
x: 75 |
||||||
|
y: 75 |
||||||
|
width: 100 |
||||||
|
height: 100 |
||||||
|
human: |
||||||
|
extends: drone |
||||||
|
file: humans.svg |
||||||
|
art: |
||||||
|
x: 75 |
||||||
|
y: 300 |
||||||
|
width: 675 |
||||||
|
height: 675 |
||||||
|
power: |
||||||
|
font: 'Serif 36' |
||||||
|
align: center |
||||||
|
width: 825 |
||||||
|
color: '#DFDFE1' |
||||||
|
y: 1000 |
||||||
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 306 KiB |
|
After Width: | Height: | Size: 548 KiB |
@ -0,0 +1,54 @@ |
|||||||
|
require 'squib' |
||||||
|
|
||||||
|
Squib::Deck.new do |
||||||
|
background color: :white |
||||||
|
|
||||||
|
grid x: 10, y: 10, width: 50, height: 50, stroke_color: '#0066FF', stroke_width: 1.5, angle: 0.1 |
||||||
|
grid x: 10, y: 10, width: 200, height: 200, stroke_color: '#0066FF', stroke_width: 3, angle: 0.1 |
||||||
|
|
||||||
|
rect x: 305, y: 105, width: 200, height: 50, dash: '4 2' |
||||||
|
|
||||||
|
rect x: 300, y: 300, width: 400, height: 400, |
||||||
|
fill_color: :blue, stroke_color: :red, stroke_width: 50.0, |
||||||
|
join: 'bevel' |
||||||
|
|
||||||
|
rect x: 550, y: 105, width: 100, height: 100, |
||||||
|
stroke_width: 5, stroke_color: :orange, angle: -0.2 |
||||||
|
|
||||||
|
ellipse x: 675, y: 105, width: 65, height: 100, |
||||||
|
stroke_width: 5, stroke_color: :orange, angle: -0.2 |
||||||
|
|
||||||
|
circle x: 600, y: 600, radius: 75, |
||||||
|
fill_color: :gray, stroke_color: :green, stroke_width: 8.0 |
||||||
|
|
||||||
|
triangle x1: 50, y1: 50, |
||||||
|
x2: 150, y2: 150, |
||||||
|
x3: 75, y3: 250, |
||||||
|
fill_color: :gray, stroke_color: :green, stroke_width: 3.0 |
||||||
|
|
||||||
|
line x1: 50, y1: 550, |
||||||
|
x2: 150, y2: 650, |
||||||
|
stroke_width: 25.0 |
||||||
|
|
||||||
|
curve x1: 50, y1: 850, cx1: 150, cy1: 700, |
||||||
|
x2: 625, y2: 900, cx2: 150, cy2: 700, |
||||||
|
stroke_width: 12.0, stroke_color: :cyan, |
||||||
|
fill_color: :burgundy, cap: 'round' |
||||||
|
|
||||||
|
ellipse x: 50, y: 925, width: 200, height: 100, |
||||||
|
stroke_width: 5.0, stroke_color: :cyan, |
||||||
|
fill_color: :burgundy |
||||||
|
|
||||||
|
star x: 300, y: 1000, n: 5, inner_radius: 15, outer_radius: 40, |
||||||
|
fill_color: :cyan, stroke_color: :burgundy, stroke_width: 5 |
||||||
|
|
||||||
|
# default draw is fill-then-stroke. Can be changed to stroke-then-fill |
||||||
|
star x: 375, y: 1000, n: 5, inner_radius: 15, outer_radius: 40, |
||||||
|
fill_color: :cyan, stroke_color: :burgundy, |
||||||
|
stroke_width: 5, stroke_strategy: :stroke_first |
||||||
|
|
||||||
|
polygon x: 500, y: 1000, n: 5, radius: 25, angle: Math::PI / 2, |
||||||
|
fill_color: :cyan, stroke_color: :burgundy, stroke_width: 2 |
||||||
|
|
||||||
|
save_png prefix: 'shape_' |
||||||
|
end |
||||||
|
After Width: | Height: | Size: 39 KiB |
@ -0,0 +1,47 @@ |
|||||||
|
require 'squib' |
||||||
|
require 'squib/sample_helpers' |
||||||
|
|
||||||
|
Squib::Deck.new(width: 1000, height: 1250) do |
||||||
|
draw_graph_paper width, height |
||||||
|
|
||||||
|
sample 'Font strings are quite expressive. Specify family, modifiers, then size. Font names with spaces in them should end with a comma to help with parsing.' do |x, y| |
||||||
|
text font: 'Arial bold italic 32', str: 'Bold and italic!', x: x, y: y - 50 |
||||||
|
text font: 'Arial weight=300 32', str: 'Light bold!', x: x, y: y |
||||||
|
text font: 'Times New Roman, 32', str: 'Times New Roman', x: x, y: y + 50 |
||||||
|
text font: 'NoSuchFont,Arial 32', str: 'Arial Backup', x: x, y: y + 100 |
||||||
|
end |
||||||
|
|
||||||
|
sample 'Specify width and height to see a text box. Also: set "hint" to see the extents of your text box' do |x, y| |
||||||
|
text str: 'This has fixed width and height.', x: x, y: y, |
||||||
|
hint: :red, width: 300, height: 100, font: 'Serif bold 24' |
||||||
|
end |
||||||
|
|
||||||
|
sample 'If you specify the width only, the text will ellipsize.' do |x, y| |
||||||
|
text str: 'The meaning of life is 42', x: x - 50, y: y, |
||||||
|
hint: :red, width: 350, font: 'Serif bold 22' |
||||||
|
end |
||||||
|
|
||||||
|
sample 'If you specify the width only, and turn off ellipsize, the height will auto-stretch.' do |x, y| |
||||||
|
text str: 'This has fixed width, but not fixed height.', x: x, y: y, |
||||||
|
hint: :red, width: 300, ellipsize: false, font: 'Serif bold 24' |
||||||
|
end |
||||||
|
|
||||||
|
sample 'The text method returns the ink extents of each card\'s rendered text. So you can custom-fit a shape around it.' do |x, y| |
||||||
|
['Auto fit!', 'Auto fit!!!!' ].each.with_index do |str, i| |
||||||
|
text_y = y + i * 50 |
||||||
|
extents = text str: str, x: x, y: text_y, font: 'Sans Bold 24' |
||||||
|
|
||||||
|
# Extents come back as an array of hashes, which can get split out like this |
||||||
|
text_width = extents[0][:width] |
||||||
|
text_height = extents[0][:height] |
||||||
|
rect x: x, y: text_y, width: text_width, height: text_height, radius: 10, |
||||||
|
stroke_color: :purple, stroke_width: 3 |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
sample 'Text can be rotated about the upper-left corner of the text box. Unit is in radians.' do |x, y| |
||||||
|
text str: 'Rotated', hint: :red, x: x, y: y, angle: Math::PI / 6 |
||||||
|
end |
||||||
|
|
||||||
|
save_png prefix: '_text_', dir: '.' |
||||||
|
end |
||||||
|
After Width: | Height: | Size: 92 KiB |