compass-canvas 0.0.4
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.
- 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
|
+
|