add kage.rb, kageserver.rb, csf.rb, stroke.rb
[chise/ruby.git] / src / stroke.rb
1 #!/usr/bin/env ruby
2 # StrokeFont library by eto 2003-0311
3
4 require 'sgl'
5 require 'kage'
6 require 'csf'
7
8 module StrokeFont
9   class StrokesRenderer #======================================================================
10     def initialize
11       @start_time = nil
12       @strokes = nil
13       @hsv = [0, 0, 100]
14       init
15     end
16     attr_accessor :hsv
17     def init() @start_time = Time.now; end
18     def set_strokes(strokes)
19       @strokes = strokes
20       init
21     end
22     def draw
23       @strokes.strokes.each_with_index {|stroke, index|
24         draw_delay(stroke, index)
25       }
26     end
27     def draw_alpha(stroke, time)
28       px, py = 0, 0
29       span = 0.1
30       time += span*2
31       stroke.points.each {|x, y|
32         a = time / span
33         colorHSV(@hsv[0], @hsv[1], @hsv[2], a*100.0)
34         line(px, py, x, y) if (px != 0 || py != 0) #最初の点ではない
35         px, py = x, y
36         time -= span
37       }
38     end
39     def draw_delay(stroke, index)
40       now = Time.now
41       @start_time = Time.now if @start_time == nil
42       diff = now - @start_time #開始からの秒数がはいる
43       draw_alpha(stroke, diff - index*0.3)
44     end
45   end
46
47   class Stroke #====================================================================== 一本の線
48     def initialize
49       @points = []
50       @length = nil
51     end
52     attr_reader :points
53     def add_point(x, y)
54       @points << [x, y]
55     end
56     def length #未チェック
57       return @length if @length
58       len = 0.0
59       px, py = -1, -1
60       @points.each {|x, y|
61         if px != -1
62           len += Math.sqrt((x-px)*(x-px)+(y-py)*(y-py))
63         end
64         px, py = x, y
65       }
66       @length = len
67       return @length
68     end
69   end
70
71   class Strokes #====================================================================== 複数の線
72     def initialize
73       @strokes = []
74       @px1, @py1, @px2, @py2 = 0, 0, 0, 0
75       @x1, @y1, @x2, @y2 = 0, 0, 0, 0
76       @px, @py = -1, -1
77     end
78     attr_reader :strokes
79     def add_line(x1, y1, x2, y2)
80       if (@px != x1 || @py != y1) #以前の点とつながっていなかったら、
81         @strokes << Stroke.new
82         @strokes.last.add_point(x1, y1)
83       end
84       @strokes.last.add_point(x2, y2)
85       @px, @py = x2, y2
86     end
87   end
88
89   class CodeSelector #======================================================================
90     WIDTH, HEIGHT = 256, 256
91     SCALE = 2
92     def initialize(cx=0, cy=0)
93       @cx, @cy = cx, cy
94       @s = SCALE
95       @x1, @y1 = @cx-@s*WIDTH/2, @cy-@s*HEIGHT/2
96       @x2, @y2 = @cx+@s*WIDTH/2, @cy+@s*HEIGHT/2
97       @px, @py = @cx, @cy #とりあえず中心が開始点
98       @pw, @ph, @pr = 30, 30, 10
99       @dragging = false
100       @onkeydown = false
101       @code = 0
102       calc_code
103     end
104     attr_reader :code
105     def draw
106       colorHSV(0, 0, 100, 10) #まずは下敷きになる枠を書きます。
107       rect(@x1, @y1, @x2, @y2)
108       lineWidth(1)
109       colorHSV(0, 0, 100, 50)
110       b = 8; s = @s*WIDTH/b
111       (0..b).each {|n|
112         line(@x1, @y1+n*s, @x2, @y1+n*s)
113         line(@x1+n*s, @y1, @x1+n*s, @y2)
114       }
115       colorHSV(0, 100, 100, 100) # 次にポインターを書きます
116       circle(@px, @py, @pr)
117       line(@px-@pw/2, @py, @px+@pw/2, @py)
118       line(@px, @py-@ph/2, @px, @py+@ph/2)
119     end
120     def onMouse(x, y)
121       if @onkeydown
122         x, y = @px, @py
123       end
124       if @dragging || @onkeydown
125         @onkeydown = false
126         @px, @py = x, y      #p [x, y]
127         @px = @x1 if @px < @x1
128         @py = @y1 if @py < @y1
129         @px = @x2-1 if @x2-1 < @px
130         @py = @y2-1 if @y2-1 < @py
131         return calc_code
132       else
133         return false
134       end
135     end
136     def calc_code()
137       x = ((@px - @x1)/@s).to_i
138       y = HEIGHT-1 - ((@py - @y1)/@s).to_i
139       code = x + y*WIDTH
140       if @code != code
141         @code = code
142         return true #changed
143         #p [x, y, code]
144         printf("%02x %02x %04x\n", x, y, @code)
145       else
146         return false
147       end
148     end
149     def show_list(list)
150       colorHSV(0, 100, 100, 100)
151       list.each {|code|
152         x, y = code_to_xy(code)
153         rect(x, y, x+2, y-2)
154       }
155     end
156     def code_to_xy(code)
157       cx = code % WIDTH
158       cy = HEIGHT - (code / WIDTH) #intになる?
159       x = cx * SCALE + @x1
160       y = cy * SCALE + @y1
161       return x, y
162     end
163     def length(x, y)    Math.sqrt(x*x + y*y)  end
164     def onMouseDown(x, y)
165       if length(@px-x, @py-y) < @pr
166         @dragging = true
167       end
168     end
169     def onMouseUp(x, y)    @dragging = false  end
170     def onKeyDown(key)
171       @onkeydown = true
172       case key
173       when 273
174         @py += @s
175       when 274
176         @py -= @s
177       when 276
178         @px -= @s
179       when 275
180         @px += @s
181       end
182     end
183   end
184
185 end
186
187 if $0 == __FILE__ #======================================================================
188     $LOAD_PATH << '../ruby/src'
189   require 'chise'
190   include CHISE
191   require 'stroke'
192   include StrokeFont
193
194   def setup
195     useSmooth()
196     window(-300,-300,300,300)
197     background 0,0,20
198     useFramerate(30)
199     @cs = CodeSelector.new
200     @csf1 = CSFFont.new()  #普通の文字
201     @csf2 = CSFFont.new(CSF_KOUKOTSU_FILE) #甲骨文字
202     @key = 1
203     @kage = KageFont.new()
204     @changed = nil
205   end
206
207   def display
208     @changed = @cs.onMouse(mouseX, mouseY) #変化があったか?
209     @cs.draw
210     @cs.show_list(@kage.cache_list)
211     code = @cs.code
212
213     push
214     scale 0.2
215     translate -500,-500
216     lineWidth(2)
217     draw_kage(code)
218     draw_csf(code)
219     pop
220   end
221
222   def draw_kage(code)
223     char = Character.get(code)
224     return if char.nil?
225     @kage.init(code) if @changed
226     @kage.print(code) if @changed
227     @kage.draw(code)
228   end
229
230   def draw_csf(ucs)
231     char = Character.get(ucs)
232     return if char.nil?
233     j = char.japanese_jisx0208
234     return if j.nil?
235     code = j
236     csf = @key == 1 ? @csf1 : @csf2
237     csf.init(code) if @changed
238     csf.print(code) if @changed
239     csf.draw(code)
240   end
241
242   def onMouseDown(x, y)  @cs.onMouseDown(x, y)end
243   def onMouseUp(x, y)  @cs.onMouseUp(x, y)end
244   def onKeyDown(key)
245     @key = key
246     @cs.onKeyDown(key)
247   end
248   mainloop
249 end
250
251 #----------------------------------------------------------------------end.