Advertisement
Guest User

Untitled

a guest
Aug 15th, 2011
694
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 10.27 KB | None | 0 0
  1. ##################
  2. #
  3. #   Bitmap Fonts, (C) 2008 Peter O.
  4. #
  5.  
  6.  
  7. ##################
  8. #
  9. #   Modified marshal class for reading raw data,
  10. #   even within encrypted archives
  11. #
  12.  
  13. module ::Marshal
  14.   class << self
  15.     if !@oldloadAliased
  16.       alias oldload load
  17.       @oldloadAliased=true
  18.     end
  19.     def neverload
  20.       return @@neverload
  21.     end
  22.     @@neverload=false
  23.     def neverload=(value)
  24.       @@neverload=value
  25.     end
  26.     def load(port,*arg)
  27.        if @@neverload
  28.          if port.is_a?(IO)
  29.             return port.read
  30.          else
  31.             return port
  32.          end
  33.        end
  34.        oldpos=port.pos if port.is_a?(IO)
  35.        begin
  36.           oldload(port,*arg)
  37.        rescue
  38.           if port.is_a?(IO)
  39.             port.pos=oldpos
  40.             return port.read
  41.           else
  42.             return port
  43.           end
  44.        end
  45.     end
  46.   end
  47. end
  48.  
  49. def loadRawData(file)
  50.   oldload=Marshal.neverload
  51.   begin
  52.      ret=load_data(file)
  53.      return ret
  54.   rescue
  55.      return ""
  56.   ensure
  57.      Marshal.neverload=oldload
  58.   end
  59. end
  60.  
  61.  
  62. ##################
  63. #
  64. #   CSV Routines
  65. #
  66.  
  67.  
  68.   def csvfield!(str)
  69.     ret=""
  70.     str.sub!(/^\s*/,"")
  71.     return nil if str.length==0
  72.     if str[0,1]=="\""
  73.       str[0,1]=""
  74.       escaped=false
  75.       fieldbytes=0
  76.       str.scan(/./) do |s|
  77.        fieldbytes+=s.length
  78.        break if s=="\"" && !escaped
  79.        if s=="\\" && !escaped
  80.          escaped=true
  81.        else
  82.          ret+=s
  83.          escaped=false
  84.        end
  85.       end
  86.       str[0,fieldbytes]=""
  87.       # Remove everything before the comma
  88.       str.sub!(/^[^,]*,?/,"")
  89.     else
  90.       if str[/,/]
  91.        str[0,str.length]=$~.post_match
  92.        ret=$~.pre_match
  93.       else
  94.        ret=str.clone
  95.        str[0,str.length]=""
  96.       end
  97.       ret.gsub!(/\s+$/,"")
  98.     end
  99.     return ret
  100.   end
  101.  
  102.   def csvGetPosInt(ret)
  103.   if !ret || !ret[/^\d+$/]
  104.     return nil
  105.   end
  106.   return ret.to_i
  107.   end
  108.  
  109.   def csvGetInt(ret)
  110.   if !ret || !ret[/^\-?\d+$/]
  111.     return nil
  112.   end
  113.   return ret.to_i
  114.   end
  115.  
  116.   def csvGetFields(str)
  117.   str=str.dup
  118.   ret=[]
  119.   loop do
  120.     field=csvfield!(str)
  121.     if field==nil
  122.       return ret
  123.     end
  124.     ret.push(field)
  125.   end
  126.   end
  127.  
  128.  
  129.   def pbFileEachPreppedLine(filename)
  130.   data=loadRawData(filename)
  131.   lineno=1
  132.   data.each_line {|line|
  133.       if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
  134.        line=line[3,line.length-3]
  135.       end
  136.       if !line[/^\#/] && !line[/^\s*$/]
  137.        yield line, lineno
  138.       end
  139.       lineno+=1
  140.   }
  141.   end
  142.  
  143.   def getBitmapFontRecords(filename)
  144.   records={}
  145.   # rr=[]
  146.   pbFileEachPreppedLine(filename) {|line, lineno|
  147.     record=csvGetFields(line)
  148.     # converting values to integers
  149.     record[1]=csvGetPosInt(record[1]) # glyph start X
  150.     record[2]=csvGetInt(record[2]) # start X
  151.     record[3]=csvGetPosInt(record[3]) # width
  152.     record[4]=csvGetInt(record[4]) # end X (if unequal to glyph start X + width)
  153.     # checking required string
  154.     if !record[0] || record[0].length==0
  155.       next
  156.     end
  157.     # checking required values
  158.     if !record[1] || !record[2] || !record[3]
  159.       next
  160.     end
  161.     # checking optional value
  162.     if !record[4]
  163.       record[4]=record[1]+record[3]
  164.     end
  165.     records[record[0]]=[
  166.       # Offset from end of last glyph to start of this glyph
  167.       record[1]-record[2],
  168.       # Offset from end of this glyph to start of next glyph
  169.       record[4]-(record[1]+record[3]),
  170.       record[1], # source start X
  171.       record[3]   # source width
  172.     ]
  173.   }
  174.   return records
  175.   end
  176.  
  177.  
  178.   def csvquote(str)
  179.   return "" if !str || str==""
  180.   if str[/[,\"]/] || str[/^\s/] || str[/\s$/] || str[/^#/]
  181.    str=str.sub(/[\"]/,"\\\"")
  182.     str="\"#{str}\""
  183.   end
  184.   return str
  185.   end
  186.  
  187.   ##################
  188.   #
  189.   #   High-speed bitmap access
  190.   #
  191.  
  192.   class Bitmap
  193.     # Fast methods for retrieving bitmap data
  194.     RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
  195.     RtlMoveMemory_ip = Win32API.new('kernel32', 'RtlMoveMemory', 'ipi', 'i')
  196.     def setData(x)
  197.        RtlMoveMemory_ip.call(self.address, x, x.length)      
  198.     end
  199.     def getData
  200.        data = "rgba" * width * height
  201.        RtlMoveMemory_pi.call(data, self.address, data.length)
  202.        return data
  203.     end
  204.     def swap32(x)
  205.       return ((x>>24)&0x000000FF)|
  206.                 ((x>>8)&0x0000FF00)|
  207.                 ((x<<8)&0x00FF0000)|            
  208.                 ((x<<24)&0xFF000000)
  209.     end
  210.     def saveToPng(filename)
  211.       bytes=[
  212.        0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,
  213.        0x00,0x00,0x00,0x0D
  214.       ].pack("CCCCCCCCCCCC")
  215.       ihdr=[
  216.        0x49,0x48,0x44,0x52,
  217.        swap32(self.width),
  218.        swap32(self.height),
  219.        0x08,0x06,0x00,0x00,0x00
  220.       ].pack("CCCCVVCCCCC")
  221.       crc=Zlib::crc32(ihdr)
  222.       ihdr+=[swap32(crc)].pack("V")
  223.       bytesPerScan=self.width*4
  224.       row=(self.height-1)*bytesPerScan
  225.       data=self.getData
  226.       width=self.width
  227.       x=""
  228.       while row>=0
  229.        x+="\0"
  230.        thisRow=data[row,bytesPerScan]
  231.        i=0;while i<width
  232.          b=i<<2
  233.          bp2=b+2
  234.          t=thisRow[b]
  235.          thisRow[b]=thisRow[bp2]
  236.          thisRow[bp2]=t
  237.          i+=1
  238.        end
  239.        x+=thisRow
  240.        row-=bytesPerScan
  241.       end
  242.       x=Zlib::Deflate.deflate(x)
  243.       length=x.length
  244.       x="IDAT"+x
  245.       crc=Zlib::crc32(x)
  246.       idat=[swap32(length)].pack("V")
  247.       idat+=x
  248.       idat+=[swap32(crc)].pack("V")
  249.       idat+=[0,0x49,0x45,0x4E,0x44,0xAE,0x42,0x60,0x82].pack("VCCCCCCCC")
  250.       File.open(filename,"wb"){|f|
  251.        f.write(bytes)
  252.        f.write(ihdr)
  253.        f.write(idat)
  254.       }
  255.     end
  256.     def address
  257.        if !@address
  258.           buffer, ad = "rgba", object_id * 2 + 16
  259.           RtlMoveMemory_pi.call(buffer, ad, 4)
  260.           ad = buffer.unpack("L")[0] + 8
  261.           RtlMoveMemory_pi.call(buffer, ad, 4)
  262.           ad = buffer.unpack("L")[0] + 16
  263.           RtlMoveMemory_pi.call(buffer, ad, 4)
  264.           @address=buffer.unpack("L")[0]
  265.        end
  266.        return @address
  267.     end
  268.   end
  269.  
  270.   ##################
  271.   #
  272.   #   Draws and saves a bitmap font
  273.   #
  274.  
  275.   def drawBitmapFont(bitmap,filename)
  276.   x=0
  277.   height=bitmap.text_size("X").height
  278.   for i in 0x20..0xFF
  279.     next if i>=0x7F && i<0xA0
  280.     s=[i].pack("U")
  281.     x+=bitmap.text_size(s).width+2
  282.   end
  283.   width=x
  284.   x=0
  285.   rbitmap=Bitmap.new([width,1].max,[height,1].max)
  286.   rbitmap.font.name=bitmap.font.name
  287.   rbitmap.font.color=bitmap.font.color
  288.   rbitmap.font.size=bitmap.font.size
  289.   File.open("#{filename}.txt","wb"){|f|
  290.     for i in 0x20..0xFF
  291.       next if i>=0x7F && i<0xA0
  292.       s=[i].pack("U")
  293.       w=rbitmap.text_size(s).width
  294.       f.write(csvquote(s)+",#{x},#{x},#{w+2},#{x+w}\r\n")
  295.       rbitmap.draw_text(x,0,w+2,height,s,0) # EDIT
  296.       x+=w+2
  297.     end
  298.   }
  299.   rbitmap.saveToPng("#{filename}.png")
  300.   end
  301.  
  302.   ##################
  303.   #
  304.   #   Bitmap Font Class
  305.   #
  306.  
  307.   class BitmapFont
  308.   def initialize(bmfont)
  309.     @bitmap=Bitmap.new("Graphics/Pictures/"+bmfont+".png")
  310.     @records=getBitmapFontRecords("Graphics/Pictures/"+bmfont+".txt")
  311.   end
  312.   def textSize(string)
  313.     x=0
  314.     textEndX=0
  315.     records=@records
  316.     string.scan(/./m){|c|
  317.       rec=records[c]
  318.       next if !rec
  319.       x+=rec[0] # move x by offset from end of last glyph
  320.       x+=rec[3] # add glyph width
  321.       textEndX=x # set total width to x
  322.       x+=rec[1] # add offset from end of this glyph
  323.     }
  324.     return Rect.new(0,0,textEndX,@bitmap.height)
  325.   end
  326.   def drawText(bitmap,x,y,width,height,string,alignment=0,opacity=255)
  327.     return if !string || string.length==0
  328.     positions=[]
  329.     records=@records
  330.     realEndX=x+width
  331.     realEndY=y+height
  332.     return if y>=bitmap.height || height<=0
  333.     return if x>=bitmap.width || width<=0
  334.     dstY=y+(height/2)-(@bitmap.height/2)
  335.     srcHeight=height<@bitmap.height ? height : @bitmap.height
  336.     textStartX=x
  337.     first=true
  338.     textEndX=x
  339.     string.scan(/./m){|c|
  340.       rec=records[c]
  341.       next if !rec
  342.       x+=rec[0] # move x by offset from end of last glyph
  343.       textStartX=x if first
  344.       first=false
  345.       break if x>=realEndX || y>=realEndY
  346.       endx=x+rec[3] # x plus glyph width
  347.       endx=width if endx>realEndX
  348.       next if x>=endx
  349.       positions.push([
  350.          # destination
  351.          x,dstY,
  352.          # source
  353.          Rect.new(rec[2],0,endx-x,srcHeight)
  354.       ])
  355.       x+=rec[3] # add glyph width
  356.       textEndX=x
  357.       x+=rec[1] # add offset from end of this glyph
  358.     }
  359.     totalWidth=textEndX-textStartX
  360.     offset=0
  361.     if alignment==1
  362.        offset=(width/2)-(totalWidth/2)
  363.     elsif alignment==2
  364.        offset=width-totalWidth
  365.     end
  366.     for pos in positions
  367.       bitmap.blt(
  368.        pos[0]+offset,pos[1],@bitmap,pos[2]
  369.       )
  370.     end
  371.   end
  372.   end
  373.  
  374.   module BitmapFontCache
  375.     @cache={}
  376.     def self.load(name)
  377.        if @cache.include?(name)
  378.           return @cache[name]
  379.        end
  380.        bmfont=nil
  381.        begin
  382.           bmfont=BitmapFont.new(name)
  383.        rescue
  384.           bmfont=nil
  385.        end
  386.        @cache[name]=bmfont
  387.        return bmfont
  388.     end
  389.   end
  390.  
  391.   class Font
  392.     def checkBitmapFont(name)
  393.        return nil if !name
  394.        if name.is_a?(Array)
  395.           for i in name
  396.             bmfont=BitmapFontCache.load(i)
  397.             return bmfont if bmfont
  398.           end
  399.           return nil
  400.        else
  401.          return BitmapFontCache.load(name)
  402.        end
  403.     end
  404.     def bitmapFont
  405.        return checkBitmapFont(self.name)
  406.     end
  407.   end
  408.  
  409.   class Bitmap
  410.     if !defined?(petero_bitmapfont_text_size)
  411.        alias petero_bitmapfont_text_size text_size
  412.        alias petero_bitmapfont_draw_text draw_text
  413.     end
  414.   def text_size(str)
  415.     bmfont=self.font.bitmapFont
  416.     if bmfont
  417.       return bmfont.textSize(str)
  418.     else
  419.       return petero_bitmapfont_text_size(str)
  420.     end
  421.   end
  422.   def draw_text(*args)
  423.     bmfont=self.font.bitmapFont
  424.     if bmfont
  425.       if args.length==2 || args.length==3
  426.        rc=args[0]
  427.        bmfont.drawText(self,rc.x,rc.y,rc.width,rc.height,
  428.           args[1],args[2] ? args[2] : 0)
  429.       elsif args.length==5 || args.length==6
  430.        bmfont.drawText(self,args[0],args[1],args[2],args[3],
  431.          args[4],args[5] ? args[5] : 0)    
  432.       end
  433.     else
  434.       return petero_bitmapfont_draw_text(*args)    
  435.     end
  436.   end
  437. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement