#</svg>
module StrokeFont
+ class QuadraticPath #======================================================================動的な分割に対応できるようにする
+ DEFAULT_DIVIDE = 4
+ def initialize(p1, p2, p3)
+ @p1, @p2, @p3 = p1, p2, p3
+ @num = DEFAULT_DIVIDE
+ end
+ def divide_adaptic #適応的分割数をする。
+ end
+ def divide()
+ divide_num(@num)
+ end
+ def divide_num(num) #分割数を指定できる
+ #p [num]
+ x1, y1 = @p1
+ x2, y2 = @p2
+ x3, y3 = @p3
+ #2次のbezier曲線の計算式、 P(t) = (1-t)^2*P1 + 2*t*(1-t)*P2 + t^2*P3
+ curve = []
+ (num+1).times {|i| #ここで最後の点を含めないのがポイント。これによって次の曲線との重複が無いようにしている。
+ t = (i.to_f)/num
+ x = (1-t)*(1-t)*x1 + 2*t*(1-t)*x2 + t*t*x3
+ y = (1-t)*(1-t)*y1 + 2*t*(1-t)*y2 + t*t*y3
+ curve << [x,y]
+ }
+ #p curve
+ return curve
+ end
+ end
+
+ class PathResolver #======================================================================
+ #M 50,540 950,255
+ #M 330,50 330,900 M 330,900 Q 330,950 380,950 M 380,950 840,950 M 840,950 Q 890,950 915,850
+ def initialize
+ reset
+ end
+ def reset
+ @lines = []
+ @px, @py = -1, -1
+ end
+ def parse(str)
+ reset
+ cmd = []
+ str.split.each {|par|
+ if par.length == 1 #コマンドである
+ exec_cmd(cmd) if 0 < cmd.length #前のコマンドが残っていたら実行
+ cmd = [par] #cmdを新規生成
+ elsif par =~ /[,0-9]+/ #座標値である
+ sx, sy = par.split(/,/)
+ x, y = sx.to_i, sy.to_i
+ cmd << [x, y] #cmdへのargを追加
+ end
+ }
+ exec_cmd(cmd) if 0 < cmd.length #前のコマンドが残っていたら実行
+ @lines
+ end
+ def exec_cmd(cmd)
+ c = cmd.shift #先頭をとる
+ case c
+ when "M"
+ cmd.each {|x, y| moveto(x, y) }
+ when "Q"
+ quadratic([@px, @py], cmd.shift, cmd.shift)
+ end
+ end
+ def moveto(x, y)
+ @lines << [@px, @py, x, y] if @px != -1
+ @px, @py = x, y
+ end
+ def quadratic(p1, p2, p3)
+ #p ['quadratic', p1, p2, p3]
+ qp = QuadraticPath.new(p1, p2, p3)
+ curve = qp.divide
+ curve.each {|x, y|
+ moveto(x, y)
+ }
+ end
+ end
+
class KageParser #======================================================================
def self.parse(svg)
@strokes = Strokes.new
+ pr = PathResolver.new
lines = svg.split(/\n/)
lines.each {|line|
next unless line =~ /^<path/
if line =~ /d=\"([a-zA-Z0-9, ]+)\"/
- KageParser.parse_path($1)
+ #lines = KageParser.parse_path($1)
+ lines = pr.parse($1)
+ lines.each {|px, py, x, y|
+ @strokes.add_line(px, 1000-py, x, 1000-y)
+ }
end
}
return @strokes
end
- def self.parse_path(str)
- #M 50,540 950,255
- #M 330,50 330,900 M 330,900 Q 330,950 380,950 M 380,950 840,950 M 840,950 Q 890,950 915,850
- px, py = -1, -1
- str.split.each {|par|
- next if par.length == 1 #一文字はとばします。本来はちゃんとベジェを展開する。
- if par =~ /[,0-9]+/
- sx, sy = par.split(/,/)
- x, y = sx.to_i, (1000 - sy.to_i)
- if px != -1
- @strokes.add_line(px, py, x, y)
- end
- px, py = x, y
- end
- }
- end
end
class KageGlyph #====================================================================== てなかんじ