squib 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +62 -14
- data/Gemfile +1 -1
- data/README.md +16 -10
- data/RELEASE TODO.md +2 -1
- data/Rakefile +11 -0
- data/lib/squib/api/data.rb +3 -3
- data/lib/squib/api/image.rb +7 -5
- data/lib/squib/api/save.rb +31 -2
- data/lib/squib/api/settings.rb +1 -1
- data/lib/squib/api/shapes.rb +86 -0
- data/lib/squib/api/text.rb +6 -2
- data/lib/squib/api/text_embed.rb +7 -5
- data/lib/squib/args/typographer.rb +22 -16
- data/lib/squib/card.rb +5 -5
- data/lib/squib/conf.rb +111 -0
- data/lib/squib/constants.rb +11 -31
- data/lib/squib/deck.rb +15 -48
- data/lib/squib/graphics/cairo_context_wrapper.rb +3 -1
- data/lib/squib/graphics/gradient_regex.rb +1 -0
- data/lib/squib/graphics/hand.rb +43 -0
- data/lib/squib/graphics/image.rb +5 -3
- data/lib/squib/graphics/save_doc.rb +1 -1
- data/lib/squib/graphics/shapes.rb +74 -0
- data/lib/squib/graphics/showcase.rb +5 -2
- data/lib/squib/graphics/text.rb +18 -7
- data/lib/squib/input_helpers.rb +2 -2
- data/lib/squib/version.rb +1 -1
- data/samples/csv_import.rb +3 -5
- data/samples/custom-config.yml +0 -1
- data/samples/custom_config.rb +1 -1
- data/samples/draw_shapes.rb +11 -0
- data/samples/embed_text.rb +1 -1
- data/samples/hand.rb +24 -0
- data/samples/load_images.rb +14 -0
- data/samples/sample.csv +3 -3
- data/samples/text_options.rb +4 -0
- data/spec/api/api_data_spec.rb +19 -0
- data/spec/api/api_image_spec.rb +1 -1
- data/spec/api/api_settings_spec.rb +18 -0
- data/spec/api/api_text_spec.rb +3 -3
- data/spec/conf_spec.rb +29 -0
- data/spec/data/conf/basic.yml +0 -0
- data/spec/data/conf/empty.yml +1 -0
- data/spec/data/samples/csv_import.rb.txt +4 -38
- data/spec/data/samples/custom_config.rb.txt +4 -0
- data/spec/data/samples/draw_shapes.rb.txt +57 -0
- data/spec/data/samples/hand.rb.txt +514 -0
- data/spec/data/samples/load_images.rb.txt +6 -0
- data/spec/data/samples/text_options.rb.txt +81 -0
- data/spec/data/xlsx/basic.xlsx +0 -0
- data/spec/data/xlsx/formulas.xlsx +0 -0
- data/spec/graphics/graphics_images_spec.rb +49 -48
- data/spec/graphics/graphics_shapes_spec.rb +43 -41
- data/spec/graphics/graphics_text_spec.rb +25 -11
- data/spec/samples/_diffs/gitkeep.txt +0 -0
- data/spec/samples/expected/autoscale_00.png +0 -0
- data/spec/samples/expected/autoscale_01.png +0 -0
- data/spec/samples/expected/autoscale_02.png +0 -0
- data/spec/samples/expected/backend_00.png +0 -0
- data/spec/samples/expected/backend_00.svg +78 -0
- data/spec/samples/expected/backend_01.png +0 -0
- data/spec/samples/expected/backend_01.svg +78 -0
- data/spec/samples/expected/basic_00.png +0 -0
- data/spec/samples/expected/basic_01.png +0 -0
- data/spec/samples/expected/basic_02.png +0 -0
- data/spec/samples/expected/cairo_access_00.png +0 -0
- data/spec/samples/expected/cairo_access_01.png +0 -0
- data/spec/samples/expected/card_00.png +0 -0
- data/spec/samples/expected/card_01.png +0 -0
- data/spec/samples/expected/colors_00.png +0 -0
- data/spec/samples/expected/config_disable_text_00.png +0 -0
- data/spec/samples/expected/config_text_00.png +0 -0
- data/spec/samples/expected/custom-config_00.png +0 -0
- data/spec/samples/expected/embed_00.png +0 -0
- data/spec/samples/expected/embed_multi_00.png +0 -0
- data/spec/samples/expected/embed_multi_01.png +0 -0
- data/spec/samples/expected/embed_multi_02.png +0 -0
- data/spec/samples/expected/embed_multisheet_00.png +0 -0
- data/spec/samples/expected/gitkeep.txt +0 -0
- data/spec/samples/expected/gradient_00.png +0 -0
- data/spec/samples/expected/hand.png +0 -0
- data/spec/samples/expected/hand_pretty.png +0 -0
- data/spec/samples/expected/landscape_00.png +0 -0
- data/spec/samples/expected/layout2_00.png +0 -0
- data/spec/samples/expected/layout_00.png +0 -0
- data/spec/samples/expected/layout_builtin_hand_00.png +0 -0
- data/spec/samples/expected/layout_builtin_playing_card_00.png +0 -0
- data/spec/samples/expected/load_images_00.png +0 -0
- data/spec/samples/expected/portrait_00.png +0 -0
- data/spec/samples/expected/ranges_00.png +0 -0
- data/spec/samples/expected/ranges_01.png +0 -0
- data/spec/samples/expected/ranges_02.png +0 -0
- data/spec/samples/expected/sample_csv_00.png +0 -0
- data/spec/samples/expected/sample_csv_01.png +0 -0
- data/spec/samples/expected/sample_excel_00.png +0 -0
- data/spec/samples/expected/sample_excel_01.png +0 -0
- data/spec/samples/expected/sample_excel_02.png +0 -0
- data/spec/samples/expected/save_sheet_00.png +0 -0
- data/spec/samples/expected/save_sheet_01.png +0 -0
- data/spec/samples/expected/save_sheet_range_00.png +0 -0
- data/spec/samples/expected/save_sheet_range_01.png +0 -0
- data/spec/samples/expected/save_single_sheet_00.png +0 -0
- data/spec/samples/expected/saves_notrim_01.png +0 -0
- data/spec/samples/expected/shape_00.png +0 -0
- data/spec/samples/expected/showcase.png +0 -0
- data/spec/samples/expected/showcase2.png +0 -0
- data/spec/samples/expected/showcase_individual_00.png +0 -0
- data/spec/samples/expected/showcase_individual_01.png +0 -0
- data/spec/samples/expected/showcase_individual_02.png +0 -0
- data/spec/samples/expected/showcase_individual_03.png +0 -0
- data/spec/samples/expected/text_00.png +0 -0
- data/spec/samples/expected/text_01.png +0 -0
- data/spec/samples/expected/text_02.png +0 -0
- data/spec/samples/expected/tgc_sample_00.png +0 -0
- data/spec/samples/expected/units_00.png +0 -0
- data/spec/samples/samples_regression_spec.rb +7 -5
- data/spec/samples/sanity.html.erb +28 -0
- data/spec/samples/sanity.rb +70 -0
- data/spec/spec_helper.rb +15 -1
- data/squib.gemspec +3 -1
- data/squib.sublime-project +27 -40
- metadata +177 -4
|
@@ -4,6 +4,7 @@ require 'squib/graphics/gradient_regex'
|
|
|
4
4
|
module Squib
|
|
5
5
|
module Graphics
|
|
6
6
|
# Wrapper class for the Cairo context. Private.
|
|
7
|
+
# @api private
|
|
7
8
|
class CairoContextWrapper
|
|
8
9
|
extend Forwardable
|
|
9
10
|
|
|
@@ -22,7 +23,8 @@ module Squib
|
|
|
22
23
|
:show_pango_layout, :rounded_rectangle, :set_line_width, :stroke, :fill,
|
|
23
24
|
:set_source, :scale, :render_rsvg_handle, :circle, :triangle, :line_to,
|
|
24
25
|
:operator=, :show_page, :clip, :transform, :mask, :create_pango_layout,
|
|
25
|
-
:antialias=, :curve_to, :matrix, :matrix=, :identity_matrix
|
|
26
|
+
:antialias=, :curve_to, :matrix, :matrix=, :identity_matrix, :pango_layout_path,
|
|
27
|
+
:stroke_preserve, :target, :new_path, :fill_preserve, :close_path
|
|
26
28
|
|
|
27
29
|
# :nodoc:
|
|
28
30
|
# @api private
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'squib/graphics/cairo_context_wrapper'
|
|
2
|
+
|
|
3
|
+
module Squib
|
|
4
|
+
class Deck
|
|
5
|
+
|
|
6
|
+
# Draw cards in a fan.
|
|
7
|
+
# @api private
|
|
8
|
+
def render_hand(range, radius, angle_range, trim, trim_radius, margin,
|
|
9
|
+
fill_color, dir, file)
|
|
10
|
+
cards = range.collect { |i| @cards[i] }
|
|
11
|
+
center_x = width / 2.0
|
|
12
|
+
center_y = radius + height
|
|
13
|
+
out_size = 3.0 * center_y
|
|
14
|
+
angle_delta = (angle_range.last - angle_range.first) / cards.size
|
|
15
|
+
cxt = Cairo::Context.new(Cairo::RecordingSurface.new(0, 0, out_size, out_size))
|
|
16
|
+
cxt.translate(out_size / 2.0, out_size / 2.0)
|
|
17
|
+
cxt.rotate(angle_range.first)
|
|
18
|
+
cxt.translate(-width, -width)
|
|
19
|
+
cards.each_with_index do |card, i|
|
|
20
|
+
cxt.translate(center_x, center_y)
|
|
21
|
+
cxt.rotate(angle_delta)
|
|
22
|
+
cxt.translate(-center_x, -center_y)
|
|
23
|
+
card.use_cairo do |card_cxt|
|
|
24
|
+
cxt.rounded_rectangle(trim, trim,
|
|
25
|
+
width - (2 * trim), height - (2 * trim),
|
|
26
|
+
trim_radius, trim_radius)
|
|
27
|
+
cxt.clip
|
|
28
|
+
cxt.set_source(card_cxt.target)
|
|
29
|
+
cxt.paint
|
|
30
|
+
cxt.reset_clip
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
x, y, w, h = cxt.target.ink_extents # I love Ruby assignment ;)
|
|
34
|
+
png_cxt = Squib::Graphics::CairoContextWrapper.new(Cairo::Context.new(Cairo::ImageSurface.new(w + 2*margin, h + 2*margin)))
|
|
35
|
+
png_cxt.set_source_squibcolor(fill_color)
|
|
36
|
+
png_cxt.paint
|
|
37
|
+
png_cxt.translate(-x + margin, -y + margin)
|
|
38
|
+
png_cxt.set_source(cxt.target)
|
|
39
|
+
png_cxt.paint
|
|
40
|
+
png_cxt.target.write_to_png("#{dir}/#{file}")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
data/lib/squib/graphics/image.rb
CHANGED
|
@@ -41,10 +41,12 @@ module Squib
|
|
|
41
41
|
|
|
42
42
|
# :nodoc:
|
|
43
43
|
# @api private
|
|
44
|
-
def svg(file, id, x, y, width, height, alpha, blend, angle, mask)
|
|
44
|
+
def svg(file, data, id, x, y, width, height, alpha, blend, angle, mask)
|
|
45
45
|
Squib.logger.debug {"Rendering: #{file}, id: #{id} @#{x},#{y} #{width}x#{height}, alpha: #{alpha}, blend: #{blend}, angle: #{angle}, mask: #{mask}"}
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
Squib.logger.warn 'Both an SVG file and SVG data were specified' unless file.to_s.empty? or data.to_s.empty?
|
|
47
|
+
return if (file.nil? or file.eql? '') and data.nil? # nothing specified
|
|
48
|
+
data = File.read(file) if data.to_s.empty?
|
|
49
|
+
svg = RSVG::Handle.new_from_data(data)
|
|
48
50
|
width = svg.width if width == :native
|
|
49
51
|
height = svg.height if height == :native
|
|
50
52
|
scale_width = width.to_f / svg.width.to_f
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
module Squib
|
|
2
|
+
# @api private
|
|
2
3
|
class Card
|
|
3
4
|
|
|
4
5
|
# :nodoc:
|
|
@@ -32,6 +33,34 @@ module Squib
|
|
|
32
33
|
end
|
|
33
34
|
end
|
|
34
35
|
|
|
36
|
+
# Ellipse drawing taken from looking at the control points in Inkscape
|
|
37
|
+
# Think of it like a rectangle. Curves go from mid-points of the sides
|
|
38
|
+
# of the rectangle. Control points are at 1/4 and 3/4 of the side.
|
|
39
|
+
# :nodoc:
|
|
40
|
+
# @api private
|
|
41
|
+
def ellipse(x, y, w, h, fill_color, stroke_color, stroke_width)
|
|
42
|
+
use_cairo do |cc|
|
|
43
|
+
cc.move_to(x, y + 0.5*h) # start west
|
|
44
|
+
cc.curve_to(x, y + 0.25*h, # west to north
|
|
45
|
+
x + 0.25*w, y,
|
|
46
|
+
x + 0.5*w, y)
|
|
47
|
+
cc.curve_to(x + 0.75*w, y, # north to east
|
|
48
|
+
x + w, y + 0.25*h,
|
|
49
|
+
x + w, y + 0.5*h)
|
|
50
|
+
cc.curve_to(x + w, y + 0.75*h, # east to south
|
|
51
|
+
x + 0.75*w, y + h,
|
|
52
|
+
x + 0.5*w, y + h)
|
|
53
|
+
cc.curve_to(x + 0.25*w, y + h, # south to west
|
|
54
|
+
x, y + 0.75*h,
|
|
55
|
+
x, y + 0.5*h)
|
|
56
|
+
cc.set_source_squibcolor(stroke_color)
|
|
57
|
+
cc.set_line_width(stroke_width)
|
|
58
|
+
cc.stroke_preserve
|
|
59
|
+
cc.set_source_squibcolor(fill_color)
|
|
60
|
+
cc.fill
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
35
64
|
# :nodoc:
|
|
36
65
|
# @api private
|
|
37
66
|
def triangle(x1, y1, x2, y2, x3, y3, fill_color, stroke_color, stroke_width)
|
|
@@ -74,5 +103,50 @@ module Squib
|
|
|
74
103
|
end
|
|
75
104
|
end
|
|
76
105
|
|
|
106
|
+
# :nodoc:
|
|
107
|
+
# @api private
|
|
108
|
+
def star(x, y, n, angle, inner_radius, outer_radius, fill_color, stroke_color, stroke_width)
|
|
109
|
+
use_cairo do |cc|
|
|
110
|
+
cc.translate(x, y)
|
|
111
|
+
cc.rotate(angle)
|
|
112
|
+
cc.translate(-x, -y)
|
|
113
|
+
cc.move_to(x + outer_radius, y) #i = 0, so cos(0)=1 and sin(0)=0
|
|
114
|
+
theta = Math::PI / n.to_f # i.e. (2*pi) / (2*n)
|
|
115
|
+
0.upto(2 * n) do |i|
|
|
116
|
+
radius = i.even? ? outer_radius : inner_radius
|
|
117
|
+
cc.line_to(x + radius * Math::cos(i * theta),
|
|
118
|
+
y + radius * Math::sin(i * theta))
|
|
119
|
+
end
|
|
120
|
+
cc.close_path
|
|
121
|
+
cc.set_source_squibcolor(stroke_color)
|
|
122
|
+
cc.set_line_width(stroke_width)
|
|
123
|
+
cc.fill_preserve
|
|
124
|
+
cc.set_source_squibcolor(fill_color)
|
|
125
|
+
cc.stroke
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# :nodoc:
|
|
130
|
+
# @api private
|
|
131
|
+
def polygon(x, y, n, angle, radius, fill_color, stroke_color, stroke_width)
|
|
132
|
+
use_cairo do |cc|
|
|
133
|
+
cc.translate(x, y)
|
|
134
|
+
cc.rotate(angle)
|
|
135
|
+
cc.translate(-x, -y)
|
|
136
|
+
cc.move_to(x + radius, y) # i = 0, so cos(0)=1 and sin(0)=0
|
|
137
|
+
theta = (2 * Math::PI) / n.to_f
|
|
138
|
+
0.upto(n) do |i|
|
|
139
|
+
cc.line_to(x + radius * Math::cos(i * theta),
|
|
140
|
+
y + radius * Math::sin(i * theta))
|
|
141
|
+
end
|
|
142
|
+
cc.close_path
|
|
143
|
+
cc.set_source_squibcolor(stroke_color)
|
|
144
|
+
cc.set_line_width(stroke_width)
|
|
145
|
+
cc.fill_preserve
|
|
146
|
+
cc.set_source_squibcolor(fill_color)
|
|
147
|
+
cc.stroke
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
77
151
|
end
|
|
78
152
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'squib/graphics/cairo_context_wrapper'
|
|
2
|
+
|
|
1
3
|
module Squib
|
|
2
4
|
class Deck
|
|
3
5
|
|
|
@@ -16,8 +18,9 @@ module Squib
|
|
|
16
18
|
out_width = range.size * ((@width - 2*trim) * scale * offset) + 2*margin
|
|
17
19
|
out_height = reflect_offset + (1.0 + reflect_percent) * (@height - 2*trim) + 2*margin
|
|
18
20
|
out_cc = Cairo::Context.new(Cairo::ImageSurface.new(out_width, out_height))
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
wrapper = Squib::Graphics::CairoContextWrapper.new(out_cc)
|
|
22
|
+
wrapper.set_source_squibcolor(fill_color)
|
|
23
|
+
wrapper.paint
|
|
21
24
|
|
|
22
25
|
cards = range.collect { |i| @cards[i] }
|
|
23
26
|
cards.each_with_index do |card, i|
|
data/lib/squib/graphics/text.rb
CHANGED
|
@@ -6,8 +6,8 @@ module Squib
|
|
|
6
6
|
|
|
7
7
|
# :nodoc:
|
|
8
8
|
# @api private
|
|
9
|
-
def draw_text_hint(cc,x,y,layout, color
|
|
10
|
-
color = @deck.text_hint if color.eql? 'off' and not @deck.text_hint.to_s.eql? 'off'
|
|
9
|
+
def draw_text_hint(cc, x, y, layout, color)
|
|
10
|
+
color = @deck.text_hint if color.to_s.eql? 'off' and not @deck.text_hint.to_s.eql? 'off'
|
|
11
11
|
return if color.to_s.eql? 'off' or color.nil?
|
|
12
12
|
# when w,h < 0, it was never set. extents[1] are ink extents
|
|
13
13
|
w = layout.width / Pango::SCALE
|
|
@@ -78,7 +78,7 @@ module Squib
|
|
|
78
78
|
|
|
79
79
|
def set_font_rendering_opts!(layout)
|
|
80
80
|
font_options = Cairo::FontOptions.new
|
|
81
|
-
font_options.antialias = ANTIALIAS_OPTS[(@deck.antialias
|
|
81
|
+
font_options.antialias = Conf::ANTIALIAS_OPTS[(@deck.antialias || 'gray').downcase]
|
|
82
82
|
font_options.hint_metrics = 'on' # TODO make this configurable
|
|
83
83
|
font_options.hint_style = 'full' # TODO make this configurable
|
|
84
84
|
layout.context.font_options = font_options
|
|
@@ -127,7 +127,7 @@ module Squib
|
|
|
127
127
|
while (key = next_embed(embed.rules.keys, clean_str)) != nil
|
|
128
128
|
rule = embed.rules[key]
|
|
129
129
|
spacing = rule[:width] * Pango::SCALE
|
|
130
|
-
index = clean_str.index(key)
|
|
130
|
+
index = clean_str.index(key)
|
|
131
131
|
index = clean_str[0..index].bytesize #convert to byte index (bug #57)
|
|
132
132
|
str = str.sub(key, "<span size=\"#{ZERO_WIDTH_CHAR_SIZE}\">a<span letter_spacing=\"#{spacing.to_i}\">a</span>a</span>")
|
|
133
133
|
layout.markup = str
|
|
@@ -143,12 +143,22 @@ module Squib
|
|
|
143
143
|
return draw_calls
|
|
144
144
|
end
|
|
145
145
|
|
|
146
|
+
def stroke_outline!(cc, layout, stroke_width, stroke_color)
|
|
147
|
+
if stroke_width > 0
|
|
148
|
+
cc.set_source_squibcolor(stroke_color)
|
|
149
|
+
cc.set_line_width(stroke_width)
|
|
150
|
+
cc.pango_layout_path(layout)
|
|
151
|
+
cc.stroke
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
146
155
|
# :nodoc:
|
|
147
156
|
# @api private
|
|
148
157
|
def text(embed,str, font, font_size, color,
|
|
149
158
|
x, y, width, height,
|
|
150
159
|
markup, justify, wrap, ellipsize,
|
|
151
|
-
spacing, align, valign, hint, angle
|
|
160
|
+
spacing, align, valign, hint, angle,
|
|
161
|
+
stroke_color, stroke_width)
|
|
152
162
|
Squib.logger.debug {"Placing '#{str}'' with font '#{font}' @ #{x}, #{y}, color: #{color}, angle: #{angle} etc."}
|
|
153
163
|
extents = nil
|
|
154
164
|
str = str.to_s
|
|
@@ -164,7 +174,7 @@ module Squib
|
|
|
164
174
|
layout.font_description = font_desc
|
|
165
175
|
layout.text = str
|
|
166
176
|
if markup
|
|
167
|
-
str =
|
|
177
|
+
str = @deck.typographer.process(layout.text)
|
|
168
178
|
layout.markup = str
|
|
169
179
|
end
|
|
170
180
|
|
|
@@ -185,6 +195,7 @@ module Squib
|
|
|
185
195
|
|
|
186
196
|
cc.update_pango_layout(layout)
|
|
187
197
|
cc.show_pango_layout(layout)
|
|
198
|
+
stroke_outline!(cc, layout, stroke_width, stroke_color)
|
|
188
199
|
begin
|
|
189
200
|
embed_draws.each { |ed| ed[:draw].call(self, ed[:x], ed[:y] + vertical_start) }
|
|
190
201
|
rescue Exception => e
|
|
@@ -194,7 +205,7 @@ module Squib
|
|
|
194
205
|
puts "=================="
|
|
195
206
|
raise e
|
|
196
207
|
end
|
|
197
|
-
draw_text_hint(cc, x, y, layout, hint
|
|
208
|
+
draw_text_hint(cc, x, y, layout, hint)
|
|
198
209
|
extents = { width: layout.extents[1].width / Pango::SCALE,
|
|
199
210
|
height: layout.extents[1].height / Pango::SCALE }
|
|
200
211
|
end
|
data/lib/squib/input_helpers.rb
CHANGED
|
@@ -130,8 +130,8 @@ module Squib
|
|
|
130
130
|
def colorify(opts, nillable=false, key=:color)
|
|
131
131
|
opts[key].each_with_index do |color, i|
|
|
132
132
|
unless nillable && color.nil?
|
|
133
|
-
if
|
|
134
|
-
color =
|
|
133
|
+
if custom_colors.key? color.to_s
|
|
134
|
+
color = custom_colors[color.to_s]
|
|
135
135
|
end
|
|
136
136
|
opts[key][i] = color
|
|
137
137
|
end
|
data/lib/squib/version.rb
CHANGED
data/samples/csv_import.rb
CHANGED
|
@@ -5,15 +5,13 @@ Squib::Deck.new(cards: 2) do
|
|
|
5
5
|
|
|
6
6
|
# Outputs a hash of arrays with the header names as keys
|
|
7
7
|
data = csv file: 'sample.csv'
|
|
8
|
-
|
|
9
|
-
text str: data['Name'], x: 250, y: 55, font: 'Arial 54'
|
|
8
|
+
text str: data['Type'], x: 250, y: 55, font: 'Arial 54'
|
|
10
9
|
text str: data['Level'], x: 65, y: 65, font: 'Arial 72'
|
|
11
|
-
|
|
10
|
+
|
|
11
|
+
save format: :png, prefix: 'sample_csv_'
|
|
12
12
|
|
|
13
13
|
# You can also specify the sheet, starting at 0
|
|
14
14
|
data = xlsx file: 'sample.xlsx', sheet: 2
|
|
15
|
-
|
|
16
|
-
save format: :png, prefix: 'sample_csv_'
|
|
17
15
|
end
|
|
18
16
|
|
|
19
17
|
# CSV is also a Squib-module-level function, so this also works:
|
data/samples/custom-config.yml
CHANGED
data/samples/custom_config.rb
CHANGED
|
@@ -4,7 +4,7 @@ Squib::Deck.new(config: 'custom-config.yml') do
|
|
|
4
4
|
# Custom color defined in our config
|
|
5
5
|
background color: :foo
|
|
6
6
|
|
|
7
|
-
# Hints
|
|
7
|
+
# Hints can be turned on in the config file
|
|
8
8
|
text str: 'The Title', x: 0, y: 78, width: 825,
|
|
9
9
|
font: 'Arial 72', align: :center
|
|
10
10
|
|
data/samples/draw_shapes.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'squib'
|
|
2
2
|
|
|
3
3
|
Squib::Deck.new do
|
|
4
|
+
background color: :white
|
|
4
5
|
rect x: 300, y: 300, width: 400, height: 400,
|
|
5
6
|
fill_color: :blue, stroke_color: :red, stroke_width: 50.0
|
|
6
7
|
|
|
@@ -20,5 +21,15 @@ Squib::Deck.new do
|
|
|
20
21
|
stroke_width: 12.0, stroke_color: :cyan,
|
|
21
22
|
fill_color: :burgundy
|
|
22
23
|
|
|
24
|
+
ellipse x: 50, y: 925, width: 200, height: 100,
|
|
25
|
+
stroke_width: 5.0, stroke_color: :cyan,
|
|
26
|
+
fill_color: :burgundy
|
|
27
|
+
|
|
28
|
+
star x: 300, y: 1000, n: 5, inner_radius: 10, outer_radius: 25,
|
|
29
|
+
fill_color: :burgundy, stroke_color: :cyan, stroke_width: 3
|
|
30
|
+
|
|
31
|
+
polygon x: 500, y: 1000, n: 5, radius: 25, angle: Math::PI / 2,
|
|
32
|
+
fill_color: :burgundy, stroke_color: :cyan, stroke_width: 2
|
|
33
|
+
|
|
23
34
|
save_png prefix: 'shape_'
|
|
24
35
|
end
|
data/samples/embed_text.rb
CHANGED
|
@@ -61,7 +61,7 @@ Squib::Deck.new do
|
|
|
61
61
|
text(str: embed_text, font: 'Sans 21',
|
|
62
62
|
x: 400, y: 320, width: 180, height: 300,
|
|
63
63
|
align: :center, ellipsize: false, justify: false, hint: :magenta) do |embed|
|
|
64
|
-
embed.svg key: ':tool:', width: 28, height: 28,
|
|
64
|
+
embed.svg key: ':tool:', width: 28, height: 28, data: File.read('spanner.svg')
|
|
65
65
|
embed.svg key: ':health:', width: 28, height: 28, file: 'glass-heart.svg'
|
|
66
66
|
embed.png key: ':purse:', width: 28, height: 28, file: 'shiny-purse.png'
|
|
67
67
|
end
|
data/samples/hand.rb
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'squib'
|
|
2
|
+
|
|
3
|
+
Squib::Deck.new(cards: 8, layout: 'playing-card.yml') do
|
|
4
|
+
background color: :cyan
|
|
5
|
+
rect x: 37, y: 37, width: 750, height: 1050, fill_color: :black, radius: 25
|
|
6
|
+
rect x: 75, y: 75, width: 675, height: 975, fill_color: :white, radius: 20
|
|
7
|
+
text str: ('A'..'Z').to_a, layout: :bonus_ul, font: 'Sans bold 100'
|
|
8
|
+
|
|
9
|
+
# Defaults are sensible
|
|
10
|
+
hand #saves to _output/hand.png
|
|
11
|
+
|
|
12
|
+
# Here's a prettier version:
|
|
13
|
+
# - Each card is trimmed with rounded corners
|
|
14
|
+
# - Zero radius means cards rotate about the bottom of the card
|
|
15
|
+
# - Cards are shown in reverse order
|
|
16
|
+
hand trim: 37.5, trim_radius: 25,
|
|
17
|
+
radius: 0,
|
|
18
|
+
range: 7.downto(0),
|
|
19
|
+
file: 'hand_pretty.png'
|
|
20
|
+
|
|
21
|
+
# Tip: you can have the top card be on the left by reversing the range
|
|
22
|
+
# angle_range: (Math::PI / 4)..(Math::PI / -4)
|
|
23
|
+
end
|
|
24
|
+
|
data/samples/load_images.rb
CHANGED
|
@@ -17,6 +17,20 @@ Squib::Deck.new(width: 825, height: 1125, cards: 1) do
|
|
|
17
17
|
# Squib prepends a #-sign if one is not specified
|
|
18
18
|
svg file: 'spanner.svg', id: 'backdrop', x: 50, y: 450, width: 125, height: 125
|
|
19
19
|
|
|
20
|
+
# We can also load SVGs as a string of XML
|
|
21
|
+
svg data: File.read('spanner.svg'), x: 50, y: 600, width: 75, height: 75
|
|
22
|
+
|
|
23
|
+
# The svg data field works nicely with modifying the SVG XML on-the-fly.
|
|
24
|
+
# To run this one, do `gem install game_icons` and uncomment the following
|
|
25
|
+
#
|
|
26
|
+
# require 'game_icons'
|
|
27
|
+
# svg data: GameIcons.get('angler-fish').recolor(fg: '#ccc', bg: '#333').string,
|
|
28
|
+
# x: 150, y: 600, width: 75, height: 75
|
|
29
|
+
#
|
|
30
|
+
# More examples at https://github.com/andymeneely/game_icons
|
|
31
|
+
# (or `gem install game_icons`) to get & manipulate art from game-icons.net
|
|
32
|
+
# Nokogiri (already included in Squib) is also great for XML manipulation.
|
|
33
|
+
|
|
20
34
|
# WARNING! If you choose to use the SVG ID, the x-y coordinates are still
|
|
21
35
|
# relative to the SVG page. See this example in an SVG editor
|
|
22
36
|
svg file: 'offset.svg', id: 'thing', x: 0, y: 0, width: 600, height: 600
|
data/samples/sample.csv
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
Type,"
|
|
2
|
-
Thief,
|
|
3
|
-
Mastermind,
|
|
1
|
+
Type,"Level"
|
|
2
|
+
Thief,1
|
|
3
|
+
Mastermind,2
|
data/samples/text_options.rb
CHANGED
|
@@ -78,6 +78,10 @@ Squib::Deck.new(width: 825, height: 1125, cards: 3) do
|
|
|
78
78
|
embed.svg key: ':health:', width: 28, height: 28, file: 'glass-heart.svg'
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
+
text str: "Stroke n <span fgcolor=\"\#ff0000\">fill</span>",
|
|
82
|
+
color: :green, stroke_width: 2.0, stroke_color: :blue,
|
|
83
|
+
x: '1.8in', y: '3in', width: '0.85in', font: 'Sans Bold 26', markup: true
|
|
84
|
+
|
|
81
85
|
text str: "<b>Markup</b> is <i>quite</i> <s>'easy'</s> <span fgcolor=\"\#ff0000\">awesome</span>. Can't beat those \"smart\" 'quotes', now with 10--20% more en-dashes --- and em-dashes --- with explicit ellipses too...",
|
|
82
86
|
markup: true,
|
|
83
87
|
x: 50, y: 1000,
|
data/spec/api/api_data_spec.rb
CHANGED
|
@@ -28,4 +28,23 @@ describe Squib::Deck do
|
|
|
28
28
|
})
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
|
+
|
|
32
|
+
context '#xlsx' do
|
|
33
|
+
it 'loads basic xlsx data' do
|
|
34
|
+
expect(Squib.xlsx(file: xlsx_file('basic.xlsx'))).to eq({
|
|
35
|
+
'Name' => %w(Larry Curly Mo),
|
|
36
|
+
'General Number' => %w(1 2 3), #general types always get loaded as strings with no conversion
|
|
37
|
+
'Actual Number' => [4.0, 5.0, 6.0], #numbers get auto-converted to integers
|
|
38
|
+
})
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'loads xlsx with formulas' do
|
|
42
|
+
expect(Squib.xlsx(file: xlsx_file('formulas.xlsx'))).to eq({
|
|
43
|
+
'A' => %w(1 2),
|
|
44
|
+
'B' => %w(3 4),
|
|
45
|
+
'Sum' => %w(4 6),
|
|
46
|
+
})
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
31
50
|
end
|