#==============================================================================
# ■ Window_digits_number vol.6.00
# 文字列数値の高速描画/回転描画/高速色変化/点滅
#------------------------------------------------------------------------------
# 12/07/08
#==============================================================================
class Window_digits_number
  #--------------------------------------------------------------------------
  # ■ オブジェクト作成と解説
  #--------------------------------------------------------------------------
  # a = Window_digits_number.new(x,y,z,num,max,min,fonts,push)
  #…………………………………………………………………………………………………
  # x                  : X座標を指定(X座標の補正位置は文字サイズの半分単位で指定？)
  # y                  : Y座標を指定
  # z                  : Z座標を指定
  #…………………………………………………………………………………………………
  # ■省略可能項目(省略した場合はデフォルト)
  #…………………………………………………………………………………………………
  # num                : 初期数値を指定(数値以外は非表示)
  # max                : 桁数(数値の場合)
  # min=10             : 数値を通常形式で描画
  # min=20             : 数値を非表示の桁数だけ左に詰める ※ [/ 999] → [/999]
  # min=0              : 数値を001←形式で描画
  # min=["text",rect]  : テキストor画像(Rect_Draw_Icon.new)を配列で指定
  # fonts              : フォント情報を指定(Copy_Font.new)
  # push               : カーソル移動時にテキストをキャッシュ化するフラグ
  #…………………………………………………………………………………………………
  # ■Copy_Font vol.2.20を参照
  # fonts = Copy_Font.new(size,bold,italic,shadow,round,name,color,s_color,
  #                       interval,colors,normals,shadows,s_colors)
  # ■Rect_Draw_Icon vol.1.00を参照
  # rect = Rect_Draw_Icon.new(text,name,id,rx,ry,rw,rh)
  #--------------------------------------------------------------------------
  # ■ カスタマイズ項目(書き換え可)
  #--------------------------------------------------------------------------
  def customize?
    # □描画位置を可視化(デバッグ用)
    @debug = false#true#
    # □補助的に回転する数値桁配列の回転スピード(大=遅い)
    @speed = 5
    # □補助的に回転する桁配列(※1=10の位,2=100の位,3=1000の位...etc)
    @updates = [2,4,6,8]
    # □点滅数値の一番薄い状態(透明度0〜255)
    @blink_min = 50
    # □点滅数値の一番濃い状態(透明度0〜255)
    @blink_max = 250
    # □点滅数値の変化する速さ(0=点滅なし 大＝速い 小＝遅い)
    @blink_speed = 8
    # □点滅の停止状態の透明度(カーソル選択済み)
    @blink_stop = 250
  end
  #--------------------------------------------------------------------------
  # ■ 公開インスタンス変数(以下書き換え不可)
  #--------------------------------------------------------------------------
  attr_accessor :fonts          # 文字装飾を取得(Copy_Fontを格納)
  attr_accessor :move           # 回転実行中フラグ
  attr_accessor :count          # アニメーションカウント
  attr_accessor :x_es           # X座標の配列を格納
  attr_accessor :y_es           # Y座標の配列を格納
  attr_accessor :z_es           # Z座標の配列を格納
  attr_accessor :screen_x       # X座標を格納
  attr_accessor :screen_y       # Y座標を格納
  attr_accessor :screen_z       # Z座標を格納
  attr_accessor :animas         # アニメーションパターン
  attr_accessor :speed          # アニメーション速度
  attr_accessor :updates        # 補助的に回転する桁の配列
  #--------------------------------------------------------------------------
  # ■ オブジェクト初期化
  #--------------------------------------------------------------------------
  def initialize(x,y,z = 102,num = 0,max = 1,min = 10,fonts = Copy_Font.new,push = false)
    # □カスタマイズ項目の初期化
    customize? 
    @screen_x = x ; @screen_y = y ; @screen_z = z
    @move = false ; @digits = []
    @count = 0
    @x_es = [] ; @y_es = [] ; @z_es = [] ; @left_x = 0
    @fonts = fonts ; @push = push
    @indexes = [] ; @old_value = num
    @max = max ; @min = min ; @key = ""
    #…………………………………………………………………………………………………
    # ■数値の場合
    #…………………………………………………………………………………………………
    if @min.is_a?(Numeric)
      # □キャッシュキーの初期化
      @key = @fonts.cache_key?
      # □最大桁数の取得
      @max_value = make_number_digits_max?(@max)
      # □回転数値ウィンドウの作成
      number_digits?(x,y,z,num,@max,@min,fonts)
    #…………………………………………………………………………………………………
    # ■テキストの場合
    #…………………………………………………………………………………………………
    else
      @speed = 0 ; @updates = nil
      @max_text = @fonts.colors.size+1
      @max_value = @min.size
      @text = min
      # □キャッシュキーを取得
      @key = @fonts.key
      for i in 0...@text.size
        icon = icon_check?(@text[i],i)
        if icon != nil
          @key += ("/" + icon[3] + "/icon")
        else
          @key += ("/" + @text[i] + "/")
        end
      end
      # □回転テキストウィンドウの作成
      rapid_text?(x,y,z,num,@text,fonts,@push)
    end
    # □更新
    refresh(num,0)
  end
  #--------------------------------------------------------------------------
  # ■ ウィンドウの可視化(a.visible = active)
  #     visible    : 可視化(true)/不可視化(false)
  #--------------------------------------------------------------------------
  def visible=(visible)
    for n in 0...@max
      @digits[n].viewport.visible = visible
    end
  end
  #--------------------------------------------------------------------------
  # ■ X座標の更新
  #--------------------------------------------------------------------------
  def x=(x)
    for n in 0...@max
      # □左詰め補正( - @left_x)
      @digits[n].viewport.rect.x = x+(n*@cw) - @left_x
      # □左詰め補正
      bx = @fonts.round ? 2 : 0
      @x_es[n] = x + (n*(@cw-bx))
    end
    @screen_x = x
  end
  #--------------------------------------------------------------------------
  # ■ Y座標の更新
  #--------------------------------------------------------------------------
  def y=(y)
    for n in 0...@max
      @digits[n].viewport.rect.y = y+16-@cy
      @y_es[n] = y-@cy
    end
    @screen_y = y
  end
  #--------------------------------------------------------------------------
  # ■ Z座標の更新
  #--------------------------------------------------------------------------
  def z=(z)
    for n in 0...@max
      @digits[n].viewport.z = z
      @z_es[n] = z
    end
    @screen_z = z
  end
  #--------------------------------------------------------------------------
  # ■ 回転の更新(数値/テキストの回転)
  #     num        : 列番号(数値)
  #     line       : カラー行番号(fonts.normals配列番号)
  #     se         : SEファイル or SEファイル名
  #--------------------------------------------------------------------------
  def update(num,line = 0,se = nil)
    @new_value = num
    if @digits != nil
      if @old_value != @new_value
        if @old_value > @new_value
          @old_value  = old_lose_value?(1)
          # □回転 SE を演奏
          if se != nil
            $game_system.se_play(se)
          end
          # □補助的に回転する桁
          if @updates != nil
            for n in @updates
              if @old_value - (10**(n)) > @new_value && @old_value % @speed == 0
                @old_value  = old_lose_value?(10**(n))
              end
            end
          end
        elsif @old_value < @new_value
          @old_value  = old_gain_value?(1)
          # □回転 SE を演奏
          if se != nil
            if se.is_a?(RPG::AudioFile)
              $game_system.se_play(se)
            else
              $game_system.se_play(RPG::AudioFile.new(se))
            end
          end
          # □補助的に回転する桁
          if @updates != nil
            for n in @updates
              if @old_value + (10**(n)) < @new_value && @old_value % @speed == 0
                @old_value  = old_gain_value?(10**(n))
              end
            end
          end
        end
        @move = true
        # □更新
        refresh(@old_value,line)
      else
        @move = false
        # □色の更新
        refresh(@new_value,line)
        @old_value = @new_value
      end
    end
  end
  #--------------------------------------------------------------------------
  # ■ テキストアニメーションの更新
  #     active     : 更新(true)/停止(false)
  #     speed      : アニメーション速度(0=点滅なし/大＝速い/小＝遅い)
  #     animas     : アニメーションループ(配列数=2以上)
  #     stop       : 停止カラー(fonts.normals配列番号)
  #--------------------------------------------------------------------------
  def animation(active = true,speed = @speed,
    animas = @animas,line = 0,stop = @fonts.normals.size-1)
    
    @animas = animas ; @speed = speed
    refresh(@animas[@count/@speed])
    if active or (! active && @count != 0)
      @count += 1
    else
      refresh(stop,line)
    end
    if @count == @animas.size*@speed
      @count = 0
    end
  end
  #--------------------------------------------------------------------------
  # ■ 点滅更新(数値/テキストの点滅)
  #     num        : 列番号(数値)
  #     line       : カラー行番号(fonts.normals配列番号)
  #     active     : 更新(true)/停止(false)
  #--------------------------------------------------------------------------
  def blink_refresh(num,line = 0,active = false)
    # □アクティブでなければ、非表示
    unless active
      num = nil
    end
    # □更新
    refresh(num,line)
    # □点滅の更新
    if active && @blink_speed != 0
      if @blink_opa
        if @digits[0].opacity >= @blink_max
          @blink_opa = false
        end
        @back_opa = -@blink_speed
      else
        if @digits[0].opacity <= @blink_min
          @blink_opa = true
        end
        @back_opa = @blink_speed
      end
      @digits[0].opacity -= @back_opa
      @digits.each{ |a| a.opacity = @digits[0].opacity }
    end
  end
  #--------------------------------------------------------------------------
  # ■ 更新(数値/テキスト)
  #     num        : 列番号(数値)
  #     line       : カラー行番号(fonts.normals配列番号)
  #--------------------------------------------------------------------------
  def refresh(num,line = 0)
    #…………………………………………………………………………………………………
    # ■数値の場合
    #…………………………………………………………………………………………………
    if @min.is_a?(Numeric)
      numbers = make_number_digits?(num,@max,@min)
      # □非表示の桁数を初期化
      mins = 0
      for d in 0...numbers.size
        @digits[d].oy = numbers[d] * @wh
        # □文字色の変更
        @digits[d].ox = line * @cw
        # □非表示の桁数を取得
        if numbers[d] == 20
          mins += 1
        end
        @digits[d].viewport.rect.x = @x_es[d]
      end
      # □左詰め補正
      bx = @fonts.round ? 2 : 0
      @left_x = (@cw-bx)*mins
      # □非表示の桁数は左に詰める
      if mins > 0
        for n in 0...@max
          @digits[n].viewport.rect.x -= @left_x
        end
      end
    #…………………………………………………………………………………………………
    # ■テキストの場合
    #…………………………………………………………………………………………………
    else
      @rapids = RPG::Cache.digits(@key)
      if @indexes == [] && @push
        
        @rapids.clear
      end
      # ■テキスト追加タイプの場合
      if @push && @rapids != nil && num != nil
        icon = icon_check?(@text[num],num)
        # □行通常色が指定されている場合(縦回転)
        if @fonts.normals[num].is_a?(Color)
          @fonts.color = @fonts.normals[num]
        else
          @fonts.color = fonts.color
        end
        # □行影色が指定されている場合
        if @fonts.shadows[num].is_a?(Color)
          @fonts.s_color = @fonts.shadows[num]
        else
          @fonts.s_color = fonts.s_color
        end
        # □アイコンの描画
        if icon != nil
          ix = [(icon[2].width)/6,0].max
          iy = [16 - (icon[2].height/2),0].max
          unless @indexes.include?(num)
            @rapids.blt(1,num*@wh+iy,icon[1],icon[2])
            @rapids.draw_cache_text(icon[2].width+ix+1,num*@wh,@cw,@wh,icon[0],0,@fonts)
            @indexes.push(num)
          end
        else
          unless @indexes.include?(num)
            @rapids.draw_cache_text(1,num*@wh,@cw,@wh,@text[num],0,@fonts)
            @indexes.push(num)
          end
        end
        # □列通常色が指定されている場合(横回転)
        for c in 0...@fonts.colors.size
          @fonts.color = fonts.colors[c]
          # □列影色が指定されている場合
          @fonts.s_color = fonts.s_colors[c]
          icon = icon_check?(@text[num],num)
          # □アイコンの描画
          if icon != nil
            unless @indexes.include?(num)
              ix = [(icon[2].width)/6,0].max
              iy = [16 - (icon[2].height/2),0].max
              @rapids.blt(1+@cw*(c+1),num*@wh+iy,icon[1],icon[2])
              @rapids.draw_cache_text(icon[2].width+ix+1+@cw*(c+1),num*@wh,@cw,@wh,icon[0],0,@fonts)
              @indexes.push(num)
            end
          else
            unless @indexes.include?(num)
              @rapids.draw_cache_text(1+@cw*(c+1),num*@wh,@cw,@wh,@text[num],0,@fonts)
              @indexes.push(num)
            end
          end
        end
      end
      if num != nil && line != nil
        @digits[0].oy = num * @wh
        # □文字色の変更
        @digits[0].ox = line * @cw
      else
        # □非表示
        @digits[0].oy = (-1) * @wh
      end
    end
  end
  #--------------------------------------------------------------------------
  # ■ カウントダウンの更新
  #     num        : 列番号(数値)
  #     line       : カラー行番号(fonts.normals配列番号)
  #     se         : SEファイル or SEファイル名
  #--------------------------------------------------------------------------
  def count_down(num,line = 0,se = nil)
    if @old_value != 0
      # □PC時間を取得
      @new_time = Time.now
      if Graphics.frame_count / Graphics.frame_rate != @skip_sec
        # □PC時間を保存
        if @old_time == nil
          @old_time = @new_time
        end
        @old_time += 1
        # □カウントダウン SE を演奏
        if se != nil
          if se.is_a?(RPG::AudioFile)
            $game_system.se_play(se)
          else
            $game_system.se_play(RPG::AudioFile.new(se))
          end
        end
        @old_value = old_lose_value?(1)
        # □ゲームが設定カウント以上、止まっている場合、カウントを0にする
        @next_time = @new_time - @old_time
        if @next_time > @old_value
          @old_value = 0
        end
        # □更新
        refresh(@old_value,line)
      end
      @skip_sec = Graphics.frame_count / Graphics.frame_rate
      return false
    else
      # □カウントの停止
      count_stop(num)
      return true
    end
  end
  #--------------------------------------------------------------------------
  # ■ 解放
  #--------------------------------------------------------------------------
  def dispose
    @digits.each{ |a| if a.viewport != nil ; a.viewport.dispose ; end }
    @digits.each{ |a| if a != nil ; a.dispose ; end }
    @digits = nil
  end
  #--------------------------------------------------------------------------
  # ■ カウントの停止
  #--------------------------------------------------------------------------
  def count_stop(count)
    @skip_sec = nil ; @old_time = nil ; @old_value = count
  end
  #--------------------------------------------------------------------------
  # ■ 値の増加 (減少)
  #--------------------------------------------------------------------------
  def old_gain_value?(n)
    @old_value = [[@old_value + n, 0].max, @max_value].min
  end
  #--------------------------------------------------------------------------
  # ■ 値の減少
  #--------------------------------------------------------------------------
  def old_lose_value?(n)
    # □数値を逆転して old_gain_value を呼ぶ
    old_gain_value?(-n)
  end
  #--------------------------------------------------------------------------
  # ■ 数値を１桁の配列に変換
  #--------------------------------------------------------------------------
  def make_number_digits?(num,max,min = 10)
    # □数値以外の場合は非表示
    unless num.is_a?(Numeric)
      return [10]*max
    end
    ds = num.abs > 0 ? [[(Math.log10(num.abs).to_i) + 1, 1].max,10].min : 1
    # □numの桁数が初期値より多くなる場合のエラー
    if (max-ds) < 0
      p "指定した桁数は" + ds.to_s + "桁の為、" + max.to_s + "桁を指定してください。" ;Error!
    end
    digits = [min]*(max-ds)
    for i in 1..ds
      digits.push(num/(10**(ds-i)))
      num = num%(10**(ds-i))
    end
    return digits
  end
  #--------------------------------------------------------------------------
  # ■ 桁数から回転数値のMax値を取得
  #--------------------------------------------------------------------------
  def make_number_digits_max?(max)
    max_value = 9
    if max > 1
      for n in 1..(max-1)
        max_value += ((10**n)*9)
      end
    end
    return max_value
  end
  #--------------------------------------------------------------------------
  # ■ アイコン描画の取得
  #--------------------------------------------------------------------------
  def icon_check?(data,n)
    # □アイコン描画のチェック
    if data.is_a?(RPG::Item) or data.is_a?(RPG::Weapon) or 
      data.is_a?(RPG::Armor) or data.is_a?(RPG::Skill)
      return [data.name,RPG::Cache.icon(data.icon_name),Rect.new(0,0,24,24),data.icon_name]
    # □rect画像描画のチェック
    elsif data.is_a?(Rect_Draw_Icon)
      icon = RPG::Cache.windowskin(data.name)
      rx = data.rx != nil ? data.rx : n*data.rw
      ry = data.ry != nil ? data.ry : n*data.rh
      # □キャッシュキーに追加するテキストを作成
      kplus = data.text + "/" +  data.name + "/" + data.id.to_s + rx.to_s + "/" + ry.to_s
      return [data.text,icon,Rect.new(rx,ry,data.rw,data.rh),kplus]
    end
    return nil
  end
  #--------------------------------------------------------------------------
  # ■ 回転数値ウィンドウの作成
  #--------------------------------------------------------------------------
  def number_digits?(x,y,z,num,max,min,fonts)
    numbers = make_number_digits?(num,max,min)
    if @digits == []
      # □縦回転の文字送りとY座標の補正値を取得
      if fonts.size > 32
        @wh = (fonts.size/32)*32+32
        # □文字の描画Y座標を1行の高さ(32)の中央に補正
        @cy = (@wh-32)/32*32/2
      else
        @wh = 32 ; @cy = 0
      end
      # □囲み文字の幅を補正
      bw = fonts.round ? 3 : 1
      bx = fonts.round ? 2 : 0
      b = RPG::Cache.dummy_bitmap?
      @fonts.rewrite(b.font)
      @cw = b.text_size("0").width + fonts.interval + bw
      ch = @wh*11
      # □横回転数値のX補正
      cx = fonts.colors.size+1
      for d in 0...numbers.size
        @digits[d] = Sprite.new(Viewport.new(0,0,@cw,@wh))
        if @debug
          @digits[d].viewport.color = Color.new(rand(20*d),rand(20*d),rand(20*d),80)
        end
        @digits[d].bitmap = Bitmap.new(@cw*cx,ch)
        @digits[d].viewport.z = z
        # □XY座標を更新
        @digits[d].viewport.rect.x = x + (d*(@cw-bx))
        @x_es[d] = x + (d*(@cw-bx))
        @digits[d].viewport.rect.y = y+16-@cy
        @y_es[d] = y-@cy
      end
      # □数値配列を作成(キャッシュ化)
      if (RPG::Cache.digits(fonts.key)) == nil
        # □影文字のBitmapを作成
        digits = Bitmap.new(@cw*cx,ch)
        # □行通常色が指定されている場合(縦回転)
        for i in 0..9
          dup_font = @fonts.data
          # □中真に描画
          digits.draw_cache_text(1,i*@wh,@cw,@wh,i.to_s,0,dup_font)
          # □列通常色が指定されている場合(横回転)
          for c in 0...fonts.colors.size
            # □フォント情報を取得
            dup_font = @fonts.data
            dup_font.color = fonts.colors[c]
            # □列影色が指定されている場合
            dup_font.s_color = fonts.s_colors[c]
            digits.draw_cache_text(1+@cw*(c+1),i*@wh,@cw,@wh,i.to_s,0,dup_font)
          end
        end
        # □bitmapをキャッシュ化
        RPG::Cache.digits(fonts.key,digits)
      else
        # □キャッシュからbitmapを指定
        digits = RPG::Cache.digits(fonts.key)
      end
      for d in 0...numbers.size
        @digits[d].bitmap = digits
        @digits[d].oy = numbers[d] * @wh
      end
    else
      for d in 0...numbers.size
        @digits[d].oy = numbers[d] * @wh
        @digits[d].viewport.z = z
      end
    end
  end
  #--------------------------------------------------------------------------
  # ■ テキストウィンドウの作成(囲み文字の補正x+1)
  #--------------------------------------------------------------------------
  def rapid_text?(x,y,z,num,text,fonts,push)
    @fonts = fonts.dup
    if @digits == []
      # □縦回転の文字送りとY座標の補正値を取得
      if @fonts.size > 32
        @wh = (@fonts.size/32)*32+32
        # □文字の描画Y座標を1行の高さ(32)の中央に補正
        @cy = (@wh-32)/32*32/2
      else
        @wh = 32 ; @cy = 0
      end
      @cw = 0
      # □最大幅取得用のBitmapを作成
      max_w = RPG::Cache.dummy_bitmap?
      @fonts.rewrite(max_w.font)
      # □最大幅のテキストを取得
      for i in 0...text.size
        icon = icon_check?(text[i],i)
        # □アイコンの描画
        if icon != nil
          ix = [(icon[2].width)/6,0].max
          iy = [16 - (icon[2].height/2),0].max
          text_w = icon[0]
          icon_w = icon[2].width + ix
        else
          text_w = text[i] ; icon_w = 0
        end
        if @cw < max_w.text_size(text_w).width+2+icon_w
          @cw = max_w.text_size(text_w).width+2+icon_w
        end
      end
      # □Bitmapの幅と高さを取得(italic補正fonts.size/2)
      ch = [@wh*text.size,1].max
      # □横回転テキストのX補正
      @digits.push(Sprite.new(Viewport.new(0,0,@cw,@wh)))
      if @debug
        @digits[0].viewport.color = Color.new(rand(20),rand(20),rand(20),100)
      end
      @digits[0].bitmap = Bitmap.new([@cw*@max_text,1].max,ch)
      @digits[0].viewport.z = z
      # □XY座標を更新
      @digits[0].viewport.rect.x = x - 1
      @digits[0].viewport.rect.y = y+16-@cy
      # □テキスト配列を作成(キャッシュ化)
      if (RPG::Cache.digits(@key)) == nil
        # □影文字のBitmapを作成
        rapids = Bitmap.new([@cw*@max_text,1].max,ch)
        #…………………………………………………………………………………………………
        # ■追加テキスト以外の場合
        #…………………………………………………………………………………………………
        unless push
          # □通常色の描画
          for i in 0...text.size
            icon = icon_check?(text[i],i)
            # □行通常色が指定されている場合(縦回転)
            if @fonts.normals[i].is_a?(Color)
              @fonts.color = @fonts.normals[i]
            else
              @fonts.color = fonts.color
            end
            # □行影色が指定されている場合
            if @fonts.shadows[i].is_a?(Color)
              @fonts.s_color = @fonts.shadows[i]
            else
              @fonts.s_color = fonts.s_color
            end
            dup_font = @fonts.data
            # □アイコンの描画
            if icon != nil
              ix = [(icon[2].width)/6,0].max
              rapids.blt(1,i*@wh+iy,icon[1],icon[2])
              rapids.draw_cache_text(icon[2].width+ix+1,i*@wh,@cw,@wh,icon[0],0,dup_font)
            else
              rapids.draw_cache_text(1,i*@wh,@cw,@wh,text[i],0,dup_font)
            end
            # □列通常色が指定されている場合(横回転)
            for c in 0...@fonts.colors.size
              @fonts.color = fonts.colors[c]
              # □フォント情報を取得
              dup_font = @fonts.data
              dup_font.color = fonts.colors[c]
              # □列影色が指定されている場合
              dup_font.s_color = fonts.s_colors[c]
              icon = icon_check?(text[i],i)
              # □アイコンの描画
              if icon != nil
                ix = [(icon[2].width)/6,0].max
                rapids.blt(1+@cw*(c+1),i*@wh+iy,icon[1],icon[2])
                rapids.draw_cache_text(icon[2].width+ix+1+@cw*(c+1),i*@wh,@cw,@wh,icon[0],0,dup_font)
              else
                rapids.draw_cache_text(1+@cw*(c+1),i*@wh,@cw,@wh,text[i],0,dup_font)
              end
            end
            @fonts.color = fonts.color
            @fonts.s_color = fonts.s_color
          end
        end
        # □bitmapをキャッシュ化
        RPG::Cache.digits(@key,rapids)
        @rapids = RPG::Cache.digits(@key)
      else
        # □キャッシュからbitmapを指定
        @rapids = RPG::Cache.digits(@key)
      end
      @digits[0].bitmap = @rapids
      @digits[0].oy = num * @wh
    else
      @digits[0].oy = num * @wh
      @digits[0].viewport.z = z
    end
  end
end
#==============================================================================
# ■ draw_cache_text vol.3.00
# Bitmap.draw_cache_text(X座標,Y座標,幅,高さ,テキスト,アレンジ,文字装飾)
#------------------------------------------------------------------------------
# Bitmap.draw_cache_textで描画したテキストは、
# 次回からキャッシュ読み込みの為、高速で描画。
# 
# ※文字装飾は『class Copy_Font』から取得
#==============================================================================
class Bitmap
  #--------------------------------------------------------------------------
  # ■ テキストを描画
  #--------------------------------------------------------------------------
  def draw_cache_text(x = 0,y = 0,width = 1,height = 1,text = "",align = 0,fonts = Copy_Font.new,save = true)
    # □キャッシュ最大数を超えた場合はキャッシュしない
    if RPG::Cache.cache_size[0] > 3000
      seve = false
    end
    if text == "" or text == nil
      return
    end
    if text.is_a?(Numeric)
      p "指定した文字列は数値 :" + text.to_s ;Error!
    end
    new_text = text.dup
    icon_names = text.scan(/\\icon\[(.*?)\]/)
    # □無効なアイコン名は削除
    icon_names.delete([""])
    # □制御文字を改行文字に置換
    new_text = new_text.gsub(/\\icon\[(.*?)\]/) {"\n"}
    w_text = new_text.gsub(/\\icon\[(.*?)\]/) {""}
    # □テキストの文字幅を取得
    unless width.is_a?(Numeric) or height.is_a?(Numeric)
      width = 1 ; height = 1
    end
    # □0の場合、幅と高さを文字幅から取得
    width = width == 0 ? fonts.text_width(w_text) : width
    height = height == 0 ? fonts.text_height(w_text) : height
    # □ダミーBitmapを取得(エラー対策)
    bitmap = RPG::Cache.cache_new?(0,0,[width,1].max,[height,1].max)
    cw = fonts.text_width(text) * 1.00
    max = 1 ; iw = icon_names.size
    if cw > width
      max = [(width - (iw*32))/cw,0.6].max
      iw = 0
    end
    ax = 0
    case align
    when 1
      ax = ((width-cw*max)/2.0)-(iw*16)
    when 2
      ax -= fonts.text_width(w_text)
      ax += width
    end
    # □アイコンの描画
    num = 0
    new_text.each_line do |a|
      w = bitmap.text_size(a).width
      a = a.gsub(/\n/) {""}
      if cw > width
        w = (bitmap.text_size(a).width * max).floor
      end
      pic = RPG::Cache.cache_new?(0,0,[width,1].max,[height,1].max,a,align,fonts,save)
      # □テキストを描画
      if pic == nil
        return
      end
      self.blt(x-1+ax,y,pic,Rect.new(0,0,pic.width,pic.height))
      ax += w
      cx = (4*max).floor
      # □アイコンが指定されていればアイコンを描画
      if icon_names[num] != nil && icon_names[num] != ""
        icon = RPG::Cache.icon(icon_names[num][0])
        self.blt(x-1+ax+cx,y+4,icon,Rect.new(0,0,24,24))
        ax += (24 + cx*2)
        num += 1
      end
    end
  end
  #--------------------------------------------------------------------------
  # ■ 影/囲み文字テキストを描画(キャッシュ化しない)
  #--------------------------------------------------------------------------
  def draw_frame_text(x = 0,y = 0,width = 1,height = 1,text = "",align = 0,fonts = Copy_Font.new)
    draw_cache_text(x,y,width,height,text,align,fonts,false)
  end
  #--------------------------------------------------------------------------
  # ■ 数値描画
  #--------------------------------------------------------------------------
  def draw_number_text(x = 0,y = 0,width = 1,height = 1,num = 0,align = 0,fonts = Copy_Font.new,save = true)
    unless num.is_a?(Numeric)
      num = num.to_i
    end
    ds = num.abs > 0 ? [[(Math.log10(num.abs).to_i) + 1, 1].max,10].min : 1
    digits = []
    for i in 1..ds
      digits.push(num/(10**(ds-i)))
      num = num%(10**(ds-i))
    end
    x -= ((fonts.size/2.00)*(ds-1))
    for n in digits
      draw_cache_text(x,y,width,height,n.to_s,align,fonts,save)
      x += (fonts.size/2.00)
    end
  end
  #--------------------------------------------------------------------------
  # ■数値画像描画
  # x :X座標 y :Y座標  width :描画幅 w :1文字の幅 h :1文字の高さ image :数値画像
  # value :値 align :(0..左揃え、1..中央揃え、2..右揃え)
  # type :縦方向(色) interval :字間(+-) zero :01表示(桁数の指定)
  # point :小数桁の範囲(第n位まで),decimal :小数桁数の指定
  # front :頭に付ける文字列 back :後ろに付ける文字列
  #--------------------------------------------------------------------------
  def draw_numbers(x,y,width,w,h,image,value,
    align = 0,type = 0,interval = 0,zero = 0,point = 2,decimal = 0,front = [],back = [])
    vanish = Color.new(0,0,0,0)
    if value.is_a?(Numeric)
      # □1以下小数の取得
      dm = value > 0 && value < 1 ? 1 : 0
      # □負の整数を取得
      minus = value < 0 ? 1 : 0
      # □絶対値に変換(-)削り
      value = value.abs
      # □小数の取得
      num = (value*(10 ** point)).floor % (10 ** point)
      # □小数の桁数を取得
      chenge = false
      if num > 0
        decimal = Math.log10(value).to_i + 1
        value = (value*(10 ** point)).floor
        min = w/2+interval
      elsif decimal > 0
        if value == 0
          value = 10 ** point
          chenge = true
        else
          value = (value*(10 ** point)).floor
        end
        min = w/2+interval
      else
        decimal = 0
        min = 0
      end
      value = value.floor
      # □常用対数を取得
      if value > 0
        digit = Math.log10(value).to_i + dm
      else
        digit = dm
      end
      if zero > 0
        digit = zero
      end
      dw = -(width - ((digit + minus + front.size + back.size + 1) * (w+interval) + min - interval))
      if width == 0
        width = ((digit + minus + front.size + back.size + 1) * (w+interval) + min - interval)
        dw = 0
      end
      # □桁数による位置の補正
      case align
      when 0
        fill_rect(Rect.new(x,y,width,h),vanish)
      when 1
        fill_rect(Rect.new(x,y,width,h),vanish)
        x = x + (width / 2) - ((digit + minus + front.size + back.size + 1) * (w+interval) + min)/2
      when 2
        x -= ((digit + minus + front.size + back.size + 1) * (w+interval) + min)
        fill_rect(Rect.new(x+dw,y,width,h),vanish)
      end
      cx = 0 ; n = 0 ; max = digit - point
      # □数値画像を並べて表示
      while digit >= 0
        # □頭に付ける文字列
        if front != []
          for t in 0...front.size
            fill_rect(Rect.new(x+cx+(interval*n)-interval,y,w+interval,h),vanish)
            blt(x+cx+(interval*n),y,image,Rect.new(front[t]*w,type*h,w,h))
            cx += (w+interval)
          end
          front = []
        end
        # □不等号の描画
        if minus > 0
          fill_rect(Rect.new(x+cx+(interval*n)-interval,y,w+interval,h),vanish)
          blt(x+cx+(interval*n),y,image,Rect.new(11*w,type*h,w,h))
          cx += (w+interval)
          minus = 0
        end
        # □小数点の描画
        if decimal > 0 && n-1 == max
          fill_rect(Rect.new(x+cx+(interval*n)-interval,y,w,h),vanish)
          blt(x+cx+(interval*n),y,image,Rect.new(10*w,type*h,w/2,h))
          cx += (w/2+interval)
        end
        # □整数の描画
        fill_rect(Rect.new(x+cx+(interval*n)-interval,y,w,h),vanish)
        if chenge && n == 0
          blt(x+cx+(interval*n),y,image,Rect.new(0,type*h,w,h))
        else
          blt(x+cx+(interval*n),y,image,Rect.new((value/(10 ** digit))*w,type*h,w,h))
        end
        cx += w
        n += 1
        value %= 10 ** digit
        digit -= 1
      end
      # □後ろに付ける文字列
      if back != []
        for t in 0...back.size
          fill_rect(Rect.new(x+cx+(interval*n)-interval,y,w+interval,h),vanish)
          blt(x+cx+(interval*n),y,image,Rect.new(back[t]*w,type*h,w,h))
          cx += (w+interval)
        end
        back = []
      end
    end
  end
end
#==============================================================================
# ■ Rect_Draw_Icon vol.1.00
#------------------------------------------------------------------------------
# 画像をrect描画する情報を格納するクラス
#==============================================================================
class Rect_Draw_Icon
  attr_accessor :text          # テキスト
  attr_accessor :name          # 画像名
  attr_accessor :id            # 番号
  attr_accessor :rx            # rect.x
  attr_accessor :ry            # rect.y
  attr_accessor :rw            # rect.width
  attr_accessor :rh            # rect.height
  attr_accessor :icon          # 画像
  #--------------------------------------------------------------------------
  # ■ オブジェクト初期化
  #--------------------------------------------------------------------------
  def initialize(text,name,id,rx,ry,rw,rh)
    @text = text ; @name = name ; @id = id ; @icon = icon
    @rx = rx ; @ry = ry ; @rw = rw ; @rh = rh
  end
end
#==============================================================================
# ■ Copy_Font vol.2.30
#------------------------------------------------------------------------------
# 文字の装飾を格納するクラス
#==============================================================================
class Copy_Font
  #--------------------------------------------------------------------------
  # ■ カスタマイズ項目(書き換え可)
  #--------------------------------------------------------------------------
  def customize? 
    # □影文字の描画位置 [[x,y]]
    @styl_s = [[1,1]]
    # ※ずらし影 [[2,2]]
    
    # □囲み文字の描画位置(8方向囲み)
    @styl_b = [[1,1],[1,-1],[-1,1],[-1,-1],[1,0],[0,1],[-1,0],[0,-1]]
    #
    # ※8方向2度囲み [[1,1],[1,-1],[-1,1],[-1,-1],[1,0],[0,1],[-1,0],
    #              [0,-1],[1,1],[1,-1],[-1,1],[-1,-1],[1,0],[0,1],[-1,0],[0,-1]]
    # ※4方向囲み [[1,1],[1,-1],[-1,1],[-1,-1]]
  end
  #--------------------------------------------------------------------------
  # ■ 公開インスタンス変数(以下書き換え不可)
  #--------------------------------------------------------------------------
  attr_accessor :size          # フォントサイズ
  attr_accessor :bold          # ボールドフラグ
  attr_accessor :italic        # イタリックフラグ
  attr_accessor :shadow        # 影文字フラグ
  attr_accessor :round         # 囲み文字フラグ
  attr_accessor :name          # フォント名
  attr_accessor :color         # フォントの色
  attr_accessor :s_color       # 影,囲み文字の色
  attr_accessor :interval      # 字間
  attr_accessor :colors        # 列文字色を格納
  attr_accessor :s_colors      # 列影文字色を格納
  attr_accessor :normals       # 行文字色を格納
  attr_accessor :shadows       # 行影文字色を格納
  attr_accessor :key           # キャッシュのキー
  attr_reader   :styl_s        # 影文字の描画位置
  attr_reader   :styl_b        # 囲み文字の描画位置
  #--------------------------------------------------------------------------
  # ■ オブジェクト初期化
  #--------------------------------------------------------------------------
  def initialize(size = Font.default_size,bold = Font.default_bold,
    italic = Font.default_italic,shadow = false,round = false,name = Font.default_name,
    color = Font.default_color,s_color = Color.new(0,0,0,255),interval = 0,colors = [],
    normals = [],shadows = [],s_colors = [])
    
    @size = size ; @bold = bold ; @italic = italic ; @shadow = shadow ; @round = round
    @name = name ; @color = color ; @s_color = s_color ; @interval = interval
    @colors = colors ; @normals = normals ; @shadows = shadows
    @s_colors = s_colors
    if @s_colors.size != @colors.size
      for i in 0...@colors.size
        @s_colors.push(@s_color)
        if @s_colors.size == @colors.size
          break
        end
      end
    end
    @key = cache_key?
    # □カスタマイズ項目の初期化
    customize?
  end
  #--------------------------------------------------------------------------
  # ■ フォントサイズの更新
  #--------------------------------------------------------------------------
  def size=(size)
    @size = size ; @key = cache_key?
  end
  #--------------------------------------------------------------------------
  # ■ ボールド(太文字)の更新
  #--------------------------------------------------------------------------
  def bold=(bold)
    @bold = bold ; @key = cache_key?
  end
  #--------------------------------------------------------------------------
  # ■ イタリック(斜め文字)の更新
  #--------------------------------------------------------------------------
  def italic=(italic)
    @italic = italic ; @key = cache_key?
  end
  #--------------------------------------------------------------------------
  # ■ 影文字の更新
  #--------------------------------------------------------------------------
  def shadow=(shadow)
    @shadow = shadow ; @key = cache_key?
  end
  #--------------------------------------------------------------------------
  # ■ 囲み文字の更新
  #--------------------------------------------------------------------------
  def round=(round)
    @round = round ; @key = cache_key?
  end
  #--------------------------------------------------------------------------
  # ■ フォント名の更新
  #--------------------------------------------------------------------------
  def name=(name)
    @name = name ; @key = cache_key?
  end
  #--------------------------------------------------------------------------
  # ■ 文字の色の更新
  #--------------------------------------------------------------------------
  def color=(color)
    @color = color ; @key = cache_key?
  end
  #--------------------------------------------------------------------------
  # ■ 影,囲み文字の色の更新
  #--------------------------------------------------------------------------
  def s_color=(s_color)
    @s_color = s_color ; @key = cache_key?
  end
  #--------------------------------------------------------------------------
  # ■ 字間の更新
  #--------------------------------------------------------------------------
  def interval=(interval)
    @interval = interval ; @key = cache_key?
  end
  #--------------------------------------------------------------------------
  # ■ 列文字色の更新
  #--------------------------------------------------------------------------
  def colors=(colors)
    if @s_colors.size != @colors.size
      for i in 0...@colors.size
        @s_colors.push(@s_color)
        if @s_colors.size == @colors.size
          break
        end
      end
    end
    @colors = colors ; @key = cache_key?
  end
  #--------------------------------------------------------------------------
  # ■ 列影文字色の更新
  #--------------------------------------------------------------------------
  def s_colors=(s_colors)
    @s_colors = s_colors ; @key = cache_key?
  end
  #--------------------------------------------------------------------------
  # ■ 行文字色の更新
  #--------------------------------------------------------------------------
  def normals=(normals)
    @normals = normals ; @key = cache_key?
  end
  #--------------------------------------------------------------------------
  # ■ 行影文字色の更新
  #--------------------------------------------------------------------------
  def shadows=(shadows)
    @normals = normals ; @key = cache_key?
  end
  #--------------------------------------------------------------------------
  # ■ Fontの一括代入
  #--------------------------------------------------------------------------
  def rewrite(font,all = false)
    font.size = @size ; font.bold = @bold
    font.italic = @italic ; font.name = @name
    if all
      font.color = @color
      font.name = @name
    end
  end
  #--------------------------------------------------------------------------
  # ■ テキストの幅を取得
  #--------------------------------------------------------------------------
  def text_width(text)
    bitmap = RPG::Cache.dummy_bitmap?
    rewrite(bitmap.font)
    w = bitmap.text_size(text).width
    return w
  end
  #--------------------------------------------------------------------------
  # ■ テキストの高さを取得
  #--------------------------------------------------------------------------
  def text_height(text)
    bitmap = RPG::Cache.dummy_bitmap?
    rewrite(bitmap.font)
    h = bitmap.text_size(text).height
    bitmap.dispose ; bitmap = nil
    return h
  end
  #--------------------------------------------------------------------------
  # ■ キャッシュに必要なFont情報を取得
  #--------------------------------------------------------------------------
  def data
    data = self.dup ; data.colors = [] ; data.s_colors = []
    data.normals = [] ; data.shadows = []
    return data
  end
  #--------------------------------------------------------------------------
  # ■ キャッシュキーの追加と取得
  #--------------------------------------------------------------------------
  def cache_key?(plus = "")
    key = (key?(@size)+key?(@bold)+key?(@italic)+key?(@shadow)+key?(@round)+key?(@interval))
    for n in @name
      key += key?(n)
    end
    # □色情報を取得
    for cs in [[@color],[@s_color],@colors,@normals,@shadows,@s_colors]
      if cs == []
        key += ("[]/")
      end
      for n in cs
        if n.is_a?(Color)
          key += ("["+key?(n.red,".")+key?(n.green,".")+key?(n.blue,".")+key?(n.alpha,"")+"]/")
        end
      end
    end
    key = plus + key
    # □キャッシュキーの再構築
    @key = key
    return key
  end
  #--------------------------------------------------------------------------
  # ■ データをテキスト化(外部操作不可)
  #--------------------------------------------------------------------------
  def key?(data,plus = "/")
    if data.is_a?(Numeric)
      ks = data.round.to_s + plus
    elsif data == true
      ks = "t" + plus
    elsif data == false
      ks = "f" + plus
    else
      ks = data.to_s + plus
    end
    return ks
  end
end
#==============================================================================
# ■ Make_Cache vol.1.00
#------------------------------------------------------------------------------
# bitmap == nil キャッシュ呼び出し
# bitmap != nil キャッシュ化
#==============================================================================
module RPG
 module Cache
  #--------------------------------------------------------------------------
  # ■ 
  #--------------------------------------------------------------------------
  def self.digits(key,bitmap = nil)
    if @cache[key].nil? or @cache[key].disposed?
      @cache[key] = bitmap
    end
    return @cache[key]
  end
  #--------------------------------------------------------------------------
  # ■ 
  #--------------------------------------------------------------------------
  def self.cache_size
    return [@cache.size,@cache_size]
  end
  #--------------------------------------------------------------------------
  # ■ ダミーBitmapを取得(エラー対策)
  #--------------------------------------------------------------------------
  def self.dummy_bitmap?
    if @dummy_bitmap.nil? or @dummy_bitmap.disposed?
      @dummy_bitmap = Bitmap.new(1,1)
    end
    return @dummy_bitmap
  end
  #--------------------------------------------------------------------------
  # ■ 描画するテキストをキャッシュ化
  #--------------------------------------------------------------------------
  def self.cache_new?(x,y,width,height,text = "",align = 0,fonts = Copy_Font.new,save = true)
    # □囲み文字/影文字の補正
    if text == nil
      return nil
    end
    # □ダミーBitmapを取得(エラー対策)
    bit = RPG::Cache.dummy_bitmap?
    # □テキスト幅/高さを取得
    twidth = bit.text_size(text).width
    theight = bit.text_size(text).height
    # □(twidth > width)自動で文字幅を補正する場合
    k0 = twidth > width ? "**/tw" + twidth.to_s : "**/w" + width.to_s
    # □heightをキャッシュキーに追加
    k1 = theight > height ? "**/th" + theight.to_s : "**/h" + height.to_s
    # □キャッシュキーを作成
    key = fonts.cache_key?("**" + text + k0 + "/" + k1 + "/")
    # □キャッシュを返す
    if save
      if (RPG::Cache.digits(key)) != nil
        if @cache_size == nil
          @cache_size = 0
        end
        @cache_size += 1
        return RPG::Cache.digits(key)
      end
    end
    # □Bitmapを作成
    bitmap = Bitmap.new(width+2,height+2)
    fonts.rewrite(bitmap.font)
    bitmap.font.color = fonts.color
    # □テキストの描画
    if fonts.shadow or fonts.round
      # □ダミーBitmapを取得(エラー対策)
      back = bitmap.dup
      fonts.rewrite(back.font)
      back.font.color = fonts.s_color
      back.draw_text(x+1,y,width,height,text)
      if fonts.shadow
        text_type = fonts.styl_s
      end
      if fonts.round
        text_type = fonts.styl_b
      end
      for s in text_type
        bitmap.blt(s[0],s[1],back,Rect.new(0,0,width,height))
      end
      back.dispose ; back = nil
    end
    bitmap.draw_text(x+1,y,width,height,text)
    # □キャッシュ化
    if save
      RPG::Cache.digits(key,bitmap)
    end
    return bitmap
  end
 end
end