compass-canvas 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -73,6 +73,12 @@ For a complete reference on Cairo methods, visit [Pycairo documentation][pycairo
73
73
  [cairo-tutorial]: http://zetcode.com/tutorials/cairographicstutorial/
74
74
  [pycairo]: http://cairographics.org/documentation/pycairo/3/reference/context.html#class-context
75
75
 
76
+ Similar Projects
77
+ ----------------
78
+
79
+ [compass-magick](https://github.com/StanAngeloff/compass-magick) is a pure Ruby dynamic image generation for Compass using ChunkyPNG/PhantomJS (no dependency on RMagick despite the name).
80
+ If you are looking for a project to generate image gradients or small & simple buttons, go check it out.
81
+
76
82
  ### Copyright
77
83
 
78
84
  > Copyright (c) 2011 Stan Angeloff. See [LICENSE.md](https://github.com/StanAngeloff/compass-canvas/blob/master/LICENSE.md) for details.
@@ -7,7 +7,7 @@ module Compass::Canvas
7
7
  # The project and Gem version. When building a Gem file for release, the
8
8
  # version is stripped to X.Y.Z. If you are using a Git cloned-repository,
9
9
  # the version will end in +.git+.
10
- VERSION = '0.0.4.git'
10
+ VERSION = '0.0.5.git'
11
11
 
12
12
  # The default backend for drawing.
13
13
  BACKEND = 'cairo'
@@ -20,6 +20,19 @@ module Compass::Canvas
20
20
  File.expand_path(File.join(File.dirname(__FILE__), '..', directory))
21
21
  end
22
22
 
23
+ # Helper function to normalize a CSS path to a filesystem path.
24
+ #
25
+ # @param [String] file A CSS file, usually with url(..) and optionally a cache buster.
26
+ # @return [String] The absolute filesystem path.
27
+ def self.absolute_path_to(file)
28
+ if file.include?('url(')
29
+ file = File.join(Compass.configuration.css_path, file.gsub(/^url\(['"]?|["']?\)$/, ''))
30
+ else
31
+ file = File.join(Compass.configuration.images_path, file)
32
+ end
33
+ file.split('?').shift()
34
+ end
35
+
23
36
  # Locations where plug-ins are installed. These paths are scanned for *.rb files
24
37
  # and loaded in order.
25
38
  PLUGINS_PATH = [
@@ -1,39 +1,40 @@
1
1
  module Compass::Canvas
2
2
  # This module contains all actions a backend must implement.
3
3
  module Actions
4
- ANTIALIAS = :antialias
5
- ARC = :arc
6
- ARC_REVERSE = :arc_reverse
7
- BRUSH = :brush
8
- CLIP = :clip
9
- CLOSE = :close
10
- CURVE = :curve
11
- DASH_PATTERN = :dash_pattern
12
- FILL = :fill
13
- FILL_RULE = :fill_rule
14
- GROUP = :group
15
- LINE = :line
16
- LINE_CAP = :line_cap
17
- LINE_JOIN = :line_join
18
- LINE_WIDTH = :line_width
19
- MASK = :mask
20
- MITER_LIMIT = :miter_limit
21
- MOVE = :move
22
- PAINT = :paint
23
- POP = :pop
24
- PUSH = :push
25
- RESET = :reset
26
- RESTORE = :restore
27
- RETRIEVE = :retrieve
28
- ROTATE = :rotate
29
- SAVE = :save
30
- SCALE = :scale
31
- SLOW_BLUR = :slow_blur
32
- STORE = :store
33
- STROKE = :stroke
34
- TOLERANCE = :tolerance
35
- TRANSFORM = :transform
36
- TRANSLATE = :translate
37
- UNCLIP = :unclip
4
+ ANTIALIAS = :antialias
5
+ ARC = :arc
6
+ ARC_REVERSE = :arc_reverse
7
+ BRUSH = :brush
8
+ CLIP = :clip
9
+ CLOSE = :close
10
+ CURVE = :curve
11
+ DASH_PATTERN = :dash_pattern
12
+ FILL = :fill
13
+ FILL_RULE = :fill_rule
14
+ GROUP = :group
15
+ LINE = :line
16
+ LINE_CAP = :line_cap
17
+ LINE_JOIN = :line_join
18
+ LINE_WIDTH = :line_width
19
+ MASK = :mask
20
+ MITER_LIMIT = :miter_limit
21
+ MOVE = :move
22
+ PAINT = :paint
23
+ POP = :pop
24
+ PUSH = :push
25
+ QUADRATIC_CURVE = :quadratic_curve
26
+ RESET = :reset
27
+ RESTORE = :restore
28
+ RETRIEVE = :retrieve
29
+ ROTATE = :rotate
30
+ SAVE = :save
31
+ SCALE = :scale
32
+ SLOW_BLUR = :slow_blur
33
+ STORE = :store
34
+ STROKE = :stroke
35
+ TOLERANCE = :tolerance
36
+ TRANSFORM = :transform
37
+ TRANSLATE = :translate
38
+ UNCLIP = :unclip
38
39
  end
39
40
  end
@@ -6,6 +6,7 @@ module Compass::Canvas::Backend
6
6
  #
7
7
  # Each implementation must respond to four methods:
8
8
  # - {Compass::Canvas::Backend::Base::load_dependencies} - initializes the backend by loading third-party dependencies
9
+ # - {Compass::Canvas::Backend::Base::read_canvas} - reads a canvas from a file
9
10
  # - {Compass::Canvas::Backend::Base::begin_canvas} - initialization code before the canvas is drawn
10
11
  # - {Compass::Canvas::Backend::Base::execute_one} - executes a single action on the canvas
11
12
  # - {Compass::Canvas::Backend::Base::to_blob} - clean up code, must return a
@@ -35,20 +36,15 @@ module Compass::Canvas::Backend
35
36
  load_dependencies
36
37
  if args[0].is_a?(String)
37
38
  file = args.shift
38
- unless args[1].is_a?(Fixnum)
39
- if file.include?('url(')
40
- file = File.join(Compass.configuration.css_path, file.gsub(/^url\(['"]?|["']?\)$/, '').split('?').shift())
41
- else
42
- file = File.join(Compass.configuration.images_path, file.split('?').shift())
43
- end
44
- end
39
+ file = Compass::Canvas.absolute_path_to(file) unless args[0].is_a?(Fixnum)
45
40
  @file = file
46
41
  end
47
42
  if args[0].is_a?(Fixnum)
48
43
  @width = args.shift
49
44
  @height = args.shift
50
45
  end
51
- @actions = args
46
+ @actions = args
47
+ @executed = false
52
48
  end
53
49
 
54
50
  # Abstract method.
@@ -60,6 +56,15 @@ module Compass::Canvas::Backend
60
56
  raise Compass::Canvas::Exception.new("(#{self.class}) Class must implement '#{this_method}'.")
61
57
  end
62
58
 
59
+ # Abstract method.
60
+ #
61
+ # Reads a canvas from a file
62
+ #
63
+ # @raise [Compass::Canvas::Exception] Backend implementation must override this method.
64
+ def read_canvas
65
+ raise Compass::Canvas::Exception.new("(#{self.class}) Class must implement '#{this_method}'.")
66
+ end
67
+
63
68
  # Abstract method.
64
69
  #
65
70
  # Initialization code before the canvas is drawn.
@@ -87,10 +92,32 @@ module Compass::Canvas::Backend
87
92
  raise Compass::Canvas::Exception.new("(#{self.class}) Class must implement '#{this_method}'.")
88
93
  end
89
94
 
95
+ # Reads a property of the backend.
96
+ #
97
+ # This can be used to provide custom information about a backend, such as
98
+ # width, height, the current point's position, etc.
99
+ #
100
+ # @param [String] name The property name.
101
+ # @return [Object] The property value, or nil if it doesn't exist.
102
+ def property(name)
103
+ case name
104
+ when :width; return @width
105
+ when :height; return @height
106
+ else return nil
107
+ end
108
+ end
109
+
90
110
  # Creates an empty canvas and executes all stored actions.
91
111
  def execute
92
- begin_canvas
93
- execute_actions
112
+ return self if @executed
113
+ if @width && @height
114
+ begin_canvas
115
+ execute_actions
116
+ else
117
+ read_canvas
118
+ end
119
+ @executed = true
120
+ self
94
121
  end
95
122
 
96
123
  # Returns the canvas as a Base64 encoded Data URI or as a file on disk
@@ -130,7 +157,6 @@ module Compass::Canvas::Backend
130
157
  end
131
158
  execute_one(action, *args)
132
159
  end
133
- self
134
160
  end
135
161
 
136
162
  private
@@ -25,6 +25,30 @@ module Compass::Canvas::Backend
25
25
  end
26
26
  end
27
27
 
28
+ # Reads a property of the Cairo backend.
29
+ #
30
+ # This can be used to obtain information about the width/height of the
31
+ # surface as well as the current point's X/Y coordinates.
32
+ #
33
+ # @param [String] name The property name.
34
+ # @return [Object] The property value, or nil if it doesn't exist.
35
+ def property(name)
36
+ execute
37
+ case name
38
+ when :width; return @surface.width
39
+ when :height; return @surface.height
40
+ when :x; return @context.current_point[0]
41
+ when :y; return @context.current_point[1]
42
+ else return nil
43
+ end
44
+ end
45
+
46
+ # Creates a new +ImageSurface+ from a file
47
+ def read_canvas
48
+ @surface = ::Cairo::ImageSurface.from_png(@file)
49
+ bind_context
50
+ end
51
+
28
52
  # Creates a new +ImageSurface+ and binds a new context to it.
29
53
  def begin_canvas
30
54
  if @width && @height
@@ -32,9 +56,7 @@ module Compass::Canvas::Backend
32
56
  else
33
57
  @surface = ::Cairo::ImageSurface.from_png(@file)
34
58
  end
35
- @context = ::Cairo::Context.new(@surface)
36
- @context.set_line_width(1)
37
- @sources = []
59
+ bind_context
38
60
  end
39
61
 
40
62
  # Executes a single action on the context bound to the surface.
@@ -46,6 +68,14 @@ module Compass::Canvas::Backend
46
68
  @context.line_to(*args)
47
69
  when Compass::Canvas::Actions::CURVE
48
70
  @context.curve_to(*args)
71
+ when Compass::Canvas::Actions::QUADRATIC_CURVE
72
+ x1, y1, x2, y2 = args
73
+ x, y = @context.current_point
74
+ @context.curve_to(
75
+ x + 2.0 / 3.0 * (x1 - x), y + 2.0 / 3.0 * (y1 - y),
76
+ x2 + 2.0 / 3.0 * (x1 - x2), y2 + 2.0 / 3.0 * (y1 - y2),
77
+ x2, y2
78
+ )
49
79
  when Compass::Canvas::Actions::ARC
50
80
  @context.arc(*args)
51
81
  when Compass::Canvas::Actions::ARC_REVERSE
@@ -117,8 +147,8 @@ module Compass::Canvas::Backend
117
147
  pattern.set_extend(constant('EXTEND', args))
118
148
  @context.mask(pattern)
119
149
  else
120
- x = args.shift if args.length
121
- y = args.shift if args.length
150
+ x = args.shift if args.length > 0
151
+ y = args.shift if args.length > 0
122
152
  @context.mask(surface, x || 0, y || 0)
123
153
  end
124
154
  elsif type == Compass::Canvas::Actions::RETRIEVE
@@ -142,7 +172,7 @@ module Compass::Canvas::Backend
142
172
  canvas = args.shift
143
173
  if canvas.is_a?(Compass::Canvas::Backend::Cairo)
144
174
  pattern = ::Cairo::SurfacePattern.new(canvas.execute.surface)
145
- pattern.set_extend(constant('EXTEND', args)) if args.length
175
+ pattern.set_extend(constant('EXTEND', args)) if args.length > 0
146
176
  @context.set_source(pattern)
147
177
  else
148
178
  raise Compass::Canvas::Exception.new("(#{self.class}.#{action}) Unsupported canvas, Cairo can only paint with Cairo: #{canvas.inspect}")
@@ -169,6 +199,12 @@ module Compass::Canvas::Backend
169
199
 
170
200
  private
171
201
 
202
+ def bind_context
203
+ @context = ::Cairo::Context.new(@surface)
204
+ @context.set_line_width(1)
205
+ @sources = []
206
+ end
207
+
172
208
  def constant(name, *args)
173
209
  ::Cairo::const_get("#{ name.upcase }_#{ args.join('_').gsub('-', '_').upcase }")
174
210
  end
@@ -16,6 +16,11 @@ module Compass::Canvas::Backend::Interface
16
16
  [x1.value, y1.value, x2.value, y2.value, x3.value, y3.value]
17
17
  end
18
18
 
19
+ # Unpacks arguments +X+[1..2] and +Y+[1..2] from Sass to Ruby objects.
20
+ def quadratic_curve(x1, y1, x2, y2)
21
+ [x1.value, y1.value, x2.value, y2.value]
22
+ end
23
+
19
24
  # Unpacks arguments +X+, +Y+, +radius+ and +angle+[1..2] from Sass to Ruby objects.
20
25
  def arc(x, y, radius, angle1, angle2)
21
26
  [x.value, y.value, radius.value, angle1.value * (Math::PI / 180.0), angle2.value * (Math::PI / 180.0)]
@@ -16,6 +16,34 @@ module Compass::Canvas
16
16
  end
17
17
  klass.new(*Compass::Canvas::Functions.unpack(args).flatten)
18
18
  end
19
+
20
+ # Gets the width of a {Compass::Canvas::Backend}.
21
+ #
22
+ # @return [Compass::Canvas::Backend] The width of the backend.
23
+ def width_of(canvas)
24
+ Sass::Script::Number.new(canvas.property(:width))
25
+ end
26
+
27
+ # Gets the height of a {Compass::Canvas::Backend}.
28
+ #
29
+ # @return [Compass::Canvas::Backend] The height of the backend.
30
+ def height_of(canvas)
31
+ Sass::Script::Number.new(canvas.property(:height))
32
+ end
33
+
34
+ # Gets the X position of the current path on a {Compass::Canvas::Backend}.
35
+ #
36
+ # @return [Compass::Canvas::Backend] The X position of the current backend path.
37
+ def path_x(canvas)
38
+ Sass::Script::Number.new(canvas.property(:x))
39
+ end
40
+
41
+ # Gets the Y position of the current path on a {Compass::Canvas::Backend}.
42
+ #
43
+ # @return [Compass::Canvas::Backend] The Y position of the current backend path.
44
+ def path_y(canvas)
45
+ Sass::Script::Number.new(canvas.property(:y))
46
+ end
19
47
  end
20
48
  end
21
49
  end
@@ -1,3 +1,27 @@
1
1
  @import 'canvas/context';
2
2
  @import 'canvas/path';
3
3
  @import 'canvas/pattern';
4
+
5
+ // @function width-of(canvas) {}
6
+ // @function height-of(canvas) {}
7
+ // @function path-x(canvas) {}
8
+ // @function path-y(canvas) {}
9
+
10
+ @function put-image($file, $x: 0, $y: 0) {
11
+ $canvas: canvas($file);
12
+ @if ($x == 'repeat') {
13
+ @return (
14
+ brush($canvas, $x)
15
+ paint
16
+ );
17
+ } @else {
18
+ @return (
19
+ save
20
+ translate($x, $y)
21
+ brush($canvas)
22
+ rectangle(0, 0, width-of($canvas), height-of($canvas))
23
+ fill
24
+ restore
25
+ );
26
+ }
27
+ }
@@ -1,2 +1,3 @@
1
+ @import 'canvas/path/curves';
1
2
  @import 'canvas/path/primitives';
2
3
  @import 'canvas/path/shapes';
@@ -0,0 +1,7 @@
1
+ @function bezier-curve-to($x1, $y1, $x2, $y2, $x3, $y3) {
2
+ @return curve-to($x1, $y1, $x2, $y2, $x3, $y3);
3
+ }
4
+
5
+ @function quadratic-curve-to($x1, $y1, $x2, $y2) {
6
+ @return canvas-path('quadratic_curve', $x1, $y1, $x2, $y2);
7
+ }
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: compass-canvas
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 4
10
- version: 0.0.4
9
+ - 5
10
+ version: 0.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Stan Angeloff
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-08-14 00:00:00 Z
18
+ date: 2011-08-29 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: compass
@@ -79,9 +79,10 @@ files:
79
79
  - stylesheets/canvas/_pattern.scss
80
80
  - stylesheets/canvas/_path.scss
81
81
  - stylesheets/canvas/_context.scss
82
+ - stylesheets/canvas/path/_curves.scss
82
83
  - stylesheets/canvas/path/_primitives.scss
83
84
  - stylesheets/canvas/path/_shapes.scss
84
- - plugins/drop-shadow.rb
85
+ - plugins/drop_shadow.rb
85
86
  homepage: http://StanAngeloff.github.com/compass-canvas/
86
87
  licenses: []
87
88