tagen 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/.yardopts +5 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +24 -0
- data/README.md +60 -0
- data/Rakefile +9 -0
- data/docs/Architecture.md +17 -0
- data/docs/CoreExtensions.md +56 -0
- data/docs/ExtraExtensions.md +20 -0
- data/lib/tagen/audioinfo.rb +21 -0
- data/lib/tagen/cairo.rb +809 -0
- data/lib/tagen/core.rb +34 -0
- data/lib/tagen/core/array.rb +41 -0
- data/lib/tagen/core/array/extract_options.rb +40 -0
- data/lib/tagen/core/hash.rb +17 -0
- data/lib/tagen/core/io.rb +29 -0
- data/lib/tagen/core/kernel.rb +73 -0
- data/lib/tagen/core/marshal.rb +34 -0
- data/lib/tagen/core/module.rb +25 -0
- data/lib/tagen/core/numeric.rb +10 -0
- data/lib/tagen/core/object.rb +21 -0
- data/lib/tagen/core/pa.rb +187 -0
- data/lib/tagen/core/pa/cmd.rb +374 -0
- data/lib/tagen/core/pa/dir.rb +144 -0
- data/lib/tagen/core/pa/path.rb +190 -0
- data/lib/tagen/core/pa/state.rb +56 -0
- data/lib/tagen/core/process.rb +11 -0
- data/lib/tagen/core/re.rb +8 -0
- data/lib/tagen/core/string.rb +43 -0
- data/lib/tagen/core/string/pyformat.rb +322 -0
- data/lib/tagen/core/time.rb +8 -0
- data/lib/tagen/gdk_pixbuf2.rb +26 -0
- data/lib/tagen/gtk2.rb +122 -0
- data/lib/tagen/magick.rb +23 -0
- data/lib/tagen/ncurses.rb +245 -0
- data/lib/tagen/net/http.rb +34 -0
- data/lib/tagen/pathname.rb +8 -0
- data/lib/tagen/poppler.rb +47 -0
- data/lib/tagen/socket.rb +20 -0
- data/lib/tagen/tree.rb +75 -0
- data/lib/tagen/vim.rb +19 -0
- data/lib/tagen/xmpp4r.rb +1 -0
- data/lib/tagen/xmpp4r/roster.rb +20 -0
- data/spec/cairo_spec.rb +137 -0
- data/spec/core/pa/cmd_spec.rb +251 -0
- data/spec/core/pa/dir_spec.rb +59 -0
- data/spec/core/string/pyformat_spec.rb +86 -0
- data/spec/spec_helper.rb +0 -0
- data/tagen.gemspec +20 -0
- data/version.rb +7 -0
- metadata +117 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
guten (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.1.2)
|
10
|
+
rspec (2.4.0)
|
11
|
+
rspec-core (~> 2.4.0)
|
12
|
+
rspec-expectations (~> 2.4.0)
|
13
|
+
rspec-mocks (~> 2.4.0)
|
14
|
+
rspec-core (2.4.0)
|
15
|
+
rspec-expectations (2.4.0)
|
16
|
+
diff-lcs (~> 1.1.2)
|
17
|
+
rspec-mocks (2.4.0)
|
18
|
+
|
19
|
+
PLATFORMS
|
20
|
+
ruby
|
21
|
+
|
22
|
+
DEPENDENCIES
|
23
|
+
guten!
|
24
|
+
rspec
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
Tagen, a core and extra extension to Ruby library.
|
2
|
+
==========================================
|
3
|
+
Ruby has an 'Open Class' feature, so we can extend any class by ourself.
|
4
|
+
|
5
|
+
This library provides some usefull Ruby core extension. some comes from ActiveSupport. ActiveSupport is mainly target to Rails, but tagen is target to generic ruby development, and tagen is smaller. It is a colletion of most common core,extra extensions.
|
6
|
+
|
7
|
+
not support ruby1.8, win32
|
8
|
+
|
9
|
+
This library comes with a path lib named {Pa} and a string format lib named {PyFormat}.
|
10
|
+
|
11
|
+
Usage
|
12
|
+
-----
|
13
|
+
use core extension
|
14
|
+
|
15
|
+
require "tagen/core"
|
16
|
+
|
17
|
+
then we have String#blank? method, for a list of core extensions, see {file:docs/CoreExtensions.md docs/CoreExtensions}.
|
18
|
+
|
19
|
+
use extra extension
|
20
|
+
|
21
|
+
require "pathname"
|
22
|
+
require "tagen/pathname"
|
23
|
+
|
24
|
+
add #path method to Pathname, see API doc.
|
25
|
+
|
26
|
+
Documentation
|
27
|
+
-------------
|
28
|
+
* {file:docs/CoreExtensions.md CoreExtensions} A list of core extensions.
|
29
|
+
* {file:docs/ExtraExtensions.md ExtraExtensions} A list of extra extensions.
|
30
|
+
* {file:docs/Architecture.md Architecture} Source code architecture.
|
31
|
+
|
32
|
+
Install
|
33
|
+
----------
|
34
|
+
gem install tagen
|
35
|
+
|
36
|
+
Contributing
|
37
|
+
-------------
|
38
|
+
* report bugs/featues to issue tracker.
|
39
|
+
* fork it and pull a request.
|
40
|
+
* improve documentation.
|
41
|
+
* any ideas are welcome.
|
42
|
+
|
43
|
+
See Also
|
44
|
+
--------
|
45
|
+
**ActiveSupport** [ActiveSupport Core Extension Guide](http://edgeguides.rubyonrails.org/active_support_core_extensions.html)
|
46
|
+
|
47
|
+
|
48
|
+
Info & Links
|
49
|
+
------------
|
50
|
+
**Homepage**: [http://github.com/GutenLinux/tagen](http://github.com/GutenLinux/tagen)
|
51
|
+
**Author**: Guten
|
52
|
+
**API-Docs**: yard
|
53
|
+
**Bugs**: github
|
54
|
+
|
55
|
+
Contributors
|
56
|
+
-------------
|
57
|
+
|
58
|
+
Copyright
|
59
|
+
---------
|
60
|
+
Copyright © 2011 by Guten. this library released under MIT-License, See {file:License} for futher details.
|
data/Rakefile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
Core extensions
|
2
|
+
==============
|
3
|
+
some come from ActiveSupport.
|
4
|
+
|
5
|
+
Usage
|
6
|
+
-----
|
7
|
+
require "tagen/core" # include "time", "date"
|
8
|
+
|
9
|
+
From Tagen
|
10
|
+
----------
|
11
|
+
* {Object#deepdup}
|
12
|
+
|
13
|
+
* {Numeric#div2}
|
14
|
+
|
15
|
+
* {String}.hexdigits octdigits letters uppercase lowercase
|
16
|
+
|
17
|
+
* {Array}
|
18
|
+
* `#extract_extend_options! extract_options!`
|
19
|
+
* \#append
|
20
|
+
* `#delete(*values) delete_at` _support delete more than one values_
|
21
|
+
|
22
|
+
* {Hash#delete}
|
23
|
+
|
24
|
+
* {IO#fd}
|
25
|
+
|
26
|
+
* {Time.time}
|
27
|
+
|
28
|
+
* {Process.exists?}(pid)
|
29
|
+
|
30
|
+
* {Marshal}.load dump _add Pa support_
|
31
|
+
|
32
|
+
* {Pa} _a path lib_
|
33
|
+
|
34
|
+
* {MatchData#to_hash}
|
35
|
+
|
36
|
+
From ActiveSupport
|
37
|
+
------------------
|
38
|
+
see [ActiveSupport Core Extensions Guide](http://edgeguides.rubyonrails.org/active_support_core_extensions.html)
|
39
|
+
|
40
|
+
* `Object #blank? present? presence try`
|
41
|
+
|
42
|
+
* `Module #mattr_x`
|
43
|
+
|
44
|
+
* `Class #cattr_x`
|
45
|
+
|
46
|
+
* `String #strip_heredoc at from to`
|
47
|
+
|
48
|
+
* `Numeric #bytes kilobytes megabytes gigabytes terabytes petabytes exabytes`
|
49
|
+
|
50
|
+
* `Enumerable #sum many? exclude?`
|
51
|
+
|
52
|
+
* `Array #from to second third fourth fifth`
|
53
|
+
|
54
|
+
* `Array.wrap`
|
55
|
+
|
56
|
+
* `Hash #deep_merge[!]`
|
@@ -0,0 +1,20 @@
|
|
1
|
+
A list of extra extensions
|
2
|
+
==========================
|
3
|
+
|
4
|
+
From stdlib
|
5
|
+
-----------
|
6
|
+
* "pathname"
|
7
|
+
* "socket"
|
8
|
+
* "net/http"
|
9
|
+
|
10
|
+
From Gems
|
11
|
+
---------
|
12
|
+
* "audioinfo"
|
13
|
+
* "cairo"
|
14
|
+
* "gtk2"
|
15
|
+
* "magick"
|
16
|
+
* "ncurses"
|
17
|
+
* "poppler"
|
18
|
+
* "tree"
|
19
|
+
* "vim"
|
20
|
+
* "xmpp4r
|
@@ -0,0 +1,21 @@
|
|
1
|
+
=begin
|
2
|
+
* **gem**: ruby-audioinfo
|
3
|
+
=end
|
4
|
+
class AudioInfo
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# check if it is a audio file?
|
8
|
+
#
|
9
|
+
# @param [String] path
|
10
|
+
# @return [Boolean]
|
11
|
+
def file? path
|
12
|
+
SUPPORTED_EXTENSIONS.include? File.extname(path)
|
13
|
+
end
|
14
|
+
|
15
|
+
# get a file's type
|
16
|
+
#
|
17
|
+
# @param [String] path
|
18
|
+
# @return [String]
|
19
|
+
def type path; File.extname(path) end
|
20
|
+
end
|
21
|
+
end
|
data/lib/tagen/cairo.rb
ADDED
@@ -0,0 +1,809 @@
|
|
1
|
+
# gdk_pixbuf2 for
|
2
|
+
# Context#set_source
|
3
|
+
# set_source_pixbuf
|
4
|
+
begin
|
5
|
+
require "gdk_pixbuf2"
|
6
|
+
require_relative "gdk_pixbuf2"
|
7
|
+
rescue
|
8
|
+
end
|
9
|
+
|
10
|
+
# confict. Gtk::PrintContext use Cairo. but not use Context#initialize method
|
11
|
+
# because inherit probleam
|
12
|
+
# FF1. only change Cairo::Context -> Cairo::Contexg
|
13
|
+
# FF2. Gtk::PrintContext config with cairo. so change Gtk::PrintContext
|
14
|
+
|
15
|
+
=begin
|
16
|
+
* **Install**: gem(cairo)
|
17
|
+
|
18
|
+
a wrap to Cairo.
|
19
|
+
|
20
|
+
this library is deprecated, please don't use it.
|
21
|
+
|
22
|
+
=end
|
23
|
+
module Cairo
|
24
|
+
|
25
|
+
# compute width height by rotate and scale
|
26
|
+
#
|
27
|
+
# @param [Numeric] w
|
28
|
+
# @param [Numeric] h
|
29
|
+
# @param [Numeric] rotate 0<=x<=1
|
30
|
+
# @param [Numeric] scale 0<=x<=1
|
31
|
+
# @return [Array<Numeric>] \[length1, length2]
|
32
|
+
def self.compute_wh(w, h, rotate=0,scale=1)
|
33
|
+
# selection=[x,y,w,h]
|
34
|
+
w,h=1,1 if w<=0 or h<=0
|
35
|
+
w,h = w*scale.to_f, h*scale.to_f
|
36
|
+
|
37
|
+
radius = 0
|
38
|
+
|
39
|
+
rotate = rotate*180/Math::PI if String===rotate
|
40
|
+
rotate %= 360
|
41
|
+
|
42
|
+
unless rotate.zero?
|
43
|
+
radius = rotate / 180.0 * Math::PI
|
44
|
+
if (90 < rotate and rotate < 180) or (270 < rotate and rotate < 360)
|
45
|
+
radius -= Math::PI / 2
|
46
|
+
end
|
47
|
+
end
|
48
|
+
inner_angle1 = Math.atan(w/h)
|
49
|
+
inner_angle2 = Math.atan(h/w)
|
50
|
+
diagonal = Math.sqrt(w**2 + h**2)
|
51
|
+
|
52
|
+
angle1 = radius + inner_angle1
|
53
|
+
angle2 = radius + inner_angle2
|
54
|
+
|
55
|
+
bottom1 = diagonal * Math.cos(angle1)
|
56
|
+
length1 = (bottom1 * Math.tan(angle1)).abs.to_up
|
57
|
+
bottom2 = diagonal * Math.cos(angle2)
|
58
|
+
length2 = (bottom2 * Math.tan(angle2)).abs.to_up
|
59
|
+
|
60
|
+
if (0 <= rotate and rotate <= 90) or (180 <= rotate and rotate <= 270)
|
61
|
+
[length1, length2]
|
62
|
+
else
|
63
|
+
[length2, length1]
|
64
|
+
end
|
65
|
+
end # def self.compute_wh
|
66
|
+
end
|
67
|
+
|
68
|
+
module Cairo
|
69
|
+
# class FontExtents and TextExtents
|
70
|
+
class FontExtents
|
71
|
+
|
72
|
+
# @return [Array] \[ascent, descent, height, max_x_advance, max_y_advance\]
|
73
|
+
def to_a
|
74
|
+
[ascent,descent,height,max_x_advance,max_y_advance]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# === Additional Method List
|
79
|
+
# * #w: _alias from width_
|
80
|
+
# * #h: _alias from h_
|
81
|
+
class TextExtents
|
82
|
+
alias w width
|
83
|
+
alias h height
|
84
|
+
|
85
|
+
# @return [Array] \[width, height]
|
86
|
+
def wh; [width, height] end
|
87
|
+
|
88
|
+
# @return [Array] \[x_advance, y_advance]
|
89
|
+
def xy_advance; [x_advance, y_advance] end
|
90
|
+
|
91
|
+
# @return [Array] \[x_bearing, y_bearing]
|
92
|
+
def xy_bearing; [x_bearing, y_bearing] end
|
93
|
+
|
94
|
+
# @return [Array] \[x_bearing, y_bearing, width, height, x_advance, y_advance\]
|
95
|
+
def to_a
|
96
|
+
[x_bearing, y_bearing, width, height, x_advance, y_advance]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class PDFSurface
|
101
|
+
alias initialize_ initialize
|
102
|
+
def initialize(filename, width, height)
|
103
|
+
initialize_(filename, width, height)
|
104
|
+
@wh=[width.to_f, height.to_f]
|
105
|
+
end
|
106
|
+
|
107
|
+
# get width, height
|
108
|
+
def wh; @wh end
|
109
|
+
# get width
|
110
|
+
def w; @wh[0] end
|
111
|
+
# get height
|
112
|
+
def h; @wh[1] end
|
113
|
+
end # class PDFSurface
|
114
|
+
|
115
|
+
class ImageSurface
|
116
|
+
alias initialize_ initialize
|
117
|
+
|
118
|
+
# get width, height
|
119
|
+
def wh; [width.to_f, height.to_f] end
|
120
|
+
# get width
|
121
|
+
def w; self.wh[0] end
|
122
|
+
# get height
|
123
|
+
def h; self.wh[1] end
|
124
|
+
|
125
|
+
end # class ImageSurface
|
126
|
+
|
127
|
+
class Context
|
128
|
+
private
|
129
|
+
# utils
|
130
|
+
def __rpos(*args)
|
131
|
+
# 10 user_relative_distance
|
132
|
+
# "10" device_relative_distance
|
133
|
+
x_,y_ = xy
|
134
|
+
args.split(2,[]) do |(x,y),i,memo|
|
135
|
+
x = String===x ? tdu(x.to_f) : x
|
136
|
+
y = String===y ? tdu(nil, y.to_f) : y
|
137
|
+
memo.push(x+x_, y+y_)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
def __tpos(*args)
|
141
|
+
# 7 device_relative_distance
|
142
|
+
x_, y_ = xy
|
143
|
+
args.split(2, []) do |(x,y), i, memo|
|
144
|
+
x,y = tdu(x, y)
|
145
|
+
memo.push(x+x_, y+y_)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def __dpos(*args)
|
150
|
+
# 10 device_pos
|
151
|
+
# "10" device_relative_distance
|
152
|
+
x_,y_ = xy
|
153
|
+
args.split(2, []) do |(x,y),i,memo|
|
154
|
+
x = String===x ? tdu(x.to_f)+x_ : du(x)
|
155
|
+
y = String===y ? tdu(nil,y.to_f)+y_ : du(nil,y)
|
156
|
+
memo.push(x,y)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def __pos(*args)
|
161
|
+
# 7 user_pos
|
162
|
+
# "7" user_relative_distance
|
163
|
+
# :d7 device_pos
|
164
|
+
# :r7 device_relative_distance
|
165
|
+
x_,y_ = xy
|
166
|
+
args.split(2, []) do |(x,y),i,memo|
|
167
|
+
x = case x
|
168
|
+
when /^d/
|
169
|
+
du(x[1..-1].to_f)
|
170
|
+
when /^r/
|
171
|
+
tdu(x[1..-1].to_f) + x_
|
172
|
+
when String
|
173
|
+
x.to_f + x_
|
174
|
+
else
|
175
|
+
x
|
176
|
+
end
|
177
|
+
|
178
|
+
#p x,y,y_
|
179
|
+
y = case y
|
180
|
+
when /^d/
|
181
|
+
du(nil, y[1..-1].to_f)
|
182
|
+
when /^r/
|
183
|
+
tdu(nil, y[1..-1].to_f) + y_
|
184
|
+
when String
|
185
|
+
y.to_f + y_
|
186
|
+
else
|
187
|
+
y
|
188
|
+
end
|
189
|
+
|
190
|
+
memo.push(x,y)
|
191
|
+
end
|
192
|
+
end # def __pos
|
193
|
+
|
194
|
+
def __angle(*args)
|
195
|
+
rst = args.split(2, []) do |(a1,a2),i,memo|
|
196
|
+
a1 = a1.to_f*Math::PI/180.0 unless String === a1
|
197
|
+
a2 = a2.to_f*Math::PI/180.0 unless String === a2
|
198
|
+
memo.push(a1,a2)
|
199
|
+
end
|
200
|
+
|
201
|
+
rst.gach!(&:to_f)
|
202
|
+
args.size==1 ? rst[0] : rst
|
203
|
+
end
|
204
|
+
|
205
|
+
def __du(x,y)
|
206
|
+
# 7
|
207
|
+
# "7" device_to_user
|
208
|
+
x = device_to_user(x.to_f,1)[0] if String === x
|
209
|
+
y = device_to_user(1,y.to_f)[1] if String === y
|
210
|
+
[x,y]
|
211
|
+
end
|
212
|
+
|
213
|
+
def __tdu(tx,ty)
|
214
|
+
# 7
|
215
|
+
# "7" device_to_user_distance
|
216
|
+
tx = device_to_user_distance(tx.to_f,1)[0] if String === tx
|
217
|
+
ty = device_to_user_distance(1,ty.to_f)[1] if String === ty
|
218
|
+
[tx,ty]
|
219
|
+
end
|
220
|
+
|
221
|
+
public
|
222
|
+
alias initialize_ initialize
|
223
|
+
def initialize(surface)
|
224
|
+
initialize_(surface)
|
225
|
+
move_to(0,0)
|
226
|
+
|
227
|
+
self.dsize = 13
|
228
|
+
self.dborder = 1
|
229
|
+
|
230
|
+
@line_cap =line_cap_
|
231
|
+
@line_join =line_join_
|
232
|
+
@line_dash =line_dash_
|
233
|
+
@font_matrix =font_matrix_
|
234
|
+
@font_options =font_options_
|
235
|
+
@font_face =font_face_
|
236
|
+
@operator =operator_
|
237
|
+
@antialias =antialias_
|
238
|
+
end # def initialize
|
239
|
+
|
240
|
+
attr_reader :size, :dsize, :border, :line_cap, :line_join, :line_dash,
|
241
|
+
:font_matrix, :font_options, :font_face, :operator, :antialias
|
242
|
+
|
243
|
+
alias showglyphs show_glyphs
|
244
|
+
alias line_cap_ line_cap
|
245
|
+
alias line_join_ line_join
|
246
|
+
alias line_dash_ dash
|
247
|
+
alias font_matrix_ font_matrix
|
248
|
+
alias font_options_ font_options
|
249
|
+
alias font_face_ font_face
|
250
|
+
alias operator_ operator
|
251
|
+
alias antialias_ antialias
|
252
|
+
alias showpage show_page
|
253
|
+
alias copypage copy_page
|
254
|
+
alias surface target
|
255
|
+
|
256
|
+
alias textpath text_path
|
257
|
+
alias glyphpath glyph_path
|
258
|
+
|
259
|
+
def font_face family, slant=:normal, weight=:normal
|
260
|
+
slant = Cairo.const_get("font_slant_#{slant}".upcase)
|
261
|
+
weight = Cairo.const_get("font_weight_#{weight}".upcase)
|
262
|
+
select_font_face family, slant, weight
|
263
|
+
end
|
264
|
+
|
265
|
+
alias size_= font_size=
|
266
|
+
def size=(size)
|
267
|
+
if String === size
|
268
|
+
self.dsize = size.to_f
|
269
|
+
else
|
270
|
+
@dsize = ud(size)
|
271
|
+
@size = size
|
272
|
+
self.font_size = @size
|
273
|
+
end
|
274
|
+
end
|
275
|
+
def dsize=(size)
|
276
|
+
@dsize = size
|
277
|
+
@size = tdu(size)
|
278
|
+
self.font_size = @size
|
279
|
+
end
|
280
|
+
|
281
|
+
def font_matrix=(matrix)
|
282
|
+
@font_matrix=matrix
|
283
|
+
set_font_matrix(@font_matrix)
|
284
|
+
@font_matrix
|
285
|
+
end
|
286
|
+
|
287
|
+
def font_options=(options)
|
288
|
+
set_font_options( @font_options=options )
|
289
|
+
@font_options
|
290
|
+
end
|
291
|
+
|
292
|
+
def font_face=(face)
|
293
|
+
set_font_face( @font_face=face )
|
294
|
+
@font_face
|
295
|
+
end
|
296
|
+
|
297
|
+
def text_scale_min
|
298
|
+
min = tud(1,1).min
|
299
|
+
bak(:scale) do
|
300
|
+
dscale min, min
|
301
|
+
yield
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def showtext(text, newline=false)
|
306
|
+
text_scale_min do
|
307
|
+
ascent, descent = font_extents.to_a
|
308
|
+
mvxy('0', ascent.to_s)
|
309
|
+
show_text(text.to_s)
|
310
|
+
mvxy('0', (-ascent).to_s)
|
311
|
+
mvxy(0, (ascent+descent).to_s) if newline
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def newline_height
|
316
|
+
out = nil; prev=nil
|
317
|
+
text_scale_min do
|
318
|
+
ascent, descent = font_extents.to_a
|
319
|
+
out = ascent+descent
|
320
|
+
prev = tud(nil, 1)
|
321
|
+
end
|
322
|
+
|
323
|
+
cur = tud(nil, 1)
|
324
|
+
out = prev/cur*out
|
325
|
+
out
|
326
|
+
end
|
327
|
+
|
328
|
+
def newline
|
329
|
+
mvxy(0, newline_height.to_s)
|
330
|
+
end
|
331
|
+
|
332
|
+
def sep(width, border="1")
|
333
|
+
mvxy(0, "0")
|
334
|
+
line("0","0", width, "0")
|
335
|
+
bak(:border) do
|
336
|
+
self.border = border
|
337
|
+
stroke
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
def centertext(text)
|
342
|
+
advanced_x = nil
|
343
|
+
advanced_x = text_extents(text.to_s).to_a[-2]
|
344
|
+
mvxy( ((1-advanced_x)/2.0).to_s , '0')
|
345
|
+
showtext(text, true)
|
346
|
+
end
|
347
|
+
|
348
|
+
def instroke?(x,y); in_stroke?(x,y) end
|
349
|
+
def infill?(x,y); in_fill?(x,y) end
|
350
|
+
|
351
|
+
alias set_source_ set_source
|
352
|
+
def set_source(source)
|
353
|
+
# [r,g,b,a=1.0] Pattern Surface
|
354
|
+
# "#rgb[a]", "name" (set_source_color)
|
355
|
+
# Pixbuf (set_source_pixbuf)
|
356
|
+
case
|
357
|
+
when String===source
|
358
|
+
set_source_color(source)
|
359
|
+
when Array===source, source.kind_of?(Pattern), source.kind_of?(Surface)
|
360
|
+
set_source_(source)
|
361
|
+
else
|
362
|
+
set_source_pixbuf(*args)
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
def operator=(operator)
|
367
|
+
@operator = Cairo.const_get("operator_#{operator}".upcase)
|
368
|
+
set_operator(@operator)
|
369
|
+
@operator
|
370
|
+
end
|
371
|
+
|
372
|
+
def antialias=(antialias)
|
373
|
+
@antialias = Cairo.const_get("antianias_#{antialias}".upcase)
|
374
|
+
set_antialias(@antialias)
|
375
|
+
@antialias
|
376
|
+
end
|
377
|
+
|
378
|
+
alias fill_ fill
|
379
|
+
def fill(keep=true)
|
380
|
+
if keep
|
381
|
+
xy = current_point
|
382
|
+
fill_()
|
383
|
+
move_to(*xy)
|
384
|
+
else
|
385
|
+
fill_()
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
def mask(*args)
|
390
|
+
if args[0].class == Pattern
|
391
|
+
mask(args[0])
|
392
|
+
elsif args[0].class == Surface
|
393
|
+
mask_surface(*args)
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
alias push_group_ push_group
|
398
|
+
def push_group(context=false)
|
399
|
+
if context
|
400
|
+
push_group_widht_context(context)
|
401
|
+
else
|
402
|
+
push_group_
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
alias pop_group_ pop_group
|
407
|
+
def pop_group(to_source=false)
|
408
|
+
group = pop_group_
|
409
|
+
set_source(group) if to_source
|
410
|
+
group
|
411
|
+
end
|
412
|
+
|
413
|
+
#alias xy_ move_to
|
414
|
+
#def xy_(*xy) xy.empty? ? current_point : move_to(*xy) end
|
415
|
+
def mvxy(*xy) xy.empty? ? current_point : move_to(*__pos(*xy)) end
|
416
|
+
def dmvxy(*xy) xy.empty? ? ud(*current_point) : move_to(*__dpos(*xy)) end
|
417
|
+
def rmvxy(x,y) move_to(*__rpos(x,y)) end
|
418
|
+
def rdmvxy(x,y) move_to(*__tpos(x,y)) end
|
419
|
+
|
420
|
+
#def dpos; ud(*pos) end
|
421
|
+
|
422
|
+
def mvx(x=nil); x ? mvxy(x, "0") : current_point[0] end
|
423
|
+
def dmvx(x=nil); x ? dmvxy(x, "0") : ud(*current_point)[0] end
|
424
|
+
def rmvx x; rmvxy(x, 0) end
|
425
|
+
def rdmvx x; rdmvxy(x, 0) end
|
426
|
+
|
427
|
+
def mvy(y=nil) y ? mvxy("0", y ) : current_point[1] end
|
428
|
+
def dmvy(y=nil) y ? dmvxy("0", y) : ud(*current_point)[1] end
|
429
|
+
def rmvy y; rmvxy(0, y) end
|
430
|
+
def rmvdy y; rdmvxy(0, y) end
|
431
|
+
|
432
|
+
alias lineto_ line_to
|
433
|
+
def lineto(x,y) line_to(*__pos(x,y) ) end
|
434
|
+
def rlineto(x,y) line_to(*__rpos(x,y)) end
|
435
|
+
def lineno(x,y) bak(:xy){lineto(x,y)} end
|
436
|
+
def rlineno(x,y) bak(:xy){rlineto(x,y)} end
|
437
|
+
def line(x,y, x1,y1) bak(:xy){mvxy(x,y); lineto(x1,y1) } end
|
438
|
+
def rline(x,y, x1,y1) bak(:xy){rmvxy(x,y); rlineto(x1,y1)} end
|
439
|
+
|
440
|
+
def circle(x,y,r); arc(x,y,r,0,360) end
|
441
|
+
alias arc_ arc
|
442
|
+
def arc(x,y,r, a1,a2)
|
443
|
+
x,y=__pos(x,y)
|
444
|
+
a1,a2=__angle(a1,a2)
|
445
|
+
new_path # need new_path to clear prior-path
|
446
|
+
arc_(x,y,r,a1,a2)
|
447
|
+
end
|
448
|
+
|
449
|
+
alias arc_neg_ arc_negative
|
450
|
+
def arg_neg(x,y,r, a1,a2)
|
451
|
+
x,y=__pos(x,y)
|
452
|
+
a1,a2=__angle(a1,a2)
|
453
|
+
new_path
|
454
|
+
arc_negative(x,y,r, a1,a2)
|
455
|
+
end
|
456
|
+
|
457
|
+
|
458
|
+
alias curveto_ curve_to
|
459
|
+
def curveto(x1,y1, x2,y2, x3,y3)
|
460
|
+
x1,y1,x2,y2,x3,y3=__pos(x1,y1,x2,y2,x3,y3)
|
461
|
+
curve_to(x1,y1, x2,y2, x3,y3)
|
462
|
+
end
|
463
|
+
alias rcurveto_ rel_curve_to
|
464
|
+
alias rcurveto rel_curve_to
|
465
|
+
|
466
|
+
alias new_subpath new_sub_path
|
467
|
+
alias copy_path_ copy_path
|
468
|
+
def copy_path(flat=false) flat ? copy_path_flat : copy_path_ end
|
469
|
+
|
470
|
+
alias stroke_ stroke
|
471
|
+
def stroke(preverse=false, &blk)
|
472
|
+
bak(:xy) {
|
473
|
+
stroke_(preverse, &blk)
|
474
|
+
}
|
475
|
+
end
|
476
|
+
|
477
|
+
# border line_cap _join _dash
|
478
|
+
alias border_= line_width=
|
479
|
+
def border=(border)
|
480
|
+
if String === border
|
481
|
+
self.dborder = border.to_f
|
482
|
+
else
|
483
|
+
@dborder = ud(border)
|
484
|
+
@border = border
|
485
|
+
self.line_width = @border
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
def dborder=(border)
|
490
|
+
@dborder = border
|
491
|
+
@border = tdu(border)
|
492
|
+
self.line_width = @border
|
493
|
+
end
|
494
|
+
|
495
|
+
def line_cap=(cap)
|
496
|
+
@line_cap = Cairo.const_get("line_cap_#{cap}".upcase)
|
497
|
+
set_line_cap(@line_cap)
|
498
|
+
@line_cap
|
499
|
+
end
|
500
|
+
|
501
|
+
def line_join=(join)
|
502
|
+
@line_join = Cairo.const_get("line_join_#{join}".upcase)
|
503
|
+
set_line_join(@line_join)
|
504
|
+
@line_join
|
505
|
+
end
|
506
|
+
|
507
|
+
def line_dash=(arg, offset=0)
|
508
|
+
@line_dash ||=arg
|
509
|
+
set_line_dash(arg, offset)
|
510
|
+
@line_dash
|
511
|
+
end
|
512
|
+
|
513
|
+
def has_pos?; has_current_point? ? true : false end
|
514
|
+
|
515
|
+
# push pos
|
516
|
+
def push
|
517
|
+
@xy_stack ||=[]
|
518
|
+
@xy_stack.push(current_point)
|
519
|
+
end
|
520
|
+
def pop
|
521
|
+
@xy_stack.pop
|
522
|
+
end
|
523
|
+
|
524
|
+
|
525
|
+
alias rotate_ rotate
|
526
|
+
def rotate(angle); rotate_(__angle(angle)) end
|
527
|
+
|
528
|
+
alias scale_ scale
|
529
|
+
# args@ tx,ty,keep=true
|
530
|
+
# keep size border
|
531
|
+
def scale(*args)
|
532
|
+
if args.empty?
|
533
|
+
tdu 1,1
|
534
|
+
else
|
535
|
+
tx, ty, keep = args
|
536
|
+
keep ||= true
|
537
|
+
tx,ty = __tdu(tx,ty)
|
538
|
+
scale_(tx,ty)
|
539
|
+
if keep
|
540
|
+
self.dsize=@dsize
|
541
|
+
self.dborder=@dborder
|
542
|
+
end
|
543
|
+
end
|
544
|
+
end
|
545
|
+
def dscale tx=1,ty=1, keep=true; scale tx.to_s, ty.to_s, keep end
|
546
|
+
|
547
|
+
alias translate_ translate
|
548
|
+
def translate(*txy)
|
549
|
+
if txy.empty?
|
550
|
+
ud 0,0
|
551
|
+
else
|
552
|
+
txy_ = xy
|
553
|
+
translate_(*__du(*txy))
|
554
|
+
mvxy(*txy_)
|
555
|
+
end
|
556
|
+
end
|
557
|
+
|
558
|
+
def btranslate tx=0,ty=0; translate tx.to_s, ty.to_s end
|
559
|
+
|
560
|
+
# ud tud du tdu
|
561
|
+
alias ud_ user_to_device
|
562
|
+
alias tud_ user_to_device_distance
|
563
|
+
# user_to_device
|
564
|
+
# (x,nil) (nil,y) (x,y)
|
565
|
+
def ud(x,y=nil)
|
566
|
+
if y==nil
|
567
|
+
user_to_device(x,0)[0]
|
568
|
+
elsif x==nil
|
569
|
+
user_to_device(0,y)[1]
|
570
|
+
else
|
571
|
+
user_to_device(x,y)
|
572
|
+
end
|
573
|
+
end
|
574
|
+
|
575
|
+
# user_to_device_sitance
|
576
|
+
# (x,nil) (nil,y) (x,y)
|
577
|
+
def tud(x,y=nil)
|
578
|
+
if y==nil
|
579
|
+
user_to_device_distance(x, 0)[0]
|
580
|
+
elsif x==nil
|
581
|
+
user_to_device_distance(0, y)[1]
|
582
|
+
else
|
583
|
+
user_to_device_distance(x,y)
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
587
|
+
alias du_ device_to_user
|
588
|
+
alias tdu_ device_to_user_distance
|
589
|
+
# device to user
|
590
|
+
# (x,nil) (nil,y) (x,y)
|
591
|
+
def du(x,y=nil)
|
592
|
+
if y==nil
|
593
|
+
device_to_user(x,0)[0]
|
594
|
+
elsif x==nil
|
595
|
+
device_to_user(0,y)[1]
|
596
|
+
else
|
597
|
+
device_to_user(x,y)
|
598
|
+
end
|
599
|
+
end
|
600
|
+
|
601
|
+
# device to user distance
|
602
|
+
# (x,nil) (nil,y) (x,y)
|
603
|
+
def tdu(x,y=nil)
|
604
|
+
if y==nil
|
605
|
+
device_to_user_distance(x, 0)[0]
|
606
|
+
elsif x==nil
|
607
|
+
device_to_user_distance(0, y)[1]
|
608
|
+
else
|
609
|
+
device_to_user_distance(x,y)
|
610
|
+
end
|
611
|
+
end
|
612
|
+
|
613
|
+
# options: xy x y translate scale matrix
|
614
|
+
# state size
|
615
|
+
def bak(name, *args)
|
616
|
+
case name.to_sym
|
617
|
+
# :xy x y
|
618
|
+
when :xy
|
619
|
+
x_, y_ = user_to_device(*current_point)
|
620
|
+
yield
|
621
|
+
move_to( *device_to_user(x_, y_))
|
622
|
+
when :x
|
623
|
+
x_, y_ = user_to_device(*current_point)
|
624
|
+
yield
|
625
|
+
x = device_to_user(x_, y_)[0]
|
626
|
+
y = current_point[1]
|
627
|
+
move_to(x,y)
|
628
|
+
when :y
|
629
|
+
x_, y_ = user_to_device(*current_point)
|
630
|
+
yield
|
631
|
+
x = current_point[0]
|
632
|
+
y = device_to_user(x_, y_)[1]
|
633
|
+
move_to(x,y)
|
634
|
+
|
635
|
+
# :translate scale matrix
|
636
|
+
when :translate
|
637
|
+
xy_d = ud(0,0)
|
638
|
+
yield
|
639
|
+
a = xy_d.gach(&:to_s)
|
640
|
+
translate(*a)
|
641
|
+
when :scale
|
642
|
+
txy_d = tud(1,1)
|
643
|
+
yield
|
644
|
+
scale(*txy_d.gach(&:to_s))
|
645
|
+
when :matrix # combine translate and scale
|
646
|
+
xy_d = ud(0,0)
|
647
|
+
txy_d = tud(1,1)
|
648
|
+
yield
|
649
|
+
scale(*txy_d.gach(&:to_s))
|
650
|
+
translate(*xy_d.gach(&:to_s))
|
651
|
+
|
652
|
+
# state
|
653
|
+
when :state
|
654
|
+
save
|
655
|
+
yield
|
656
|
+
restore
|
657
|
+
|
658
|
+
# size
|
659
|
+
when :size
|
660
|
+
size_ = @dsize
|
661
|
+
yield
|
662
|
+
self.dsize = size_
|
663
|
+
when :border
|
664
|
+
border_ = @dborder
|
665
|
+
yield
|
666
|
+
self.dborder = border_
|
667
|
+
|
668
|
+
# all: save xy size
|
669
|
+
when :all
|
670
|
+
x_, y_ = user_to_device(*current_point)
|
671
|
+
size_ = @dsize
|
672
|
+
save
|
673
|
+
yield
|
674
|
+
restore
|
675
|
+
move_to( *device_to_user(x_, y_))
|
676
|
+
self.dsize = size_
|
677
|
+
else
|
678
|
+
raise ArgumentError, "bak(:#{name})"
|
679
|
+
end
|
680
|
+
end # def bak
|
681
|
+
# selection=[x|y=nil, w|h=nil]
|
682
|
+
def paint_img(img, selection=nil, rotate=0, scale=1)
|
683
|
+
# handle arg selection
|
684
|
+
selection ||= []
|
685
|
+
select_x,select_y,select_w,select_h = selection
|
686
|
+
select_x ||= 0; select_y ||= 0
|
687
|
+
select_w ||= img.w-select_x; select_h ||= img.h-select_y
|
688
|
+
select_w,select_h=1,1 if select_w<=0 or select_h<=0
|
689
|
+
|
690
|
+
select_w,select_h = select_w*scale.to_f, select_h*scale.to_f
|
691
|
+
select_x,select_y = select_x*scale.to_f, select_y*scale.to_f
|
692
|
+
|
693
|
+
bak(:state) do
|
694
|
+
|
695
|
+
# rotate
|
696
|
+
translate(surface.w/2, surface.h/2)
|
697
|
+
rotate(rotate)
|
698
|
+
translate(-select_w/2, -select_h/2)
|
699
|
+
|
700
|
+
# selection [x,y,w,h]
|
701
|
+
rectangle(0,0,select_w,select_h)
|
702
|
+
clip
|
703
|
+
translate(-select_x,-select_y)
|
704
|
+
|
705
|
+
# scale
|
706
|
+
scale(scale, scale)
|
707
|
+
|
708
|
+
# paint
|
709
|
+
set_source(img)
|
710
|
+
paint
|
711
|
+
end
|
712
|
+
end # def paint_img
|
713
|
+
|
714
|
+
# base on scale(*wh)
|
715
|
+
# datas: \[ \[..\], \]
|
716
|
+
def table(datas, oph={})
|
717
|
+
|
718
|
+
# width height
|
719
|
+
# row_nrs col_nrs
|
720
|
+
cols = oph[:pos]
|
721
|
+
spacing = oph[:spacing] || [4,1]
|
722
|
+
spacing = tdu(*spacing)
|
723
|
+
|
724
|
+
# ==>datas row_nrs and col_nrs
|
725
|
+
datas = [datas] if not Array===datas[0]
|
726
|
+
row_nrs = datas.size
|
727
|
+
col_nrs = datas[0].size
|
728
|
+
|
729
|
+
# ==> cell_height 0.05 height
|
730
|
+
cell_height = newline_height + spacing[1]*2
|
731
|
+
height = cell_height * datas.size
|
732
|
+
|
733
|
+
## ==>cols [0, 0.5, 1.0]
|
734
|
+
# cell_widths [text_extents..]
|
735
|
+
if oph[:pos] == "<" || oph[:pos] == ">"
|
736
|
+
cell_widths = [0]
|
737
|
+
cell_widths += datas.transpose.gach do |cols|
|
738
|
+
cols.gach{|v| text_extents(v.to_s).to_a[-2]}.max
|
739
|
+
end
|
740
|
+
end
|
741
|
+
|
742
|
+
case oph[:pos]
|
743
|
+
when "<"
|
744
|
+
if oph[:border]
|
745
|
+
pos = cell_widths[0]+spacing[0]*2
|
746
|
+
cols = [0, pos, pos+cell_widths[1]+spacing[0] ]
|
747
|
+
else
|
748
|
+
pos = cell_widths[0]+spacing[0]
|
749
|
+
cols = [0, pos, pos+cell_widths[1]+spacing[0] ]
|
750
|
+
end
|
751
|
+
when ">"
|
752
|
+
if oph[:border]
|
753
|
+
pos = 1-(cell_widths[0]+cell_widths[1]+spacing[0]*4)
|
754
|
+
cols = [ pos, pos+cell_widths[0]+spacing[0]*2, 1 ]
|
755
|
+
else
|
756
|
+
pos = 1-(cell_widths[0]+cell_widths[1]+spacing[0]*3)
|
757
|
+
cols = [ pos, pos+cell_widths[0]+spacing[0], 1 ]
|
758
|
+
end
|
759
|
+
else
|
760
|
+
cols ||= (0..col_nrs).map{|v| v/col_nrs.to_f}
|
761
|
+
end
|
762
|
+
width = cols[-1]
|
763
|
+
|
764
|
+
|
765
|
+
# draw border
|
766
|
+
if oph[:border]
|
767
|
+
rectangle cols[0], "0", cols[-1], height
|
768
|
+
|
769
|
+
# draw rows
|
770
|
+
bak(:xy) {
|
771
|
+
row_nrs.each do
|
772
|
+
ry cell_height; rlineno cols[-1], 0
|
773
|
+
end
|
774
|
+
}
|
775
|
+
|
776
|
+
# draw cols
|
777
|
+
bak(:xy) {
|
778
|
+
cols.gach do |v|
|
779
|
+
x v; rlineno 0, height
|
780
|
+
end
|
781
|
+
}
|
782
|
+
|
783
|
+
stroke
|
784
|
+
end
|
785
|
+
|
786
|
+
# draw text
|
787
|
+
datas.gach do |rows|
|
788
|
+
bak(:xy) {
|
789
|
+
rxy 0, spacing[1]
|
790
|
+
rows.gach do |row, i|
|
791
|
+
xy cols[i], "0"
|
792
|
+
rx spacing[0]
|
793
|
+
showtext row
|
794
|
+
end
|
795
|
+
}
|
796
|
+
ry cell_height
|
797
|
+
end
|
798
|
+
|
799
|
+
[width, height]
|
800
|
+
end # def table
|
801
|
+
|
802
|
+
# rectangle with rounded support
|
803
|
+
alias rectangle_ rectangle
|
804
|
+
def rectangle(x,y,w,h) rectangle_(*__pos(x,y), *__du(w,h) ) end
|
805
|
+
def rrectangle(x,y,w,h) rectangle_(*__rpos(x,y), *__du(w,h) ) end
|
806
|
+
|
807
|
+
end # class Context
|
808
|
+
|
809
|
+
end # module Cairo
|