squib 0.0.4 → 0.0.5

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +9 -0
  4. data/README.md +38 -33
  5. data/Rakefile +1 -1
  6. data/bin/squib +6 -6
  7. data/lib/squib.rb +8 -8
  8. data/lib/squib/api/background.rb +3 -3
  9. data/lib/squib/api/data.rb +5 -6
  10. data/lib/squib/api/image.rb +13 -10
  11. data/lib/squib/api/save.rb +4 -5
  12. data/lib/squib/api/settings.rb +4 -4
  13. data/lib/squib/api/shapes.rb +20 -20
  14. data/lib/squib/api/text.rb +11 -11
  15. data/lib/squib/api/units.rb +4 -4
  16. data/lib/squib/card.rb +5 -5
  17. data/lib/squib/commands/new.rb +5 -5
  18. data/lib/squib/constants.rb +10 -10
  19. data/lib/squib/deck.rb +24 -22
  20. data/lib/squib/graphics/background.rb +3 -3
  21. data/lib/squib/graphics/image.rb +13 -6
  22. data/lib/squib/graphics/save_doc.rb +13 -11
  23. data/lib/squib/graphics/save_images.rb +3 -3
  24. data/lib/squib/graphics/shapes.rb +9 -8
  25. data/lib/squib/graphics/text.rb +61 -59
  26. data/lib/squib/input_helpers.rb +13 -13
  27. data/lib/squib/progress.rb +4 -4
  28. data/lib/squib/project_template/Gemfile +1 -1
  29. data/lib/squib/project_template/deck.rb +3 -3
  30. data/lib/squib/version.rb +6 -2
  31. data/samples/autoscale_font.rb +4 -4
  32. data/samples/basic.rb +6 -7
  33. data/samples/cairo_access.rb +27 -0
  34. data/samples/colors.rb +2 -2
  35. data/samples/custom-layout.yml +5 -5
  36. data/samples/custom_config.rb +4 -4
  37. data/samples/draw_shapes.rb +8 -8
  38. data/samples/hello_world.rb +2 -3
  39. data/samples/load_images.rb +6 -1
  40. data/samples/portrait-landscape.rb +7 -7
  41. data/samples/ranges.rb +13 -14
  42. data/samples/save_pdf.rb +2 -2
  43. data/samples/text_options.rb +17 -17
  44. data/samples/tgc_proofs.rb +3 -3
  45. data/samples/use_layout.rb +3 -3
  46. data/spec/api/api_text_spec.rb +11 -17
  47. data/spec/commands/new_spec.rb +10 -10
  48. data/spec/data/easy-circular-extends.yml +1 -1
  49. data/spec/data/hard-circular-extends.yml +2 -2
  50. data/spec/data/multi-extends-single-entry.yml +3 -3
  51. data/spec/data/multi-level-extends.yml +1 -1
  52. data/spec/data/no-extends.yml +2 -2
  53. data/spec/data/pre-extends.yml +1 -1
  54. data/spec/data/self-circular-extends.yml +1 -1
  55. data/spec/data/single-extends.yml +1 -1
  56. data/spec/data/single-level-multi-extends.yml +1 -1
  57. data/spec/deck_spec.rb +62 -62
  58. data/spec/graphics/graphics_images_spec.rb +79 -0
  59. data/spec/graphics/graphics_save_doc_spec.rb +66 -0
  60. data/spec/graphics/graphics_shapes_spec.rb +74 -0
  61. data/spec/graphics/graphics_text_spec.rb +135 -0
  62. data/spec/input_helpers_spec.rb +61 -40
  63. data/spec/samples_run_spec.rb +6 -6
  64. data/spec/spec_helper.rb +32 -1
  65. data/squib.gemspec +21 -21
  66. metadata +22 -14
@@ -1,11 +1,11 @@
1
1
  module Squib
2
2
  class Deck
3
-
3
+
4
4
  # Draw a rounded rectangle
5
- #
6
- # @example
5
+ #
6
+ # @example
7
7
  # rect x: 0, y: 0, width: 825, height: 1125, radius: 25
8
- #
8
+ #
9
9
  # Options support Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
10
10
  #
11
11
  # @option opts range [Enumerable, :all] (:all) the range of cards over which this will be rendered. See {file:README.md#Specifying_Ranges Specifying Ranges}
@@ -26,16 +26,16 @@ module Squib
26
26
  opts = needs(opts, [:range, :x, :y, :width, :height, :rect_radius, :x_radius, :y_radius,
27
27
  :fill_color, :stroke_color, :stroke_width, :layout])
28
28
  opts[:range].each do |i|
29
- @cards[i].rect(opts[:x][i], opts[:y][i], opts[:width][i], opts[:height][i],
30
- opts[:x_radius][i], opts[:y_radius][i],
31
- opts[:fill_color][i], opts[:stroke_color][i],
29
+ @cards[i].rect(opts[:x][i], opts[:y][i], opts[:width][i], opts[:height][i],
30
+ opts[:x_radius][i], opts[:y_radius][i],
31
+ opts[:fill_color][i], opts[:stroke_color][i],
32
32
  opts[:stroke_width][i])
33
33
  end
34
34
  end
35
35
 
36
36
  # Draw a circle centered at the given coordinates
37
- #
38
- # @example
37
+ #
38
+ # @example
39
39
  # circle x: 0, y: 0, radius: 100
40
40
  #
41
41
  # Options support Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
@@ -54,14 +54,14 @@ module Squib
54
54
  opts = needs(opts, [:range, :x, :y, :circle_radius, :layout,
55
55
  :fill_color, :stroke_color, :stroke_width])
56
56
  opts[:range].each do |i|
57
- @cards[i].circle(opts[:x][i], opts[:y][i], opts[:radius][i],
57
+ @cards[i].circle(opts[:x][i], opts[:y][i], opts[:radius][i],
58
58
  opts[:fill_color][i], opts[:stroke_color][i], opts[:stroke_width][i])
59
59
  end
60
60
  end
61
61
 
62
62
  # Draw a triangle using the given coordinates
63
- #
64
- # @example
63
+ #
64
+ # @example
65
65
  # triangle :x1 => 0, :y1 => 0, :x2 => 50, :y2 => 50, :x3 => 0, :y3 => 50
66
66
  #
67
67
  # Options support Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
@@ -82,17 +82,17 @@ module Squib
82
82
  opts = needs(opts, [:range, :x1, :y1, :x2, :y2, :x3, :y3, :layout,
83
83
  :fill_color, :stroke_color, :stroke_width])
84
84
  opts[:range].each do |i|
85
- @cards[i].triangle(opts[:x1][i], opts[:y1][i],
86
- opts[:x2][i], opts[:y2][i],
87
- opts[:x3][i], opts[:y3][i],
88
- opts[:fill_color][i], opts[:stroke_color][i],
85
+ @cards[i].triangle(opts[:x1][i], opts[:y1][i],
86
+ opts[:x2][i], opts[:y2][i],
87
+ opts[:x3][i], opts[:y3][i],
88
+ opts[:fill_color][i], opts[:stroke_color][i],
89
89
  opts[:stroke_width][i])
90
90
  end
91
91
  end
92
92
 
93
93
  # Draw a line using the given coordinates
94
- #
95
- # @example
94
+ #
95
+ # @example
96
96
  # triangle :x1 => 0, :y1 => 0, :x2 => 50, :y2 => 50
97
97
  #
98
98
  # @option opts range [Enumerable, :all] (:all) the range of cards over which this will be rendered. See {file:README.md#Specifying_Ranges Specifying Ranges}
@@ -112,6 +112,6 @@ module Squib
112
112
  opts[:stroke_color][i], opts[:stroke_width][i])
113
113
  end
114
114
  end
115
-
115
+
116
116
  end
117
- end
117
+ end
@@ -3,20 +3,20 @@ module Squib
3
3
 
4
4
  # Renders a string at a given location, width, alignment, font, etc.
5
5
  #
6
- # Unix-like newlines are interpreted even on Windows.
6
+ # Unix-like newlines are interpreted even on Windows.
7
7
  # See the {file:samples/text-options.rb samples/text.rb} for a lengthy example.
8
8
  #
9
- # @example
9
+ # @example
10
10
  # text str: 'hello'
11
11
  # text str: 'hello', x: 50, y:50, align: center
12
- #
12
+ #
13
13
  # Options support Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
14
14
  #
15
15
  # @option opts range [Enumerable, :all] (:all) the range of cards over which this will be rendered. See {file:README.md#Specifying_Ranges Specifying Ranges}
16
16
  # @option opts str [String, Array] ('') the string to be rendered. Must support `#to_s`. If the card responds to `#each`, it's mapped out one at a time across the cards.
17
17
  # @option opts font [String] (Arial 36 or whatever was set with `set`) the Font description string, including family, styles, and size.
18
18
  # (e.g. `'Arial bold italic 12'`)
19
- # For the official documentation, see the [Pango docs](http://ruby-gnome2.sourceforge.jp/hiki.cgi?Pango%3A%3AFontDescription#style).
19
+ # For the official documentation, see the [Pango docs](http://ruby-gnome2.sourceforge.jp/hiki.cgi?Pango%3A%3AFontDescription#style).
20
20
  # This [description](http://www.pygtk.org/pygtk2reference/class-pangofontdescription.html) is also quite good.
21
21
  # See the {file:samples/text-options.rb samples/text.rb} as well.
22
22
  # @option opts font_size [Integer] (nil) an override of font string description, for scaling the font according to the size of the string
@@ -27,15 +27,15 @@ module Squib
27
27
  # @option opts width [Integer, :native] (:native) the width of the box the string will be placed in. Stretches to the content by default.
28
28
  # @option opts height [Integer, :native] the height of the box the string will be placed in. Stretches to the content by default.
29
29
  # @option opts layout [String, Symbol] (nil) entry in the layout to use as defaults for this command. See {file:README.md#Custom_Layouts Custom Layouts}
30
- # @option opts wrap [:none, :word, :char, :word_char, true, false] (:word_char) When height is set, determines the behavior of how the string wraps. The `:word_char` option will break at words, but then fall back to characters when the word cannot fit. #
30
+ # @option opts wrap [:none, :word, :char, :word_char, true, false] (:word_char) When height is set, determines the behavior of how the string wraps. The `:word_char` option will break at words, but then fall back to characters when the word cannot fit. #
31
31
  # Options are `:none, :word, :char, :word_char`. Also: `true` is the same as `:word_char`, `false` is the same as `:none`. Default `:word_char`
32
32
  # @option opts spacing [Integer] (0) Adjust the spacing when the text is multiple lines. No effect when the text does not wrap.
33
33
  # @option opts align [:left, right, :center] (:left) The alignment of the text
34
- # @option opts justify [Boolean] (false) toggles whether or not the text is justified or not.
34
+ # @option opts justify [Boolean] (false) toggles whether or not the text is justified or not.
35
35
  # @option opts valign [:top, :middle, :bottom] (:top) When width and height are set, align text vertically according to the ink extents of the text.
36
36
  # @option opts ellipsize [:none, :start, :middle, :end, true, false] (:end) When width and height are set, determines the behavior of overflowing text. Also: `true` maps to `:end` and `false` maps to `:none`. Default `:end`
37
- # @option opts angle [FixNum] (0) Rotation of the text in radians.
38
- # @option opts hint [String] (:nil) draw a rectangle around the text with the given color. Overrides global hints (see {Deck#hint}).
37
+ # @option opts angle [FixNum] (0) Rotation of the text in radians. Note that this rotates around the upper-left corner of the text box, making the placement of x-y coordinates slightly tricky.
38
+ # @option opts hint [String] (:nil) draw a rectangle around the text with the given color. Overrides global hints (see {Deck#hint}).
39
39
  # @return [nil] Returns nothing
40
40
  # @api public
41
41
  def text(opts = {})
@@ -44,11 +44,11 @@ module Squib
44
44
  opts[:range].each do |i|
45
45
  @cards[i].text(opts[:str][i], opts[:font][i], opts[:font_size][i], opts[:color][i],
46
46
  opts[:x][i], opts[:y][i], opts[:width][i], opts[:height][i],
47
- opts[:markup][i], opts[:justify][i], opts[:wrap][i],
48
- opts[:ellipsize][i], opts[:spacing][i], opts[:align][i],
47
+ opts[:markup][i], opts[:justify][i], opts[:wrap][i],
48
+ opts[:ellipsize][i], opts[:spacing][i], opts[:align][i],
49
49
  opts[:valign][i], opts[:hint][i], opts[:angle][i])
50
50
  end
51
51
  end
52
52
 
53
53
  end
54
- end
54
+ end
@@ -2,11 +2,11 @@ module Squib
2
2
  class Deck
3
3
 
4
4
  # Given inches, returns the number of pixels according to the deck's DPI.
5
- #
6
- # @example
5
+ #
6
+ # @example
7
7
  # inches(2.5) # 750 (for default Deck::dpi of 300)
8
8
  #
9
- # @param [Decimal] n, the number of inches
9
+ # @param n [Decimal], the number of inches
10
10
  # @return [Decimal] the number of pixels, according to the deck's DPI
11
11
  # @api public
12
12
  def inches(n)
@@ -14,4 +14,4 @@ module Squib
14
14
  end
15
15
 
16
16
  end
17
- end
17
+ end
data/lib/squib/card.rb CHANGED
@@ -7,15 +7,15 @@ module Squib
7
7
  include Squib::InputHelpers
8
8
 
9
9
  # :nodoc:
10
- # @api private
10
+ # @api private
11
11
  attr_reader :width, :height
12
12
 
13
13
  # :nodoc:
14
- # @api private
14
+ # @api private
15
15
  attr_accessor :cairo_surface, :cairo_context
16
16
 
17
17
  # :nodoc:
18
- # @api private
18
+ # @api private
19
19
  def initialize(deck, width, height)
20
20
  @deck=deck; @width=width; @height=height
21
21
  @cairo_surface = Cairo::ImageSurface.new(width,height)
@@ -37,6 +37,6 @@ module Squib
37
37
  require 'squib/graphics/save_images'
38
38
  require 'squib/graphics/shapes'
39
39
  require 'squib/graphics/text'
40
-
40
+
41
41
  end
42
- end
42
+ end
@@ -6,9 +6,9 @@ module Squib
6
6
 
7
7
  # Generate a new Squib project into a fresh directory.
8
8
  #
9
- # Provides conventions for using Git (you are using version control, right??).
9
+ # Provides conventions for using Git (you are using version control, right??).
10
10
  # Also provides some basic layout and config files to start from, along with templates for instructions and other notes you don't want to forget.
11
- #
11
+ #
12
12
  #
13
13
  # @example
14
14
  # squib new foo-blasters
@@ -22,11 +22,11 @@ module Squib
22
22
  class New
23
23
 
24
24
  # :nodoc:
25
- # @api private
25
+ # @api private
26
26
  def process(args)
27
27
  raise ArgumentError.new('Please specify a path.') if args.empty?
28
28
 
29
- new_project_path = File.expand_path(args.join(" "), Dir.pwd)
29
+ new_project_path = File.expand_path(args.join(' '), Dir.pwd)
30
30
  template_path = File.expand_path('../project_template', File.dirname(__FILE__))
31
31
 
32
32
  FileUtils.mkdir_p new_project_path
@@ -41,4 +41,4 @@ module Squib
41
41
 
42
42
  end
43
43
  end
44
- end
44
+ end
@@ -1,15 +1,15 @@
1
1
  module Squib
2
2
  # Squib's defaults for when arguments are not specified in the command nor layouts.
3
- #
3
+ #
4
4
  # @api public
5
- SYSTEM_DEFAULTS = {
5
+ SYSTEM_DEFAULTS = {
6
6
  :align => :left,
7
7
  :alpha => 1.0,
8
8
  :angle => 0,
9
9
  :blend => :none,
10
10
  :color => :black,
11
11
  :default_font => 'Arial 36',
12
- :dir => "_output",
12
+ :dir => '_output',
13
13
  :ellipsize => :end,
14
14
  :fill_color => '#0000',
15
15
  :force_id => false,
@@ -23,7 +23,7 @@ module Squib
23
23
  :justify => false,
24
24
  :margin => 75,
25
25
  :markup => false,
26
- :prefix => "card_",
26
+ :prefix => 'card_',
27
27
  :progress_bar => false,
28
28
  :range => :all,
29
29
  :rotate => false,
@@ -40,7 +40,7 @@ module Squib
40
40
  :x1 => 100,
41
41
  :x2 => 150,
42
42
  :x3 => 100,
43
- :x_radius => 0,
43
+ :x_radius => 0,
44
44
  :y => 0,
45
45
  :y1 => 100,
46
46
  :y2 => 150,
@@ -49,9 +49,9 @@ module Squib
49
49
  }
50
50
 
51
51
  # Squib's configuration defaults
52
- #
52
+ #
53
53
  # @api public
54
- CONFIG_DEFAULTS = {
54
+ CONFIG_DEFAULTS = {
55
55
  'custom_colors' => {},
56
56
  'dpi' => 300,
57
57
  'hint' => :none,
@@ -59,8 +59,8 @@ module Squib
59
59
  'img_dir' => '.',
60
60
  }
61
61
 
62
- # These are parameters that are intended to be "expanded" across
63
- # range if they are singletons.
62
+ # These are parameters that are intended to be "expanded" across
63
+ # range if they are singletons.
64
64
  #
65
65
  # For example, using a different font for each card, using one `text`
66
66
  #
@@ -106,4 +106,4 @@ module Squib
106
106
  :y3 => :y3,
107
107
  :y_radius => :y_radius,
108
108
  }
109
- end
109
+ end
data/lib/squib/deck.rb CHANGED
@@ -19,37 +19,37 @@ module Squib
19
19
  include Squib::InputHelpers
20
20
 
21
21
  # :nodoc:
22
- # @api private
22
+ # @api private
23
23
  attr_reader :width, :height
24
-
24
+
25
25
  # :nodoc:
26
- # @api private
26
+ # @api private
27
27
  attr_reader :cards
28
-
28
+
29
29
  # :nodoc:
30
- # @api private
30
+ # @api private
31
31
  attr_reader :text_hint
32
32
 
33
33
  # :nodoc:
34
- # @api private
34
+ # @api private
35
35
  attr_reader :layout, :config
36
36
 
37
37
  # Squib's constructor that sets the immutable properties.
38
38
  #
39
- # This is the starting point for Squib. In providing a block to the constructor, you have access to all of Deck's instance methods.
40
- # The documented methods in Deck are the ones intended for use by most users.
39
+ # This is the starting point for Squib. In providing a block to the constructor, you have access to all of Deck's instance methods.
40
+ # The documented methods in Deck are the ones intended for use by most users.
41
41
  # If your game requires multiple different sizes or orientations, I recommend using multiple `Squib::Deck`s in your `deck.rb`. You can modify the internals of `Squib::Deck` (e.g. `@cards`), but that's not recommended.
42
- # @example
42
+ # @example
43
43
  # require 'squib'
44
44
  # Squib::Deck.new do
45
- # text str: 'Hello, World!'
45
+ # text str: 'Hello, World!"
46
46
  # end
47
- #
48
- # @param width: [Integer] the width of each card in pixels
49
- # @param height: [Integer] the height of each card in pixels
50
- # @param cards: [Integer] the number of cards in the deck
51
- # @param dpi: [Integer] the pixels per inch when rendering out to PDF or calculating using inches.
52
- # @param config: [String] the file used for global settings of this deck
47
+ #
48
+ # @param width [Integer] the width of each card in pixels
49
+ # @param height [Integer] the height of each card in pixels
50
+ # @param cards [Integer] the number of cards in the deck
51
+ # @param dpi [Integer] the pixels per inch when rendering out to PDF or calculating using inches.
52
+ # @param config [String] the file used for global settings of this deck
53
53
  # @param block [Block] the main body of the script.
54
54
  # @api public
55
55
  def initialize(width: 825, height: 1125, cards: 1, dpi: 300, config: 'config.yml', layout: nil, &block)
@@ -77,13 +77,15 @@ module Squib
77
77
  end
78
78
 
79
79
  # Iterates over each card in the deck
80
- #
80
+ #
81
81
  # @api private
82
82
  def each(&block)
83
83
  @cards.each { |card| block.call(card) }
84
84
  end
85
85
 
86
86
  # Shows a descriptive place of the location
87
+ #
88
+ # @api private
87
89
  def location(opts)
88
90
  opts[:layout] || (" @ #{opts[:x]},#{opts[:y]}")
89
91
  end
@@ -124,13 +126,13 @@ module Squib
124
126
  parent_keys.each do |parent_key|
125
127
  from_extends = yml[key].merge(recurse_extends(yml, parent_key, visited)) do |key, child_val, parent_val|
126
128
  if child_val.to_s.strip.start_with?('+=')
127
- parent_val + child_val.sub("+=",'').strip.to_f
129
+ parent_val + child_val.sub('+=','').strip.to_f
128
130
  elsif child_val.to_s.strip.start_with?('-=')
129
- parent_val - child_val.sub("-=",'').strip.to_f
130
- else
131
+ parent_val - child_val.sub('-=','').strip.to_f
132
+ else
131
133
  child_val #child overrides parent when merging, no +=
132
134
  end
133
- end
135
+ end
134
136
  h = h.merge(from_extends) do |key, older_sibling, younger_sibling|
135
137
  younger_sibling #when two siblings have the same entry, the "younger" (lower one) overrides
136
138
  end
@@ -168,4 +170,4 @@ module Squib
168
170
  require 'squib/api/units'
169
171
 
170
172
  end
171
- end
173
+ end
@@ -2,13 +2,13 @@ module Squib
2
2
  class Card
3
3
 
4
4
  # :nodoc:
5
- # @api private
5
+ # @api private
6
6
  def background(color)
7
7
  use_cairo do |cc|
8
8
  cc.set_source_color(color)
9
9
  cc.paint
10
10
  end
11
11
  end
12
-
12
+
13
13
  end
14
- end
14
+ end
@@ -1,7 +1,7 @@
1
1
  module Squib
2
2
 
3
3
  # Cache all pngs we've already loaded
4
- #
4
+ #
5
5
  # :nodoc:
6
6
  # @api private
7
7
  def cache_load_image(file)
@@ -13,11 +13,15 @@ module Squib
13
13
  class Card
14
14
 
15
15
  # :nodoc:
16
- # @api private
17
- def png(file, x, y, alpha, blend)
16
+ # @api private
17
+ def png(file, x, y, alpha, blend, angle)
18
+ Squib.logger.debug {"Rendering: #{file} @#{x},#{y} #{width}x#{height}, alpha: #{alpha}, blend: #{blend}, angle: #{angle}"}
18
19
  return if file.nil? or file.eql? ''
19
20
  png = Squib.cache_load_image(file)
20
21
  use_cairo do |cc|
22
+ cc.translate(x, y)
23
+ cc.rotate(angle)
24
+ cc.translate(-1 * x, -1 * y)
21
25
  cc.set_source(png, x, y)
22
26
  cc.operator = blend unless blend == :none
23
27
  cc.paint(alpha)
@@ -25,9 +29,9 @@ module Squib
25
29
  end
26
30
 
27
31
  # :nodoc:
28
- # @api private
29
- def svg(file, id, x, y, width, height, alpha, blend)
30
- Squib.logger.debug {"Rendering: #{file}, #{id} #{x}, #{y}, #{width}, #{height}, #{alpha}, #{blend}"}
32
+ # @api private
33
+ def svg(file, id, x, y, width, height, alpha, blend, angle)
34
+ Squib.logger.debug {"Rendering: #{file}, id: #{id} @#{x},#{y} #{width}x#{height}, alpha: #{alpha}, blend: #{blend}, angle: #{angle}"}
31
35
  return if file.nil? or file.eql? ''
32
36
  svg = RSVG::Handle.new_from_file(file)
33
37
  width = svg.width if width == :native
@@ -37,6 +41,9 @@ module Squib
37
41
  tmp_cc.scale(width.to_f / svg.width.to_f, height.to_f / svg.height.to_f)
38
42
  tmp_cc.render_rsvg_handle(svg, id)
39
43
  use_cairo do |cc|
44
+ cc.translate(x, y)
45
+ cc.rotate(angle)
46
+ cc.translate(-1 * x, -1 * y)
40
47
  cc.set_source(tmp, x, y)
41
48
  cc.operator = blend unless blend == :none
42
49
  cc.paint(alpha)