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.
Files changed (162) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +41 -41
  3. data/.travis.yml +19 -19
  4. data/CHANGELOG.md +357 -340
  5. data/CONTRIBUTING.md +40 -40
  6. data/Gemfile +2 -2
  7. data/LICENSE.txt +22 -22
  8. data/README.md +121 -121
  9. data/RELEASE TODO.md +21 -21
  10. data/Rakefile +48 -48
  11. data/appveyor.yml +24 -24
  12. data/bin/squib +4 -4
  13. data/lib/squib.rb +32 -32
  14. data/lib/squib/api/background.rb +15 -15
  15. data/lib/squib/api/data.rb +137 -137
  16. data/lib/squib/api/groups.rb +54 -54
  17. data/lib/squib/api/image.rb +49 -49
  18. data/lib/squib/api/save.rb +83 -83
  19. data/lib/squib/api/settings.rb +21 -21
  20. data/lib/squib/api/shapes.rb +124 -124
  21. data/lib/squib/api/text.rb +25 -25
  22. data/lib/squib/api/text_embed.rb +71 -71
  23. data/lib/squib/api/units.rb +27 -27
  24. data/lib/squib/args/arg_loader.rb +126 -126
  25. data/lib/squib/args/box.rb +55 -55
  26. data/lib/squib/args/card_range.rb +32 -32
  27. data/lib/squib/args/color_validator.rb +12 -12
  28. data/lib/squib/args/coords.rb +35 -35
  29. data/lib/squib/args/csv_opts.rb +25 -25
  30. data/lib/squib/args/dir_validator.rb +16 -16
  31. data/lib/squib/args/draw.rb +92 -92
  32. data/lib/squib/args/embed_adjust.rb +25 -25
  33. data/lib/squib/args/embed_key.rb +17 -17
  34. data/lib/squib/args/hand_special.rb +37 -37
  35. data/lib/squib/args/import.rb +40 -40
  36. data/lib/squib/args/input_file.rb +37 -37
  37. data/lib/squib/args/paint.rb +44 -44
  38. data/lib/squib/args/paragraph.rb +116 -116
  39. data/lib/squib/args/save_batch.rb +63 -63
  40. data/lib/squib/args/scale_box.rb +53 -53
  41. data/lib/squib/args/sheet.rb +172 -172
  42. data/lib/squib/args/showcase_special.rb +38 -38
  43. data/lib/squib/args/sprue_file.rb +44 -44
  44. data/lib/squib/args/svg_special.rb +37 -37
  45. data/lib/squib/args/transform.rb +61 -61
  46. data/lib/squib/args/typographer.rb +119 -119
  47. data/lib/squib/args/unit_conversion.rb +29 -29
  48. data/lib/squib/builtin/layouts/economy.yml +85 -85
  49. data/lib/squib/builtin/layouts/fantasy.yml +101 -101
  50. data/lib/squib/builtin/layouts/hand.yml +62 -62
  51. data/lib/squib/builtin/layouts/party.yml +94 -94
  52. data/lib/squib/builtin/layouts/playing-card.yml +35 -35
  53. data/lib/squib/builtin/layouts/tuck_box.yml +46 -46
  54. data/lib/squib/builtin/projects/advanced/.gitignore +4 -4
  55. data/lib/squib/builtin/projects/advanced/ABOUT.md +19 -19
  56. data/lib/squib/builtin/projects/advanced/Gemfile +11 -11
  57. data/lib/squib/builtin/projects/advanced/Guardfile +21 -21
  58. data/lib/squib/builtin/projects/advanced/IDEAS.md +22 -22
  59. data/lib/squib/builtin/projects/advanced/PLAYTESTING.md +26 -26
  60. data/lib/squib/builtin/projects/advanced/Rakefile +27 -27
  61. data/lib/squib/builtin/projects/advanced/config.yml +49 -49
  62. data/lib/squib/builtin/projects/advanced/docs/PNP NOTES.md +3 -3
  63. data/lib/squib/builtin/projects/advanced/docs/RULES.md +21 -21
  64. data/lib/squib/builtin/projects/advanced/img/example.svg +60 -60
  65. data/lib/squib/builtin/projects/advanced/layouts/deck.yml +27 -27
  66. data/lib/squib/builtin/projects/advanced/src/deck.rb +34 -34
  67. data/lib/squib/builtin/projects/advanced/src/version.rb +3 -3
  68. data/lib/squib/builtin/projects/basic/.gitignore +4 -4
  69. data/lib/squib/builtin/projects/basic/ABOUT.md +19 -19
  70. data/lib/squib/builtin/projects/basic/Gemfile +3 -3
  71. data/lib/squib/builtin/projects/basic/IDEAS.md +22 -22
  72. data/lib/squib/builtin/projects/basic/PLAYTESTING.md +26 -26
  73. data/lib/squib/builtin/projects/basic/PNP NOTES.md +3 -3
  74. data/lib/squib/builtin/projects/basic/RULES.md +21 -21
  75. data/lib/squib/builtin/projects/basic/Rakefile +7 -7
  76. data/lib/squib/builtin/projects/basic/config.yml +49 -49
  77. data/lib/squib/builtin/projects/basic/deck.rb +6 -6
  78. data/lib/squib/builtin/sprues/a4_euro_card.yml +42 -42
  79. data/lib/squib/builtin/sprues/a4_poker_card_8up.yml +40 -40
  80. data/lib/squib/builtin/sprues/a4_poker_card_9up.yml +42 -42
  81. data/lib/squib/builtin/sprues/a4_usa_card.yml +42 -42
  82. data/lib/squib/builtin/sprues/drivethrucards_1up.yml +10 -0
  83. data/lib/squib/builtin/sprues/letter_poker_card_9up.yml +25 -25
  84. data/lib/squib/builtin/sprues/letter_poker_foldable_8up.yml +52 -52
  85. data/lib/squib/builtin/sprues/printplaygames_18up.yml +68 -0
  86. data/lib/squib/card.rb +75 -74
  87. data/lib/squib/commands/cli.rb +39 -39
  88. data/lib/squib/commands/data/template_option.rb +109 -109
  89. data/lib/squib/commands/make_sprue.rb +275 -275
  90. data/lib/squib/commands/new.rb +77 -77
  91. data/lib/squib/conf.rb +139 -139
  92. data/lib/squib/constants.rb +17 -17
  93. data/lib/squib/deck.rb +116 -116
  94. data/lib/squib/graphics/background.rb +14 -14
  95. data/lib/squib/graphics/cairo_context_wrapper.rb +113 -113
  96. data/lib/squib/graphics/embedding_utils.rb +28 -28
  97. data/lib/squib/graphics/gradient_regex.rb +47 -47
  98. data/lib/squib/graphics/hand.rb +42 -42
  99. data/lib/squib/graphics/image.rb +108 -108
  100. data/lib/squib/graphics/save_doc.rb +61 -61
  101. data/lib/squib/graphics/save_images.rb +52 -52
  102. data/lib/squib/graphics/save_pdf.rb +90 -90
  103. data/lib/squib/graphics/save_sprue.rb +204 -205
  104. data/lib/squib/graphics/shapes.rb +143 -143
  105. data/lib/squib/graphics/showcase.rb +85 -85
  106. data/lib/squib/graphics/text.rb +174 -174
  107. data/lib/squib/import/data_frame.rb +108 -108
  108. data/lib/squib/layout_parser.rb +138 -126
  109. data/lib/squib/progress.rb +38 -38
  110. data/lib/squib/sample_helpers.rb +34 -34
  111. data/lib/squib/sprues/crop_line.rb +28 -28
  112. data/lib/squib/sprues/crop_line_dash.rb +35 -35
  113. data/lib/squib/sprues/invalid_sprue_definition.rb +9 -9
  114. data/lib/squib/sprues/sprue.rb +203 -203
  115. data/lib/squib/sprues/sprue_schema.rb +48 -48
  116. data/lib/squib/version.rb +10 -10
  117. data/samples/autoscale_font/_autoscale_font.rb +29 -29
  118. data/samples/backend/_backend.rb +26 -26
  119. data/samples/basic.rb +19 -19
  120. data/samples/build_groups/build_groups.rb +36 -36
  121. data/samples/colors/_colors.rb +38 -38
  122. data/samples/colors/_gradients.rb +34 -34
  123. data/samples/config/config_text_markup.rb +20 -20
  124. data/samples/config/custom_config.rb +18 -18
  125. data/samples/data/_csv.rb +33 -33
  126. data/samples/data/_excel.rb +55 -55
  127. data/samples/data/_yaml.rb +12 -12
  128. data/samples/hello_world.rb +6 -6
  129. data/samples/images/_cairo_access.rb +39 -39
  130. data/samples/images/_images.rb +104 -104
  131. data/samples/images/_more_load_images.rb +102 -102
  132. data/samples/intro/01_hello.rb +8 -8
  133. data/samples/intro/02_options.rb +14 -14
  134. data/samples/intro/03_layout.rb +11 -11
  135. data/samples/intro/04_arrays.rb +15 -15
  136. data/samples/intro/05_excel.rb +14 -14
  137. data/samples/layouts/builtin_layouts.rb +97 -97
  138. data/samples/layouts/layouts.rb +71 -71
  139. data/samples/project/src/characters.rb +8 -8
  140. data/samples/project/src/skills.rb +7 -7
  141. data/samples/proofs/_tgc_proofs.rb +16 -16
  142. data/samples/ranges/_ranges.rb +64 -64
  143. data/samples/saves/_hand.rb +23 -23
  144. data/samples/saves/_portrait_landscape.rb +23 -23
  145. data/samples/saves/_save_pdf.rb +29 -29
  146. data/samples/saves/_saves.rb +51 -51
  147. data/samples/saves/_showcase.rb +25 -25
  148. data/samples/shapes/_draw_shapes.rb +60 -58
  149. data/samples/shapes/_proofs.rb +22 -22
  150. data/samples/sprues/_advanced_sprues.rb +24 -24
  151. data/samples/sprues/_builtin_sprues.rb +21 -19
  152. data/samples/sprues/_fold_sheet.rb +27 -27
  153. data/samples/sprues/_hex_tiles.rb +15 -15
  154. data/samples/sprues/_mints.rb +11 -11
  155. data/samples/sprues/_sprue_example.rb +11 -11
  156. data/samples/text/_embed_text.rb +128 -128
  157. data/samples/text/_text.rb +47 -47
  158. data/samples/text/_text_options.rb +102 -102
  159. data/samples/text/bug134.rb +14 -14
  160. data/samples/units/_units.rb +32 -32
  161. data/squib.gemspec +52 -51
  162. 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
@@ -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
@@ -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