compass-canvas 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.md +22 -0
- data/README.md +78 -0
- data/lib/canvas.rb +48 -0
- data/lib/canvas/actions.rb +39 -0
- data/lib/canvas/backend.rb +145 -0
- data/lib/canvas/backend/cairo.rb +176 -0
- data/lib/canvas/backend/interface.rb +42 -0
- data/lib/canvas/backend/interface/context.rb +68 -0
- data/lib/canvas/backend/interface/path.rb +29 -0
- data/lib/canvas/backend/interface/pattern.rb +100 -0
- data/lib/canvas/configuration.rb +3 -0
- data/lib/canvas/constants.rb +9 -0
- data/lib/canvas/functions.rb +37 -0
- data/lib/canvas/functions/canvas.rb +21 -0
- data/lib/canvas/functions/context.rb +20 -0
- data/lib/canvas/functions/path.rb +13 -0
- data/lib/canvas/functions/pattern.rb +34 -0
- data/lib/canvas/plugins.rb +16 -0
- data/plugins/drop-shadow.rb +14 -0
- data/stylesheets/_canvas.scss +3 -0
- data/stylesheets/canvas/_context.scss +43 -0
- data/stylesheets/canvas/_path.scss +2 -0
- data/stylesheets/canvas/_pattern.scss +3 -0
- data/stylesheets/canvas/path/_primitives.scss +19 -0
- data/stylesheets/canvas/path/_shapes.scss +47 -0
- metadata +119 -0
data/LICENSE.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License
|
2
|
+
===============
|
3
|
+
|
4
|
+
> Copyright (c) 2011 Stan Angeloff
|
5
|
+
>
|
6
|
+
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
> of this software and associated documentation files (the "Software"), to deal
|
8
|
+
> in the Software without restriction, including without limitation the rights
|
9
|
+
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
> copies of the Software, and to permit persons to whom the Software is
|
11
|
+
> furnished to do so, subject to the following conditions:
|
12
|
+
>
|
13
|
+
> The above copyright notice and this permission notice shall be included in
|
14
|
+
> all copies or substantial portions of the Software.
|
15
|
+
>
|
16
|
+
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
> THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
compass-canvas
|
2
|
+
==============
|
3
|
+
|
4
|
+
### Canvas drawing support for Compass with Cairo backend(s)
|
5
|
+
|
6
|
+
Description
|
7
|
+
-----------
|
8
|
+
|
9
|
+
Canvas is a Compass plugin that provides a drawing surface similar to the `<canvas>` element in JavaScript and [Turtle graphics][turtle] in other programming languages.
|
10
|
+
It uses [Cairo][cairo] as a back-end to perform all graphics operations.
|
11
|
+
Canvas supports anti-aliasing, vector graphics, gradients, masks, clipping, complex operations like drop shadow and many more.
|
12
|
+
|
13
|
+
[turtle]: http://en.wikipedia.org/wiki/Turtle_graphics
|
14
|
+
[cairo]: http://en.wikipedia.org/wiki/Cairo_(graphics)
|
15
|
+
|
16
|
+
Installation
|
17
|
+
------------
|
18
|
+
|
19
|
+
Installation is done through [RubyGems][gems]:
|
20
|
+
|
21
|
+
gem install compass-canvas
|
22
|
+
|
23
|
+
### Dependencies
|
24
|
+
|
25
|
+
The `compass-canvas` gem depends on the `cairo` gem. In order to install both gems, you must have Cairo's development files present on your system.
|
26
|
+
You can usually install these using your OS package manager.
|
27
|
+
|
28
|
+
#### Ubuntu
|
29
|
+
|
30
|
+
sudo apt-get install libcairo2-dev
|
31
|
+
|
32
|
+
[gems]: http://rubygems.org/
|
33
|
+
|
34
|
+
Example
|
35
|
+
-------
|
36
|
+
|
37
|
+
@import 'canvas';
|
38
|
+
|
39
|
+
$shape: triangle(10, 10, 310, 10, 160, 190);
|
40
|
+
|
41
|
+
html {
|
42
|
+
background: canvas(320, 200,
|
43
|
+
$shape
|
44
|
+
brush(10, 10, 160, 100, rgba(red, 0.5) 50%, rgba(red, 0.75))
|
45
|
+
fill
|
46
|
+
reset
|
47
|
+
save
|
48
|
+
translate(40, 20)
|
49
|
+
scale(0.75, 0.75)
|
50
|
+
$shape
|
51
|
+
brush(black)
|
52
|
+
stroke
|
53
|
+
brush(10, 10, 160, 100, rgba(blue, 0.75) 50%, rgba(blue, 0.5))
|
54
|
+
fill
|
55
|
+
restore
|
56
|
+
) no-repeat 50% 50%;
|
57
|
+
}
|
58
|
+
|
59
|
+
License
|
60
|
+
-------
|
61
|
+
|
62
|
+
Canvas is licensed under the MIT License.
|
63
|
+
|
64
|
+
## [Documentation](http://StanAngeloff.github.com/compass-canvas/)
|
65
|
+
|
66
|
+
[RDoc is available][rdoc] for the entire project.
|
67
|
+
|
68
|
+
For more information on Cairo, visit [The Cairo graphics tutorial][cairo-tutorial].
|
69
|
+
|
70
|
+
For a complete reference on Cairo methods, visit [Pycairo documentation][pycairo].
|
71
|
+
|
72
|
+
[rdoc]: http://rubydoc.info/gems/compass-canvas/frames
|
73
|
+
[cairo-tutorial]: http://zetcode.com/tutorials/cairographicstutorial/
|
74
|
+
[pycairo]: http://cairographics.org/documentation/pycairo/3/reference/context.html#class-context
|
75
|
+
|
76
|
+
### Copyright
|
77
|
+
|
78
|
+
> Copyright (c) 2011 Stan Angeloff. See [LICENSE.md](https://github.com/StanAngeloff/compass-canvas/blob/master/LICENSE.md) for details.
|
data/lib/canvas.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Canvas drawing support for Compass with Cairo backend(s).
|
2
|
+
#
|
3
|
+
# This module defines the current project version and useful helper functions.
|
4
|
+
#
|
5
|
+
# @author Stan Angeloff
|
6
|
+
module Compass::Canvas
|
7
|
+
# The project and Gem version. When building a Gem file for release, the
|
8
|
+
# version is stripped to X.Y.Z. If you are using a Git cloned-repository,
|
9
|
+
# the version will end in +.git+.
|
10
|
+
VERSION = '0.0.4.git'
|
11
|
+
|
12
|
+
# The default backend for drawing.
|
13
|
+
BACKEND = 'cairo'
|
14
|
+
|
15
|
+
# Helper function to construct an absolute path to a given directory in
|
16
|
+
# the project.
|
17
|
+
#
|
18
|
+
# @return [String] The absolute path to the directory.
|
19
|
+
def self.path_to(directory)
|
20
|
+
File.expand_path(File.join(File.dirname(__FILE__), '..', directory))
|
21
|
+
end
|
22
|
+
|
23
|
+
# Locations where plug-ins are installed. These paths are scanned for *.rb files
|
24
|
+
# and loaded in order.
|
25
|
+
PLUGINS_PATH = [
|
26
|
+
Compass::Canvas.path_to('plugins'),
|
27
|
+
File.join(ENV['HOME'], '.compass-canvas', 'plugins'),
|
28
|
+
File.join(Dir.getwd, 'plugins')
|
29
|
+
]
|
30
|
+
|
31
|
+
# Default exception class.
|
32
|
+
class Exception < ::StandardError; end
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'canvas/actions'
|
36
|
+
require 'canvas/constants'
|
37
|
+
require 'canvas/backend'
|
38
|
+
require 'canvas/configuration'
|
39
|
+
require 'canvas/plugins'
|
40
|
+
require 'canvas/functions'
|
41
|
+
|
42
|
+
# Register Canvas as a Compass framework.
|
43
|
+
#
|
44
|
+
# @see http://compass-style.org/docs/tutorials/extensions/
|
45
|
+
Compass::Frameworks.register('canvas',
|
46
|
+
:stylesheets_directory => Compass::Canvas.path_to('stylesheets'),
|
47
|
+
:templates_directory => Compass::Canvas.path_to('templates')
|
48
|
+
)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Compass::Canvas
|
2
|
+
# This module contains all actions a backend must implement.
|
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
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
# This module defines the base backend class for all implementations
|
4
|
+
module Compass::Canvas::Backend
|
5
|
+
# Base abstract backend class.
|
6
|
+
#
|
7
|
+
# Each implementation must respond to four methods:
|
8
|
+
# - {Compass::Canvas::Backend::Base::load_dependencies} - initializes the backend by loading third-party dependencies
|
9
|
+
# - {Compass::Canvas::Backend::Base::begin_canvas} - initialization code before the canvas is drawn
|
10
|
+
# - {Compass::Canvas::Backend::Base::execute_one} - executes a single action on the canvas
|
11
|
+
# - {Compass::Canvas::Backend::Base::to_blob} - clean up code, must return a
|
12
|
+
# +String+ representation of the canvas in a PNG format
|
13
|
+
class Base < Sass::Script::Literal
|
14
|
+
# @return [Fixnum] The width of the canvas, in pixels.
|
15
|
+
attr_accessor :width
|
16
|
+
# @return [Fixnum] The height of the canvas, in pixels.
|
17
|
+
attr_accessor :height
|
18
|
+
# @return [String] The external file where the backend will be loaded/saved in a PNG format.
|
19
|
+
attr_accessor :file
|
20
|
+
|
21
|
+
# Initializes a new instance of a backend class.
|
22
|
+
#
|
23
|
+
# @overload initialize(width, height, *actions)
|
24
|
+
# @param [Fixnum] width The width of the canvas, in pixels.
|
25
|
+
# @param [Fixnum] height The height of the canvas, in pixels.
|
26
|
+
# @param [Array<Object>] actions The actions to execute.
|
27
|
+
# @overload initialize(file, width, height, *actions)
|
28
|
+
# @param [String] file The file where the backend will be saved in a PNG format.
|
29
|
+
# @param [Fixnum] width The width of the canvas, in pixels.
|
30
|
+
# @param [Fixnum] height The height of the canvas, in pixels.
|
31
|
+
# @param [Array<Object>] actions The actions to execute.
|
32
|
+
# @overload initialize(file)
|
33
|
+
# @param [String] file An external file to read.
|
34
|
+
def initialize(*args)
|
35
|
+
load_dependencies
|
36
|
+
if args[0].is_a?(String)
|
37
|
+
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
|
45
|
+
@file = file
|
46
|
+
end
|
47
|
+
if args[0].is_a?(Fixnum)
|
48
|
+
@width = args.shift
|
49
|
+
@height = args.shift
|
50
|
+
end
|
51
|
+
@actions = args
|
52
|
+
end
|
53
|
+
|
54
|
+
# Abstract method.
|
55
|
+
#
|
56
|
+
# Initializes the backend by loading third-party dependencies.
|
57
|
+
#
|
58
|
+
# @raise [Compass::Canvas::Exception] Backend implementation must override this method.
|
59
|
+
def load_dependencies
|
60
|
+
raise Compass::Canvas::Exception.new("(#{self.class}) Class must implement '#{this_method}'.")
|
61
|
+
end
|
62
|
+
|
63
|
+
# Abstract method.
|
64
|
+
#
|
65
|
+
# Initialization code before the canvas is drawn.
|
66
|
+
#
|
67
|
+
# @raise [Compass::Canvas::Exception] Backend implementation must override this method.
|
68
|
+
def begin_canvas
|
69
|
+
raise Compass::Canvas::Exception.new("(#{self.class}) Class must implement '#{this_method}'.")
|
70
|
+
end
|
71
|
+
|
72
|
+
# Abstract method.
|
73
|
+
#
|
74
|
+
# Executes a single action on the canvas.
|
75
|
+
#
|
76
|
+
# @raise [Compass::Canvas::Exception] Backend implementation must override this method.
|
77
|
+
def execute_one(action, *args)
|
78
|
+
raise Compass::Canvas::Exception.new("(#{self.class}) Class must implement '#{this_method}'.")
|
79
|
+
end
|
80
|
+
|
81
|
+
# Abstract method.
|
82
|
+
#
|
83
|
+
# Clean up code, must return a +String+ representation of the canvas in a PNG format.
|
84
|
+
#
|
85
|
+
# @raise [Compass::Canvas::Exception] Backend implementation must override this method.
|
86
|
+
def to_blob
|
87
|
+
raise Compass::Canvas::Exception.new("(#{self.class}) Class must implement '#{this_method}'.")
|
88
|
+
end
|
89
|
+
|
90
|
+
# Creates an empty canvas and executes all stored actions.
|
91
|
+
def execute
|
92
|
+
begin_canvas
|
93
|
+
execute_actions
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns the canvas as a Base64 encoded Data URI or as a file on disk
|
97
|
+
# depending on the configuration.
|
98
|
+
def value
|
99
|
+
execute
|
100
|
+
if @file
|
101
|
+
extension = '.png'
|
102
|
+
filename = @file.chomp(extension) + extension
|
103
|
+
path = File.join(Compass.configuration.images_path, filename)
|
104
|
+
FileUtils.mkpath(File.dirname(path))
|
105
|
+
File.open(path, 'wb') { |io| io << to_blob }
|
106
|
+
filename
|
107
|
+
else
|
108
|
+
"url('data:image/png;base64,#{ Base64.encode64(to_blob).gsub("\n", '') }')"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Serializes the canvas as a Sass type
|
113
|
+
def to_s(options = {})
|
114
|
+
Sass::Script::String.new(value)
|
115
|
+
end
|
116
|
+
|
117
|
+
protected
|
118
|
+
|
119
|
+
def execute_actions(actions = nil)
|
120
|
+
actions ||= @actions
|
121
|
+
actions.each do |child|
|
122
|
+
if child.is_a?(Compass::Canvas::Backend::Interface::Base)
|
123
|
+
action = child.action
|
124
|
+
args = child.args
|
125
|
+
elsif child.is_a?(String)
|
126
|
+
action = child.to_sym
|
127
|
+
args = []
|
128
|
+
else
|
129
|
+
raise Compass::Canvas::Exception.new("(#{self.class}) Unsupported action: #{child.inspect}")
|
130
|
+
end
|
131
|
+
execute_one(action, *args)
|
132
|
+
end
|
133
|
+
self
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
|
138
|
+
def this_method
|
139
|
+
caller[0][/`([^']*)'/, 1]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
require 'canvas/backend/interface';
|
145
|
+
require 'canvas/backend/cairo';
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
module Compass::Canvas::Backend
|
4
|
+
# Cairo backend implementation.
|
5
|
+
class Cairo < Base
|
6
|
+
# @return [::Cairo::ImageSurface] The internal image surface.
|
7
|
+
attr_accessor :surface
|
8
|
+
|
9
|
+
# Loads the +cairo+ gem dependency. If it is not on +$LOAD_PATH+, attempts
|
10
|
+
# to load RubyGems.
|
11
|
+
def load_dependencies
|
12
|
+
begin
|
13
|
+
require 'cairo'
|
14
|
+
rescue LoadError
|
15
|
+
require 'rubygems'
|
16
|
+
begin
|
17
|
+
require 'cairo'
|
18
|
+
rescue LoadError
|
19
|
+
puts "Compass::Canvas\n_______________\n\n"
|
20
|
+
puts "Unable to load Cairo backend. Please install it with the following command:\n\n"
|
21
|
+
puts " gem install cairo\n\n"
|
22
|
+
puts "For more information, please visit https://github.com/rcairo/rcairo"
|
23
|
+
raise
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Creates a new +ImageSurface+ and binds a new context to it.
|
29
|
+
def begin_canvas
|
30
|
+
if @width && @height
|
31
|
+
@surface = ::Cairo::ImageSurface.new(::Cairo::FORMAT_ARGB32, @width, @height)
|
32
|
+
else
|
33
|
+
@surface = ::Cairo::ImageSurface.from_png(@file)
|
34
|
+
end
|
35
|
+
@context = ::Cairo::Context.new(@surface)
|
36
|
+
@context.set_line_width(1)
|
37
|
+
@sources = []
|
38
|
+
end
|
39
|
+
|
40
|
+
# Executes a single action on the context bound to the surface.
|
41
|
+
def execute_one(action, *args)
|
42
|
+
case action
|
43
|
+
when Compass::Canvas::Actions::MOVE
|
44
|
+
@context.move_to(*args)
|
45
|
+
when Compass::Canvas::Actions::LINE
|
46
|
+
@context.line_to(*args)
|
47
|
+
when Compass::Canvas::Actions::CURVE
|
48
|
+
@context.curve_to(*args)
|
49
|
+
when Compass::Canvas::Actions::ARC
|
50
|
+
@context.arc(*args)
|
51
|
+
when Compass::Canvas::Actions::ARC_REVERSE
|
52
|
+
@context.arc_negative(*args)
|
53
|
+
when Compass::Canvas::Actions::PAINT
|
54
|
+
@context.paint(*args)
|
55
|
+
when Compass::Canvas::Actions::STROKE
|
56
|
+
@context.stroke_preserve(*args)
|
57
|
+
when Compass::Canvas::Actions::FILL
|
58
|
+
@context.fill_preserve(*args)
|
59
|
+
when Compass::Canvas::Actions::LINE_WIDTH
|
60
|
+
@context.set_line_width(*args)
|
61
|
+
when Compass::Canvas::Actions::PUSH
|
62
|
+
@context.push_group
|
63
|
+
when Compass::Canvas::Actions::POP
|
64
|
+
@context.pop_group_to_source
|
65
|
+
when Compass::Canvas::Actions::STORE
|
66
|
+
@sources.push(@context.source)
|
67
|
+
when Compass::Canvas::Actions::RETRIEVE
|
68
|
+
@context.set_source(@sources.pop)
|
69
|
+
when Compass::Canvas::Actions::GROUP
|
70
|
+
@context.new_sub_path
|
71
|
+
when Compass::Canvas::Actions::CLIP
|
72
|
+
@context.clip_preserve
|
73
|
+
when Compass::Canvas::Actions::UNCLIP
|
74
|
+
@context.reset_clip
|
75
|
+
when Compass::Canvas::Actions::CLOSE
|
76
|
+
@context.close_path
|
77
|
+
when Compass::Canvas::Actions::RESET
|
78
|
+
@context.new_path
|
79
|
+
when Compass::Canvas::Actions::SAVE
|
80
|
+
@context.save
|
81
|
+
when Compass::Canvas::Actions::RESTORE
|
82
|
+
@context.restore
|
83
|
+
when Compass::Canvas::Actions::ANTIALIAS
|
84
|
+
@context.set_antialias(constant('ANTIALIAS', args))
|
85
|
+
when Compass::Canvas::Actions::FILL_RULE
|
86
|
+
@context.set_fill_rule(constant('FILL_RULE', args))
|
87
|
+
when Compass::Canvas::Actions::TOLERANCE
|
88
|
+
@context.set_tolerance(*args)
|
89
|
+
when Compass::Canvas::Actions::LINE_CAP
|
90
|
+
@context.set_line_cap(constant('LINE_CAP', args))
|
91
|
+
when Compass::Canvas::Actions::LINE_JOIN
|
92
|
+
@context.set_line_join(constant('LINE_JOIN', args))
|
93
|
+
when Compass::Canvas::Actions::MITER_LIMIT
|
94
|
+
@context.set_miter_limit(*args)
|
95
|
+
when Compass::Canvas::Actions::DASH_PATTERN
|
96
|
+
# If at least two lengths exist, create a new pattern
|
97
|
+
if args.length > 1
|
98
|
+
@context.set_dash(args)
|
99
|
+
# Otherwise return to a solid stroke
|
100
|
+
else
|
101
|
+
@context.set_dash(nil, 0)
|
102
|
+
end
|
103
|
+
when Compass::Canvas::Actions::TRANSLATE
|
104
|
+
@context.translate(*args)
|
105
|
+
when Compass::Canvas::Actions::SCALE
|
106
|
+
@context.scale(*args)
|
107
|
+
when Compass::Canvas::Actions::ROTATE
|
108
|
+
@context.rotate(*args)
|
109
|
+
when Compass::Canvas::Actions::TRANSFORM
|
110
|
+
@context.transform(::Cairo::Matrix.new(*args))
|
111
|
+
when Compass::Canvas::Actions::MASK
|
112
|
+
type = args.shift
|
113
|
+
if type.is_a?(Compass::Canvas::Backend::Cairo)
|
114
|
+
surface = type.execute.surface
|
115
|
+
if args.length == 1
|
116
|
+
pattern = ::Cairo::SurfacePattern.new(surface)
|
117
|
+
pattern.set_extend(constant('EXTEND', args))
|
118
|
+
@context.mask(pattern)
|
119
|
+
else
|
120
|
+
x = args.shift if args.length
|
121
|
+
y = args.shift if args.length
|
122
|
+
@context.mask(surface, x || 0, y || 0)
|
123
|
+
end
|
124
|
+
elsif type == Compass::Canvas::Actions::RETRIEVE
|
125
|
+
@context.mask(@sources.pop)
|
126
|
+
else
|
127
|
+
raise Compass::Canvas::Exception.new("(#{self.class}.#{action}) Unsupported canvas, Cairo can only mask with Cairo: #{type.inspect}")
|
128
|
+
end
|
129
|
+
when Compass::Canvas::Actions::BRUSH
|
130
|
+
type = args.shift
|
131
|
+
case type
|
132
|
+
when Compass::Canvas::Constants::SOLID
|
133
|
+
components = args.shift
|
134
|
+
@context.set_source_rgba(*components)
|
135
|
+
when Compass::Canvas::Constants::LINEAR, Compass::Canvas::Constants::RADIAL
|
136
|
+
coordinates = args.shift
|
137
|
+
stops = args.shift
|
138
|
+
gradient = ::Cairo::const_get("#{ type.to_s.sub(/^\w/) { |s| s.capitalize } }Pattern").new(*coordinates)
|
139
|
+
stops.each { |value| gradient.add_color_stop_rgba(*value) }
|
140
|
+
@context.set_source(gradient)
|
141
|
+
when Compass::Canvas::Constants::CANVAS
|
142
|
+
canvas = args.shift
|
143
|
+
if canvas.is_a?(Compass::Canvas::Backend::Cairo)
|
144
|
+
pattern = ::Cairo::SurfacePattern.new(canvas.execute.surface)
|
145
|
+
pattern.set_extend(constant('EXTEND', args)) if args.length
|
146
|
+
@context.set_source(pattern)
|
147
|
+
else
|
148
|
+
raise Compass::Canvas::Exception.new("(#{self.class}.#{action}) Unsupported canvas, Cairo can only paint with Cairo: #{canvas.inspect}")
|
149
|
+
end
|
150
|
+
else
|
151
|
+
raise Compass::Canvas::Exception.new("(#{self.class}.#{action}) Unsupported type (supported types are 'solid', 'linear', 'radial'): #{type.inspect}")
|
152
|
+
end
|
153
|
+
when Compass::Canvas::Actions::SLOW_BLUR
|
154
|
+
radius = args.shift
|
155
|
+
@context.pseudo_blur(radius) do
|
156
|
+
execute_actions(args)
|
157
|
+
end
|
158
|
+
else
|
159
|
+
raise Compass::Canvas::Exception.new("(#{self.class}) '#{action}' is not supported.")
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Serializes the +ImageSurface+ to a +String+.
|
164
|
+
def to_blob
|
165
|
+
stream = StringIO.new
|
166
|
+
@surface.write_to_png(stream)
|
167
|
+
stream.string
|
168
|
+
end
|
169
|
+
|
170
|
+
private
|
171
|
+
|
172
|
+
def constant(name, *args)
|
173
|
+
::Cairo::const_get("#{ name.upcase }_#{ args.join('_').gsub('-', '_').upcase }")
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Compass::Canvas::Backend
|
2
|
+
# This module defines classes for parsing Sass types and constructing Ruby
|
3
|
+
# objects for use in backend implementations.
|
4
|
+
module Interface
|
5
|
+
# Base class for all interface classes.
|
6
|
+
#
|
7
|
+
# This class unpacks Sass types to Ruby objects before passing them to a
|
8
|
+
# backend implementation.
|
9
|
+
class Base < Sass::Script::Literal
|
10
|
+
# @return [String] The action to take, e.g., +move+, +line+.
|
11
|
+
attr_accessor :action
|
12
|
+
# @return [Array] The arguments to pass, e.g., +X+ and +Y+ coordinates.
|
13
|
+
attr_accessor :args
|
14
|
+
|
15
|
+
# Initializes a new instance of an interface class.
|
16
|
+
#
|
17
|
+
# @param [String] action The action to take, e.g., +move+, +line+.
|
18
|
+
# @param [Array<Sass::Script::Literal>] args The arguments to pass.
|
19
|
+
def initialize(action, *args)
|
20
|
+
@action = action.value.to_sym
|
21
|
+
unless self.respond_to?(@action)
|
22
|
+
recognised = self.class.public_instance_methods - self.class.superclass.public_instance_methods
|
23
|
+
raise Compass::Canvas::Exception.new("(#{self.class}) '#{@action}' is not a recognised action. Did you mean any of the following: '#{ recognised.join("', '") }'?")
|
24
|
+
end
|
25
|
+
arity = self.method(@action).arity.abs
|
26
|
+
unless args.length >= arity
|
27
|
+
raise Compass::Canvas::Exception.new("(#{self.class}.#{@action}) Wrong number of arguments (#{args.length} for #{arity}).")
|
28
|
+
end
|
29
|
+
@args = self.send(@action, *args)
|
30
|
+
end
|
31
|
+
|
32
|
+
# @raise [Compass::Canvas::Exception] Interface objects cannot be used as property values.
|
33
|
+
def to_s(options = {})
|
34
|
+
raise Compass::Canvas::Exception.new("(#{self.class}.#{@action}) Not available in this context.")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
require 'canvas/backend/interface/context';
|
41
|
+
require 'canvas/backend/interface/path';
|
42
|
+
require 'canvas/backend/interface/pattern';
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Compass::Canvas::Backend::Interface
|
2
|
+
# Interface Context class.
|
3
|
+
class Context < Base
|
4
|
+
# Unpacks argument +width+ from Sass to a Ruby object.
|
5
|
+
def line_width(width)
|
6
|
+
[width.value]
|
7
|
+
end
|
8
|
+
|
9
|
+
# Unpacks argument +type+ from Sass to a Ruby object.
|
10
|
+
def line_cap(type)
|
11
|
+
[type.value]
|
12
|
+
end
|
13
|
+
|
14
|
+
# Unpacks argument +type+ from Sass to a Ruby object.
|
15
|
+
def line_join(type)
|
16
|
+
[type.value]
|
17
|
+
end
|
18
|
+
|
19
|
+
# Unpacks argument +limit+ from Sass to a Ruby object.
|
20
|
+
def miter_limit(limit)
|
21
|
+
[limit.value]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Unpacks argument +type+ from Sass to a Ruby object.
|
25
|
+
def antialias(type)
|
26
|
+
if type.is_a?(Sass::Script::Color)
|
27
|
+
[type.to_s]
|
28
|
+
else
|
29
|
+
[type.value]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Unpacks argument +type+ from Sass to a Ruby object.
|
34
|
+
def fill_rule(type)
|
35
|
+
[type.value]
|
36
|
+
end
|
37
|
+
|
38
|
+
# Unpacks argument +level+ from Sass to a Ruby object.
|
39
|
+
def tolerance(level)
|
40
|
+
[level.value]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Unpacks arguments +X+ and +Y+ from Sass to Ruby objects.
|
44
|
+
def translate(x, y)
|
45
|
+
[x.value, y.value]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Unpacks arguments +X+ and +Y+ from Sass to Ruby objects.
|
49
|
+
def scale(x, y)
|
50
|
+
[x.value, y.value]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Unpacks argument +angle+ from Sass to a Ruby object.
|
54
|
+
def rotate(angle)
|
55
|
+
[angle.value * (Math::PI / 180.0)]
|
56
|
+
end
|
57
|
+
|
58
|
+
# Unpacks matrix arguments from Sass to Ruby objects.
|
59
|
+
def transform(xx, yx, xy, yy, x0, y0)
|
60
|
+
[xx.value, yx.value, xy.value, yy.value, x0.value, y0.value]
|
61
|
+
end
|
62
|
+
|
63
|
+
def slow_blur(*args)
|
64
|
+
radius = args.shift.value
|
65
|
+
[radius].concat(Compass::Canvas::Functions.unpack(args).flatten)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Compass::Canvas::Backend::Interface
|
2
|
+
# Interface Path class.
|
3
|
+
class Path < Base
|
4
|
+
# Unpacks arguments +X+ and +Y+ from Sass to Ruby objects.
|
5
|
+
def move(x, y)
|
6
|
+
[x.value, y.value]
|
7
|
+
end
|
8
|
+
|
9
|
+
# Unpacks arguments +X+ and +Y+ from Sass to Ruby objects.
|
10
|
+
def line(x, y)
|
11
|
+
[x.value, y.value]
|
12
|
+
end
|
13
|
+
|
14
|
+
# Unpacks arguments +X+[1..3] and +Y+[1..3] from Sass to Ruby objects.
|
15
|
+
def curve(x1, y1, x2, y2, x3, y3)
|
16
|
+
[x1.value, y1.value, x2.value, y2.value, x3.value, y3.value]
|
17
|
+
end
|
18
|
+
|
19
|
+
# Unpacks arguments +X+, +Y+, +radius+ and +angle+[1..2] from Sass to Ruby objects.
|
20
|
+
def arc(x, y, radius, angle1, angle2)
|
21
|
+
[x.value, y.value, radius.value, angle1.value * (Math::PI / 180.0), angle2.value * (Math::PI / 180.0)]
|
22
|
+
end
|
23
|
+
|
24
|
+
# @see {arc}
|
25
|
+
def arc_reverse(*args)
|
26
|
+
arc(*args)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Compass::Canvas::Backend::Interface
|
2
|
+
# Interface Pattern class.
|
3
|
+
class Pattern < Base
|
4
|
+
# Unpacks brush arguments to a Ruby object.
|
5
|
+
def brush(*args)
|
6
|
+
if args.length == 1
|
7
|
+
type = args.shift
|
8
|
+
if type.is_a?(Sass::Script::Color)
|
9
|
+
[Compass::Canvas::Constants::SOLID, Pattern.split(type)]
|
10
|
+
elsif type.is_a?(Sass::Script::String) && type.value == Compass::Canvas::Actions::RETRIEVE.to_s
|
11
|
+
[Compass::Canvas::Actions::RETRIEVE]
|
12
|
+
elsif type.is_a?(Compass::Canvas::Backend::Base)
|
13
|
+
[Compass::Canvas::Constants::CANVAS, type]
|
14
|
+
else
|
15
|
+
raise Compass::Canvas::Exception.new("(#{self.class}.#{@action}) Unsupported solid brush type: #{type.inspect}")
|
16
|
+
end
|
17
|
+
elsif args.length == 2
|
18
|
+
canvas = args.shift
|
19
|
+
extends = args.shift
|
20
|
+
if canvas.is_a?(Compass::Canvas::Backend::Base) && extends.is_a?(Sass::Script::String)
|
21
|
+
[Compass::Canvas::Constants::CANVAS, canvas, extends.value]
|
22
|
+
else
|
23
|
+
raise Compass::Canvas::Exception.new("(#{self.class}.#{@action}) Unsupported pattern brush type: #{canvas.inspect}")
|
24
|
+
end
|
25
|
+
elsif args.length > 4
|
26
|
+
index = 0
|
27
|
+
index = index + 1 while index < args.length && args[index].is_a?(Sass::Script::Number)
|
28
|
+
type = Compass::Canvas::Constants::LINEAR if index == 4
|
29
|
+
type = Compass::Canvas::Constants::RADIAL if index == 6
|
30
|
+
if type
|
31
|
+
[type, args.slice(0, index).map { |value| value.value }, Pattern.stops(args.slice(index, args.length))]
|
32
|
+
else
|
33
|
+
raise Compass::Canvas::Exception.new("(#{self.class}.#{@action}) Unsupported gradient brush type: #{args.inspect}")
|
34
|
+
end
|
35
|
+
else
|
36
|
+
raise Compass::Canvas::Exception.new("(#{self.class}.#{@action}) Unsupported brush type: #{args.inspect}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Unpacks dash +pattern+ arguments to Ruby objects.
|
41
|
+
def dash_pattern(*pattern)
|
42
|
+
pattern.map { |value| value.value }
|
43
|
+
end
|
44
|
+
|
45
|
+
# Unpacks +canvas+ and optional arguments to a Ruby object.
|
46
|
+
def mask(*args)
|
47
|
+
type = args.shift
|
48
|
+
if type.is_a?(Sass::Script::String) && type.value == Compass::Canvas::Actions::RETRIEVE.to_s
|
49
|
+
type = Compass::Canvas::Actions::RETRIEVE
|
50
|
+
end
|
51
|
+
[type].concat(args.map { |value| value.value })
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def self.split(value)
|
57
|
+
[value.red / 255.0, value.green / 255.0, value.blue / 255.0, value.alpha]
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.stops(list)
|
61
|
+
result = []
|
62
|
+
last_offset = 0
|
63
|
+
list.each_with_index do |value, index|
|
64
|
+
if value.is_a?(Sass::Script::Color)
|
65
|
+
if index > 0
|
66
|
+
if index == list.length - 1
|
67
|
+
offset = 100
|
68
|
+
else
|
69
|
+
next_index = 0
|
70
|
+
next_offset = nil
|
71
|
+
list.slice(index, list.length).each do |next_value|
|
72
|
+
next_index = next_index + 1
|
73
|
+
if next_value.is_a?(Sass::Script::List)
|
74
|
+
next_value.value.each { |child| next_offset = child.value if child.is_a?(Sass::Script::Number) }
|
75
|
+
break
|
76
|
+
end
|
77
|
+
end
|
78
|
+
next_offset ||= 100
|
79
|
+
offset = last_offset + (next_offset - last_offset) / next_index
|
80
|
+
end
|
81
|
+
else
|
82
|
+
offset = 0
|
83
|
+
end
|
84
|
+
last_offset = offset
|
85
|
+
result.push([last_offset / 100.0].concat(Pattern.split(value)))
|
86
|
+
elsif value.is_a?(Sass::Script::List)
|
87
|
+
color = nil
|
88
|
+
value.value.each do |child|
|
89
|
+
color = child if child.is_a?(Sass::Script::Color)
|
90
|
+
last_offset = child.value if child.is_a?(Sass::Script::Number)
|
91
|
+
end
|
92
|
+
result.push([last_offset / 100.0].concat(Pattern.split(color))) if color
|
93
|
+
else
|
94
|
+
raise Compass::Canvas::Exception.new("(#{self.class}) Unsupported gradient brush color-stop: #{value.inspect}")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
result
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'canvas/functions/canvas'
|
2
|
+
require 'canvas/functions/context'
|
3
|
+
require 'canvas/functions/path'
|
4
|
+
require 'canvas/functions/pattern'
|
5
|
+
|
6
|
+
module Compass::Canvas
|
7
|
+
# The +Functions+ module aggregates all exported functions.
|
8
|
+
#
|
9
|
+
# @see Compass::Canvas::Functions::Canvas
|
10
|
+
# @see Compass::Canvas::Functions::Context
|
11
|
+
# @see Compass::Canvas::Functions::Path
|
12
|
+
# @see Compass::Canvas::Functions::Pattern
|
13
|
+
module Functions
|
14
|
+
include Canvas
|
15
|
+
include Context
|
16
|
+
include Path
|
17
|
+
include Pattern
|
18
|
+
include Compass::Canvas::Plugins::Functions
|
19
|
+
|
20
|
+
def self.unpack(value)
|
21
|
+
if value.is_a?(Compass::Canvas::Backend::Interface::Base)
|
22
|
+
value
|
23
|
+
elsif value.is_a?(Sass::Script::Literal)
|
24
|
+
Compass::Canvas::Functions.unpack(value.value)
|
25
|
+
elsif value.is_a?(Array)
|
26
|
+
value.map { |child| Compass::Canvas::Functions.unpack(child) }
|
27
|
+
else
|
28
|
+
value
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Exports {Compass::Canvas::Functions} to Sass.
|
35
|
+
module Sass::Script::Functions
|
36
|
+
include Compass::Canvas::Functions
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Compass::Canvas
|
2
|
+
module Functions
|
3
|
+
# Functions for creating a canvas backend.
|
4
|
+
module Canvas
|
5
|
+
# Creates a new {Compass::Canvas::Backend}.
|
6
|
+
#
|
7
|
+
# This function cannot be created in Sass as it is a variadic function.
|
8
|
+
#
|
9
|
+
# @return [Compass::Canvas::Backend] A new backend instance.
|
10
|
+
def canvas(*args)
|
11
|
+
backend = Compass.configuration.canvas_backend.sub(/^\w/) { |s| s.capitalize }
|
12
|
+
begin
|
13
|
+
klass = Compass::Canvas::Backend.const_get(backend)
|
14
|
+
rescue NameError
|
15
|
+
raise Compass::Canvas::Exception.new("(Compass::Canvas) '#{backend}' backend is not installed.")
|
16
|
+
end
|
17
|
+
klass.new(*Compass::Canvas::Functions.unpack(args).flatten)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Compass::Canvas
|
2
|
+
module Functions
|
3
|
+
# Functions for creating a Context interface.
|
4
|
+
module Context
|
5
|
+
# Creates a new {Compass::Canvas::Backend::Interface::Context}.
|
6
|
+
#
|
7
|
+
# @return [Compass::Canvas::Backend::Interface::Context] A new Context interface.
|
8
|
+
def canvas_context(*args)
|
9
|
+
Compass::Canvas::Backend::Interface::Context.new(*args)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Constructs a slow-blur group.
|
13
|
+
#
|
14
|
+
# This function cannot be created in Sass as it is a variadic function.
|
15
|
+
def slow_blur(radius, *args)
|
16
|
+
canvas_context(Sass::Script::String.new(Compass::Canvas::Actions::SLOW_BLUR.to_s), *[radius].concat(args))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Compass::Canvas
|
2
|
+
module Functions
|
3
|
+
# Functions for creating a Path interface.
|
4
|
+
module Path
|
5
|
+
# Creates a new {Compass::Canvas::Backend::Interface::Path}.
|
6
|
+
#
|
7
|
+
# @return [Compass::Canvas::Backend::Interface::Path] A new Path interface.
|
8
|
+
def canvas_path(*args)
|
9
|
+
Compass::Canvas::Backend::Interface::Path.new(*args)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Compass::Canvas
|
2
|
+
module Functions
|
3
|
+
# Functions for creating a Pattern interface.
|
4
|
+
module Pattern
|
5
|
+
# Creates a new {Compass::Canvas::Backend::Interface::Pattern}.
|
6
|
+
#
|
7
|
+
# @return [Compass::Canvas::Backend::Interface::Pattern] A new Pattern interface.
|
8
|
+
def canvas_pattern(*args)
|
9
|
+
Compass::Canvas::Backend::Interface::Pattern.new(*args)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Constructs a paint pattern.
|
13
|
+
#
|
14
|
+
# This function cannot be created in Sass as it is a variadic function.
|
15
|
+
def brush(*args)
|
16
|
+
canvas_pattern(Sass::Script::String.new(Compass::Canvas::Actions::BRUSH), *args)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Constructs a dash pattern array from positive On/Off lengths.
|
20
|
+
#
|
21
|
+
# This function cannot be created in Sass as it is a variadic function.
|
22
|
+
def dash_pattern(*args)
|
23
|
+
canvas_pattern(Sass::Script::String.new(Compass::Canvas::Actions::DASH_PATTERN), *args)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Constructs a mask from a canvas.
|
27
|
+
#
|
28
|
+
# This function cannot be created in Sass as it is a variadic function.
|
29
|
+
def mask(*args)
|
30
|
+
canvas_pattern(Sass::Script::String.new(Compass::Canvas::Actions::MASK), *args)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Compass::Canvas
|
2
|
+
# This module includes external files in registered locations.
|
3
|
+
#
|
4
|
+
# @see Compass::Canvas::PLUGINS_PATH
|
5
|
+
module Plugins
|
6
|
+
module Functions; end
|
7
|
+
end
|
8
|
+
|
9
|
+
PLUGINS_PATH.each do |path|
|
10
|
+
if File.exists?(path)
|
11
|
+
Dir.glob(File.join(path, '**', '*.rb')).each do |plugin|
|
12
|
+
require plugin
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Compass::Canvas::Plugins::Functions
|
2
|
+
def slow_drop_shadow(x, y, radius, brush, *args)
|
3
|
+
Sass::Script::List.new(
|
4
|
+
[Sass::Script::String.new('push')].concat([canvas_context(Sass::Script::String.new('slow_blur'), radius, args)]).concat([Sass::Script::String.new('pop'), Sass::Script::String.new('store')]).concat([
|
5
|
+
brush,
|
6
|
+
Sass::Script::String.new('save'),
|
7
|
+
canvas_context(Sass::Script::String.new('translate'), x, y),
|
8
|
+
canvas_pattern(Sass::Script::String.new('mask'), Sass::Script::String.new('retrieve')),
|
9
|
+
Sass::Script::String.new('restore')
|
10
|
+
].concat(args)),
|
11
|
+
:space
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
@function line-width($width) {
|
2
|
+
@return canvas-context('line_width', $width);
|
3
|
+
}
|
4
|
+
|
5
|
+
@function line-cap($type) {
|
6
|
+
@return canvas-context('line_cap', $type);
|
7
|
+
}
|
8
|
+
|
9
|
+
@function line-join($type) {
|
10
|
+
@return canvas-context('line_join', $type);
|
11
|
+
}
|
12
|
+
|
13
|
+
@function miter-limit($limit) {
|
14
|
+
@return canvas-context('miter_limit', $limit);
|
15
|
+
}
|
16
|
+
|
17
|
+
@function antialias($type) {
|
18
|
+
@return canvas-context('antialias', $type);
|
19
|
+
}
|
20
|
+
|
21
|
+
@function fill-rule($type) {
|
22
|
+
@return canvas-context('fill_rule', $type);
|
23
|
+
}
|
24
|
+
|
25
|
+
@function tolerance($level) {
|
26
|
+
@return canvas-context('tolerance', $level);
|
27
|
+
}
|
28
|
+
|
29
|
+
@function translate($x, $y) {
|
30
|
+
@return canvas-context('translate', $x, $y);
|
31
|
+
}
|
32
|
+
|
33
|
+
@function scale($x, $y) {
|
34
|
+
@return canvas-context('scale', $x, $y);
|
35
|
+
}
|
36
|
+
|
37
|
+
@function rotate($angle) {
|
38
|
+
@return canvas-context('rotate', $angle);
|
39
|
+
}
|
40
|
+
|
41
|
+
@function transform($xx: 1.0, $yx: 0.0, $xy: 0.0, $yy: 1.0, $x0: 0.0, $y0: 0.0) {
|
42
|
+
@return canvas-context('transform', $xx, $yx, $xy, $yy, $x0, $y0);
|
43
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
@function move-to($x, $y) {
|
2
|
+
@return canvas-path('move', $x, $y);
|
3
|
+
}
|
4
|
+
|
5
|
+
@function line-to($x, $y) {
|
6
|
+
@return canvas-path('line', $x, $y);
|
7
|
+
}
|
8
|
+
|
9
|
+
@function arc($x, $y, $radius, $angle1, $angle2) {
|
10
|
+
@return canvas-path('arc', $x, $y, $radius, $angle1, $angle2);
|
11
|
+
}
|
12
|
+
|
13
|
+
@function arc-reverse($x, $y, $radius, $angle1, $angle2) {
|
14
|
+
@return canvas-path('arc_reverse', $x, $y, $radius, $angle1, $angle2);
|
15
|
+
}
|
16
|
+
|
17
|
+
@function curve-to($x1, $y1, $x2, $y2, $x3, $y3) {
|
18
|
+
@return canvas-path('curve', $x1, $y1, $x2, $y2, $x3, $y3);
|
19
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
@function rectangle($x1, $y1, $x2, $y2) {
|
2
|
+
@return (
|
3
|
+
move-to($x1, $y1)
|
4
|
+
line-to($x2, $y1)
|
5
|
+
line-to($x2, $y2)
|
6
|
+
line-to($x1, $y2)
|
7
|
+
close
|
8
|
+
);
|
9
|
+
}
|
10
|
+
|
11
|
+
@function circle($x, $y, $radius) {
|
12
|
+
@return arc($x, $y, $radius, 0, 360);
|
13
|
+
}
|
14
|
+
|
15
|
+
@function rounded-rectangle($x1, $y1, $x2, $y2, $x_radius, $y_radius: $x_radius) {
|
16
|
+
$max_x_radius: ($x2 - $x1) / 2.0;
|
17
|
+
$max_y_radius: ($y2 - $y1) / 2.0;
|
18
|
+
@if $x_radius > $max_x_radius {
|
19
|
+
$x_radius: $max_x_radius;
|
20
|
+
}
|
21
|
+
@if $y_radius > $max_y_radius {
|
22
|
+
$y_radius: $max_y_radius;
|
23
|
+
}
|
24
|
+
$half_x_radius: $x_radius / 2.0;
|
25
|
+
$half_y_radius: $y_radius / 2.0;
|
26
|
+
@return (
|
27
|
+
move-to($x1 + $x_radius, $y1)
|
28
|
+
line-to($x2 - $x_radius, $y1)
|
29
|
+
curve-to($x2 - $half_x_radius, $y1, $x2, $y1 + $half_y_radius, $x2, $y1 + $y_radius)
|
30
|
+
line-to($x2, $y2 - $y_radius)
|
31
|
+
curve-to($x2, $y2 - $half_y_radius, $x2 - $half_x_radius, $y2, $x2 - $x_radius, $y2)
|
32
|
+
line-to($x1 + $x_radius, $y2)
|
33
|
+
curve-to($x1 + $half_x_radius, $y2, $x1, $y2 - $half_y_radius, $x1, $y2 - $y_radius)
|
34
|
+
line-to($x1, $y1 + $y_radius)
|
35
|
+
curve-to($x1, $y1 + $half_y_radius, $x1 + $half_x_radius, $y1, $x1 + $x_radius, $y1)
|
36
|
+
close
|
37
|
+
);
|
38
|
+
}
|
39
|
+
|
40
|
+
@function triangle($x1, $y1, $x2, $y2, $x3, $y3) {
|
41
|
+
@return (
|
42
|
+
move-to($x1, $y1)
|
43
|
+
line-to($x2, $y2)
|
44
|
+
line-to($x3, $y3)
|
45
|
+
close
|
46
|
+
)
|
47
|
+
}
|
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: compass-canvas
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Stan Angeloff
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-08-14 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: compass
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 29
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
- 11
|
32
|
+
version: "0.11"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: cairo
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 27
|
44
|
+
segments:
|
45
|
+
- 1
|
46
|
+
- 10
|
47
|
+
version: "1.10"
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id002
|
50
|
+
description:
|
51
|
+
email:
|
52
|
+
- stanimir@angeloff.name
|
53
|
+
executables: []
|
54
|
+
|
55
|
+
extensions: []
|
56
|
+
|
57
|
+
extra_rdoc_files: []
|
58
|
+
|
59
|
+
files:
|
60
|
+
- README.md
|
61
|
+
- LICENSE.md
|
62
|
+
- lib/canvas.rb
|
63
|
+
- lib/canvas/functions/canvas.rb
|
64
|
+
- lib/canvas/functions/path.rb
|
65
|
+
- lib/canvas/functions/pattern.rb
|
66
|
+
- lib/canvas/functions/context.rb
|
67
|
+
- lib/canvas/backend.rb
|
68
|
+
- lib/canvas/functions.rb
|
69
|
+
- lib/canvas/backend/cairo.rb
|
70
|
+
- lib/canvas/backend/interface/path.rb
|
71
|
+
- lib/canvas/backend/interface/pattern.rb
|
72
|
+
- lib/canvas/backend/interface/context.rb
|
73
|
+
- lib/canvas/backend/interface.rb
|
74
|
+
- lib/canvas/constants.rb
|
75
|
+
- lib/canvas/configuration.rb
|
76
|
+
- lib/canvas/plugins.rb
|
77
|
+
- lib/canvas/actions.rb
|
78
|
+
- stylesheets/_canvas.scss
|
79
|
+
- stylesheets/canvas/_pattern.scss
|
80
|
+
- stylesheets/canvas/_path.scss
|
81
|
+
- stylesheets/canvas/_context.scss
|
82
|
+
- stylesheets/canvas/path/_primitives.scss
|
83
|
+
- stylesheets/canvas/path/_shapes.scss
|
84
|
+
- plugins/drop-shadow.rb
|
85
|
+
homepage: http://StanAngeloff.github.com/compass-canvas/
|
86
|
+
licenses: []
|
87
|
+
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
hash: 3
|
99
|
+
segments:
|
100
|
+
- 0
|
101
|
+
version: "0"
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
hash: 3
|
108
|
+
segments:
|
109
|
+
- 0
|
110
|
+
version: "0"
|
111
|
+
requirements: []
|
112
|
+
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 1.8.5
|
115
|
+
signing_key:
|
116
|
+
specification_version: 3
|
117
|
+
summary: Canvas drawing support for Compass with Cairo backend(s).
|
118
|
+
test_files: []
|
119
|
+
|