cf3 0.0.5 → 1.0.0
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.
- checksums.yaml +5 -5
- data/CHANGELOG +6 -0
- data/Gemfile +1 -1
- data/README.md +21 -21
- data/Rakefile +6 -2
- data/cf3ruby.gemspec +13 -13
- data/lib/cf3.rb +75 -90
- data/lib/cf3/version.rb +1 -1
- data/samples/Rakefile +30 -0
- data/samples/accident.rb +34 -30
- data/samples/alhambra.rb +32 -29
- data/samples/bar_code.rb +26 -22
- data/samples/city.rb +14 -11
- data/samples/creature.rb +10 -6
- data/samples/dark_star.rb +5 -3
- data/samples/data/java_args.txt +1 -2
- data/samples/dragon.rb +8 -4
- data/samples/escher.rb +115 -116
- data/samples/fern.rb +10 -6
- data/samples/hex_tube.rb +16 -13
- data/samples/isosceles.rb +16 -11
- data/samples/levy.rb +4 -1
- data/samples/pcr.rb +28 -24
- data/samples/rubystar.rb +23 -17
- data/samples/sierpinski.rb +15 -11
- data/samples/spiral.rb +14 -10
- data/samples/star.rb +10 -6
- data/samples/tree.rb +19 -16
- data/samples/tree4.rb +12 -8
- data/samples/vine.rb +11 -7
- data/samples/xcross.rb +10 -7
- data/samples/y.rb +12 -8
- data/test/test_cf3.rb +11 -7
- metadata +23 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b71a0ec8b28c1fd599073b44c0d22ae1522d505b7969a535edf3dfed706491ad
|
4
|
+
data.tar.gz: 36e50b4f45a4e77c6937e2e268f654c8563647045c44824c798cfb18879f3494
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7d53015eeaff4ffe3b5a641c29e1774ce02ed669f2b4447b2da66d6babbc03c58c48b9c69292bc10ba71895069bc03a22f078aaff1337a434f8a5384234d581
|
7
|
+
data.tar.gz: 4aca28d84f49c8f11bda4f028c20c8b9334eed0cab8259f3011129ff1f3c8e72d4dd4dcb67f7afc310e9525e1b36041d96dacb1a8b25d418d7fb81eda282c1ad
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
v1.0.0 About time for a regular release number, fixed and update some examples NB: see also https://github.com/funatsufumiya/cf3ruby_sketches
|
2
|
+
|
3
|
+
v0.0.7 Update for processing3 and JRubyArt by Funatsufumiya san (aka funniti)
|
4
|
+
|
5
|
+
v0.0.6 Some tidy up remove @finished
|
6
|
+
|
1
7
|
v0.0.4 Introduce :w and :h as options to supplement size
|
2
8
|
* start support for width and height options (:w, :h)
|
3
9
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,38 +1,42 @@
|
|
1
1
|
# cf3ruby
|
2
2
|
|
3
|
-
|
3
|
+
Now updated to be compatible with ruby 2.4, JRubyArt 1.4.4 (newer version of ruby-processing), and Processing 3+.*
|
4
|
+
|
5
|
+
**context-free DSL for ruby-2.4 and CF3 syntax**
|
6
|
+
|
7
|
+
Very much derived from [context-free.rb](https://github.com/jashkenas/context_free) by Jeremy Ashkenas this version is updated to be more in line with CF3 and ruby 2.3 syntax. NB this version will not work with original ruby-processing.
|
4
8
|
|
5
|
-
Very much derived from [context-free.rb][] by Jeremy Ashkenas this version is updated to be more in line with CF3 and ruby 1.9 syntax. Tested as working with last rubygems release of ruby-processing (v 1.0.11) as well as the current [version][] (v 2.4.0).
|
6
|
-
[context-free.rb]:https://github.com/jashkenas/context_free/
|
7
|
-
[version]:https://github.com/monkstone/ruby-processing/releases/
|
8
9
|
## Installation
|
9
10
|
|
10
|
-
To use this library you need install jruby (preferably jruby-1
|
11
|
+
To use this library you need install jruby (preferably jruby-9.1+), you will also need [ruby-processing/JRubyArt](https://github.com/ruby-processing/JRubyArt) to be installed (preferred version 1.4.4). There are three ways you can install this library:-
|
11
12
|
|
12
13
|
***rake test and gem install***
|
13
14
|
|
14
|
-
|
15
|
+
Clone this repository,
|
15
16
|
|
16
17
|
```bash
|
17
|
-
cd cf3ruby
|
18
|
+
cd cf3ruby
|
18
19
|
jruby -S rake test # builds and tests gem (mouse click on frame for test image to show)
|
19
|
-
jruby -S gem install cf3-0.0.
|
20
|
+
jruby -S gem install cf3-1.0.0.gem # may need sudo access
|
20
21
|
```
|
21
22
|
|
22
23
|
***local bundle install***
|
23
24
|
|
24
|
-
|
25
|
+
Clone this repository,
|
25
26
|
|
26
27
|
```bash
|
27
|
-
cd
|
28
|
-
bundle install # using regular installed bundler may need to set GEM_PATH
|
28
|
+
cd cf3ruby
|
29
|
+
# bundle install # using regular installed bundler may need to set GEM_PATH
|
29
30
|
jruby -S bundle install # if you installed bundler with jruby
|
30
31
|
```
|
31
32
|
|
32
33
|
***gem install from rubygems***
|
34
|
+
|
33
35
|
```bash
|
34
|
-
|
35
|
-
|
36
|
+
# When rubygems is updatd for this release.
|
37
|
+
|
38
|
+
# gem install cf3 # regular install may need to set GEM_PATH env variable
|
39
|
+
# jruby -S gem install cf3 # jruby install
|
36
40
|
```
|
37
41
|
it couldn't be easier could it?
|
38
42
|
|
@@ -44,19 +48,15 @@ cf3samples # should work
|
|
44
48
|
jruby -S cf3samples # else if installed with jruby this should also work
|
45
49
|
```
|
46
50
|
|
47
|
-
As for running ruby-processing,
|
51
|
+
As for running ruby-processing,
|
48
52
|
```bash
|
49
|
-
|
53
|
+
k9 --run city.rb # providing you installed both ruby-processing (JRubyArt) and cf3ruby using jruby
|
50
54
|
|
51
55
|
```
|
52
|
-
You should read the [ruby-
|
56
|
+
You should read the [JRubyArt documentation](https://github.com/ruby-processing/JRubyArt/blob/master/README.md) on using rubygems.
|
53
57
|
|
54
58
|
## Contributing
|
55
59
|
|
56
|
-
[
|
57
|
-
[contributing]:CONTRIBUTING.md
|
58
|
-
[ruby-processing_documentation]:https://github.com/jashkenas/ruby-processing/wiki/Using-Rubygems/
|
59
|
-
[snapshot]:https://github.com/monkstone/cf3ruby/releases
|
60
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md)
|
60
61
|
|
61
62
|

|
62
|
-
|
data/Rakefile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
1
|
+
#require "bundler/gem_tasks"
|
2
2
|
|
3
3
|
task :install => :build do
|
4
4
|
sh "jruby -S gem install #{Dir.glob('*.gem').join(' ')} --no-ri --no-rdoc"
|
@@ -9,7 +9,11 @@ task :build do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
task :test do
|
12
|
-
sh "jruby -S
|
12
|
+
sh "jruby -S k9 --run test/test_cf3.rb"
|
13
13
|
end
|
14
14
|
|
15
|
+
task :clean do
|
16
|
+
sh "rm *.gem"
|
17
|
+
end
|
18
|
+
|
15
19
|
task :default => [:install]
|
data/cf3ruby.gemspec
CHANGED
@@ -4,26 +4,26 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'cf3/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'cf3'
|
8
8
|
spec.version = Cf3::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
9
|
+
spec.authors = ['Jeremy Ashkenas', 'Martin Prout, Funatsufumiya']
|
10
|
+
spec.email = ['mamba2928@yahoo.co.uk']
|
11
11
|
spec.description = <<-EOF
|
12
|
-
A library for
|
12
|
+
A library for JRubyArt, that allows the writing of context free
|
13
13
|
sketches (like context free art) in a ruby DSL. It is a bit of a toy
|
14
|
-
compared to the c++ version. However you can get quite a bit of
|
14
|
+
compared to the c++ version. However you can get quite a bit of
|
15
15
|
satisfaction creating an interesting graphic, and you can't always
|
16
16
|
predict what you are going to get.
|
17
17
|
EOF
|
18
18
|
spec.summary = %q{A ruby-DSL library for CF3 sketches}
|
19
|
-
spec.homepage =
|
20
|
-
spec.default_executable =
|
21
|
-
spec.
|
19
|
+
spec.homepage = 'http://learning-ruby-processing.blogspot.co.uk/'
|
20
|
+
spec.default_executable = 'cf3samples'
|
21
|
+
spec.licenses = %w(GPL-3.0 LGPL-2.0)
|
22
22
|
spec.files = `git ls-files`.split($/)
|
23
23
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
24
|
-
spec.executables = [
|
25
|
-
spec.require_paths = [
|
26
|
-
spec.add_runtime_dependency '
|
27
|
-
spec.add_development_dependency
|
28
|
-
spec.add_development_dependency
|
24
|
+
spec.executables = ['cf3samples']
|
25
|
+
spec.require_paths = ['lib']
|
26
|
+
spec.add_runtime_dependency 'jruby_art', '~> 1.4'
|
27
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
28
|
+
spec.add_development_dependency 'rake', '~> 12.0'
|
29
29
|
end
|
data/lib/cf3.rb
CHANGED
@@ -1,42 +1,37 @@
|
|
1
|
-
# A Context-Free library for Ruby-Processing, inspired by
|
2
|
-
# based on context_free.rb by Jeremy Ashkenas. Which in turn
|
3
|
-
# was inspired by contextfreeart.org
|
4
|
-
|
5
1
|
module Processing
|
6
|
-
|
2
|
+
# A Context-Free library for JRubyArt, inspired by and
|
3
|
+
# based on context_free.rb by Jeremy Ashkenas. That in turn
|
4
|
+
# was inspired by contextfreeart.org
|
7
5
|
class ContextFree
|
8
|
-
|
9
6
|
include Processing::Proxy
|
10
|
-
|
11
7
|
attr_accessor :rule, :app, :width, :height
|
12
8
|
|
13
|
-
AVAILABLE_OPTIONS = [
|
14
|
-
|
15
|
-
|
16
|
-
|
9
|
+
AVAILABLE_OPTIONS = %i[
|
10
|
+
x y w h rotation size flip color hue saturation brightness alpha
|
11
|
+
].freeze
|
12
|
+
HSB_ORDER = { hue: 0, saturation: 1, brightness: 2, alpha: 3 }.freeze
|
13
|
+
TRIANGLE_TOP = -1 / Math.sqrt(3)
|
14
|
+
TRIANGLE_BOTTOM = Math.sqrt(3) / 6
|
17
15
|
RADIANS = (Math::PI / 180.0)
|
18
16
|
# Define a context-free system. Use this method to create a ContextFree
|
19
17
|
# object. Call render() on it to make it draw.
|
20
18
|
def self.define(&block)
|
21
19
|
cf = ContextFree.new
|
22
|
-
cf.instance_eval
|
20
|
+
cf.instance_eval(&block)
|
23
21
|
cf
|
24
22
|
end
|
25
23
|
|
26
|
-
|
27
24
|
# Initialize a bare ContextFree object with empty recursion stacks.
|
28
25
|
def initialize
|
29
|
-
@app
|
30
|
-
@graphics =
|
31
|
-
@width =
|
32
|
-
@height =
|
33
|
-
@finished = false
|
26
|
+
@app = Processing.app
|
27
|
+
@graphics = @app.g
|
28
|
+
@width = @app.width
|
29
|
+
@height = @app.height
|
34
30
|
@rules = {}
|
35
31
|
@rewind_stack = []
|
36
32
|
@matrix_stack = []
|
37
33
|
end
|
38
34
|
|
39
|
-
|
40
35
|
# Create an accessor for the current value of every option. We use a values
|
41
36
|
# object so that all the state can be saved and restored as a unit.
|
42
37
|
AVAILABLE_OPTIONS.each do |option_name|
|
@@ -45,17 +40,16 @@ module Processing
|
|
45
40
|
end
|
46
41
|
end
|
47
42
|
|
48
|
-
|
49
43
|
# Here's the first serious method: A Rule has an
|
50
44
|
# identifying name, a probability, and is associated with
|
51
45
|
# a block of code. These code blocks are saved, and indexed
|
52
46
|
# by name in a hash, to be run later, when needed.
|
53
47
|
# The method then dynamically defines a method of the same
|
54
48
|
# name here, in order to determine which rule to run.
|
55
|
-
def shape(rule_name, prob=1, &proc)
|
56
|
-
@rules[rule_name] ||= {procs: [], total: 0}
|
49
|
+
def shape(rule_name, prob = 1, &proc)
|
50
|
+
@rules[rule_name] ||= { procs: [], total: 0 }
|
57
51
|
total = @rules[rule_name][:total]
|
58
|
-
@rules[rule_name][:procs] << [(total...(prob+total)), proc]
|
52
|
+
@rules[rule_name][:procs] << [(total...(prob + total)), proc]
|
59
53
|
@rules[rule_name][:total] += prob
|
60
54
|
unless ContextFree.method_defined? rule_name
|
61
55
|
self.class.class_eval do
|
@@ -63,9 +57,8 @@ module Processing
|
|
63
57
|
def #{rule_name}(options)
|
64
58
|
merge_options(@values, options)
|
65
59
|
pick = determine_rule(#{rule_name.inspect})
|
66
|
-
|
67
|
-
|
68
|
-
get_ready_to_draw
|
60
|
+
unless (@values[:size] - @values[:stop_size]) < 0
|
61
|
+
prepare_to_draw
|
69
62
|
pick[1].call(options)
|
70
63
|
end
|
71
64
|
end
|
@@ -74,37 +67,37 @@ module Processing
|
|
74
67
|
end
|
75
68
|
end
|
76
69
|
|
77
|
-
|
78
70
|
# Rule choice is random, based on the assigned probabilities.
|
79
71
|
def determine_rule(rule_name)
|
80
72
|
rule = @rules[rule_name]
|
81
|
-
chance = rand
|
82
|
-
|
83
|
-
|
73
|
+
chance = rand(0.0..rule[:total])
|
74
|
+
@rules[rule_name][:procs].select do |the_proc|
|
75
|
+
the_proc[0].include?(chance)
|
76
|
+
end.flatten
|
84
77
|
end
|
85
78
|
|
86
|
-
|
87
79
|
# At each step of the way, any of the options may change, slightly.
|
88
80
|
# Many of them have different strategies for being merged.
|
89
81
|
def merge_options(old_ops, new_ops)
|
90
82
|
return unless new_ops
|
91
83
|
# Do size first
|
92
|
-
old_ops[:size] *= new_ops
|
84
|
+
old_ops[:size] *= new_ops.fetch(:size, 1.0)
|
93
85
|
new_ops.each do |key, value|
|
94
86
|
case key
|
95
|
-
when :size
|
87
|
+
# when :size
|
96
88
|
when :x, :y
|
97
|
-
old_ops[key] = value * old_ops
|
89
|
+
old_ops[key] = value * old_ops.fetch(:size, 1.0)
|
98
90
|
when :rotation
|
99
91
|
old_ops[key] = value * RADIANS
|
100
92
|
when :hue, :saturation, :brightness, :alpha
|
101
93
|
adjusted = old_ops[:color].dup
|
102
|
-
adjusted[HSB_ORDER[key]] *= value
|
94
|
+
adjusted[HSB_ORDER[key]] *= value unless key == :hue
|
95
|
+
adjusted[HSB_ORDER[key]] += value if key == :hue
|
103
96
|
old_ops[:color] = adjusted
|
104
97
|
when :flip
|
105
98
|
old_ops[key] = !old_ops[key]
|
106
99
|
when :w, :h
|
107
|
-
old_ops[key] = value * old_ops
|
100
|
+
old_ops[key] = value * old_ops.fetch(:size, 1.0)
|
108
101
|
when :color
|
109
102
|
old_ops[key] = value
|
110
103
|
else # Used a key that we don't know about or trying to set
|
@@ -113,133 +106,125 @@ module Processing
|
|
113
106
|
end
|
114
107
|
end
|
115
108
|
|
116
|
-
|
117
109
|
# Using an unknown key let's you set arbitrary values,
|
118
110
|
# to keep track of for your own ends.
|
119
111
|
def merge_unknown_key(key, value, old_ops)
|
120
112
|
key_s = key.to_s
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
end
|
113
|
+
return unless key_s =~ /^set/
|
114
|
+
key_sym = key_s.sub('set_', '').to_sym
|
115
|
+
if key_s =~ /(brightness|hue|saturation)/
|
116
|
+
adjusted = old_ops[:color].dup
|
117
|
+
adjusted[HSB_ORDER[key_sym]] = value
|
118
|
+
old_ops[:color] = adjusted
|
119
|
+
else
|
120
|
+
old_ops[key_sym] = value
|
130
121
|
end
|
131
122
|
end
|
132
123
|
|
133
|
-
|
134
124
|
# Doing a 'split' saves the context, and proceeds from there,
|
135
125
|
# allowing you to rewind to where you split from at any moment.
|
136
|
-
def split(options=nil
|
126
|
+
def split(options = nil)
|
137
127
|
save_context
|
138
128
|
merge_options(@values, options) if options
|
139
129
|
yield
|
140
130
|
restore_context
|
141
131
|
end
|
142
132
|
|
143
|
-
|
144
133
|
# Saving the context means the values plus the coordinate matrix.
|
145
134
|
def save_context
|
146
135
|
@rewind_stack.push @values.dup
|
147
136
|
@matrix_stack << @graphics.get_matrix
|
148
137
|
end
|
149
138
|
|
150
|
-
|
151
139
|
# Restore the values and the coordinate matrix as the recursion unwinds.
|
152
140
|
def restore_context
|
153
141
|
@values = @rewind_stack.pop
|
154
142
|
@graphics.set_matrix @matrix_stack.pop
|
155
143
|
end
|
156
144
|
|
157
|
-
|
158
145
|
# Rewinding goes back one step.
|
159
146
|
def rewind
|
160
|
-
@finished = false
|
161
147
|
restore_context
|
162
148
|
save_context
|
163
149
|
end
|
164
150
|
|
165
|
-
|
166
151
|
# Render the is method that kicks it all off, initializing the options
|
167
152
|
# and calling the first rule.
|
168
|
-
def render(rule_name, starting_values={})
|
169
|
-
@values =
|
170
|
-
rotation: 0, flip: false,
|
171
|
-
size: 20, w: nil, h: nil,
|
172
|
-
start_x: width/2, start_y: height/2,
|
173
|
-
color: [180, 0.5, 0.5, 1],
|
174
|
-
stop_size: 1.5}
|
153
|
+
def render(rule_name, starting_values = {})
|
154
|
+
@values = defaults
|
175
155
|
@values.merge!(starting_values)
|
176
|
-
@finished = false
|
177
156
|
@app.reset_matrix
|
178
157
|
@app.rect_mode CENTER
|
179
158
|
@app.ellipse_mode CENTER
|
180
159
|
@app.no_stroke
|
181
|
-
@app.color_mode HSB, 360, 1.0, 1.0, 1.0
|
182
|
-
@app.translate @values
|
183
|
-
|
160
|
+
@app.color_mode HSB, 360, 1.0, 1.0, 1.0 # match cfdg
|
161
|
+
@app.translate @values.fetch(:start_x, 0), @values.fetch(:start_y, 0)
|
162
|
+
send(rule_name, {})
|
184
163
|
end
|
185
164
|
|
165
|
+
def defaults
|
166
|
+
{
|
167
|
+
x: 0,
|
168
|
+
y: 0,
|
169
|
+
rotation: 0,
|
170
|
+
flip: false,
|
171
|
+
size: 20,
|
172
|
+
start_x: width / 2,
|
173
|
+
start_y: height / 2,
|
174
|
+
color: [180, 0.5, 0.5, 1],
|
175
|
+
stop_size: 1.5
|
176
|
+
}
|
177
|
+
end
|
186
178
|
|
187
179
|
# Before actually drawing the next step, we need to move to the appropriate
|
188
180
|
# location.
|
189
|
-
def
|
190
|
-
@app.translate(@values
|
181
|
+
def prepare_to_draw
|
182
|
+
@app.translate(@values.fetch(:x, 0), @values.fetch(:y, 0))
|
191
183
|
sign = (@values[:flip] ? -1 : 1)
|
192
184
|
@app.rotate(sign * @values[:rotation])
|
193
185
|
end
|
194
186
|
|
195
|
-
|
196
187
|
# Compute the rendering parameters for drawing a shape.
|
197
188
|
def get_shape_values(some_options)
|
198
189
|
old_ops = @values.dup
|
199
|
-
merge_options(old_ops, some_options)
|
200
|
-
@app.fill
|
201
|
-
|
190
|
+
merge_options(old_ops, some_options) unless some_options.empty?
|
191
|
+
@app.fill(*old_ops[:color])
|
192
|
+
old_ops
|
202
193
|
end
|
203
194
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
def square(some_options={})
|
208
|
-
size, options = *get_shape_values(some_options)
|
195
|
+
# Square, circle, ellipse and triangles are the primitive shapes
|
196
|
+
def square(some_options = {})
|
197
|
+
options = get_shape_values(some_options)
|
209
198
|
width = options[:w] || options[:size]
|
210
199
|
height = options[:h] || options[:size]
|
211
|
-
rot = options[:rotation]
|
200
|
+
rot = options[:rotation]
|
212
201
|
@app.rotate(rot) if rot
|
213
202
|
@app.rect(0, 0, width, height)
|
214
|
-
@app.rotate(-rot) if rot
|
203
|
+
@app.rotate(-rot) if rot
|
215
204
|
end
|
216
205
|
|
217
|
-
|
218
|
-
|
219
|
-
size, options = *get_shape_values(some_options)
|
206
|
+
def circle(some_options = {})
|
207
|
+
get_shape_values(some_options)
|
220
208
|
@app.ellipse(0, 0, size, size)
|
221
209
|
end
|
222
210
|
|
223
|
-
def triangle(some_options={})
|
224
|
-
|
225
|
-
rot = options[:rotation]
|
211
|
+
def triangle(some_options = {})
|
212
|
+
options = get_shape_values(some_options)
|
213
|
+
rot = options[:rotation]
|
226
214
|
@app.rotate(rot) if rot
|
227
215
|
@app.triangle(0, TRIANGLE_TOP * size, 0.5 * size, TRIANGLE_BOTTOM * size, -0.5 * size, TRIANGLE_BOTTOM * size)
|
228
216
|
@app.rotate(-rot) if rot
|
229
217
|
end
|
230
218
|
|
231
|
-
|
232
|
-
|
233
|
-
size, options = *get_shape_values(some_options)
|
219
|
+
def ellipse(some_options = {})
|
220
|
+
options = get_shape_values(some_options)
|
234
221
|
width = options[:w] || options[:size]
|
235
222
|
height = options[:h] || options[:size]
|
236
|
-
rot = some_options[:rotation]
|
223
|
+
rot = some_options[:rotation]
|
237
224
|
@app.rotate(rot) if rot
|
238
225
|
@app.oval(options[:x] || 0, options[:y] || 0, width, height)
|
239
226
|
@app.rotate(-rot) if rot
|
240
227
|
end
|
241
|
-
|
242
|
-
|
228
|
+
alias oval ellipse
|
243
229
|
end
|
244
|
-
|
245
230
|
end
|