
#==============================================================================#
# $Id: true_type_font.rb,v 1.17 2004/01/19 00:00:52 yuya Exp $
# $Source: /cvsroot/gruby/gruby/lib/grb/font/true_type_font.rb,v $
#==============================================================================#

require 'kconv'
require 'iconv'
require 'grb/math_ex'

#==============================================================================#

module GRb

  class Font

    class TrueTypeFont

      def initialize(filepath, size)
        @filepath       = filepath
        @size           = size

        char_x = self.null_draw(@filepath, @size, 0, 'X')
        char_y = self.null_draw(@filepath, @size, 0, 'y')

        @body_size    = char_y[:y1] - char_x[:y4]
        @descend_size = char_y[:y1] - char_x[:y1]
        @capital_size = @body_size - @descend_size
      end

      def null_draw(filepath, size, angle, text)
        error, bounds = GD::Image.stringFT(0, @filepath, @size, MathEx.deg2rad(angle), 0, 0, self.convert(text))
        x1, y1, x2, y2, x3, y3, x4, y4 = bounds
        return {:x1 => x1, :y1 => y1, :x2 => x2, :y2 => y2, :x3 => x3, :y3 => y3, :x4 => x4, :y4 => y4}
      end
      protected :null_draw

      def null_draw_fixed(filepath, size, angle, text, x, y)
        bounds = self.null_draw(filepath, size, 0, text)
        width  = bounds[:x2] - bounds[:x1]

        x1 = x  + MathEx.sin(angle) * @body_size
        y1 = y  + MathEx.cos(angle) * @body_size
        x2 = x1 + MathEx.sin(angle + 90) * width
        y2 = y1 + MathEx.cos(angle + 90) * width
        x3 = x2 + MathEx.sin(angle + 180) * @body_size
        y3 = y2 + MathEx.cos(angle + 180) * @body_size
        x4 = x
        y4 = y

        return {:x1 => x1, :y1 => y1, :x2 => x2, :y2 => y2, :x3 => x3, :y3 => y3, :x4 => x4, :y4 => y4}
      end
      protected :null_draw_fixed

      def draw(image, x, y, angle, color, text)
        xx = x + MathEx.sin(angle) * @capital_size
        yy = y + MathEx.cos(angle) * @capital_size

        image.stringFT(color, @filepath, @size, MathEx.deg2rad(angle), xx, yy, self.convert(text))
      end

      def bound(text, angle = 0)
        bounds = self.null_draw_fixed(@filepath, @size, angle, text, 0, 0)
        xx     = [bounds[:x1], bounds[:x2], bounds[:x3], bounds[:x4]]
        yy     = [bounds[:y1], bounds[:y2], bounds[:y3], bounds[:y4]]

        return [xx.min, yy.min, xx.max - xx.min, yy.max - yy.min]
      end

      def width(text, angle = 0)
        x, y, dx, dy = self.bound(text, angle)
        return dx
      end

      def height(text, angle = 0)
        x, y, dx, dy = self.bound(text, angle)
        return dy
      end

      def convert(text)
        return Iconv.iconv('UTF-8', 'SHIFT-JIS', Kconv.tosjis(text)).first
      end
      protected :convert

    end # TrueTypeFont

  end # Font

end # GRb

#==============================================================================#

if $0 == __FILE__
  require 'grb/image'

  GRb::Image.create_and_write_png_file(600, 750, false, __FILE__.sub(/\.rb/, '.png')) { |image|
    grid = GRb::Color.red(128)
    image.line(0, 150, 600, 150, grid)
    image.line(0, 300, 600, 300, grid)
    image.line(0, 450, 600, 450, grid)
    image.line(0, 600, 600, 600, grid)
    image.line(150, 0, 150, 750, grid)
    image.line(300, 0, 300, 750, grid)
    image.line(450, 0, 450, 750, grid)

    font = GRb::Font.truetype('/cygdrive/c/WINDOWS/Fonts/CENTURY.TTF', 22)
    text = 'abcde'

    [-90, -60, -30, 0, 30, 60, 90].each_with_index { |angle, i|
      color = image.set(GRb::Color.blue(256 / 6.0 * i))

      font.draw(image.image, 150, 150, angle, color, text, GRb::Font::ALIGN_RIGHT,  GRb::Font::VALIGN_BOTTOM)
      font.draw(image.image, 150, 300, angle, color, text, GRb::Font::ALIGN_RIGHT,  GRb::Font::VALIGN_MIDDLE)
      font.draw(image.image, 150, 450, angle, color, text, GRb::Font::ALIGN_RIGHT,  GRb::Font::VALIGN_TOP)
      font.draw(image.image, 300, 150, angle, color, text, GRb::Font::ALIGN_CENTER, GRb::Font::VALIGN_BOTTOM)
      font.draw(image.image, 300, 300, angle, color, text, GRb::Font::ALIGN_CENTER, GRb::Font::VALIGN_MIDDLE)
      font.draw(image.image, 300, 450, angle, color, text, GRb::Font::ALIGN_CENTER, GRb::Font::VALIGN_TOP)
      font.draw(image.image, 450, 150, angle, color, text, GRb::Font::ALIGN_LEFT,   GRb::Font::VALIGN_BOTTOM)
      font.draw(image.image, 450, 300, angle, color, text, GRb::Font::ALIGN_LEFT,   GRb::Font::VALIGN_MIDDLE)
      font.draw(image.image, 450, 450, angle, color, text, GRb::Font::ALIGN_LEFT,   GRb::Font::VALIGN_TOP)
    }

    color = image.set(GRb::Color.blue(128))
    0.step(360, 30) { |angle|
      font.draw(image.image, 150, 600, angle, color, text, :fit_left, :fit_top)
    }
  }
end

#==============================================================================#
#==============================================================================#
