squib 0.14.1 → 0.14.2
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 +5 -5
- data/.gitignore +41 -41
- data/.travis.yml +19 -19
- data/CHANGELOG.md +357 -340
- data/CONTRIBUTING.md +40 -40
- data/Gemfile +2 -2
- data/LICENSE.txt +22 -22
- data/README.md +121 -121
- data/RELEASE TODO.md +21 -21
- data/Rakefile +48 -48
- data/appveyor.yml +24 -24
- data/bin/squib +4 -4
- data/lib/squib.rb +32 -32
- data/lib/squib/api/background.rb +15 -15
- data/lib/squib/api/data.rb +137 -137
- data/lib/squib/api/groups.rb +54 -54
- data/lib/squib/api/image.rb +49 -49
- data/lib/squib/api/save.rb +83 -83
- data/lib/squib/api/settings.rb +21 -21
- data/lib/squib/api/shapes.rb +124 -124
- data/lib/squib/api/text.rb +25 -25
- data/lib/squib/api/text_embed.rb +71 -71
- data/lib/squib/api/units.rb +27 -27
- data/lib/squib/args/arg_loader.rb +126 -126
- data/lib/squib/args/box.rb +55 -55
- data/lib/squib/args/card_range.rb +32 -32
- data/lib/squib/args/color_validator.rb +12 -12
- data/lib/squib/args/coords.rb +35 -35
- data/lib/squib/args/csv_opts.rb +25 -25
- data/lib/squib/args/dir_validator.rb +16 -16
- data/lib/squib/args/draw.rb +92 -92
- data/lib/squib/args/embed_adjust.rb +25 -25
- data/lib/squib/args/embed_key.rb +17 -17
- data/lib/squib/args/hand_special.rb +37 -37
- data/lib/squib/args/import.rb +40 -40
- data/lib/squib/args/input_file.rb +37 -37
- data/lib/squib/args/paint.rb +44 -44
- data/lib/squib/args/paragraph.rb +116 -116
- data/lib/squib/args/save_batch.rb +63 -63
- data/lib/squib/args/scale_box.rb +53 -53
- data/lib/squib/args/sheet.rb +172 -172
- data/lib/squib/args/showcase_special.rb +38 -38
- data/lib/squib/args/sprue_file.rb +44 -44
- data/lib/squib/args/svg_special.rb +37 -37
- data/lib/squib/args/transform.rb +61 -61
- data/lib/squib/args/typographer.rb +119 -119
- data/lib/squib/args/unit_conversion.rb +29 -29
- data/lib/squib/builtin/layouts/economy.yml +85 -85
- data/lib/squib/builtin/layouts/fantasy.yml +101 -101
- data/lib/squib/builtin/layouts/hand.yml +62 -62
- data/lib/squib/builtin/layouts/party.yml +94 -94
- data/lib/squib/builtin/layouts/playing-card.yml +35 -35
- data/lib/squib/builtin/layouts/tuck_box.yml +46 -46
- data/lib/squib/builtin/projects/advanced/.gitignore +4 -4
- data/lib/squib/builtin/projects/advanced/ABOUT.md +19 -19
- data/lib/squib/builtin/projects/advanced/Gemfile +11 -11
- data/lib/squib/builtin/projects/advanced/Guardfile +21 -21
- data/lib/squib/builtin/projects/advanced/IDEAS.md +22 -22
- data/lib/squib/builtin/projects/advanced/PLAYTESTING.md +26 -26
- data/lib/squib/builtin/projects/advanced/Rakefile +27 -27
- data/lib/squib/builtin/projects/advanced/config.yml +49 -49
- data/lib/squib/builtin/projects/advanced/docs/PNP NOTES.md +3 -3
- data/lib/squib/builtin/projects/advanced/docs/RULES.md +21 -21
- data/lib/squib/builtin/projects/advanced/img/example.svg +60 -60
- data/lib/squib/builtin/projects/advanced/layouts/deck.yml +27 -27
- data/lib/squib/builtin/projects/advanced/src/deck.rb +34 -34
- data/lib/squib/builtin/projects/advanced/src/version.rb +3 -3
- data/lib/squib/builtin/projects/basic/.gitignore +4 -4
- data/lib/squib/builtin/projects/basic/ABOUT.md +19 -19
- data/lib/squib/builtin/projects/basic/Gemfile +3 -3
- data/lib/squib/builtin/projects/basic/IDEAS.md +22 -22
- data/lib/squib/builtin/projects/basic/PLAYTESTING.md +26 -26
- data/lib/squib/builtin/projects/basic/PNP NOTES.md +3 -3
- data/lib/squib/builtin/projects/basic/RULES.md +21 -21
- data/lib/squib/builtin/projects/basic/Rakefile +7 -7
- data/lib/squib/builtin/projects/basic/config.yml +49 -49
- data/lib/squib/builtin/projects/basic/deck.rb +6 -6
- data/lib/squib/builtin/sprues/a4_euro_card.yml +42 -42
- data/lib/squib/builtin/sprues/a4_poker_card_8up.yml +40 -40
- data/lib/squib/builtin/sprues/a4_poker_card_9up.yml +42 -42
- data/lib/squib/builtin/sprues/a4_usa_card.yml +42 -42
- data/lib/squib/builtin/sprues/drivethrucards_1up.yml +10 -0
- data/lib/squib/builtin/sprues/letter_poker_card_9up.yml +25 -25
- data/lib/squib/builtin/sprues/letter_poker_foldable_8up.yml +52 -52
- data/lib/squib/builtin/sprues/printplaygames_18up.yml +68 -0
- data/lib/squib/card.rb +75 -74
- data/lib/squib/commands/cli.rb +39 -39
- data/lib/squib/commands/data/template_option.rb +109 -109
- data/lib/squib/commands/make_sprue.rb +275 -275
- data/lib/squib/commands/new.rb +77 -77
- data/lib/squib/conf.rb +139 -139
- data/lib/squib/constants.rb +17 -17
- data/lib/squib/deck.rb +116 -116
- data/lib/squib/graphics/background.rb +14 -14
- data/lib/squib/graphics/cairo_context_wrapper.rb +113 -113
- data/lib/squib/graphics/embedding_utils.rb +28 -28
- data/lib/squib/graphics/gradient_regex.rb +47 -47
- data/lib/squib/graphics/hand.rb +42 -42
- data/lib/squib/graphics/image.rb +108 -108
- data/lib/squib/graphics/save_doc.rb +61 -61
- data/lib/squib/graphics/save_images.rb +52 -52
- data/lib/squib/graphics/save_pdf.rb +90 -90
- data/lib/squib/graphics/save_sprue.rb +204 -205
- data/lib/squib/graphics/shapes.rb +143 -143
- data/lib/squib/graphics/showcase.rb +85 -85
- data/lib/squib/graphics/text.rb +174 -174
- data/lib/squib/import/data_frame.rb +108 -108
- data/lib/squib/layout_parser.rb +138 -126
- data/lib/squib/progress.rb +38 -38
- data/lib/squib/sample_helpers.rb +34 -34
- data/lib/squib/sprues/crop_line.rb +28 -28
- data/lib/squib/sprues/crop_line_dash.rb +35 -35
- data/lib/squib/sprues/invalid_sprue_definition.rb +9 -9
- data/lib/squib/sprues/sprue.rb +203 -203
- data/lib/squib/sprues/sprue_schema.rb +48 -48
- data/lib/squib/version.rb +10 -10
- data/samples/autoscale_font/_autoscale_font.rb +29 -29
- data/samples/backend/_backend.rb +26 -26
- data/samples/basic.rb +19 -19
- data/samples/build_groups/build_groups.rb +36 -36
- data/samples/colors/_colors.rb +38 -38
- data/samples/colors/_gradients.rb +34 -34
- data/samples/config/config_text_markup.rb +20 -20
- data/samples/config/custom_config.rb +18 -18
- data/samples/data/_csv.rb +33 -33
- data/samples/data/_excel.rb +55 -55
- data/samples/data/_yaml.rb +12 -12
- data/samples/hello_world.rb +6 -6
- data/samples/images/_cairo_access.rb +39 -39
- data/samples/images/_images.rb +104 -104
- data/samples/images/_more_load_images.rb +102 -102
- data/samples/intro/01_hello.rb +8 -8
- data/samples/intro/02_options.rb +14 -14
- data/samples/intro/03_layout.rb +11 -11
- data/samples/intro/04_arrays.rb +15 -15
- data/samples/intro/05_excel.rb +14 -14
- data/samples/layouts/builtin_layouts.rb +97 -97
- data/samples/layouts/layouts.rb +71 -71
- data/samples/project/src/characters.rb +8 -8
- data/samples/project/src/skills.rb +7 -7
- data/samples/proofs/_tgc_proofs.rb +16 -16
- data/samples/ranges/_ranges.rb +64 -64
- data/samples/saves/_hand.rb +23 -23
- data/samples/saves/_portrait_landscape.rb +23 -23
- data/samples/saves/_save_pdf.rb +29 -29
- data/samples/saves/_saves.rb +51 -51
- data/samples/saves/_showcase.rb +25 -25
- data/samples/shapes/_draw_shapes.rb +60 -58
- data/samples/shapes/_proofs.rb +22 -22
- data/samples/sprues/_advanced_sprues.rb +24 -24
- data/samples/sprues/_builtin_sprues.rb +21 -19
- data/samples/sprues/_fold_sheet.rb +27 -27
- data/samples/sprues/_hex_tiles.rb +15 -15
- data/samples/sprues/_mints.rb +11 -11
- data/samples/sprues/_sprue_example.rb +11 -11
- data/samples/text/_embed_text.rb +128 -128
- data/samples/text/_text.rb +47 -47
- data/samples/text/_text_options.rb +102 -102
- data/samples/text/bug134.rb +14 -14
- data/samples/units/_units.rb +32 -32
- data/squib.gemspec +52 -51
- metadata +66 -50
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
module Squib
|
|
2
|
-
class EmbeddingUtils
|
|
3
|
-
|
|
4
|
-
# Given a string and a bunch of keys, give us back a mapping of those keys
|
|
5
|
-
# to where those keys start, and where they end (in ranges)
|
|
6
|
-
#
|
|
7
|
-
# See the spec for expected outputs
|
|
8
|
-
def self.indices(str, keys)
|
|
9
|
-
map = {}
|
|
10
|
-
keys.each do |key|
|
|
11
|
-
map[key] ||= []
|
|
12
|
-
start = 0
|
|
13
|
-
while true
|
|
14
|
-
idx = str.index(key, start)
|
|
15
|
-
if idx.nil?
|
|
16
|
-
break; # done searching
|
|
17
|
-
else
|
|
18
|
-
idx_bytes = str[0..idx].bytesize - 1
|
|
19
|
-
map[key] << (idx_bytes..(idx_bytes + key.size))
|
|
20
|
-
start = idx + 1
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
return map
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
end
|
|
28
|
-
end
|
|
1
|
+
module Squib
|
|
2
|
+
class EmbeddingUtils
|
|
3
|
+
|
|
4
|
+
# Given a string and a bunch of keys, give us back a mapping of those keys
|
|
5
|
+
# to where those keys start, and where they end (in ranges)
|
|
6
|
+
#
|
|
7
|
+
# See the spec for expected outputs
|
|
8
|
+
def self.indices(str, keys)
|
|
9
|
+
map = {}
|
|
10
|
+
keys.each do |key|
|
|
11
|
+
map[key] ||= []
|
|
12
|
+
start = 0
|
|
13
|
+
while true
|
|
14
|
+
idx = str.index(key, start)
|
|
15
|
+
if idx.nil?
|
|
16
|
+
break; # done searching
|
|
17
|
+
else
|
|
18
|
+
idx_bytes = str[0..idx].bytesize - 1
|
|
19
|
+
map[key] << (idx_bytes..(idx_bytes + key.size))
|
|
20
|
+
start = idx + 1
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
return map
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
module Squib
|
|
2
|
-
# @api private
|
|
3
|
-
module Graphics
|
|
4
|
-
STOPS = / # used to capture the stops
|
|
5
|
-
\s* # leading whitespace is ok
|
|
6
|
-
(\#?[\w]+) # color
|
|
7
|
-
@ # no spaces here
|
|
8
|
-
(\d+\.?\d*) # offset number
|
|
9
|
-
/x
|
|
10
|
-
|
|
11
|
-
LINEAR_GRADIENT = /
|
|
12
|
-
\( \s* # coordinate 1
|
|
13
|
-
(\d+\.?\d*) \s* # x1 number
|
|
14
|
-
,\s* # whitespace after comma is ok
|
|
15
|
-
(\d+\.?\d*) \s* # y1 number
|
|
16
|
-
\)
|
|
17
|
-
\s* # space between coordinates is ok
|
|
18
|
-
\( \s* # coordinate 2
|
|
19
|
-
(\d+\.?\d*) \s* # x2 number
|
|
20
|
-
,\s* # whitespace after comma is ok
|
|
21
|
-
(\d+\.?\d*) \s* # y2 number
|
|
22
|
-
\)
|
|
23
|
-
(#{STOPS})+ # stops
|
|
24
|
-
\s* # trailing whitespace is ok
|
|
25
|
-
/x
|
|
26
|
-
|
|
27
|
-
RADIAL_GRADIENT = /
|
|
28
|
-
\( \s* # coordinate 1
|
|
29
|
-
(\d+\.?\d*) \s* # x1 number
|
|
30
|
-
,\s* # whitespace after comma is ok
|
|
31
|
-
(\d+\.?\d*) \s* # y1 number
|
|
32
|
-
,\s* # whitespace after comma is ok
|
|
33
|
-
(\d+\.?\d*) \s* # r1 number
|
|
34
|
-
\)
|
|
35
|
-
\s* # space between coordinates is ok
|
|
36
|
-
\( \s* # coordinate 2
|
|
37
|
-
(\d+\.?\d*) \s* # x2 number
|
|
38
|
-
,\s* # whitespace after comma is ok
|
|
39
|
-
(\d+\.?\d*) \s* # y2 number
|
|
40
|
-
,\s* # whitespace after comma is ok
|
|
41
|
-
(\d+\.?\d*) \s* # r2 number
|
|
42
|
-
\)
|
|
43
|
-
(#{STOPS})+ # stops
|
|
44
|
-
\s* # trailing whitespace is ok
|
|
45
|
-
/x
|
|
46
|
-
end
|
|
47
|
-
end
|
|
1
|
+
module Squib
|
|
2
|
+
# @api private
|
|
3
|
+
module Graphics
|
|
4
|
+
STOPS = / # used to capture the stops
|
|
5
|
+
\s* # leading whitespace is ok
|
|
6
|
+
(\#?[\w]+) # color
|
|
7
|
+
@ # no spaces here
|
|
8
|
+
(\d+\.?\d*) # offset number
|
|
9
|
+
/x
|
|
10
|
+
|
|
11
|
+
LINEAR_GRADIENT = /
|
|
12
|
+
\( \s* # coordinate 1
|
|
13
|
+
(\d+\.?\d*) \s* # x1 number
|
|
14
|
+
,\s* # whitespace after comma is ok
|
|
15
|
+
(\d+\.?\d*) \s* # y1 number
|
|
16
|
+
\)
|
|
17
|
+
\s* # space between coordinates is ok
|
|
18
|
+
\( \s* # coordinate 2
|
|
19
|
+
(\d+\.?\d*) \s* # x2 number
|
|
20
|
+
,\s* # whitespace after comma is ok
|
|
21
|
+
(\d+\.?\d*) \s* # y2 number
|
|
22
|
+
\)
|
|
23
|
+
(#{STOPS})+ # stops
|
|
24
|
+
\s* # trailing whitespace is ok
|
|
25
|
+
/x
|
|
26
|
+
|
|
27
|
+
RADIAL_GRADIENT = /
|
|
28
|
+
\( \s* # coordinate 1
|
|
29
|
+
(\d+\.?\d*) \s* # x1 number
|
|
30
|
+
,\s* # whitespace after comma is ok
|
|
31
|
+
(\d+\.?\d*) \s* # y1 number
|
|
32
|
+
,\s* # whitespace after comma is ok
|
|
33
|
+
(\d+\.?\d*) \s* # r1 number
|
|
34
|
+
\)
|
|
35
|
+
\s* # space between coordinates is ok
|
|
36
|
+
\( \s* # coordinate 2
|
|
37
|
+
(\d+\.?\d*) \s* # x2 number
|
|
38
|
+
,\s* # whitespace after comma is ok
|
|
39
|
+
(\d+\.?\d*) \s* # y2 number
|
|
40
|
+
,\s* # whitespace after comma is ok
|
|
41
|
+
(\d+\.?\d*) \s* # r2 number
|
|
42
|
+
\)
|
|
43
|
+
(#{STOPS})+ # stops
|
|
44
|
+
\s* # trailing whitespace is ok
|
|
45
|
+
/x
|
|
46
|
+
end
|
|
47
|
+
end
|
data/lib/squib/graphics/hand.rb
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
require_relative '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, sheet, hand)
|
|
9
|
-
cards = range.collect { |i| @cards[i] }
|
|
10
|
-
center_x = width / 2.0
|
|
11
|
-
center_y = hand.radius + height
|
|
12
|
-
out_size = 3.0 * center_y
|
|
13
|
-
angle_delta = (hand.angle_range.last - hand.angle_range.first) / cards.size
|
|
14
|
-
cxt = Cairo::Context.new(Cairo::RecordingSurface.new(0, 0, out_size, out_size))
|
|
15
|
-
cxt.translate(out_size / 2.0, out_size / 2.0)
|
|
16
|
-
cxt.rotate(hand.angle_range.first)
|
|
17
|
-
cxt.translate(-width, -width)
|
|
18
|
-
cards.each_with_index do |card, i|
|
|
19
|
-
cxt.translate(center_x, center_y)
|
|
20
|
-
cxt.rotate(angle_delta)
|
|
21
|
-
cxt.translate(-center_x, -center_y)
|
|
22
|
-
card.use_cairo do |card_cxt|
|
|
23
|
-
cxt.rounded_rectangle(sheet.trim, sheet.trim,
|
|
24
|
-
width - (2 * sheet.trim), height - (2 * sheet.trim),
|
|
25
|
-
sheet.trim_radius, sheet.trim_radius)
|
|
26
|
-
cxt.clip
|
|
27
|
-
cxt.set_source(card_cxt.target)
|
|
28
|
-
cxt.paint
|
|
29
|
-
cxt.reset_clip
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
x, y, w, h = cxt.target.ink_extents # I love Ruby assignment ;)
|
|
33
|
-
png_cxt = Squib::Graphics::CairoContextWrapper.new(Cairo::Context.new(Cairo::ImageSurface.new(w + 2 * sheet.margin, h + 2 * sheet.margin)))
|
|
34
|
-
png_cxt.set_source_squibcolor(sheet.fill_color)
|
|
35
|
-
png_cxt.paint
|
|
36
|
-
png_cxt.translate(-x + sheet.margin, -y + sheet.margin)
|
|
37
|
-
png_cxt.set_source(cxt.target)
|
|
38
|
-
png_cxt.paint
|
|
39
|
-
png_cxt.target.write_to_png sheet.full_filename
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
1
|
+
require_relative '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, sheet, hand)
|
|
9
|
+
cards = range.collect { |i| @cards[i] }
|
|
10
|
+
center_x = width / 2.0
|
|
11
|
+
center_y = hand.radius + height
|
|
12
|
+
out_size = 3.0 * center_y
|
|
13
|
+
angle_delta = (hand.angle_range.last - hand.angle_range.first) / cards.size
|
|
14
|
+
cxt = Cairo::Context.new(Cairo::RecordingSurface.new(0, 0, out_size, out_size))
|
|
15
|
+
cxt.translate(out_size / 2.0, out_size / 2.0)
|
|
16
|
+
cxt.rotate(hand.angle_range.first)
|
|
17
|
+
cxt.translate(-width, -width)
|
|
18
|
+
cards.each_with_index do |card, i|
|
|
19
|
+
cxt.translate(center_x, center_y)
|
|
20
|
+
cxt.rotate(angle_delta)
|
|
21
|
+
cxt.translate(-center_x, -center_y)
|
|
22
|
+
card.use_cairo do |card_cxt|
|
|
23
|
+
cxt.rounded_rectangle(sheet.trim, sheet.trim,
|
|
24
|
+
width - (2 * sheet.trim), height - (2 * sheet.trim),
|
|
25
|
+
sheet.trim_radius, sheet.trim_radius)
|
|
26
|
+
cxt.clip
|
|
27
|
+
cxt.set_source(card_cxt.target)
|
|
28
|
+
cxt.paint
|
|
29
|
+
cxt.reset_clip
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
x, y, w, h = cxt.target.ink_extents # I love Ruby assignment ;)
|
|
33
|
+
png_cxt = Squib::Graphics::CairoContextWrapper.new(Cairo::Context.new(Cairo::ImageSurface.new(w + 2 * sheet.margin, h + 2 * sheet.margin)))
|
|
34
|
+
png_cxt.set_source_squibcolor(sheet.fill_color)
|
|
35
|
+
png_cxt.paint
|
|
36
|
+
png_cxt.translate(-x + sheet.margin, -y + sheet.margin)
|
|
37
|
+
png_cxt.set_source(cxt.target)
|
|
38
|
+
png_cxt.paint
|
|
39
|
+
png_cxt.target.write_to_png sheet.full_filename
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
data/lib/squib/graphics/image.rb
CHANGED
|
@@ -1,108 +1,108 @@
|
|
|
1
|
-
module Squib
|
|
2
|
-
|
|
3
|
-
# Cache all pngs we've already loaded
|
|
4
|
-
#
|
|
5
|
-
# :nodoc:
|
|
6
|
-
# @api private
|
|
7
|
-
def cache_load_image(file)
|
|
8
|
-
@img_cache ||= {}
|
|
9
|
-
@img_cache[file] || @img_cache[file] = Cairo::ImageSurface.from_png(file)
|
|
10
|
-
end
|
|
11
|
-
module_function :cache_load_image
|
|
12
|
-
|
|
13
|
-
class Card
|
|
14
|
-
|
|
15
|
-
# :nodoc:
|
|
16
|
-
# @api private
|
|
17
|
-
def png(file, box, paint, trans)
|
|
18
|
-
Squib.logger.debug {"RENDERING PNG: \n file: #{file}\n box: #{box}\n paint: #{paint}\n trans: #{trans}"}
|
|
19
|
-
return if file.nil? or file.eql? ''
|
|
20
|
-
png = Squib.cache_load_image(file)
|
|
21
|
-
use_cairo do |cc|
|
|
22
|
-
cc.translate(box.x, box.y)
|
|
23
|
-
box.width = png.width.to_f if box.width == :native
|
|
24
|
-
box.height = png.height.to_f if box.height == :native
|
|
25
|
-
box.width = png.width.to_f * box.height.to_f / png.height.to_f if box.width == :scale
|
|
26
|
-
box.height = png.height.to_f * box.width.to_f / png.width.to_f if box.height == :scale
|
|
27
|
-
|
|
28
|
-
scale_width = box.width.to_f / png.width.to_f
|
|
29
|
-
scale_height = box.height.to_f / png.height.to_f
|
|
30
|
-
warn_png_scale(file, scale_width, scale_height)
|
|
31
|
-
cc.scale(scale_width, scale_height)
|
|
32
|
-
|
|
33
|
-
cc.rotate(trans.angle)
|
|
34
|
-
cc.flip(trans.flip_vertical, trans.flip_horizontal, box.width / 2, box.height / 2)
|
|
35
|
-
cc.translate(-box.x, -box.y)
|
|
36
|
-
|
|
37
|
-
trans.crop_width = png.width.to_f if trans.crop_width == :native
|
|
38
|
-
trans.crop_height = png.height.to_f if trans.crop_height == :native
|
|
39
|
-
cc.rounded_rectangle(box.x, box.y, trans.crop_width, trans.crop_height, trans.crop_corner_x_radius, trans.crop_corner_y_radius)
|
|
40
|
-
cc.clip
|
|
41
|
-
cc.translate(-trans.crop_x, -trans.crop_y)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
cc.set_source(png, box.x, box.y)
|
|
45
|
-
cc.operator = paint.blend unless paint.blend == :none
|
|
46
|
-
if paint.mask.empty?
|
|
47
|
-
cc.paint(paint.alpha)
|
|
48
|
-
else
|
|
49
|
-
cc.set_source_squibcolor(paint.mask)
|
|
50
|
-
cc.mask(png, box.x, box.y)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# :nodoc:
|
|
56
|
-
# @api private
|
|
57
|
-
def warn_png_scale(file, scale_width, scale_height)
|
|
58
|
-
if @deck.conf.warn_png_scale? && (scale_width > 1.0 || scale_height > 1.0)
|
|
59
|
-
Squib.logger.warn "PNG is being upscaled - antialiasing could result: #{file}"
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# :nodoc:
|
|
64
|
-
# @api private
|
|
65
|
-
def svg(file, svg_args, box, paint, trans)
|
|
66
|
-
Squib.logger.debug {"Rendering: #{file}, id: #{id} @#{x},#{y} #{width}x#{height}, alpha: #{alpha}, blend: #{blend}, angle: #{angle}, mask: #{mask}"}
|
|
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
|
-
return if (file.nil? or file.eql? '') and svg_args.data.nil? # nothing specified TODO Move this out to arg validator
|
|
69
|
-
svg_args.data = File.read(file) if svg_args.data.to_s.empty?
|
|
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
|
|
76
|
-
box.width = svg.width if box.width == :native
|
|
77
|
-
box.height = svg.height if box.height == :native
|
|
78
|
-
box.width = svg.width.to_f * box.height.to_f / svg.height.to_f if box.width == :scale
|
|
79
|
-
box.height = svg.height.to_f * box.width.to_f / svg.width.to_f if box.height == :scale
|
|
80
|
-
scale_width = box.width.to_f / svg.width.to_f
|
|
81
|
-
scale_height = box.height.to_f / svg.height.to_f
|
|
82
|
-
use_cairo do |cc|
|
|
83
|
-
cc.translate(box.x, box.y)
|
|
84
|
-
cc.flip(trans.flip_vertical, trans.flip_horizontal, box.width / 2, box.height / 2)
|
|
85
|
-
cc.rotate(trans.angle)
|
|
86
|
-
cc.scale(scale_width, scale_height)
|
|
87
|
-
|
|
88
|
-
trans.crop_width = box.width if trans.crop_width == :native
|
|
89
|
-
trans.crop_height = box.height if trans.crop_height == :native
|
|
90
|
-
cc.rounded_rectangle(0, 0, trans.crop_width / scale_width, trans.crop_height / scale_height, trans.crop_corner_x_radius, trans.crop_corner_y_radius)
|
|
91
|
-
cc.clip
|
|
92
|
-
cc.translate(-trans.crop_x, -trans.crop_y)
|
|
93
|
-
|
|
94
|
-
cc.operator = paint.blend unless paint.blend == :none
|
|
95
|
-
if paint.mask.to_s.empty?
|
|
96
|
-
cc.render_rsvg_handle(svg, id: svg_args.id)
|
|
97
|
-
else
|
|
98
|
-
tmp = Cairo::ImageSurface.new(box.width / scale_width, box.height / scale_height)
|
|
99
|
-
tmp_cc = Cairo::Context.new(tmp)
|
|
100
|
-
tmp_cc.render_rsvg_handle(svg, id: svg_args.id)
|
|
101
|
-
cc.set_source_squibcolor(paint.mask)
|
|
102
|
-
cc.mask(tmp, 0, 0)
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
end
|
|
108
|
-
end
|
|
1
|
+
module Squib
|
|
2
|
+
|
|
3
|
+
# Cache all pngs we've already loaded
|
|
4
|
+
#
|
|
5
|
+
# :nodoc:
|
|
6
|
+
# @api private
|
|
7
|
+
def cache_load_image(file)
|
|
8
|
+
@img_cache ||= {}
|
|
9
|
+
@img_cache[file] || @img_cache[file] = Cairo::ImageSurface.from_png(file)
|
|
10
|
+
end
|
|
11
|
+
module_function :cache_load_image
|
|
12
|
+
|
|
13
|
+
class Card
|
|
14
|
+
|
|
15
|
+
# :nodoc:
|
|
16
|
+
# @api private
|
|
17
|
+
def png(file, box, paint, trans)
|
|
18
|
+
Squib.logger.debug {"RENDERING PNG: \n file: #{file}\n box: #{box}\n paint: #{paint}\n trans: #{trans}"}
|
|
19
|
+
return if file.nil? or file.eql? ''
|
|
20
|
+
png = Squib.cache_load_image(file)
|
|
21
|
+
use_cairo do |cc|
|
|
22
|
+
cc.translate(box.x, box.y)
|
|
23
|
+
box.width = png.width.to_f if box.width == :native
|
|
24
|
+
box.height = png.height.to_f if box.height == :native
|
|
25
|
+
box.width = png.width.to_f * box.height.to_f / png.height.to_f if box.width == :scale
|
|
26
|
+
box.height = png.height.to_f * box.width.to_f / png.width.to_f if box.height == :scale
|
|
27
|
+
|
|
28
|
+
scale_width = box.width.to_f / png.width.to_f
|
|
29
|
+
scale_height = box.height.to_f / png.height.to_f
|
|
30
|
+
warn_png_scale(file, scale_width, scale_height)
|
|
31
|
+
cc.scale(scale_width, scale_height)
|
|
32
|
+
|
|
33
|
+
cc.rotate(trans.angle)
|
|
34
|
+
cc.flip(trans.flip_vertical, trans.flip_horizontal, box.width / 2, box.height / 2)
|
|
35
|
+
cc.translate(-box.x, -box.y)
|
|
36
|
+
|
|
37
|
+
trans.crop_width = png.width.to_f if trans.crop_width == :native
|
|
38
|
+
trans.crop_height = png.height.to_f if trans.crop_height == :native
|
|
39
|
+
cc.rounded_rectangle(box.x, box.y, trans.crop_width, trans.crop_height, trans.crop_corner_x_radius, trans.crop_corner_y_radius)
|
|
40
|
+
cc.clip
|
|
41
|
+
cc.translate(-trans.crop_x, -trans.crop_y)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
cc.set_source(png, box.x, box.y)
|
|
45
|
+
cc.operator = paint.blend unless paint.blend == :none
|
|
46
|
+
if paint.mask.empty?
|
|
47
|
+
cc.paint(paint.alpha)
|
|
48
|
+
else
|
|
49
|
+
cc.set_source_squibcolor(paint.mask)
|
|
50
|
+
cc.mask(png, box.x, box.y)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# :nodoc:
|
|
56
|
+
# @api private
|
|
57
|
+
def warn_png_scale(file, scale_width, scale_height)
|
|
58
|
+
if @deck.conf.warn_png_scale? && (scale_width > 1.0 || scale_height > 1.0)
|
|
59
|
+
Squib.logger.warn "PNG is being upscaled - antialiasing could result: #{file}"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# :nodoc:
|
|
64
|
+
# @api private
|
|
65
|
+
def svg(file, svg_args, box, paint, trans)
|
|
66
|
+
Squib.logger.debug {"Rendering: #{file}, id: #{id} @#{x},#{y} #{width}x#{height}, alpha: #{alpha}, blend: #{blend}, angle: #{angle}, mask: #{mask}"}
|
|
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
|
+
return if (file.nil? or file.eql? '') and svg_args.data.nil? # nothing specified TODO Move this out to arg validator
|
|
69
|
+
svg_args.data = File.read(file) if svg_args.data.to_s.empty?
|
|
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
|
|
76
|
+
box.width = svg.width if box.width == :native
|
|
77
|
+
box.height = svg.height if box.height == :native
|
|
78
|
+
box.width = svg.width.to_f * box.height.to_f / svg.height.to_f if box.width == :scale
|
|
79
|
+
box.height = svg.height.to_f * box.width.to_f / svg.width.to_f if box.height == :scale
|
|
80
|
+
scale_width = box.width.to_f / svg.width.to_f
|
|
81
|
+
scale_height = box.height.to_f / svg.height.to_f
|
|
82
|
+
use_cairo do |cc|
|
|
83
|
+
cc.translate(box.x, box.y)
|
|
84
|
+
cc.flip(trans.flip_vertical, trans.flip_horizontal, box.width / 2, box.height / 2)
|
|
85
|
+
cc.rotate(trans.angle)
|
|
86
|
+
cc.scale(scale_width, scale_height)
|
|
87
|
+
|
|
88
|
+
trans.crop_width = box.width if trans.crop_width == :native
|
|
89
|
+
trans.crop_height = box.height if trans.crop_height == :native
|
|
90
|
+
cc.rounded_rectangle(0, 0, trans.crop_width / scale_width, trans.crop_height / scale_height, trans.crop_corner_x_radius, trans.crop_corner_y_radius)
|
|
91
|
+
cc.clip
|
|
92
|
+
cc.translate(-trans.crop_x, -trans.crop_y)
|
|
93
|
+
|
|
94
|
+
cc.operator = paint.blend unless paint.blend == :none
|
|
95
|
+
if paint.mask.to_s.empty?
|
|
96
|
+
cc.render_rsvg_handle(svg, id: svg_args.id)
|
|
97
|
+
else
|
|
98
|
+
tmp = Cairo::ImageSurface.new(box.width / scale_width, box.height / scale_height)
|
|
99
|
+
tmp_cc = Cairo::Context.new(tmp)
|
|
100
|
+
tmp_cc.render_rsvg_handle(svg, id: svg_args.id)
|
|
101
|
+
cc.set_source_squibcolor(paint.mask)
|
|
102
|
+
cc.mask(tmp, 0, 0)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
end
|
|
108
|
+
end
|