squib 0.10.0 → 0.11.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/.travis.yml +6 -0
- data/CHANGELOG.md +24 -3
- data/README.md +4 -3
- data/RELEASE TODO.md +3 -1
- data/docs/_static/css/squibdocs.css +5 -0
- data/docs/conf.py +2 -2
- data/docs/config.rst +5 -0
- data/docs/dsl/ellipse.rst +6 -0
- data/docs/dsl/mm.rst +19 -0
- data/docs/dsl/rect.rst +4 -0
- data/docs/dsl/text.rst +2 -2
- data/docs/dsl/triangle.rst +20 -8
- data/docs/guides/game_icons.rst +4 -0
- data/docs/layouts.rst +55 -0
- data/docs/units.rst +1 -1
- data/lib/squib/api/background.rb +1 -1
- data/lib/squib/api/data.rb +4 -4
- data/lib/squib/api/groups.rb +4 -4
- data/lib/squib/api/image.rb +2 -2
- data/lib/squib/api/save.rb +6 -6
- data/lib/squib/api/settings.rb +4 -4
- data/lib/squib/api/shapes.rb +13 -11
- data/lib/squib/api/text.rb +1 -1
- data/lib/squib/api/text_embed.rb +4 -29
- data/lib/squib/api/units.rb +7 -2
- data/lib/squib/args/arg_loader.rb +2 -14
- data/lib/squib/args/draw.rb +1 -1
- data/lib/squib/args/hand_special.rb +37 -37
- data/lib/squib/args/unit_conversion.rb +2 -0
- data/lib/squib/deck.rb +1 -1
- data/lib/squib/graphics/embedding_utils.rb +28 -0
- data/lib/squib/graphics/shapes.rb +6 -3
- data/lib/squib/graphics/text.rb +49 -52
- data/lib/squib/layout_parser.rb +28 -9
- data/lib/squib/layouts/economy.yml +85 -85
- data/lib/squib/layouts/fantasy.yml +101 -101
- data/lib/squib/layouts/hand.yml +62 -62
- data/lib/squib/layouts/playing-card.yml +35 -35
- data/lib/squib/layouts/tuck_box.yml +45 -45
- data/lib/squib/version.rb +1 -1
- data/samples/custom-config.yml +5 -5
- data/samples/custom_config.rb +18 -18
- data/samples/embed_text.rb +27 -9
- data/samples/layouts/_output/.gitignore +2 -0
- data/samples/{layouts_builtin.rb → layouts/builtin_layouts.rb} +74 -51
- data/samples/{custom-layout.yml → layouts/custom-layout.yml} +0 -0
- data/samples/{custom-layout2.yml → layouts/custom-layout2.yml} +0 -0
- data/samples/layouts/expected_layouts_builtin_economy_00.png +0 -0
- data/samples/layouts/expected_layouts_builtin_fantasy_00.png +0 -0
- data/samples/layouts/expected_layouts_builtin_hand_00.png +0 -0
- data/samples/layouts/expected_layouts_builtin_playing_card_00.png +0 -0
- data/samples/layouts/expected_layouts_builtin_tuck_box_00.png +0 -0
- data/samples/{layouts.rb → layouts/layouts.rb} +0 -1
- data/samples/layouts/shiny-purse.png +0 -0
- data/samples/layouts/spanner.svg +91 -0
- data/samples/offset.svg +71 -71
- data/samples/shapes/_draw_shapes.rb +8 -2
- data/spec/api/api_units_spec.rb +37 -0
- data/spec/args/embed_key_spec.rb +13 -13
- data/spec/args/showcase_special_spec.rb +15 -15
- data/spec/args/unit_conversion_spec.rb +8 -1
- data/spec/data/csv/qty.csv +2 -2
- data/spec/data/csv/qty_named.csv +2 -2
- data/spec/data/csv/with_spaces.csv +2 -2
- data/spec/data/layouts/extends-units-mixed.yml +8 -0
- data/spec/data/layouts/extends-units.yml +8 -0
- data/spec/data/samples/autoscale_font/_autoscale_font.rb.txt +9 -0
- data/spec/data/samples/basic.rb.txt +18 -0
- data/spec/data/samples/cairo_access.rb.txt +6 -0
- data/spec/data/samples/colors/_gradients.rb.txt +6 -0
- data/spec/data/samples/config_text_markup.rb.txt +72 -72
- data/spec/data/samples/data/_csv.rb.txt +12 -0
- data/spec/data/samples/data/_excel.rb.txt +30 -0
- data/spec/data/samples/embed_text.rb.txt +70 -5
- data/spec/data/samples/hello_world.rb.txt +36 -36
- data/spec/data/samples/images/_more_load_images.rb.txt +3 -0
- data/spec/data/samples/ranges.rb.txt +9 -0
- data/spec/data/samples/saves/_hand.rb.txt +48 -0
- data/spec/data/samples/saves/_saves.rb.txt +48 -0
- data/spec/data/samples/saves/_showcase.rb.txt +12 -0
- data/spec/data/samples/shapes/_draw_shapes.rb.txt +41 -0
- data/spec/data/samples/text_options.rb.txt +1155 -1125
- data/spec/data/samples/tgc_proofs.rb.txt +6 -0
- data/spec/data/samples/units.rb.txt +9 -0
- data/spec/graphics/embedding_utils_spec.rb +73 -0
- data/spec/layout_parser_spec.rb +42 -17
- data/spec/spec_helper.rb +5 -1
- data/squib.gemspec +5 -3
- metadata +61 -15
data/lib/squib/layout_parser.rb
CHANGED
|
@@ -5,16 +5,21 @@ module Squib
|
|
|
5
5
|
# @api private
|
|
6
6
|
class LayoutParser
|
|
7
7
|
|
|
8
|
+
def initialize(dpi = 300)
|
|
9
|
+
@dpi = dpi
|
|
10
|
+
end
|
|
11
|
+
|
|
8
12
|
# Load the layout file(s), if exists
|
|
9
13
|
# @api private
|
|
10
|
-
def
|
|
14
|
+
def load_layout(files, initial = {})
|
|
11
15
|
layout = initial
|
|
12
16
|
Squib::logger.info { " using layout(s): #{files}" }
|
|
13
17
|
Array(files).each do |file|
|
|
14
18
|
thefile = file
|
|
15
19
|
thefile = builtin(file) unless File.exists?(file)
|
|
16
20
|
if File.exists? thefile
|
|
17
|
-
|
|
21
|
+
# note: YAML.load_file returns false on empty file
|
|
22
|
+
yml = layout.merge(YAML.load_file(thefile) || {})
|
|
18
23
|
yml.each do |key, value|
|
|
19
24
|
layout[key] = recurse_extends(yml, key, {})
|
|
20
25
|
end
|
|
@@ -25,15 +30,17 @@ module Squib
|
|
|
25
30
|
return layout
|
|
26
31
|
end
|
|
27
32
|
|
|
33
|
+
private
|
|
34
|
+
|
|
28
35
|
# Determine the file path of the built-in layout file
|
|
29
|
-
def
|
|
36
|
+
def builtin(file)
|
|
30
37
|
"#{File.dirname(__FILE__)}/layouts/#{file}"
|
|
31
38
|
end
|
|
32
39
|
|
|
33
40
|
# Process the extends recursively
|
|
34
41
|
# :nodoc:
|
|
35
42
|
# @api private
|
|
36
|
-
def
|
|
43
|
+
def recurse_extends(yml, key, visited)
|
|
37
44
|
assert_not_visited(key, visited)
|
|
38
45
|
return yml[key] unless has_extends?(yml, key)
|
|
39
46
|
return yml[key] unless parents_exist?(yml, key)
|
|
@@ -43,9 +50,9 @@ module Squib
|
|
|
43
50
|
parent_keys.each do |parent_key|
|
|
44
51
|
from_extends = yml[key].merge(recurse_extends(yml, parent_key, visited)) do |key, child_val, parent_val|
|
|
45
52
|
if child_val.to_s.strip.start_with?('+=')
|
|
46
|
-
parent_val
|
|
53
|
+
add_parent_child(parent_val, child_val)
|
|
47
54
|
elsif child_val.to_s.strip.start_with?('-=')
|
|
48
|
-
parent_val
|
|
55
|
+
sub_parent_child(parent_val, child_val)
|
|
49
56
|
else
|
|
50
57
|
child_val # child overrides parent when merging, no +=
|
|
51
58
|
end
|
|
@@ -57,17 +64,29 @@ module Squib
|
|
|
57
64
|
return h
|
|
58
65
|
end
|
|
59
66
|
|
|
67
|
+
def add_parent_child(parent, child)
|
|
68
|
+
parent_pixels = Args::UnitConversion.parse(parent, @dpi).to_f
|
|
69
|
+
child_pixels = Args::UnitConversion.parse(child.sub('+=', ''), @dpi).to_f
|
|
70
|
+
parent_pixels + child_pixels
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def sub_parent_child(parent, child)
|
|
74
|
+
parent_pixels = Args::UnitConversion.parse(parent, @dpi).to_f
|
|
75
|
+
child_pixels = Args::UnitConversion.parse(child.sub('-=', ''), @dpi).to_f
|
|
76
|
+
parent_pixels - child_pixels
|
|
77
|
+
end
|
|
78
|
+
|
|
60
79
|
# Does this layout entry have an extends field?
|
|
61
80
|
# i.e. is it a base-case or will it need recursion?
|
|
62
81
|
# :nodoc:
|
|
63
82
|
# @api private
|
|
64
|
-
def
|
|
83
|
+
def has_extends?(yml, key)
|
|
65
84
|
!!yml[key] && yml[key].key?('extends')
|
|
66
85
|
end
|
|
67
86
|
|
|
68
87
|
# Checks if we have any absentee parents
|
|
69
88
|
# @api private
|
|
70
|
-
def
|
|
89
|
+
def parents_exist?(yml, key)
|
|
71
90
|
exists = true
|
|
72
91
|
Array(yml[key]['extends']).each do |parent|
|
|
73
92
|
unless yml.key?(parent)
|
|
@@ -81,7 +100,7 @@ module Squib
|
|
|
81
100
|
# Safeguard against malformed circular extends
|
|
82
101
|
# :nodoc:
|
|
83
102
|
# @api private
|
|
84
|
-
def
|
|
103
|
+
def assert_not_visited(key, visited)
|
|
85
104
|
if visited.key? key
|
|
86
105
|
raise "Invalid layout: circular extends with '#{key}'"
|
|
87
106
|
end
|
|
@@ -1,85 +1,85 @@
|
|
|
1
|
-
#This layout inspired by popular fantasy games
|
|
2
|
-
title:
|
|
3
|
-
x: 90
|
|
4
|
-
y: 90
|
|
5
|
-
width: 635
|
|
6
|
-
height: 50
|
|
7
|
-
align: center
|
|
8
|
-
|
|
9
|
-
art:
|
|
10
|
-
x: 75
|
|
11
|
-
y: 150
|
|
12
|
-
width: 675
|
|
13
|
-
height: 520
|
|
14
|
-
|
|
15
|
-
description:
|
|
16
|
-
x: 100
|
|
17
|
-
y: 675
|
|
18
|
-
width: 625
|
|
19
|
-
height: 275
|
|
20
|
-
valign: middle
|
|
21
|
-
align: center
|
|
22
|
-
font_size: 18
|
|
23
|
-
desc: # alias
|
|
24
|
-
extends: description
|
|
25
|
-
|
|
26
|
-
type:
|
|
27
|
-
x: 90
|
|
28
|
-
y: 955
|
|
29
|
-
width: 645
|
|
30
|
-
height: 50
|
|
31
|
-
align: center
|
|
32
|
-
|
|
33
|
-
lower_right:
|
|
34
|
-
x: 675
|
|
35
|
-
y: 975
|
|
36
|
-
width: 75
|
|
37
|
-
height: 75
|
|
38
|
-
font_size: 18
|
|
39
|
-
valign: bottom
|
|
40
|
-
align: right
|
|
41
|
-
lr: #alias
|
|
42
|
-
extends: lower_right
|
|
43
|
-
|
|
44
|
-
lower_left:
|
|
45
|
-
x: 75
|
|
46
|
-
y: 975
|
|
47
|
-
width: 75
|
|
48
|
-
height: 75
|
|
49
|
-
font_size: 18
|
|
50
|
-
valign: bottom
|
|
51
|
-
align: left
|
|
52
|
-
ll: # alias
|
|
53
|
-
extends: lower_left
|
|
54
|
-
|
|
55
|
-
copyright:
|
|
56
|
-
x: 75
|
|
57
|
-
y: 1025
|
|
58
|
-
width: 675
|
|
59
|
-
height: 25
|
|
60
|
-
font_size: 16
|
|
61
|
-
align: center
|
|
62
|
-
valign: bottom
|
|
63
|
-
#aliases for copyright
|
|
64
|
-
copy:
|
|
65
|
-
extends: copyright
|
|
66
|
-
credit:
|
|
67
|
-
extends: copyright
|
|
68
|
-
credits:
|
|
69
|
-
extends: copyright
|
|
70
|
-
|
|
71
|
-
# The "cut line", without rounded corners
|
|
72
|
-
cut:
|
|
73
|
-
x: 37.5
|
|
74
|
-
y: 37.5
|
|
75
|
-
width: 750
|
|
76
|
-
height: 1050
|
|
77
|
-
|
|
78
|
-
# The "safe zone" as defined by TheGameCrafter poker cards
|
|
79
|
-
safe:
|
|
80
|
-
x: 75
|
|
81
|
-
y: 75
|
|
82
|
-
width: 675
|
|
83
|
-
height: 975
|
|
84
|
-
radius: 16
|
|
85
|
-
dash: 3 3
|
|
1
|
+
#This layout inspired by popular fantasy games
|
|
2
|
+
title:
|
|
3
|
+
x: 90
|
|
4
|
+
y: 90
|
|
5
|
+
width: 635
|
|
6
|
+
height: 50
|
|
7
|
+
align: center
|
|
8
|
+
|
|
9
|
+
art:
|
|
10
|
+
x: 75
|
|
11
|
+
y: 150
|
|
12
|
+
width: 675
|
|
13
|
+
height: 520
|
|
14
|
+
|
|
15
|
+
description:
|
|
16
|
+
x: 100
|
|
17
|
+
y: 675
|
|
18
|
+
width: 625
|
|
19
|
+
height: 275
|
|
20
|
+
valign: middle
|
|
21
|
+
align: center
|
|
22
|
+
font_size: 18
|
|
23
|
+
desc: # alias
|
|
24
|
+
extends: description
|
|
25
|
+
|
|
26
|
+
type:
|
|
27
|
+
x: 90
|
|
28
|
+
y: 955
|
|
29
|
+
width: 645
|
|
30
|
+
height: 50
|
|
31
|
+
align: center
|
|
32
|
+
|
|
33
|
+
lower_right:
|
|
34
|
+
x: 675
|
|
35
|
+
y: 975
|
|
36
|
+
width: 75
|
|
37
|
+
height: 75
|
|
38
|
+
font_size: 18
|
|
39
|
+
valign: bottom
|
|
40
|
+
align: right
|
|
41
|
+
lr: #alias
|
|
42
|
+
extends: lower_right
|
|
43
|
+
|
|
44
|
+
lower_left:
|
|
45
|
+
x: 75
|
|
46
|
+
y: 975
|
|
47
|
+
width: 75
|
|
48
|
+
height: 75
|
|
49
|
+
font_size: 18
|
|
50
|
+
valign: bottom
|
|
51
|
+
align: left
|
|
52
|
+
ll: # alias
|
|
53
|
+
extends: lower_left
|
|
54
|
+
|
|
55
|
+
copyright:
|
|
56
|
+
x: 75
|
|
57
|
+
y: 1025
|
|
58
|
+
width: 675
|
|
59
|
+
height: 25
|
|
60
|
+
font_size: 16
|
|
61
|
+
align: center
|
|
62
|
+
valign: bottom
|
|
63
|
+
#aliases for copyright
|
|
64
|
+
copy:
|
|
65
|
+
extends: copyright
|
|
66
|
+
credit:
|
|
67
|
+
extends: copyright
|
|
68
|
+
credits:
|
|
69
|
+
extends: copyright
|
|
70
|
+
|
|
71
|
+
# The "cut line", without rounded corners
|
|
72
|
+
cut:
|
|
73
|
+
x: 37.5
|
|
74
|
+
y: 37.5
|
|
75
|
+
width: 750
|
|
76
|
+
height: 1050
|
|
77
|
+
|
|
78
|
+
# The "safe zone" as defined by TheGameCrafter poker cards
|
|
79
|
+
safe:
|
|
80
|
+
x: 75
|
|
81
|
+
y: 75
|
|
82
|
+
width: 675
|
|
83
|
+
height: 975
|
|
84
|
+
radius: 16
|
|
85
|
+
dash: 3 3
|
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
#This layout inspired by popular fantasy games
|
|
2
|
-
title:
|
|
3
|
-
x: 90
|
|
4
|
-
y: 90
|
|
5
|
-
width: 500
|
|
6
|
-
height: 50
|
|
7
|
-
|
|
8
|
-
upper_right:
|
|
9
|
-
x: 595
|
|
10
|
-
y: 90
|
|
11
|
-
width: 135
|
|
12
|
-
height: 50
|
|
13
|
-
align: right
|
|
14
|
-
ur: # alias
|
|
15
|
-
extends: upper_right
|
|
16
|
-
|
|
17
|
-
art:
|
|
18
|
-
x: 75
|
|
19
|
-
y: 150
|
|
20
|
-
width: 675
|
|
21
|
-
height: 520
|
|
22
|
-
|
|
23
|
-
type:
|
|
24
|
-
x: 90
|
|
25
|
-
y: 675
|
|
26
|
-
width: 500
|
|
27
|
-
height: 50
|
|
28
|
-
|
|
29
|
-
type_right:
|
|
30
|
-
x: 595
|
|
31
|
-
y: 675
|
|
32
|
-
width: 135
|
|
33
|
-
height: 50
|
|
34
|
-
align: right
|
|
35
|
-
tr: #alias
|
|
36
|
-
extends: type_right
|
|
37
|
-
|
|
38
|
-
description:
|
|
39
|
-
x: 100
|
|
40
|
-
y: 730
|
|
41
|
-
width: 625
|
|
42
|
-
height: 275
|
|
43
|
-
valign: middle
|
|
44
|
-
align: center
|
|
45
|
-
font_size: 18
|
|
46
|
-
desc: # alias
|
|
47
|
-
extends: description
|
|
48
|
-
|
|
49
|
-
lower_right:
|
|
50
|
-
x: 675
|
|
51
|
-
y: 975
|
|
52
|
-
width: 75
|
|
53
|
-
height: 75
|
|
54
|
-
font_size: 18
|
|
55
|
-
valign: bottom
|
|
56
|
-
align: right
|
|
57
|
-
lr: #alias
|
|
58
|
-
extends: lower_right
|
|
59
|
-
|
|
60
|
-
lower_left:
|
|
61
|
-
x: 75
|
|
62
|
-
y: 975
|
|
63
|
-
width: 75
|
|
64
|
-
height: 75
|
|
65
|
-
font_size: 18
|
|
66
|
-
valign: bottom
|
|
67
|
-
align: left
|
|
68
|
-
ll: # alias
|
|
69
|
-
extends: lower_left
|
|
70
|
-
|
|
71
|
-
copyright:
|
|
72
|
-
x: 75
|
|
73
|
-
y: 1025
|
|
74
|
-
width: 675
|
|
75
|
-
height: 25
|
|
76
|
-
font_size: 16
|
|
77
|
-
align: center
|
|
78
|
-
valign: bottom
|
|
79
|
-
#aliases for copyright
|
|
80
|
-
copy:
|
|
81
|
-
extends: copyright
|
|
82
|
-
credit:
|
|
83
|
-
extends: copyright
|
|
84
|
-
credits:
|
|
85
|
-
extends: copyright
|
|
86
|
-
|
|
87
|
-
# The "cut line", without rounded corners
|
|
88
|
-
cut:
|
|
89
|
-
x: 37.5
|
|
90
|
-
y: 37.5
|
|
91
|
-
width: 750
|
|
92
|
-
height: 1050
|
|
93
|
-
|
|
94
|
-
# The "safe zone" as defined by TheGameCrafter poker cards
|
|
95
|
-
safe:
|
|
96
|
-
x: 75
|
|
97
|
-
y: 75
|
|
98
|
-
width: 675
|
|
99
|
-
height: 975
|
|
100
|
-
radius: 16
|
|
101
|
-
dash: 3 3
|
|
1
|
+
#This layout inspired by popular fantasy games
|
|
2
|
+
title:
|
|
3
|
+
x: 90
|
|
4
|
+
y: 90
|
|
5
|
+
width: 500
|
|
6
|
+
height: 50
|
|
7
|
+
|
|
8
|
+
upper_right:
|
|
9
|
+
x: 595
|
|
10
|
+
y: 90
|
|
11
|
+
width: 135
|
|
12
|
+
height: 50
|
|
13
|
+
align: right
|
|
14
|
+
ur: # alias
|
|
15
|
+
extends: upper_right
|
|
16
|
+
|
|
17
|
+
art:
|
|
18
|
+
x: 75
|
|
19
|
+
y: 150
|
|
20
|
+
width: 675
|
|
21
|
+
height: 520
|
|
22
|
+
|
|
23
|
+
type:
|
|
24
|
+
x: 90
|
|
25
|
+
y: 675
|
|
26
|
+
width: 500
|
|
27
|
+
height: 50
|
|
28
|
+
|
|
29
|
+
type_right:
|
|
30
|
+
x: 595
|
|
31
|
+
y: 675
|
|
32
|
+
width: 135
|
|
33
|
+
height: 50
|
|
34
|
+
align: right
|
|
35
|
+
tr: #alias
|
|
36
|
+
extends: type_right
|
|
37
|
+
|
|
38
|
+
description:
|
|
39
|
+
x: 100
|
|
40
|
+
y: 730
|
|
41
|
+
width: 625
|
|
42
|
+
height: 275
|
|
43
|
+
valign: middle
|
|
44
|
+
align: center
|
|
45
|
+
font_size: 18
|
|
46
|
+
desc: # alias
|
|
47
|
+
extends: description
|
|
48
|
+
|
|
49
|
+
lower_right:
|
|
50
|
+
x: 675
|
|
51
|
+
y: 975
|
|
52
|
+
width: 75
|
|
53
|
+
height: 75
|
|
54
|
+
font_size: 18
|
|
55
|
+
valign: bottom
|
|
56
|
+
align: right
|
|
57
|
+
lr: #alias
|
|
58
|
+
extends: lower_right
|
|
59
|
+
|
|
60
|
+
lower_left:
|
|
61
|
+
x: 75
|
|
62
|
+
y: 975
|
|
63
|
+
width: 75
|
|
64
|
+
height: 75
|
|
65
|
+
font_size: 18
|
|
66
|
+
valign: bottom
|
|
67
|
+
align: left
|
|
68
|
+
ll: # alias
|
|
69
|
+
extends: lower_left
|
|
70
|
+
|
|
71
|
+
copyright:
|
|
72
|
+
x: 75
|
|
73
|
+
y: 1025
|
|
74
|
+
width: 675
|
|
75
|
+
height: 25
|
|
76
|
+
font_size: 16
|
|
77
|
+
align: center
|
|
78
|
+
valign: bottom
|
|
79
|
+
#aliases for copyright
|
|
80
|
+
copy:
|
|
81
|
+
extends: copyright
|
|
82
|
+
credit:
|
|
83
|
+
extends: copyright
|
|
84
|
+
credits:
|
|
85
|
+
extends: copyright
|
|
86
|
+
|
|
87
|
+
# The "cut line", without rounded corners
|
|
88
|
+
cut:
|
|
89
|
+
x: 37.5
|
|
90
|
+
y: 37.5
|
|
91
|
+
width: 750
|
|
92
|
+
height: 1050
|
|
93
|
+
|
|
94
|
+
# The "safe zone" as defined by TheGameCrafter poker cards
|
|
95
|
+
safe:
|
|
96
|
+
x: 75
|
|
97
|
+
y: 75
|
|
98
|
+
width: 675
|
|
99
|
+
height: 975
|
|
100
|
+
radius: 16
|
|
101
|
+
dash: 3 3
|