読者です 読者をやめる 読者になる 読者になる

WHITELEAF:Kindle応援サイト

KindleでWEB小説を読もう! Narou.rb 公開中

SFont

by http://d.hatena.ne.jp/mirichi/20100619/p1
(Twitter で reply したんだけど気づかれなかったようだ lol)

更新。
てきとうなコードを書いた( http://twitter.com/mirichi/status/16531632255 )お詫び(?)にちょっと真面目に書いてみました。
Image#draw の第4引数以降に関しては「使ってもいいけど理解して使ってね!意味ないけど!」的な感じで。ドキュメントで縛るのがいいかなと。

require 'dxruby'

class SFont
  SFontData = Struct.new(:image, :size)
  BLANK_COLOR = [255,255,0,255]

  attr_reader :height

  def initialize(filename)
    image = Image.load(filename)
    @sfont_array = []
    @height = image.height
    x = 0
    count = 0
    loop do
      char_size = 0
      while image.compare(x, 0, BLANK_COLOR) && x < image.width do
        x += 1
      end
      break if x >= image.width
      while !image.compare(x + char_size, 0, BLANK_COLOR) do
        char_size += 1
      end
      @sfont_array[0x21 + count] = SFontData.new(image.slice(x, 0, char_size, @height), char_size)
      x += char_size
      count += 1
    end
  end

  def [](index)
    return @sfont_array[index]
  end

  module Drawable
    SPACE_WIDTH = 20
    TAB_SIZE = 2

    def draw_sfont(x, y, str, sfont, line_height = nil, *opt)
      px = x
      py = y
      str.gsub!(/\r/, "")
      margin = (line_height ? (line_height - sfont.height) / 2.0 : 0)
      str.each_byte do |code|
        mx = case code.chr
             when " "
               SPACE_WIDTH
             when "\t"
               SPACE_WIDTH * TAB_SIZE
             when "\n"
               px = x
               py += sfont.height + margin
               0
             else
               self.draw(px, py, sfont[code].image, *opt)
               sfont[code].size
             end
        px += mx
      end
      return py + sfont.height - y
    end
  end
end

module Window
  extend SFont::Drawable
end

class Image
  include SFont::Drawable
end

str1 = "!\"\#$%&'()*+,-./0123456789:;<=>?@"
str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`"
str3 = "abcdefghitjklmnopqrstuvwxyz{|}~"
str4 = "def foo\n\tbar(buzz)\nend"

sfont = SFont.new('24P_Arial_NeonYellow.png')
image = Image.new(640, 480)
y = 0
y += image.draw_sfont(0, y, str1, sfont)
y += image.draw_sfont(0, y, str2, sfont)
y += image.draw_sfont(0, y, str3, sfont)
y += image.draw_sfont(0, y, str4, sfont, 20)

Window.loop do
  y = 0
  y += Window.draw_sfont(0, y, str1, sfont)
  y += Window.draw_sfont(0, y, str2, sfont)
  y += Window.draw_sfont(0, y, str3, sfont)
  y += Window.draw_sfont(0, y, str4, sfont, 10)

  Window.draw(0, 200, image)
end