tagen 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.gitignore +2 -0
  2. data/.yardopts +5 -0
  3. data/Gemfile +7 -0
  4. data/Gemfile.lock +24 -0
  5. data/README.md +60 -0
  6. data/Rakefile +9 -0
  7. data/docs/Architecture.md +17 -0
  8. data/docs/CoreExtensions.md +56 -0
  9. data/docs/ExtraExtensions.md +20 -0
  10. data/lib/tagen/audioinfo.rb +21 -0
  11. data/lib/tagen/cairo.rb +809 -0
  12. data/lib/tagen/core.rb +34 -0
  13. data/lib/tagen/core/array.rb +41 -0
  14. data/lib/tagen/core/array/extract_options.rb +40 -0
  15. data/lib/tagen/core/hash.rb +17 -0
  16. data/lib/tagen/core/io.rb +29 -0
  17. data/lib/tagen/core/kernel.rb +73 -0
  18. data/lib/tagen/core/marshal.rb +34 -0
  19. data/lib/tagen/core/module.rb +25 -0
  20. data/lib/tagen/core/numeric.rb +10 -0
  21. data/lib/tagen/core/object.rb +21 -0
  22. data/lib/tagen/core/pa.rb +187 -0
  23. data/lib/tagen/core/pa/cmd.rb +374 -0
  24. data/lib/tagen/core/pa/dir.rb +144 -0
  25. data/lib/tagen/core/pa/path.rb +190 -0
  26. data/lib/tagen/core/pa/state.rb +56 -0
  27. data/lib/tagen/core/process.rb +11 -0
  28. data/lib/tagen/core/re.rb +8 -0
  29. data/lib/tagen/core/string.rb +43 -0
  30. data/lib/tagen/core/string/pyformat.rb +322 -0
  31. data/lib/tagen/core/time.rb +8 -0
  32. data/lib/tagen/gdk_pixbuf2.rb +26 -0
  33. data/lib/tagen/gtk2.rb +122 -0
  34. data/lib/tagen/magick.rb +23 -0
  35. data/lib/tagen/ncurses.rb +245 -0
  36. data/lib/tagen/net/http.rb +34 -0
  37. data/lib/tagen/pathname.rb +8 -0
  38. data/lib/tagen/poppler.rb +47 -0
  39. data/lib/tagen/socket.rb +20 -0
  40. data/lib/tagen/tree.rb +75 -0
  41. data/lib/tagen/vim.rb +19 -0
  42. data/lib/tagen/xmpp4r.rb +1 -0
  43. data/lib/tagen/xmpp4r/roster.rb +20 -0
  44. data/spec/cairo_spec.rb +137 -0
  45. data/spec/core/pa/cmd_spec.rb +251 -0
  46. data/spec/core/pa/dir_spec.rb +59 -0
  47. data/spec/core/string/pyformat_spec.rb +86 -0
  48. data/spec/spec_helper.rb +0 -0
  49. data/tagen.gemspec +20 -0
  50. data/version.rb +7 -0
  51. metadata +117 -0
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *~
2
+ /.yardoc
data/.yardopts ADDED
@@ -0,0 +1,5 @@
1
+ --markup markdown
2
+
3
+ -
4
+ docs/**/*.md
5
+
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source :rubygems
2
+
3
+ group :development do
4
+ gem "rspec"
5
+ end
6
+
7
+ gemspec
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,9 @@
1
+ desc "build a gem file"
2
+ task :build do
3
+ `gem build tagen.gemspec`
4
+ end
5
+
6
+ desc "testing the library"
7
+ task :test do
8
+ `rspec spec/`
9
+ end
@@ -0,0 +1,17 @@
1
+ Architecture
2
+ ============
3
+
4
+ **source file layout**:
5
+
6
+ lib/tagen/
7
+ core.rb
8
+ core/
9
+ array/extract_options.rb
10
+ ...
11
+ pathname.rb # extra lib
12
+ ...
13
+
14
+
15
+
16
+
17
+
@@ -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
@@ -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