squib 0.13.4 → 0.14.beta1
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/.travis.yml +2 -4
- data/CHANGELOG.md +19 -3
- data/README.md +1 -1
- data/bin/squib +1 -16
- data/lib/squib.rb +1 -1
- data/lib/squib/api/data.rb +29 -0
- data/lib/squib/api/save.rb +23 -2
- data/lib/squib/api/shapes.rb +37 -0
- data/lib/squib/api/text.rb +1 -1
- data/lib/squib/api/units.rb +5 -0
- data/lib/squib/args/arg_loader.rb +1 -1
- data/lib/squib/args/coords.rb +3 -1
- data/lib/squib/args/dir_validator.rb +1 -1
- data/lib/squib/args/sheet.rb +9 -2
- data/lib/squib/args/sprue_file.rb +44 -0
- data/lib/squib/args/unit_conversion.rb +2 -0
- data/lib/squib/{layouts → builtin/layouts}/economy.yml +5 -5
- data/lib/squib/{layouts → builtin/layouts}/fantasy.yml +4 -4
- data/lib/squib/{layouts → builtin/layouts}/hand.yml +0 -0
- data/lib/squib/builtin/layouts/party.yml +94 -0
- data/lib/squib/{layouts → builtin/layouts}/playing-card.yml +0 -0
- data/lib/squib/{layouts → builtin/layouts}/tuck_box.yml +1 -1
- data/lib/squib/{project_template → builtin/projects/advanced}/.gitignore +0 -0
- data/lib/squib/{project_template → builtin/projects/advanced}/ABOUT.md +0 -0
- data/lib/squib/builtin/projects/advanced/Gemfile +11 -0
- data/lib/squib/builtin/projects/advanced/Guardfile +21 -0
- data/lib/squib/{project_template → builtin/projects/advanced}/IDEAS.md +0 -0
- data/lib/squib/{project_template → builtin/projects/advanced}/PLAYTESTING.md +0 -0
- data/lib/squib/builtin/projects/advanced/Rakefile +27 -0
- data/lib/squib/{project_template → builtin/projects/advanced}/_output/gitkeep.txt +0 -0
- data/lib/squib/builtin/projects/advanced/config.yml +49 -0
- data/lib/squib/builtin/projects/advanced/data/game.xlsx +0 -0
- data/lib/squib/project_template/PNP NOTES.md b/data/lib/squib/builtin/projects/advanced/docs/PNP → NOTES.md +0 -0
- data/lib/squib/{project_template → builtin/projects/advanced/docs}/RULES.md +0 -0
- data/lib/squib/builtin/projects/advanced/img/example.svg +60 -0
- data/lib/squib/builtin/projects/advanced/layouts/deck.yml +27 -0
- data/lib/squib/builtin/projects/advanced/src/deck.rb +34 -0
- data/lib/squib/builtin/projects/advanced/src/version.rb +3 -0
- data/lib/squib/builtin/projects/basic/.gitignore +4 -0
- data/lib/squib/builtin/projects/basic/ABOUT.md +19 -0
- data/lib/squib/{project_template → builtin/projects/basic}/Gemfile +0 -0
- data/lib/squib/builtin/projects/basic/IDEAS.md +22 -0
- data/lib/squib/builtin/projects/basic/PLAYTESTING.md +26 -0
- data/lib/squib/builtin/projects/basic/PNP NOTES.md +4 -0
- data/lib/squib/builtin/projects/basic/RULES.md +21 -0
- data/lib/squib/{project_template → builtin/projects/basic}/Rakefile +0 -0
- data/lib/squib/builtin/projects/basic/_output/gitkeep.txt +1 -0
- data/lib/squib/{project_template → builtin/projects/basic}/config.yml +0 -0
- data/lib/squib/{project_template → builtin/projects/basic}/deck.rb +0 -0
- data/lib/squib/{project_template → builtin/projects/basic}/layout.yml +0 -0
- data/lib/squib/builtin/sprues/a4_euro_card.yml +42 -0
- data/lib/squib/builtin/sprues/a4_poker_card_8up.yml +40 -0
- data/lib/squib/builtin/sprues/a4_poker_card_9up.yml +42 -0
- data/lib/squib/builtin/sprues/a4_usa_card.yml +42 -0
- data/lib/squib/builtin/sprues/letter_poker_card_9up.yml +25 -0
- data/lib/squib/builtin/sprues/letter_poker_foldable_8up.yml +52 -0
- data/lib/squib/card.rb +1 -1
- data/lib/squib/commands/cli.rb +39 -0
- data/lib/squib/commands/data/template_option.rb +109 -0
- data/lib/squib/commands/make_sprue.rb +275 -0
- data/lib/squib/commands/new.rb +37 -4
- data/lib/squib/constants.rb +6 -1
- data/lib/squib/graphics/cairo_context_wrapper.rb +1 -1
- data/lib/squib/graphics/image.rb +6 -1
- data/lib/squib/graphics/save_doc.rb +6 -4
- data/lib/squib/graphics/save_pdf.rb +13 -8
- data/lib/squib/graphics/save_sprue.rb +228 -0
- data/lib/squib/graphics/shapes.rb +8 -2
- data/lib/squib/graphics/text.rb +4 -3
- data/lib/squib/layout_parser.rb +17 -1
- data/lib/squib/sample_helpers.rb +1 -1
- data/lib/squib/sprues/crop_line.rb +28 -0
- data/lib/squib/sprues/crop_line_dash.rb +35 -0
- data/lib/squib/sprues/invalid_sprue_definition.rb +9 -0
- data/lib/squib/sprues/sprue.rb +203 -0
- data/lib/squib/sprues/sprue_schema.rb +48 -0
- data/lib/squib/version.rb +1 -1
- data/samples/autoscale_font/_autoscale_font.rb +3 -3
- data/samples/backend/_backend.rb +1 -1
- data/samples/basic.rb +2 -2
- data/samples/colors/_colors.rb +1 -1
- data/samples/colors/_gradients.rb +1 -1
- data/samples/config/config_text_markup.rb +3 -3
- data/samples/config/custom_config.rb +1 -1
- data/samples/data/_csv.rb +3 -3
- data/samples/data/_excel.rb +4 -4
- data/samples/data/_yaml.rb +12 -0
- data/samples/images/_images.rb +2 -2
- data/samples/images/_more_load_images.rb +3 -0
- data/samples/images/_unicode.rb +2 -2
- data/samples/intro/02_options.rb +2 -2
- data/samples/layouts/builtin_layouts.rb +27 -4
- data/samples/layouts/layouts.rb +2 -2
- data/samples/proofs/_tgc_proofs.rb +2 -2
- data/samples/ranges/_ranges.rb +3 -3
- data/samples/saves/_hand.rb +1 -1
- data/samples/saves/_save_pdf.rb +4 -0
- data/samples/saves/_saves.rb +7 -1
- data/samples/saves/_showcase.rb +1 -1
- data/samples/shapes/_draw_shapes.rb +5 -1
- data/samples/shapes/_proofs.rb +22 -0
- data/samples/sprues/_builtin_sprues.rb +19 -0
- data/samples/sprues/_fold_sheet.rb +27 -0
- data/samples/sprues/_hex_tiles.rb +15 -0
- data/samples/sprues/_mints.rb +11 -0
- data/samples/sprues/_sprue_example.rb +11 -0
- data/samples/text/_embed_text.rb +14 -14
- data/samples/text/_text.rb +8 -8
- data/samples/text/_text_options.rb +17 -17
- data/squib.gemspec +18 -17
- metadata +126 -44
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'pathname'
|
|
3
|
+
require 'highline'
|
|
4
|
+
require 'bigdecimal'
|
|
5
|
+
require 'yaml'
|
|
6
|
+
require_relative 'data/template_option'
|
|
7
|
+
|
|
8
|
+
module Squib
|
|
9
|
+
# Squib's command-line option
|
|
10
|
+
module Commands
|
|
11
|
+
# Generate a template definition file that can be used for
|
|
12
|
+
# +save_templated_sheet+
|
|
13
|
+
#
|
|
14
|
+
# @api public
|
|
15
|
+
class MakeSprue
|
|
16
|
+
# :nodoc:
|
|
17
|
+
# @api private
|
|
18
|
+
def process(args, input = $stdin, output = $stdout)
|
|
19
|
+
# Get definitions from the user
|
|
20
|
+
@option = prompt(input, output)
|
|
21
|
+
|
|
22
|
+
@printable_edge_right = (
|
|
23
|
+
@option.sheet_width - @option.sheet_margin.right)
|
|
24
|
+
@printable_edge_bottom = (
|
|
25
|
+
@option.sheet_height - @option.sheet_margin.bottom)
|
|
26
|
+
@card_iter_x = @option.card_width + @option.card_gap.horizontal
|
|
27
|
+
@card_iter_y = @option.card_height + @option.card_gap.vertical
|
|
28
|
+
|
|
29
|
+
# Recalculate the sheet margin if the sheet alignment is in the center
|
|
30
|
+
if @option.sheet_align == :center
|
|
31
|
+
@option.sheet_margin = recalculate_center_align_sheet
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# We would now have to output the file
|
|
35
|
+
YAML.dump generate_template, File.new(@option.output_file, 'w')
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
# Accept user input that defines the template.
|
|
41
|
+
def prompt(input, output)
|
|
42
|
+
option = TemplateOption.new
|
|
43
|
+
cli = HighLine.new(input, output)
|
|
44
|
+
|
|
45
|
+
option.unit = cli.choose do |menu|
|
|
46
|
+
menu.prompt = 'What measure unit should we use? '
|
|
47
|
+
menu.choice(:in)
|
|
48
|
+
menu.choice(:cm)
|
|
49
|
+
menu.choice(:mm)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
cli.choose do |menu|
|
|
53
|
+
menu.prompt = 'What paper size you are using? '
|
|
54
|
+
menu.choice('A4, portrait') do
|
|
55
|
+
option.sheet_width = convert_measurement_value(
|
|
56
|
+
210, :mm, option.unit
|
|
57
|
+
)
|
|
58
|
+
option.sheet_height = convert_measurement_value(
|
|
59
|
+
297, :mm, option.unit
|
|
60
|
+
)
|
|
61
|
+
end
|
|
62
|
+
menu.choice('A4, landscape') do
|
|
63
|
+
option.sheet_width = convert_measurement_value(
|
|
64
|
+
297, :mm, option.unit
|
|
65
|
+
)
|
|
66
|
+
option.sheet_height = convert_measurement_value(
|
|
67
|
+
210, :mm, option.unit
|
|
68
|
+
)
|
|
69
|
+
end
|
|
70
|
+
menu.choice('US letter, portrait') do
|
|
71
|
+
option.sheet_width = convert_measurement_value(
|
|
72
|
+
8.5, :in, option.unit
|
|
73
|
+
)
|
|
74
|
+
option.sheet_height = convert_measurement_value(
|
|
75
|
+
11, :in, option.unit
|
|
76
|
+
)
|
|
77
|
+
end
|
|
78
|
+
menu.choice('US letter, landscape') do
|
|
79
|
+
option.sheet_width = convert_measurement_value(
|
|
80
|
+
11, :in, option.unit
|
|
81
|
+
)
|
|
82
|
+
option.sheet_height = convert_measurement_value(
|
|
83
|
+
8.5, :in, option.unit
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
menu.choice('Custom size') do
|
|
87
|
+
option.sheet_width = cli.ask(
|
|
88
|
+
"Custom paper width? (#{option.unit}) ", Float
|
|
89
|
+
)
|
|
90
|
+
option.sheet_height = cli.ask(
|
|
91
|
+
"Custom paper height? (#{option.unit}) ", Float
|
|
92
|
+
)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
option.sheet_margin = cli.ask(
|
|
97
|
+
"Sheet margins? (#{option.unit}) "
|
|
98
|
+
) do |q|
|
|
99
|
+
q.validate = /^((\d+\.\d+|\d+) ){0,3}(\d+\.\d+|\d+)/
|
|
100
|
+
end
|
|
101
|
+
option.sheet_align = cli.choose do |menu|
|
|
102
|
+
menu.prompt = 'How to align cards on sheet? [left] '
|
|
103
|
+
menu.choice(:left)
|
|
104
|
+
menu.choice(:right)
|
|
105
|
+
menu.choice(:center)
|
|
106
|
+
menu.default = :left
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
option.card_width = cli.ask(
|
|
110
|
+
"Card width? (#{option.unit}) ", Float
|
|
111
|
+
) { |q| q.above = 0 }
|
|
112
|
+
option.card_height = cli.ask(
|
|
113
|
+
"Card height? (#{option.unit}) ", Float
|
|
114
|
+
) { |q| q.above = 0 }
|
|
115
|
+
option.card_gap = cli.ask(
|
|
116
|
+
"Gap between cards? (#{option.unit}) "
|
|
117
|
+
) { |q| q.validate = /^((\d+\.\d+|\d+))(\s+(\d+\.\d+|\d+))?/ }
|
|
118
|
+
|
|
119
|
+
option.card_ordering = cli.choose do |menu|
|
|
120
|
+
menu.prompt = 'How to layout your cards? [rows]'
|
|
121
|
+
menu.choice(:rows, text: 'In rows')
|
|
122
|
+
menu.choice(:columns, text: 'In columns')
|
|
123
|
+
menu.default = :rows
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
option.crop_lines = cli.choose do |menu|
|
|
127
|
+
menu.prompt = 'Generate crop lines? [true]'
|
|
128
|
+
menu.choice(:true)
|
|
129
|
+
menu.choice(:false)
|
|
130
|
+
menu.default = :true
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
option.output_file = cli.ask('Output to? ') do |q|
|
|
134
|
+
q.validate = lambda do |path_str|
|
|
135
|
+
path = Pathname.new path_str
|
|
136
|
+
if path.exist?
|
|
137
|
+
path.writable? && !path.directory?
|
|
138
|
+
else
|
|
139
|
+
path.dirname.writable?
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
q.responses[:not_valid] = (
|
|
144
|
+
'The filename specified is not a writable file or is a directory.'
|
|
145
|
+
)
|
|
146
|
+
q.default = 'template.yml'
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
option
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def convert_measurement_value(val, from_unit, to_unit)
|
|
153
|
+
return val if from_unit == to_unit
|
|
154
|
+
|
|
155
|
+
if from_unit == :in
|
|
156
|
+
val_mm = val * 25.4
|
|
157
|
+
elsif from_unit == :cm
|
|
158
|
+
val_mm = val * 10.0
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
if to_unit == :in
|
|
162
|
+
val_mm / 25.4
|
|
163
|
+
elsif to_unit == :cm
|
|
164
|
+
val_mm / 10.0
|
|
165
|
+
else
|
|
166
|
+
val_mm
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def generate_template
|
|
171
|
+
x = @option.sheet_margin.left
|
|
172
|
+
y = @option.sheet_margin.top
|
|
173
|
+
cards = []
|
|
174
|
+
horizontal_crop_lines = Set.new
|
|
175
|
+
vertical_crop_lines = Set.new
|
|
176
|
+
|
|
177
|
+
while (
|
|
178
|
+
x + @card_iter_x < @printable_edge_right &&
|
|
179
|
+
y + @card_iter_y < @printable_edge_bottom)
|
|
180
|
+
xpos = x + @option.card_gap.horizontal
|
|
181
|
+
ypos = y + @option.card_gap.vertical
|
|
182
|
+
cards.push(
|
|
183
|
+
'x' => "#{xpos}#{@option.unit}",
|
|
184
|
+
'y' => "#{ypos}#{@option.unit}"
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# Append the crop lines
|
|
188
|
+
vertical_crop_lines.add xpos
|
|
189
|
+
vertical_crop_lines.add xpos + @option.card_width
|
|
190
|
+
horizontal_crop_lines.add ypos
|
|
191
|
+
horizontal_crop_lines.add ypos + @option.card_height
|
|
192
|
+
|
|
193
|
+
# Calculate the next iterator
|
|
194
|
+
if @option.card_ordering == :rows
|
|
195
|
+
x, y = next_card_pos_row(x, y)
|
|
196
|
+
elsif @option.card_ordering == :columns
|
|
197
|
+
x, y = next_card_pos_col(x, y)
|
|
198
|
+
else
|
|
199
|
+
raise RunTimeException, 'Invalid card ordering value received'
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
output = {
|
|
204
|
+
'sheet_width' => "#{@option.sheet_width}#{@option.unit}",
|
|
205
|
+
'sheet_height' => "#{@option.sheet_height}#{@option.unit}",
|
|
206
|
+
'card_width' => "#{@option.card_width}#{@option.unit}",
|
|
207
|
+
'card_height' => "#{@option.card_height}#{@option.unit}",
|
|
208
|
+
'cards' => cards
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if @option.crop_lines == :true
|
|
212
|
+
lines = []
|
|
213
|
+
vertical_crop_lines.each do |val|
|
|
214
|
+
lines.push(
|
|
215
|
+
'type' => :vertical, 'position' => "#{val}#{@option.unit}"
|
|
216
|
+
)
|
|
217
|
+
end
|
|
218
|
+
horizontal_crop_lines.each do |val|
|
|
219
|
+
lines.push(
|
|
220
|
+
'type' => :horizontal, 'position' => "#{val}#{@option.unit}"
|
|
221
|
+
)
|
|
222
|
+
end
|
|
223
|
+
output['crop_line'] = { 'lines' => lines }
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Return the output data
|
|
227
|
+
output
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def recalculate_center_align_sheet
|
|
231
|
+
# We will still respect the user specified margins
|
|
232
|
+
printable_width = (
|
|
233
|
+
@option.sheet_width - @option.sheet_margin.left -
|
|
234
|
+
@option.sheet_margin.right)
|
|
235
|
+
num_of_cols, remainder = printable_width.divmod(@card_iter_x)
|
|
236
|
+
if (
|
|
237
|
+
@option.card_gap.horizontal > 0 &&
|
|
238
|
+
remainder < @option.card_gap.horizontal)
|
|
239
|
+
num_of_cols -= 1
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
new_hor_margin = (
|
|
243
|
+
(@option.sheet_width - num_of_cols * @card_iter_x -
|
|
244
|
+
@option.card_gap.horizontal) / 2)
|
|
245
|
+
Margin.new [
|
|
246
|
+
@option.sheet_margin.top,
|
|
247
|
+
new_hor_margin,
|
|
248
|
+
@option.sheet_margin.bottom
|
|
249
|
+
]
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def next_card_pos_row(x, y)
|
|
253
|
+
x += @card_iter_x
|
|
254
|
+
|
|
255
|
+
if (x + @card_iter_x) > @printable_edge_right
|
|
256
|
+
x = @option.sheet_margin.left
|
|
257
|
+
y += @card_iter_y
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
[x, y]
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def next_card_pos_col(x, y)
|
|
264
|
+
y += @card_iter_y
|
|
265
|
+
|
|
266
|
+
if (y + @card_iter_y) > @printable_edge_bottom
|
|
267
|
+
x += @card_iter_x
|
|
268
|
+
y = @option.sheet_margin.top
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
[x, y]
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
end
|
data/lib/squib/commands/new.rb
CHANGED
|
@@ -23,20 +23,53 @@ module Squib
|
|
|
23
23
|
|
|
24
24
|
# :nodoc:
|
|
25
25
|
# @api private
|
|
26
|
-
def process(args)
|
|
27
|
-
raise
|
|
26
|
+
def process(args, advanced)
|
|
27
|
+
raise empty_path_error if args.empty?
|
|
28
28
|
|
|
29
29
|
new_project_path = File.expand_path(args.join(' '), Dir.pwd)
|
|
30
|
-
template_path = File.expand_path('../project_template', File.dirname(__FILE__))
|
|
31
30
|
|
|
32
31
|
FileUtils.mkdir_p new_project_path
|
|
33
32
|
if !Dir["#{new_project_path}/**/*"].empty?
|
|
34
33
|
$stderr.puts "#{new_project_path} exists and is not empty. Doing nothing and quitting."
|
|
35
34
|
else
|
|
36
35
|
Dir.chdir(new_project_path) do
|
|
37
|
-
FileUtils.cp_r template_path + '/.', new_project_path
|
|
36
|
+
FileUtils.cp_r template_path(advanced) + '/.', new_project_path
|
|
38
37
|
end
|
|
39
38
|
end
|
|
39
|
+
puts "Created basic Squib project in #{new_project_path}."
|
|
40
|
+
puts advanced_message if advanced
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def empty_path_error
|
|
44
|
+
ArgumentError.new('Please specify a path.')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def template_path(advanced)
|
|
48
|
+
path = case advanced
|
|
49
|
+
when true
|
|
50
|
+
'../builtin/projects/advanced'
|
|
51
|
+
else
|
|
52
|
+
'../builtin/projects/basic'
|
|
53
|
+
end
|
|
54
|
+
File.expand_path(path, File.dirname(__FILE__))
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def advanced_message
|
|
58
|
+
<<-EOS
|
|
59
|
+
|
|
60
|
+
This is the advanced layout designed for larger games. Everything is
|
|
61
|
+
organized into separate directories and the workflow is all based on
|
|
62
|
+
the Rakefile.
|
|
63
|
+
|
|
64
|
+
From within this directory, run `bundle install` to install extra
|
|
65
|
+
gems.
|
|
66
|
+
|
|
67
|
+
After that, run `rake` to build. Check out the Rakefile for more.
|
|
68
|
+
|
|
69
|
+
Happy Squibbing! And best of luck with your game.
|
|
70
|
+
-Andy (@andymeneely)
|
|
71
|
+
|
|
72
|
+
EOS
|
|
40
73
|
end
|
|
41
74
|
|
|
42
75
|
end
|
data/lib/squib/constants.rb
CHANGED
|
@@ -3,10 +3,15 @@ module Squib
|
|
|
3
3
|
# System-wide default font
|
|
4
4
|
# :nodoc:
|
|
5
5
|
# @api public
|
|
6
|
-
DEFAULT_FONT = 'Arial
|
|
6
|
+
DEFAULT_FONT = 'Arial 12'
|
|
7
7
|
|
|
8
8
|
# Used for inch-cm conversion
|
|
9
9
|
# :nodoc:
|
|
10
10
|
# @api private
|
|
11
11
|
INCHES_IN_CM = 0.393700787
|
|
12
|
+
|
|
13
|
+
# Used for points-inch conversion
|
|
14
|
+
# :nodoc:
|
|
15
|
+
# @api private
|
|
16
|
+
POINTS_PER_IN = 72.0
|
|
12
17
|
end
|
|
@@ -25,7 +25,7 @@ module Squib
|
|
|
25
25
|
:operator=, :show_page, :clip, :transform, :mask, :create_pango_layout,
|
|
26
26
|
:antialias=, :curve_to, :matrix, :matrix=, :identity_matrix, :pango_layout_path,
|
|
27
27
|
:stroke_preserve, :target, :new_path, :fill_preserve, :close_path,
|
|
28
|
-
:set_line_join, :set_line_cap, :set_dash
|
|
28
|
+
:set_line_join, :set_line_cap, :set_dash, :arc, :arc_negative
|
|
29
29
|
|
|
30
30
|
# :nodoc:
|
|
31
31
|
# @api private
|
data/lib/squib/graphics/image.rb
CHANGED
|
@@ -67,7 +67,12 @@ module Squib
|
|
|
67
67
|
Squib.logger.warn 'Both an SVG file and SVG data were specified' unless file.to_s.empty? || svg_args.data.to_s.empty?
|
|
68
68
|
return if (file.nil? or file.eql? '') and svg_args.data.nil? # nothing specified TODO Move this out to arg validator
|
|
69
69
|
svg_args.data = File.read(file) if svg_args.data.to_s.empty?
|
|
70
|
-
|
|
70
|
+
begin
|
|
71
|
+
svg = Rsvg::Handle.new_from_data(svg_args.data)
|
|
72
|
+
rescue Rsvg::Error::Failed
|
|
73
|
+
Squib.logger.error "Invalid SVG data. Is '#{file}' a valid svg file?"
|
|
74
|
+
return
|
|
75
|
+
end
|
|
71
76
|
box.width = svg.width if box.width == :native
|
|
72
77
|
box.height = svg.height if box.height == :native
|
|
73
78
|
box.width = svg.width.to_f * box.height.to_f / svg.height.to_f if box.width == :scale
|
|
@@ -9,7 +9,8 @@ module Squib
|
|
|
9
9
|
cc = Cairo::Context.new(Cairo::ImageSurface.new(sheet_width, sheet_height))
|
|
10
10
|
num_this_sheet = 0
|
|
11
11
|
sheet_num = 0
|
|
12
|
-
|
|
12
|
+
y = sheet.margin
|
|
13
|
+
x = sheet.rtl ? (sheet_width - sheet.margin - sheet.gap - @width) : sheet.margin
|
|
13
14
|
@progress_bar.start("Saving PNG sheet to #{batch.summary}", @cards.size + 1) do |bar|
|
|
14
15
|
range.each do |i|
|
|
15
16
|
if num_this_sheet >= (sheet.columns * sheet.rows) # new sheet
|
|
@@ -18,16 +19,17 @@ module Squib
|
|
|
18
19
|
new_sheet = false
|
|
19
20
|
num_this_sheet = 0
|
|
20
21
|
sheet_num += 1
|
|
21
|
-
|
|
22
|
+
y = sheet.margin
|
|
23
|
+
x = sheet.rtl ? (sheet_width - sheet.margin - sheet.gap - @width) : sheet.margin
|
|
22
24
|
cc = Cairo::Context.new(Cairo::ImageSurface.new(sheet_width, sheet_height))
|
|
23
25
|
end
|
|
24
26
|
surface = trim(@cards[i].cairo_surface, sheet.trim, @width, @height)
|
|
25
27
|
cc.set_source(surface, x, y)
|
|
26
28
|
cc.paint
|
|
27
29
|
num_this_sheet += 1
|
|
28
|
-
x += surface.width + sheet.gap
|
|
30
|
+
x += (surface.width + sheet.gap) * (sheet.rtl ? -1 : 1)
|
|
29
31
|
if num_this_sheet % sheet.columns == 0 # new row
|
|
30
|
-
x = sheet.margin
|
|
32
|
+
x = sheet.rtl ? (sheet_width - sheet.margin - sheet.gap - @width) : sheet.margin
|
|
31
33
|
y += surface.height + sheet.gap
|
|
32
34
|
end
|
|
33
35
|
bar.increment
|
|
@@ -12,10 +12,13 @@ module Squib
|
|
|
12
12
|
# @api private
|
|
13
13
|
def render_pdf(range, sheet)
|
|
14
14
|
cc = init_cc(sheet)
|
|
15
|
-
cc.scale(
|
|
16
|
-
x, y = sheet.margin, sheet.margin
|
|
15
|
+
cc.scale(POINTS_PER_IN / @deck.dpi, POINTS_PER_IN / @deck.dpi) # for bug #62
|
|
17
16
|
card_width = @deck.width - 2 * sheet.trim
|
|
18
17
|
card_height = @deck.height - 2 * sheet.trim
|
|
18
|
+
start_x_pos = sheet.rtl ? sheet.width - sheet.margin - card_width - 2 * sheet.trim : sheet.margin
|
|
19
|
+
x_increment = (card_width + sheet.gap) * (sheet.rtl ? -1 : 1)
|
|
20
|
+
y = sheet.margin
|
|
21
|
+
x = start_x_pos
|
|
19
22
|
track_progress(range, sheet) do |bar|
|
|
20
23
|
range.each do |i|
|
|
21
24
|
card = @deck.cards[i]
|
|
@@ -38,14 +41,16 @@ module Squib
|
|
|
38
41
|
bar.increment
|
|
39
42
|
cc.reset_clip
|
|
40
43
|
cc.translate(-x, -y)
|
|
44
|
+
|
|
41
45
|
draw_crop_marks(cc, x, y, sheet)
|
|
42
|
-
x +=
|
|
43
|
-
if x > (sheet.width - card_width - sheet.margin)
|
|
44
|
-
x =
|
|
46
|
+
x += x_increment
|
|
47
|
+
if (x > (sheet.width - card_width - sheet.margin)) or (x < sheet.margin)
|
|
48
|
+
x = start_x_pos
|
|
45
49
|
y += card.height + sheet.gap - 2 * sheet.trim
|
|
46
50
|
if y > (sheet.height - card_height - sheet.margin)
|
|
47
51
|
cc.show_page # next page
|
|
48
|
-
|
|
52
|
+
y = sheet.margin
|
|
53
|
+
x = start_x_pos
|
|
49
54
|
end
|
|
50
55
|
end
|
|
51
56
|
end
|
|
@@ -59,8 +64,8 @@ module Squib
|
|
|
59
64
|
def init_cc(sheet)
|
|
60
65
|
Cairo::Context.new(Cairo::PDFSurface.new(
|
|
61
66
|
"#{sheet.dir}/#{sheet.file}",
|
|
62
|
-
sheet.width *
|
|
63
|
-
sheet.height *
|
|
67
|
+
sheet.width * POINTS_PER_IN / @deck.dpi, #PDF thinks in 72 DPI "points"
|
|
68
|
+
sheet.height * POINTS_PER_IN / @deck.dpi)
|
|
64
69
|
)
|
|
65
70
|
end
|
|
66
71
|
|