squib 0.18.0 → 0.19.0a
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/.github/ISSUE_TEMPLATE/bug_report.md +39 -39
- data/.github/ISSUE_TEMPLATE/feature_request.md +22 -22
- data/.github/ISSUE_TEMPLATE/help-wanted.md +13 -13
- data/.github/ISSUE_TEMPLATE/release-todo.md +45 -33
- data/.github/PULL_REQUEST_TEMPLATE.md +13 -13
- data/.github/workflows/tests.yml +22 -22
- data/.gitignore +41 -41
- data/.vscode/settings.json +4 -3
- data/CHANGELOG.md +460 -460
- data/CONTRIBUTING.md +40 -40
- data/Dockerfile +27 -27
- data/Gemfile +2 -2
- data/Guardfile +8 -8
- data/LICENSE.txt +22 -22
- data/README.md +139 -139
- data/Rakefile +51 -51
- data/bin/squib +5 -5
- data/lib/squib/api/settings.rb +21 -21
- data/lib/squib/args/arg_loader.rb +138 -138
- data/lib/squib/args/box.rb +59 -59
- data/lib/squib/args/card_range.rb +34 -34
- data/lib/squib/args/color_validator.rb +7 -7
- data/lib/squib/args/coords.rb +49 -49
- data/lib/squib/args/csv_opts.rb +22 -22
- data/lib/squib/args/dir_validator.rb +11 -11
- data/lib/squib/args/draw.rb +93 -93
- data/lib/squib/args/drop_shadow.rb +39 -39
- data/lib/squib/args/embed_adjust.rb +22 -22
- data/lib/squib/args/embed_key.rb +12 -12
- data/lib/squib/args/hand_special.rb +37 -37
- data/lib/squib/args/import.rb +67 -67
- data/lib/squib/args/input_file.rb +55 -55
- data/lib/squib/args/paint.rb +43 -43
- data/lib/squib/args/paragraph.rb +118 -118
- data/lib/squib/args/save_batch.rb +65 -65
- data/lib/squib/args/scale_box.rb +57 -57
- data/lib/squib/args/sheet.rb +165 -165
- data/lib/squib/args/showcase_special.rb +41 -41
- data/lib/squib/args/sprue_file.rb +44 -44
- data/lib/squib/args/svg_special.rb +37 -37
- data/lib/squib/args/transform.rb +55 -55
- data/lib/squib/args/typographer.rb +115 -115
- data/lib/squib/args/unit_conversion.rb +27 -27
- data/lib/squib/args/xywh_shorthands.rb +50 -50
- 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 +50 -50
- 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 -10
- 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 -68
- data/lib/squib/card.rb +75 -75
- 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 +277 -277
- data/lib/squib/commands/new.rb +77 -77
- data/lib/squib/conf.rb +149 -149
- data/lib/squib/constants.rb +17 -17
- data/lib/squib/deck.rb +138 -138
- data/lib/squib/dsl/background.rb +35 -35
- data/lib/squib/dsl/circle.rb +39 -39
- data/lib/squib/dsl/csv.rb +42 -42
- data/lib/squib/dsl/curve.rb +35 -35
- data/lib/squib/dsl/cut_zone.rb +47 -47
- data/lib/squib/dsl/ellipse.rb +37 -37
- data/lib/squib/dsl/grid.rb +35 -35
- data/lib/squib/dsl/groups.rb +54 -54
- data/lib/squib/dsl/hand.rb +42 -42
- data/lib/squib/dsl/line.rb +35 -35
- data/lib/squib/dsl/png.rb +57 -57
- data/lib/squib/dsl/polygon.rb +36 -36
- data/lib/squib/dsl/rect.rb +37 -37
- data/lib/squib/dsl/safe_zone.rb +48 -48
- data/lib/squib/dsl/save.rb +21 -21
- data/lib/squib/dsl/save_pdf.rb +50 -50
- data/lib/squib/dsl/save_png.rb +48 -48
- data/lib/squib/dsl/save_sheet.rb +53 -53
- data/lib/squib/dsl/showcase.rb +43 -43
- data/lib/squib/dsl/star.rb +37 -37
- data/lib/squib/dsl/svg.rb +63 -63
- data/lib/squib/dsl/text.rb +54 -54
- data/lib/squib/dsl/text_embed.rb +79 -79
- data/lib/squib/dsl/triangle.rb +35 -35
- data/lib/squib/dsl/units.rb +37 -37
- data/lib/squib/dsl/xlsx.rb +40 -40
- data/lib/squib/dsl/yaml.rb +40 -40
- data/lib/squib/errors_warnings/warn_unexpected_params.rb +14 -14
- data/lib/squib/graphics/background.rb +14 -14
- data/lib/squib/graphics/cairo_context_wrapper.rb +115 -115
- 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 +123 -123
- data/lib/squib/graphics/save_doc.rb +77 -77
- data/lib/squib/graphics/save_images.rb +91 -91
- data/lib/squib/graphics/save_pdf.rb +90 -90
- data/lib/squib/graphics/save_sprue.rb +231 -231
- data/lib/squib/graphics/shapes.rb +143 -143
- data/lib/squib/graphics/showcase.rb +85 -85
- data/lib/squib/graphics/text.rb +202 -202
- data/lib/squib/import/csv_importer.rb +45 -45
- data/lib/squib/import/data_frame.rb +108 -108
- data/lib/squib/import/quantity_exploder.rb +17 -17
- data/lib/squib/import/xlsx_importer.rb +28 -28
- data/lib/squib/import/yaml_importer.rb +30 -30
- data/lib/squib/layout_parser.rb +155 -155
- 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 +208 -208
- data/lib/squib/sprues/sprue_schema.rb +51 -51
- data/lib/squib/system_fonts.rb +16 -16
- data/lib/squib/version.rb +11 -11
- data/lib/squib.rb +35 -35
- data/samples/autoscale_font/_autoscale_font.rb +98 -98
- 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 +44 -44
- data/samples/colors/_gradients.rb +34 -34
- data/samples/colors/_switch_color.rb +33 -33
- 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/images/_placeholders.rb +48 -48
- 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_filenames.rb +28 -28
- data/samples/saves/_save_pdf.rb +29 -29
- data/samples/saves/_saves.rb +75 -75
- data/samples/saves/_showcase.rb +25 -25
- data/samples/shadows/_shadow.rb +71 -71
- data/samples/shapes/_draw_shapes.rb +60 -60
- data/samples/shapes/_proofs.rb +22 -22
- data/samples/sprues/_advanced_sprues.rb +25 -25
- data/samples/sprues/_builtin_sprues.rb +22 -22
- data/samples/sprues/_fold_sheet.rb +30 -30
- data/samples/sprues/_hex_tiles.rb +15 -15
- data/samples/sprues/_mints.rb +11 -11
- data/samples/sprues/_negative_coords.rb +6 -6
- data/samples/sprues/_sprue_example.rb +11 -11
- data/samples/system_font_debug/_list_fonts.rb +14 -14
- data/samples/text/_embed_text.rb +128 -128
- data/samples/text/_text.rb +52 -52
- data/samples/text/_text_options.rb +103 -103
- data/samples/text/bug134.rb +14 -14
- data/samples/units/_cells.rb +50 -50
- data/samples/units/_shorthands.rb +48 -48
- data/samples/units/_units.rb +39 -39
- data/squib.gemspec +58 -58
- metadata +21 -21
|
@@ -1,143 +1,143 @@
|
|
|
1
|
-
module Squib
|
|
2
|
-
# @api private
|
|
3
|
-
class Card
|
|
4
|
-
|
|
5
|
-
# :nodoc:
|
|
6
|
-
# @api private
|
|
7
|
-
def rect(box, draw, trans)
|
|
8
|
-
use_cairo do |cc|
|
|
9
|
-
cc.rotate_about(box.x, box.y, trans.angle)
|
|
10
|
-
cc.rounded_rectangle(box.x, box.y, box.width, box.height,
|
|
11
|
-
box.x_radius, box.y_radius)
|
|
12
|
-
cc.fill_n_stroke(draw)
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# :nodoc:
|
|
17
|
-
# @api private
|
|
18
|
-
def circle(box, draw)
|
|
19
|
-
x, y, r = box.x, box.y, box.radius
|
|
20
|
-
use_cairo do |cc|
|
|
21
|
-
if box.arc_direction == :clockwise
|
|
22
|
-
cc.arc(x, y, r, box.arc_start, box.arc_end)
|
|
23
|
-
else
|
|
24
|
-
cc.arc_negative(x, y, r, box.arc_start, box.arc_end)
|
|
25
|
-
end
|
|
26
|
-
if box.arc_close
|
|
27
|
-
cc.close_path();
|
|
28
|
-
end
|
|
29
|
-
cc.fill_n_stroke(draw)
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# Ellipse drawing taken from looking at the control points in Inkscape
|
|
34
|
-
# Think of it like a rectangle. Curves go from mid-points of the sides
|
|
35
|
-
# of the rectangle. Control points are at 1/4 and 3/4 of the side.
|
|
36
|
-
# :nodoc:
|
|
37
|
-
# @api private
|
|
38
|
-
def ellipse(box, draw, trans)
|
|
39
|
-
x, y, w, h = box.x, box.y, box.width, box.height
|
|
40
|
-
use_cairo do |cc|
|
|
41
|
-
cc.rotate_about(box.x, box.y, trans.angle)
|
|
42
|
-
cc.move_to(x, y + 0.5 * h) # start west
|
|
43
|
-
cc.curve_to(x, y + 0.25 * h, # west to north
|
|
44
|
-
x + 0.25 * w, y,
|
|
45
|
-
x + 0.5 * w, y)
|
|
46
|
-
cc.curve_to(x + 0.75 * w, y, # north to east
|
|
47
|
-
x + w, y + 0.25 * h,
|
|
48
|
-
x + w, y + 0.5 * h)
|
|
49
|
-
cc.curve_to(x + w, y + 0.75 * h, # east to south
|
|
50
|
-
x + 0.75 * w, y + h,
|
|
51
|
-
x + 0.5 * w, y + h)
|
|
52
|
-
cc.curve_to(x + 0.25 * w, y + h, # south to west
|
|
53
|
-
x, y + 0.75 * h,
|
|
54
|
-
x, y + 0.5 * h)
|
|
55
|
-
cc.fill_n_stroke(draw)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# :nodoc:
|
|
60
|
-
# @api private
|
|
61
|
-
def grid(box, draw)
|
|
62
|
-
x, y, w, h = box.x, box.y, box.width, box.height
|
|
63
|
-
use_cairo do |cc|
|
|
64
|
-
(x..@width + w).step(w) { |ix| line_xy(ix, y - @height, ix, @height + y, draw) }
|
|
65
|
-
(y..@height + h).step(h) { |iy| line_xy(x - @width, iy, @width + x, iy, draw) }
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# :nodoc:
|
|
70
|
-
# @api private
|
|
71
|
-
def triangle(tri, draw)
|
|
72
|
-
use_cairo do |cc|
|
|
73
|
-
cc.triangle(tri.x1, tri.y1, tri.x2, tri.y2, tri.x3, tri.y3)
|
|
74
|
-
cc.fill_n_stroke(draw)
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# :nodoc:
|
|
79
|
-
# @api private
|
|
80
|
-
def line(coord, draw)
|
|
81
|
-
line_xy(coord.x1, coord.y1, coord.x2, coord.y2, draw)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# :nodoc:
|
|
85
|
-
# @api private
|
|
86
|
-
def line_xy(x1, y1, x2, y2, draw)
|
|
87
|
-
use_cairo do |cc|
|
|
88
|
-
cc.move_to(x1, y1)
|
|
89
|
-
cc.line_to(x2, y2)
|
|
90
|
-
cc.fancy_stroke(draw)
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
# :nodoc:
|
|
95
|
-
# @api private
|
|
96
|
-
def curve(bez, draw)
|
|
97
|
-
x1, y1, cx1, cy1 = bez.x1, bez.y1, bez.cx1, bez.cy1
|
|
98
|
-
cx2, cy2, x2, y2 = bez.cx2, bez.cy2, bez.x2, bez.y2
|
|
99
|
-
use_cairo do |cc|
|
|
100
|
-
cc.move_to(x1, y1)
|
|
101
|
-
cc.curve_to(cx1, cy1, cx2, cy2, x2, y2)
|
|
102
|
-
cc.fill_n_stroke(draw)
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
# :nodoc:
|
|
107
|
-
# @api private
|
|
108
|
-
def star(poly, trans, draw)
|
|
109
|
-
x, y, n = poly.x, poly.y, poly.n
|
|
110
|
-
inner_radius, outer_radius = poly.inner_radius, poly.outer_radius
|
|
111
|
-
use_cairo do |cc|
|
|
112
|
-
cc.rotate_about(x, y, trans.angle)
|
|
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.fill_n_stroke(draw)
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
# :nodoc:
|
|
126
|
-
# @api private
|
|
127
|
-
def polygon(poly, trans, draw)
|
|
128
|
-
x, y, n, radius = poly.x, poly.y, poly.n, poly.radius
|
|
129
|
-
use_cairo do |cc|
|
|
130
|
-
cc.rotate_about(x, y, trans.angle)
|
|
131
|
-
cc.move_to(x + radius, y) # i = 0, so cos(0)=1 and sin(0)=0
|
|
132
|
-
theta = (2 * Math::PI) / n.to_f
|
|
133
|
-
0.upto(n) do |i|
|
|
134
|
-
cc.line_to(x + radius * Math::cos(i * theta),
|
|
135
|
-
y + radius * Math::sin(i * theta))
|
|
136
|
-
end
|
|
137
|
-
cc.close_path
|
|
138
|
-
cc.fill_n_stroke(draw)
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
end
|
|
143
|
-
end
|
|
1
|
+
module Squib
|
|
2
|
+
# @api private
|
|
3
|
+
class Card
|
|
4
|
+
|
|
5
|
+
# :nodoc:
|
|
6
|
+
# @api private
|
|
7
|
+
def rect(box, draw, trans)
|
|
8
|
+
use_cairo do |cc|
|
|
9
|
+
cc.rotate_about(box.x, box.y, trans.angle)
|
|
10
|
+
cc.rounded_rectangle(box.x, box.y, box.width, box.height,
|
|
11
|
+
box.x_radius, box.y_radius)
|
|
12
|
+
cc.fill_n_stroke(draw)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# :nodoc:
|
|
17
|
+
# @api private
|
|
18
|
+
def circle(box, draw)
|
|
19
|
+
x, y, r = box.x, box.y, box.radius
|
|
20
|
+
use_cairo do |cc|
|
|
21
|
+
if box.arc_direction == :clockwise
|
|
22
|
+
cc.arc(x, y, r, box.arc_start, box.arc_end)
|
|
23
|
+
else
|
|
24
|
+
cc.arc_negative(x, y, r, box.arc_start, box.arc_end)
|
|
25
|
+
end
|
|
26
|
+
if box.arc_close
|
|
27
|
+
cc.close_path();
|
|
28
|
+
end
|
|
29
|
+
cc.fill_n_stroke(draw)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Ellipse drawing taken from looking at the control points in Inkscape
|
|
34
|
+
# Think of it like a rectangle. Curves go from mid-points of the sides
|
|
35
|
+
# of the rectangle. Control points are at 1/4 and 3/4 of the side.
|
|
36
|
+
# :nodoc:
|
|
37
|
+
# @api private
|
|
38
|
+
def ellipse(box, draw, trans)
|
|
39
|
+
x, y, w, h = box.x, box.y, box.width, box.height
|
|
40
|
+
use_cairo do |cc|
|
|
41
|
+
cc.rotate_about(box.x, box.y, trans.angle)
|
|
42
|
+
cc.move_to(x, y + 0.5 * h) # start west
|
|
43
|
+
cc.curve_to(x, y + 0.25 * h, # west to north
|
|
44
|
+
x + 0.25 * w, y,
|
|
45
|
+
x + 0.5 * w, y)
|
|
46
|
+
cc.curve_to(x + 0.75 * w, y, # north to east
|
|
47
|
+
x + w, y + 0.25 * h,
|
|
48
|
+
x + w, y + 0.5 * h)
|
|
49
|
+
cc.curve_to(x + w, y + 0.75 * h, # east to south
|
|
50
|
+
x + 0.75 * w, y + h,
|
|
51
|
+
x + 0.5 * w, y + h)
|
|
52
|
+
cc.curve_to(x + 0.25 * w, y + h, # south to west
|
|
53
|
+
x, y + 0.75 * h,
|
|
54
|
+
x, y + 0.5 * h)
|
|
55
|
+
cc.fill_n_stroke(draw)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# :nodoc:
|
|
60
|
+
# @api private
|
|
61
|
+
def grid(box, draw)
|
|
62
|
+
x, y, w, h = box.x, box.y, box.width, box.height
|
|
63
|
+
use_cairo do |cc|
|
|
64
|
+
(x..@width + w).step(w) { |ix| line_xy(ix, y - @height, ix, @height + y, draw) }
|
|
65
|
+
(y..@height + h).step(h) { |iy| line_xy(x - @width, iy, @width + x, iy, draw) }
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# :nodoc:
|
|
70
|
+
# @api private
|
|
71
|
+
def triangle(tri, draw)
|
|
72
|
+
use_cairo do |cc|
|
|
73
|
+
cc.triangle(tri.x1, tri.y1, tri.x2, tri.y2, tri.x3, tri.y3)
|
|
74
|
+
cc.fill_n_stroke(draw)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# :nodoc:
|
|
79
|
+
# @api private
|
|
80
|
+
def line(coord, draw)
|
|
81
|
+
line_xy(coord.x1, coord.y1, coord.x2, coord.y2, draw)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# :nodoc:
|
|
85
|
+
# @api private
|
|
86
|
+
def line_xy(x1, y1, x2, y2, draw)
|
|
87
|
+
use_cairo do |cc|
|
|
88
|
+
cc.move_to(x1, y1)
|
|
89
|
+
cc.line_to(x2, y2)
|
|
90
|
+
cc.fancy_stroke(draw)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# :nodoc:
|
|
95
|
+
# @api private
|
|
96
|
+
def curve(bez, draw)
|
|
97
|
+
x1, y1, cx1, cy1 = bez.x1, bez.y1, bez.cx1, bez.cy1
|
|
98
|
+
cx2, cy2, x2, y2 = bez.cx2, bez.cy2, bez.x2, bez.y2
|
|
99
|
+
use_cairo do |cc|
|
|
100
|
+
cc.move_to(x1, y1)
|
|
101
|
+
cc.curve_to(cx1, cy1, cx2, cy2, x2, y2)
|
|
102
|
+
cc.fill_n_stroke(draw)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# :nodoc:
|
|
107
|
+
# @api private
|
|
108
|
+
def star(poly, trans, draw)
|
|
109
|
+
x, y, n = poly.x, poly.y, poly.n
|
|
110
|
+
inner_radius, outer_radius = poly.inner_radius, poly.outer_radius
|
|
111
|
+
use_cairo do |cc|
|
|
112
|
+
cc.rotate_about(x, y, trans.angle)
|
|
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.fill_n_stroke(draw)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# :nodoc:
|
|
126
|
+
# @api private
|
|
127
|
+
def polygon(poly, trans, draw)
|
|
128
|
+
x, y, n, radius = poly.x, poly.y, poly.n, poly.radius
|
|
129
|
+
use_cairo do |cc|
|
|
130
|
+
cc.rotate_about(x, y, trans.angle)
|
|
131
|
+
cc.move_to(x + radius, y) # i = 0, so cos(0)=1 and sin(0)=0
|
|
132
|
+
theta = (2 * Math::PI) / n.to_f
|
|
133
|
+
0.upto(n) do |i|
|
|
134
|
+
cc.line_to(x + radius * Math::cos(i * theta),
|
|
135
|
+
y + radius * Math::sin(i * theta))
|
|
136
|
+
end
|
|
137
|
+
cc.close_path
|
|
138
|
+
cc.fill_n_stroke(draw)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -1,85 +1,85 @@
|
|
|
1
|
-
require_relative 'cairo_context_wrapper'
|
|
2
|
-
|
|
3
|
-
module Squib
|
|
4
|
-
class Deck
|
|
5
|
-
|
|
6
|
-
# So the Cairo people have said over and over again that they won't support the 3x3 matrices that would handle perspective transforms.
|
|
7
|
-
# Since our perspective transform needs are a bit simpler, we can use a "striping method" that does the job for us.
|
|
8
|
-
# It's a little bit involved, but it works well enough for limited ranges of our parameters.
|
|
9
|
-
# These were also helpful:
|
|
10
|
-
# http://kapo-cpp.blogspot.com/2008/01/perspective-effect-using-cairo.html
|
|
11
|
-
# http://zetcode.com/gui/pygtk/drawingII/
|
|
12
|
-
# :nodoc:
|
|
13
|
-
# @api private
|
|
14
|
-
def render_showcase(range, sheet, showcase)
|
|
15
|
-
out_width = range.size * ((@width - 2 * sheet.trim) * showcase.scale * showcase.offset) + 2 * sheet.margin
|
|
16
|
-
out_height = showcase.reflect_offset + (1.0 + showcase.reflect_percent) * (@height - 2 * sheet.trim) + 2 * sheet.margin
|
|
17
|
-
out_cc = Cairo::Context.new(Cairo::ImageSurface.new(out_width, out_height))
|
|
18
|
-
wrapper = Squib::Graphics::CairoContextWrapper.new(out_cc)
|
|
19
|
-
wrapper.set_source_squibcolor(sheet.fill_color)
|
|
20
|
-
wrapper.paint
|
|
21
|
-
|
|
22
|
-
cards = range.collect { |i| @cards[i] }
|
|
23
|
-
cards.each_with_index do |card, i|
|
|
24
|
-
trimmed = trim_rounded(card.cairo_surface, showcase.trim, showcase.trim_radius)
|
|
25
|
-
reflected = reflect(trimmed, showcase.reflect_offset, showcase.reflect_percent, showcase.reflect_strength)
|
|
26
|
-
perspectived = perspective(reflected, showcase.scale, showcase.face_right?)
|
|
27
|
-
out_cc.set_source(perspectived, sheet.margin + i * perspectived.width * showcase.offset, sheet.margin)
|
|
28
|
-
out_cc.paint
|
|
29
|
-
end
|
|
30
|
-
out_cc.target.write_to_png("#{sheet.dir}/#{sheet.file}")
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# :nodoc:
|
|
34
|
-
# @api private
|
|
35
|
-
def trim_rounded(src, trim, radius)
|
|
36
|
-
trim_cc = Cairo::Context.new(Cairo::ImageSurface.new(@width - 2.0 * trim, @height - 2.0 * trim))
|
|
37
|
-
trim_cc.rounded_rectangle(0, 0, trim_cc.target.width, trim_cc.target.height, radius, radius)
|
|
38
|
-
trim_cc.set_source(src, -1 * trim, -1 * trim)
|
|
39
|
-
trim_cc.clip
|
|
40
|
-
trim_cc.paint
|
|
41
|
-
return trim_cc.target
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# :nodoc:
|
|
45
|
-
# @api private
|
|
46
|
-
def reflect(src, roffset, rpercent, rstrength)
|
|
47
|
-
tmp_cc = Cairo::Context.new(Cairo::ImageSurface.new(src.width, src.height * (1.0 + rpercent) + roffset))
|
|
48
|
-
tmp_cc.set_source(src, 0, 0)
|
|
49
|
-
tmp_cc.paint
|
|
50
|
-
# Flip affine magic from: http://cairographics.org/matrix_transform/
|
|
51
|
-
matrix = Cairo::Matrix.new(1, 0, 0, -1, 0, 2 * src.height + roffset)
|
|
52
|
-
tmp_cc.transform(matrix) # flips the coordinate system
|
|
53
|
-
top_y = src.height # top of the reflection
|
|
54
|
-
bottom_y = src.height * (1.0 - rpercent) + roffset # bottom of the reflection
|
|
55
|
-
gradient = Cairo::LinearPattern.new(0, top_y, 0, bottom_y)
|
|
56
|
-
gradient.add_color_stop_rgba(0.0, 0, 0, 0, rstrength) # start a little reflected
|
|
57
|
-
gradient.add_color_stop_rgba(1.0, 0, 0, 0, 0.0) # fade to nothing
|
|
58
|
-
tmp_cc.set_source(src, 0, 0)
|
|
59
|
-
tmp_cc.mask(gradient)
|
|
60
|
-
return tmp_cc.target
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# :nodoc:
|
|
64
|
-
# @api private
|
|
65
|
-
def perspective(src, scale, face_right)
|
|
66
|
-
dest_cxt = Cairo::Context.new(Cairo::ImageSurface.new(src.width * scale, src.height))
|
|
67
|
-
in_thickness = 1 # Take strip 1 pixel-width at a time
|
|
68
|
-
out_thickness = 3 # Scale it to 3 pixels wider to cover any gaps
|
|
69
|
-
(0..src.width).step(in_thickness) do |i|
|
|
70
|
-
percentage = i / src.width.to_f
|
|
71
|
-
i = src.width - i if face_right
|
|
72
|
-
factor = scale + (percentage * (1.0 - scale)) # linear interpolation
|
|
73
|
-
dest_cxt.save
|
|
74
|
-
dest_cxt.translate 0, src.height / 2.0 * (1.0 - factor)
|
|
75
|
-
dest_cxt.scale factor * scale, factor
|
|
76
|
-
dest_cxt.set_source src, 0, 0
|
|
77
|
-
dest_cxt.rounded_rectangle i, 0, out_thickness, src.height, 0, 0
|
|
78
|
-
dest_cxt.fill
|
|
79
|
-
dest_cxt.restore
|
|
80
|
-
end
|
|
81
|
-
return dest_cxt.target
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
end
|
|
85
|
-
end
|
|
1
|
+
require_relative 'cairo_context_wrapper'
|
|
2
|
+
|
|
3
|
+
module Squib
|
|
4
|
+
class Deck
|
|
5
|
+
|
|
6
|
+
# So the Cairo people have said over and over again that they won't support the 3x3 matrices that would handle perspective transforms.
|
|
7
|
+
# Since our perspective transform needs are a bit simpler, we can use a "striping method" that does the job for us.
|
|
8
|
+
# It's a little bit involved, but it works well enough for limited ranges of our parameters.
|
|
9
|
+
# These were also helpful:
|
|
10
|
+
# http://kapo-cpp.blogspot.com/2008/01/perspective-effect-using-cairo.html
|
|
11
|
+
# http://zetcode.com/gui/pygtk/drawingII/
|
|
12
|
+
# :nodoc:
|
|
13
|
+
# @api private
|
|
14
|
+
def render_showcase(range, sheet, showcase)
|
|
15
|
+
out_width = range.size * ((@width - 2 * sheet.trim) * showcase.scale * showcase.offset) + 2 * sheet.margin
|
|
16
|
+
out_height = showcase.reflect_offset + (1.0 + showcase.reflect_percent) * (@height - 2 * sheet.trim) + 2 * sheet.margin
|
|
17
|
+
out_cc = Cairo::Context.new(Cairo::ImageSurface.new(out_width, out_height))
|
|
18
|
+
wrapper = Squib::Graphics::CairoContextWrapper.new(out_cc)
|
|
19
|
+
wrapper.set_source_squibcolor(sheet.fill_color)
|
|
20
|
+
wrapper.paint
|
|
21
|
+
|
|
22
|
+
cards = range.collect { |i| @cards[i] }
|
|
23
|
+
cards.each_with_index do |card, i|
|
|
24
|
+
trimmed = trim_rounded(card.cairo_surface, showcase.trim, showcase.trim_radius)
|
|
25
|
+
reflected = reflect(trimmed, showcase.reflect_offset, showcase.reflect_percent, showcase.reflect_strength)
|
|
26
|
+
perspectived = perspective(reflected, showcase.scale, showcase.face_right?)
|
|
27
|
+
out_cc.set_source(perspectived, sheet.margin + i * perspectived.width * showcase.offset, sheet.margin)
|
|
28
|
+
out_cc.paint
|
|
29
|
+
end
|
|
30
|
+
out_cc.target.write_to_png("#{sheet.dir}/#{sheet.file}")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# :nodoc:
|
|
34
|
+
# @api private
|
|
35
|
+
def trim_rounded(src, trim, radius)
|
|
36
|
+
trim_cc = Cairo::Context.new(Cairo::ImageSurface.new(@width - 2.0 * trim, @height - 2.0 * trim))
|
|
37
|
+
trim_cc.rounded_rectangle(0, 0, trim_cc.target.width, trim_cc.target.height, radius, radius)
|
|
38
|
+
trim_cc.set_source(src, -1 * trim, -1 * trim)
|
|
39
|
+
trim_cc.clip
|
|
40
|
+
trim_cc.paint
|
|
41
|
+
return trim_cc.target
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# :nodoc:
|
|
45
|
+
# @api private
|
|
46
|
+
def reflect(src, roffset, rpercent, rstrength)
|
|
47
|
+
tmp_cc = Cairo::Context.new(Cairo::ImageSurface.new(src.width, src.height * (1.0 + rpercent) + roffset))
|
|
48
|
+
tmp_cc.set_source(src, 0, 0)
|
|
49
|
+
tmp_cc.paint
|
|
50
|
+
# Flip affine magic from: http://cairographics.org/matrix_transform/
|
|
51
|
+
matrix = Cairo::Matrix.new(1, 0, 0, -1, 0, 2 * src.height + roffset)
|
|
52
|
+
tmp_cc.transform(matrix) # flips the coordinate system
|
|
53
|
+
top_y = src.height # top of the reflection
|
|
54
|
+
bottom_y = src.height * (1.0 - rpercent) + roffset # bottom of the reflection
|
|
55
|
+
gradient = Cairo::LinearPattern.new(0, top_y, 0, bottom_y)
|
|
56
|
+
gradient.add_color_stop_rgba(0.0, 0, 0, 0, rstrength) # start a little reflected
|
|
57
|
+
gradient.add_color_stop_rgba(1.0, 0, 0, 0, 0.0) # fade to nothing
|
|
58
|
+
tmp_cc.set_source(src, 0, 0)
|
|
59
|
+
tmp_cc.mask(gradient)
|
|
60
|
+
return tmp_cc.target
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# :nodoc:
|
|
64
|
+
# @api private
|
|
65
|
+
def perspective(src, scale, face_right)
|
|
66
|
+
dest_cxt = Cairo::Context.new(Cairo::ImageSurface.new(src.width * scale, src.height))
|
|
67
|
+
in_thickness = 1 # Take strip 1 pixel-width at a time
|
|
68
|
+
out_thickness = 3 # Scale it to 3 pixels wider to cover any gaps
|
|
69
|
+
(0..src.width).step(in_thickness) do |i|
|
|
70
|
+
percentage = i / src.width.to_f
|
|
71
|
+
i = src.width - i if face_right
|
|
72
|
+
factor = scale + (percentage * (1.0 - scale)) # linear interpolation
|
|
73
|
+
dest_cxt.save
|
|
74
|
+
dest_cxt.translate 0, src.height / 2.0 * (1.0 - factor)
|
|
75
|
+
dest_cxt.scale factor * scale, factor
|
|
76
|
+
dest_cxt.set_source src, 0, 0
|
|
77
|
+
dest_cxt.rounded_rectangle i, 0, out_thickness, src.height, 0, 0
|
|
78
|
+
dest_cxt.fill
|
|
79
|
+
dest_cxt.restore
|
|
80
|
+
end
|
|
81
|
+
return dest_cxt.target
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
end
|