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

module GRb

  class Font

    class GDFont

      R = 0.5

      def initialize(name, bold, italic)
        @font   = GD::Font.new(name)
        @bold   = bold
        @italic = italic
      end

      def vertical?(angle)
        return angle % 360 == 90
      end
      protected :vertical?

      def draw_normal(image, x, y, angle, color, text)
        if self.vertical?(angle)
          image.stringUp(@font, x, y, text, color)
        else
          image.string(@font, x, y, text, color)
        end
      end
      protected :draw_normal

      def draw_bold(image, x, y, angle, color, text)
        self.draw_normal(image, x, y, angle, color, text)

        if self.vertical?(angle)
          self.draw_normal(image, x, y + 1, angle, color, text)
        else
          self.draw_normal(image, x + 1, y, angle, color, text)
        end
      end
      protected :draw_bold

      def draw_italic(image, x, y, angle, color, text)
        fdx = self.raw_width(text)
        fdy = self.raw_height(text)
        ndx = fdx + (fdy * R).floor
        ndy = fdy

        red, green, blue = image.rgb(color)

        if self.vertical?(angle)
          fdx, fdy = fdy, fdx
          ndx, ndy = ndy, ndx
        end

        dummy1 = GD::Image.new(fdx, fdy)
        dummy1.colorAllocate(255, 255, 255)
        dummy1.transparent(0)

        if self.vertical?(angle)
          dummy1.stringUp(@font, 0, fdy - 1, text, dummy1.colorAllocate(red, green, blue))
        else
          dummy1.string(@font, 0, 0, text, dummy1.colorAllocate(red, green, blue))
        end

        dummy2 = GD::Image.new(ndx, ndy)
        dummy2.colorAllocate(255, 255, 255)
        dummy2.colorAllocate(red, green, blue)
        dummy2.transparent(0)

        if self.vertical?(angle)
          (0...fdx).each { |i|
            from_x = i
            from_y = 0
            to_x   = i
            to_y   = (i * R).floor
            width  = 1
            height = fdy
            dummy1.copy(dummy2, to_x, to_y, from_x, from_y, width, height)
          }
          dummy2.copy(image, x, y - fdy, 0, 0, ndx, ndy)
        else
          (0...fdy).each { |i|
            from_x = 0
            from_y = i
            to_x   = ((fdy - i) * R).floor
            to_y   = i
            width  = fdx
            height = 1
            dummy1.copy(dummy2, to_x, to_y, from_x, from_y, width, height)
          }
          dummy2.copy(image, x, y, 0, 0, ndx, ndy)
        end
      end
      protected :draw_italic

      def draw_bolditalic(image, x, y, angle, color, text)
        self.draw_italic(image, x, y, angle, color, text)

        if self.vertical?(angle)
          self.draw_italic(image, x, y + 1, angle, color, text)
        else
          self.draw_italic(image, x + 1, y, angle, color, text)
        end
      end
      protected :draw_bolditalic

      def draw(image, x, y, angle, color, text)
        case [@bold, @italic]
        when [false, false] then self.draw_normal(image, x, y, angle, color, text)
        when [true, false]  then self.draw_bold(image, x, y, angle, color, text)
        when [false, true]  then self.draw_italic(image, x, y, angle, color, text)
        when [true, true]   then self.draw_bolditalic(image, x, y, angle, color, text)
        end
      end

      def bound(text, angle = 0)
        raise(NotImplementedError)
      end

      def width(text, angle = 0)
        unless self.vertical?(angle)
          case [@bold, @italic]
          when [false, false] then return @font.width * text.size
          when [true, false]  then return @font.width * text.size + 1
          when [false, true]  then return @font.width * text.size + @font.height * R
          when [true, true]   then return @font.width * text.size + @font.height * R + 1
          end
        else
          return self.height(text, 0)
        end
      end

      def height(text, angle = 0)
        unless self.vertical?(angle)
          return @font.height
        else
          return self.width(text, 0)
        end
      end

      def raw_width(text)
        return @font.width * text.size
      end

      def raw_height(text)
        return @font.height
      end

    end # GDFont

  end # Font

end # GRb

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

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

  GRb::Image.create_and_write_png_file(600, 600, 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(150, 0, 150, 600, grid)
    image.line(300, 0, 300, 600, grid)
    image.line(450, 0, 450, 600, grid)
    image.line(225, 200, 225, 250, grid)
    image.line(200, 225, 250, 225, grid)

    font = GRb::Font.gd('Giant')
    text = 'abcde'

    c = image.set(GRb::Color.black)
    GRb::Font::Giant.draw(image.image,  25,  25, 0, c, 'Giant')
    GRb::Font::Large.draw(image.image,  25,  45, 0, c, 'Large')
    GRb::Font::Medium.draw(image.image, 25,  65, 0, c, 'Medium')
    GRb::Font::Small.draw(image.image,  25,  85, 0, c, 'Small')
    GRb::Font::Tiny.draw(image.image,   25, 105, 0, c, 'Tiny')
    GRb::Font::BoldGiant.draw(image.image,  25, 125, 0, c, 'BoldGiant')
    GRb::Font::BoldLarge.draw(image.image,  25, 145, 0, c, 'BoldLarge')
    GRb::Font::BoldMedium.draw(image.image, 25, 165, 0, c, 'BoldMedium')
    GRb::Font::BoldSmall.draw(image.image,  25, 185, 0, c, 'BoldSmall')
    GRb::Font::BoldTiny.draw(image.image,   25, 205, 0, c, 'BoldTiny')
    GRb::Font::ItalicGiant.draw(image.image,  25, 225, 0, c, 'ItalicGiant')
    GRb::Font::ItalicLarge.draw(image.image,  25, 245, 0, c, 'ItalicLarge')
    GRb::Font::ItalicMedium.draw(image.image, 25, 265, 0, c, 'ItalicMedium')
    GRb::Font::ItalicSmall.draw(image.image,  25, 285, 0, c, 'ItalicSmall')
    GRb::Font::ItalicTiny.draw(image.image,   25, 305, 0, c, 'ItalicTiny')
    GRb::Font::BoldItalicGiant.draw(image.image,  25, 325, 0, c, 'BoldItalicGiant')
    GRb::Font::BoldItalicLarge.draw(image.image,  25, 345, 0, c, 'BoldItalicLarge')
    GRb::Font::BoldItalicMedium.draw(image.image, 25, 365, 0, c, 'BoldItalicMedium')
    GRb::Font::BoldItalicSmall.draw(image.image,  25, 385, 0, c, 'BoldItalicSmall')
    GRb::Font::BoldItalicTiny.draw(image.image,   25, 405, 0, c, 'BoldItalicTiny')

    GRb::Font::Giant.draw(image.image,   25, 575, 90, c, 'Giant')
    GRb::Font::Large.draw(image.image,   45, 575, 90, c, 'Large')
    GRb::Font::Medium.draw(image.image,  65, 575, 90, c, 'Medium')
    GRb::Font::Small.draw(image.image,   85, 575, 90, c, 'Small')
    GRb::Font::Tiny.draw(image.image,   105, 575, 90, c, 'Tiny')
    GRb::Font::BoldGiant.draw(image.image,  125, 575, 90, c, 'BoldGiant')
    GRb::Font::BoldLarge.draw(image.image,  145, 575, 90, c, 'BoldLarge')
    GRb::Font::BoldMedium.draw(image.image, 165, 575, 90, c, 'BoldMedium')
    GRb::Font::BoldSmall.draw(image.image,  185, 575, 90, c, 'BoldSmall')
    GRb::Font::BoldTiny.draw(image.image,   205, 575, 90, c, 'BoldTiny')
    GRb::Font::ItalicGiant.draw(image.image,  225, 575, 90, c, 'ItalicGiant')
    GRb::Font::ItalicLarge.draw(image.image,  245, 575, 90, c, 'ItalicLarge')
    GRb::Font::ItalicMedium.draw(image.image, 265, 575, 90, c, 'ItalicMedium')
    GRb::Font::ItalicSmall.draw(image.image,  285, 575, 90, c, 'ItalicSmall')
    GRb::Font::ItalicTiny.draw(image.image,   305, 575, 90, c, 'ItalicTiny')
    GRb::Font::BoldItalicGiant.draw(image.image,  325, 575, 90, c, 'BoldItalicGiant')
    GRb::Font::BoldItalicLarge.draw(image.image,  345, 575, 90, c, 'BoldItalicLarge')
    GRb::Font::BoldItalicMedium.draw(image.image, 365, 575, 90, c, 'BoldItalicMedium')
    GRb::Font::BoldItalicSmall.draw(image.image,  385, 575, 90, c, 'BoldItalicSmall')
    GRb::Font::BoldItalicTiny.draw(image.image,   405, 575, 90, c, 'BoldItalicTiny')

    [0, 90].each_with_index { |angle, i|
      color = image.set(GRb::Color.blue(128 / 2 * i + 128))

      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))
    font.draw(image.image, 225, 225,  0, color, text, GRb::Font::ALIGN_FIT_LEFT, GRb::Font::VALIGN_FIT_TOP)
    font.draw(image.image, 225, 225, 90, color, text, GRb::Font::ALIGN_FIT_LEFT, GRb::Font::VALIGN_FIT_TOP)
  }
end

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