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 +6 -0
- data/lib/canvas.rb +14 -1
- data/lib/canvas/actions.rb +35 -34
- data/lib/canvas/backend.rb +37 -11
- data/lib/canvas/backend/cairo.rb +42 -6
- data/lib/canvas/backend/interface/path.rb +5 -0
- data/lib/canvas/functions/canvas.rb +28 -0
- data/plugins/{drop-shadow.rb → drop_shadow.rb} +0 -0
- data/stylesheets/_canvas.scss +24 -0
- data/stylesheets/canvas/_path.scss +1 -0
- data/stylesheets/canvas/path/_curves.scss +7 -0
- metadata +6 -5
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.
|
data/lib/canvas.rb
CHANGED
@@ -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.
|
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 = [
|
data/lib/canvas/actions.rb
CHANGED
@@ -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
|
5
|
-
ARC
|
6
|
-
ARC_REVERSE
|
7
|
-
BRUSH
|
8
|
-
CLIP
|
9
|
-
CLOSE
|
10
|
-
CURVE
|
11
|
-
DASH_PATTERN
|
12
|
-
FILL
|
13
|
-
FILL_RULE
|
14
|
-
GROUP
|
15
|
-
LINE
|
16
|
-
LINE_CAP
|
17
|
-
LINE_JOIN
|
18
|
-
LINE_WIDTH
|
19
|
-
MASK
|
20
|
-
MITER_LIMIT
|
21
|
-
MOVE
|
22
|
-
PAINT
|
23
|
-
POP
|
24
|
-
PUSH
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
data/lib/canvas/backend.rb
CHANGED
@@ -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[
|
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
|
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
|
-
|
93
|
-
|
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
|
data/lib/canvas/backend/cairo.rb
CHANGED
@@ -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
|
-
|
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
|
File without changes
|
data/stylesheets/_canvas.scss
CHANGED
@@ -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
|
+
}
|
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:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
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-
|
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/
|
85
|
+
- plugins/drop_shadow.rb
|
85
86
|
homepage: http://StanAngeloff.github.com/compass-canvas/
|
86
87
|
licenses: []
|
87
88
|
|