人気ブログランキング | 話題のタグを見る

ruby/sdlでgoogleAPIを使って日本語入力

日本語変換をインターネット上で実現するための、CGI サービス
http://www.google.com/intl/ja/ime/cgiapi.html
を見つけた。
で、さっそく作ってみた。
sdlでは、半角/全角のキーが使えないみたい。
とりあえず、全角のみのローマ字入力でやってみた。
記号キーは悩みそうだから、今回はパス。
簡単な仕組みだけのものにした。


#!usr/bin/env ruby

require 'rubygems'
require 'sdl'
require 'cairo'
require 'cgi'

class EventHandle
def initialize(handle)
@handle = handle
@type = {
SDL::Event::KeyDown => :sym,
SDL::Event::KeyUp => :sym,
SDL::Event::MouseButtonDown => :button,
SDL::Event::MouseButtonUp => :button
}
end

def handling(event)
name = event.class
if @type[name]
if callback = @handle[[name,event.method(@type[name]).call]]
return callback.call(event)
end
end
if callback = @handle[name]
return callback.call(event)
end
nil
end
end

class IM
attr_reader :words,:focus_idx

def initialize
self.clear
@handle = EventHandle.new(
SDL::Event::KeyDown => proc{|e| key_down(e)}
)
@char = {
SDL::Key::K0 => '0',
SDL::Key::K1 => '1',
SDL::Key::K2 => '2',
SDL::Key::K3 => '3',
SDL::Key::K4 => '4',
SDL::Key::K5 => '5',
SDL::Key::K6 => '6',
SDL::Key::K7 => '7',
SDL::Key::K8 => '8',
SDL::Key::K9 => '9',
SDL::Key::A => "a",
SDL::Key::B => "b",
SDL::Key::C => "c",
SDL::Key::D => "d",
SDL::Key::E => "e",
SDL::Key::F => "f",
SDL::Key::G => "g",
SDL::Key::H => "h",
SDL::Key::I => "i",
SDL::Key::J => "j",
SDL::Key::K => "k",
SDL::Key::L => "l",
SDL::Key::M => "m",
SDL::Key::N => "n",
SDL::Key::O => "o",
SDL::Key::P => "p",
SDL::Key::Q => "q",
SDL::Key::R => "r",
SDL::Key::S => "s",
SDL::Key::T => "t",
SDL::Key::U => "u",
SDL::Key::V => "v",
SDL::Key::W => "w",
SDL::Key::X => "x",
SDL::Key::Y => "y",
SDL::Key::Z => "z",
SDL::Key::MINUS => "ー"
}

@map = [
["kk","っk"],["ss","っs"],["tt","っt"],["nn","ん"],["hh","っh"],
["mm","っm"],["yy","っy"],["rr","っr"],["ww","っw"],
["gg","っg"],["zz","っz"],["dd","っd"],["bb","っb"],["pp","っp"],
["xtu","っ"],["ltu","っ"],
["xa","ぁ"],["xi","ぃ"],["xu","ぅ"],["xe","ぇ"],["xo","ぉ"],
["la","ぁ"],["li","ぃ"],["lu","ぅ"],["le","ぇ"],["lo","ぉ"],
["xya","ゃ"],["xyu","ゅ"],["xyo","ょ"],
["lya","ゃ"],["lyu","ゅ"],["lyo","ょ"],
["kya","きゃ"],["kyi","きゃ"],["kyu","きゅ"],["kye","きぇ"],["kyo","きょ"],
["sya","しゃ"],["syi","しぃ"],["syu","しゅ"],["sye","しぇ"],["syo","しぇ"],
["tya","ちゃ"],["tyi","ちぃ"],["tyu","ちゅ"],["tye","ちぇ"],["tyo","ちょ"],
["nya","にゃ"],["nyi","にぃ"],["nyu","にゅ"],["nye","にぇ"],["nyo","にょ"],
["hya","ひゃ"],["hyi","ひぃ"],["hyu","ひゅ"],["hye","ひぇ"],["hyo","ひょ"],
["mya","みゃ"],["myi","みぃ"],["myu","みゅ"],["mye","みぇ"],["myo","みょ"],
["rya","りゃ"],["ryi","りぃ"],["ryu","りゅ"],["rye","りぇ"],["ryo","りょ"],
["gya","ぎゃ"],["gyi","ぎぃ"],["gyu","ぎゅ"],["gye","ぎぇ"],["gyo","ぎょ"],
["zya","じゃ"],["zyi","じぃ"],["zyu","じゅ"],["zye","じぇ"],["zyo","じょ"],
["dya","ぢゃ"],["dyi","ぢぃ"],["dyu","ぢゅ"],["dye","ぢぇ"],["dyo","ぢょ"],
["bya","びゃ"],["byi","びぃ"],["byu","びゅ"],["bye","びぇ"],["byo","びょ"],
["pya","ぴゃ"],["pyi","ぴぃ"],["pyu","ぴゅ"],["pye","ぴぇ"],["pyo","ぴょ"],
["ka","か"],["ki","き"],["ku","く"],["ke","け"],["ko","こ"],
["ca","か"],["ci","し"],["cu","く"],["ce","せ"],["co","こ"],
["qa","くぁ"],["qi","くぃ"],["qu","く"],["qe","くぇ"],["qo","くぉ"],
["sa","さ"],["si","し"],["su","す"],["se","せ"],["so","そ"],
["sha","しゃ"],["shi","し"],["shu","しゅ"],["she","しぇ"],["sho","しょ"],
["ta","た"],["ti","ち"],["tu","つ"],["te","て"],["to","と"],
["tha","てゃ"],["thi","てぃ"],["thu","てゅ"],["the","てぇ"],["tho","てょ"],
["na","な"],["ni","に"],["nu","ぬ"],["ne","ね"],["no","の"],
["ha","は"],["hi","ひ"],["hu","ふ"],["he","へ"],["ho","ほ"],
["fa","ふぁ"],["fi","ふぃ"],["fu","ふ"],["fe","ふぇ"],["fo","ふぉ"],
["ma","ま"],["mi","み"],["mu","む"],["me","め"],["mo","も"],
["ya","や"],["yi","い"],["yu","ゆ"],["ye","いぇ"],["yo","よ"],
["ra","ら"],["ri","り"],["ru","る"],["re","れ"],["ro","ろ"],
["wa","わ"],["wi","うぃ"],["wu","う"],["we","うぇ"],["wo","を"],
["ga","が"],["gi","ぎ"],["gu","ぐ"],["ge","げ"],["go","ご"],
["za","ざ"],["zi","じ"],["zu","ず"],["ze","ぜ"],["zo","ぞ"],
["ja","じょ"],["ji","じ"],["ju","じゅ"],["je","じぇ"],["jo","じょ"],
["da","だ"],["di","ぢ"],["du","づ"],["de","で"],["do","ど"],
["ba","ば"],["bi","び"],["bu","ぶ"],["be","べ"],["bo","ぼ"],
["pa","ぱ"],["pi","ぴ"],["pu","ぷ"],["pe","ぺ"],["po","ぽ"],
["a","あ"],["b","b"],["c","c"],["d","d"],["e","え"],["f","f"],
["g","g"],["h","h"],["i","い"],["j","j"],["k","k"],["l","l"],
["m","m"],["n","n"],["o","お"],["p","p"],["q","q"],["r","r"],
["s","s"],["t","t"],["u","う"],["v","v"],["w","w"],["x","x"],
["y","y"],["z","z"]
]
end

def convart_kanji
url = "http://www.google.com/transliterate?langpair=ja-Hira|ja&text=#{CGI.escape(@words.join(","))}"
json = `wget -q -O - '#{url}' --user-agent='Mozilla/5.0'`
json.gsub!(/\s/,"")
json.gsub!('"',"")
json.sub!("[","")
@words = []
@candidate = []
json.scan(/\[(.*?),\[(.*?)\]/) do |x|
cand = $2.split(",")
@candidate << cand
@candidate_idx << 0
@words << cand[0]
end
@status = :kanji
@focus_idx = 0
end

def convart_hira
text = @buf.dup
@map.each do |r,k|
text.gsub!(r,k)
end
@words[0] = text
end

def clear
@status = :hira
@buf = ""
@words = [""]
@focus_idx = 0
@candidate = []
@candidate_idx = []
end


def key_down(e)
if char = @char[e.sym]
if @status == :hira
@buf << char
convart_hira
"x"
else
ret = @words.join
self.clear
@buf << char
convart_hira
ret
end
elsif e.sym == SDL::Key::RETURN
if @buf.empty?
"e"
else
ret = @words.join
self.clear
ret
end
elsif e.sym == SDL::Key::BACKSPACE
return nil if @status == :kanji
if @buf.empty?
"b"
else
buf = @words[0].chop.chop.chop
self.clear
@buf = @words[0] = buf
"x"
end
elsif e.sym == SDL::Key::ESCAPE
buf = @buf
self.clear
@buf = buf
convart_hira
"x"
elsif e.sym == SDL::Key::SPACE
return " " if @buf.empty?
if @status == :kanji
@candidate_idx[@focus_idx] += 1
@candidate_idx[@focus_idx] = 0 if @candidate_idx[@focus_idx] == @candidate[@focus_idx].size
@words[@focus_idx] = @candidate[@focus_idx][@candidate_idx[@focus_idx]]
else
convart_kanji
end
"x"
elsif e.sym == SDL::Key::LEFT
@focus_idx -= 1
@focus_idx = @words.size - 1 if @focus_idx < 0
"x"
elsif e.sym == SDL::Key::RIGHT
@focus_idx += 1
@focus_idx = 0 if @focus_idx == @words.size
"x"
end
end

def handling(e)
@handle.handling(e)
end
end

class Canvas
def initialize(screen)
@screen = screen
@x,@y = 0,0
@im =IM.new
@text = ""
self.draw
end

def handling(e)
if text = @im.handling(e)
if text == "e"
@text = ""
elsif text == "b"
@text.chop.chop.chop if !@text.empty?
elsif text != "x"
@text << text
end
self.draw
end
end

def draw
image = Cairo::ImageSurface.new(600,45)
context = Cairo::Context.new(image)
context.set_source_rgb(1, 1, 1)
context.rectangle(0, 0, 600, 45)
context.fill
context.set_source_color(Cairo::Color::BLACK)
context.font_size = 20
context.move_to(10, 30)
context.show_text(@text)
@im.words.size.times do |i|
if @im.focus_idx == i
context.set_source_color(Cairo::Color::RED)
else
context.set_source_color(Cairo::Color::BLUE)
end
context.show_text(@im.words[i])
end
@surface = SDL::Surface.new_from(image.data,image.width,image.height,32,image.stride,0,0,0,0)
end

def update
@screen.put(@surface,10,25)
end
end

class Phase
def initialize(screen)
@screen = screen
@canvas = Canvas.new(@screen)
@handle = EventHandle.new(
SDL::Event::Quit => proc{exit}
)
end

def update
@screen.draw_rect(0,0,@screen.w,@screen.h,[150,150,150],true)
@canvas.update
end

def handling(e)
@handle.handling(e)
@canvas.handling(e)
end

def run
loop do
while e=SDL::Event.poll
handling(e)
end
update
@screen.flip
SDL.delay(50)
end
end
end

width,height = 620,100
SDL.init(SDL::INIT_VIDEO)
screen = SDL::Screen.open(width,height,SDL::Screen.info.bpp,SDL::SWSURFACE)
Phase.new(screen).run
by gaziya | 2011-04-22 22:40