#!ruby -Ks # -*- mode: ruby; encoding: sjis -*- # Last updated: <2014/12/13 18:01:34 +0900> require 'dxruby' # DXRuby BMFont 描画用クラス # # ShoeBox で作成したビットマップフォントを描画する # @see http://renderhjs.net/shoebox/ # # @example # require 'dxruby' # require_relative 'bmfont' # bmfont = BMFont.new("bmfont.png", "bmfont.fnt") # Window.loop do # Window.draw_bmfont(100, 20, "Hello BMFont", bmfont) # end # # @version 0.0.2 # class BMFont # フォントの各文字を格納する構造体 BMFontData = Struct.new(:image, :w, :h, :xofs, :yofs, :xadvance) # @return [Integer] 文字間スペース(単位はドット) attr_accessor :spacing # @return [Integer] フォント縦幅(単位はドット) attr_reader :height # @return [Integer] フォント縦幅調整値(単位はドット) attr_reader :line_height # @return [Integer] フォントベースライン位置 attr_reader :baseofs # コンストラクタ # @param [String] imgfilename 画像ファイル名 # @param [String] fntfilename 文字配置情報(.fnt)ファイル名 # @param [Integer] spacing 文字間スペース def initialize(imgfilename, fntfilename, spacing = 0) img = Image.load(imgfilename) @bmfont_array = {} @spacing = spacing @height = 0 @line_height = 0 @baseofs = 0 @chars_count = 0 cnt = 0 # .fntファイルを1行ずつ読み込んで処理 open(fntfilename) {|file| while l = file.gets l.chomp! if l =~ /^chars count=(\d+)$/ # 文字数取得 @chars_count = $1.to_i elsif l =~ /^common (.+)$/ # フォントの縦幅やベースライン位置を取得 p = $1 p.split(' ').each do |s| if s=~ /^(\S+)=(\d+)$/ case $1 when "lineHeight" @line_height = $2.to_i when "base" @baseofs = $2.to_i end end end elsif l =~ /^char (.+) letter=\"(.)\"$/ # 1文字分の情報を取得 str, c = $1, $2 p = {} str.split(' ').each do |s| p[$1] = $2.to_i if s =~ /^(\S+)=(\d+)$/ end id, x, y, w, h = p["id"], p["x"], p["y"], p["width"], p["height"] xs, ys, xa = p["xoffset"], p["yoffset"], p["xadvance"] cimg = img.slice(x, y, w, h) # 画像切り出し @bmfont_array[id] = BMFontData.new(cimg, w, h, xs, ys, xa) @height = h if @height < h cnt += 1 end end } img.dispose end # 配列として指定した際に、BMFont情報の構造体を返す # @param [Integer] index 配列添字 def [](index) return @bmfont_array[index] end end # Windowクラスに追加するBMFont描画用メソッド module Window # BMFontを描画 # @param [Number] x 描画x座標 # @param [Number] y 描画y座標 # @param [String] str 描画文字列 # @param [Object] bmfont BMFontクラス # @param [Number] z 描画優先順位 def self.draw_bmfont(x, y, str, bmfont, z = 0) str.each_byte do |code| x1 = x + bmfont[code].xofs y1 = y + bmfont[code].yofs - bmfont.line_height + bmfont.baseofs Window.draw(x1, y1, bmfont[code].image, z) # Window.drawBoxFill(x, y, x+2, y+2, C_RED) x += bmfont[code].xadvance + bmfont.spacing end end end # Imageクラスに追加するBMFont描画用メソッド class Image # BMFontを描画 # @param [Number] x 描画x座標 # @param [Number] y 描画y座標 # @param [String] str 描画文字列 # @param [Object] bmfont BMFontクラス def draw_bmfont(x, y, str, bmfont) str.each_byte do |code| x1 = x + bmfont[code].xofs y1 = y + bmfont[code].yofs - bmfont.line_height + bmfont.baseofs self.draw(x1, y1, bmfont[code].image) x += bmfont[code].xadvance + bmfont.spacing end end end if $0 == __FILE__ #テストコード lst = [ "!\"\#$%&'()*+,-./0", "123456789:;<=>?@", "A B C D EFGHIJKLMNOP", "QRSTUVWXYZ[\]^_`", "abcdefghijklmnop", "qrstuvwxyz{|}~" ] # BMFontクラスを生成 bmfont = BMFont.new('mplus1p_heavy_0-export.png', 'mplus1p_heavy_0-export.fnt') # 画像に描画してみる例 image = Image.new(640, 240) x, y = 0, 0 lst.each do |s| image.draw_bmfont(x, y, s, bmfont) y += bmfont.height end Window.bgcolor = [96, 96, 96] Window.loop do break if Input.keyPush?(K_ESCAPE) # 画面に描画してみる例 x, y = 0, 0 lst.each do |s| Window.draw_bmfont(x, y, s, bmfont) y += bmfont.height end Window.draw(0, 240, image) end end