ShoeBox: Free Cross Platform Sprite Packer/Bitmap Font Tool

ShoeBox is an interesting drag-and-drop tool for Sprite Packing and Bitmap Fonts. Best of all it’s free and cross platform…

http://renderhjs.net/shoebox/

It’s pretty easy to get the Sprite Sheet setup for Corona ImageSheets. Here’s how you do it… Right Click on the Sprite Packer to get to it’s settings.

In the Sprite Sheet Settings this line goes in the File Format Loop :

[lua]\t\t{ name=@ID, x = @x, y = @y, width = @w, height = @h, sourceX=@fx, sourceY=@fy, sourceWidth=@fw , sourceHeight=@fh },\n[/lua]

In the Sprite Sheet Settings this line goes in the File Format Outer :

[lua]local M = {}\nM.sheetData = {\n\tframes = {\n@loop\t},\n\tsheetContentWidth = @W,\n\tsheetContentHeight = @H\n}\nreturn M[/lua]

Finally, Change the " File Name" value to something that ends in “.lua”

Now, drop a bunch of sprites on it and that will pack with the current settings. Hit save and ShoeBox will generate a lua module with the imageSheet data needed to load the newly packed sheets.

To load them, it’s just this simple

[lua]

local test = require(“sheet”)

local imageSheet = graphics.newImageSheet( “sheet.png”, test.sheetData )

[/lua]

I will post examples on my GitHub page with Bitmap Font Support as well.

https://github.com/superqix

Enjoy!

Does this code work for bitmap fonts? Thanks! A.

Here’s the bitmap font code… I’m planning on getting it on GitHub as some point…

[lua]

– ******************************************

– * Shoe Box/AngelCode Bitmap Font support *

– ******************************************

– Adapted from “AngelCode bitmap font support” (bmf.lua) in the CoronaSDK Community

– NOTE: This code is in a grey area as far as licencing goes, I couldn’t contact the

– orignal author, but it was released in the old portion of the Corona Labs site

– by “p120ph37”.

http://developer.coronalabs.com/forum/2011/02/05/bitmap-font

– Updates by Michael Wilson

– April 30, 2013

– 

– * Updated to a table based module

– * Moved from Sprites to Imagesheets

– * Added “path” from forum post by KenRogoway

– * Removed Input object (broken)

local sbFont = {}

local sbFont_mt = { __index = sbFont }

– Specify an Angelcode format bitmap font definition file (".FNT")

– The imagesheet that this file references need to be located in the resource directory.

– Return value is a font object that can be used when calling newString

function sbFont:load( fntFile, path )

    path = path or “”

  local function extract( s, p )

    return string.match( s, p ), string.gsub( s, p, ‘’, 1 )

  end

  local font = { info = {}, spritesheets = {}, sprites = {}, chars = {}, kernings = {} }

   local readline = io.lines( system.pathForFile( path…fntFile, system.ResourceDirectory ) )

  for line in readline do

    local t = {}; local tag;

    tag, line = extract( line, ‘^%s*([%a_]+)%s*’ )

    while string.len( line ) > 0 do

      local k, v

      k, line = extract( line, ‘^([%a_]+)=’ )

      if not k then break end

      v, line = extract( line, ‘^"([^"]*)"%s*’ )

      if not v then

        v, line = extract( line, ‘^([^%s]*)%s*’ )

      end

      if not v then break end

      t[k] = v

    end

    if tag == ‘info’ or tag == ‘common’ then

      for k, v in pairs( t ) do font.info[k] = v end

    elseif tag == ‘page’ then

      font.spritesheets[1 + t.id] = { file = t.file, frames = {} }

    elseif tag == ‘char’ then

      t.letter = string.char( t.id )

      font.chars[t.letter] = {}

      for k, v in pairs( t ) do font.chars[t.letter][k] = v end

      if 0 + font.chars[t.letter].width > 0 and 0 + font.chars[t.letter].height > 0 then

        font.spritesheets[1 + t.page].frames[#font.spritesheets[ 1 + t.page].frames + 1 ] = {

–          textureRect = { x = 0 + t.x, y = 0 + t.y, width = -1 + t.width, height = -1 + t.height },

–          spriteSourceSize = { width = 0 + t.width, height = 0 + t.height },

–          spriteColorRect = { x = 0, y = 0, width = -1 + t.width, height = -1 + t.height },

–          spriteTrimmed = true

          x = 0 + t.x, y = 0 + t.y, width = 0 + t.width, height = 0 + t.height,

        }

        font.sprites[t.letter] = {

          spritesheet = 1 + t.page,

          frame = #font.spritesheets[1 + t.page].frames

        }

      end

    elseif( tag == ‘kerning’ ) then

      font.kernings[string.char( t.first ) … string.char( t.second )] = 0 + t.amount

    end

  end

  for k, v in pairs( font.spritesheets ) do

    --font.spritesheets[k].sheet = sprite.newSpriteSheetFromData( v.file, v )

        font.spritesheets[k].sheet =graphics.newImageSheet( path…v.file, v )

  end

  for k, v in pairs( font.sprites ) do

–    font.sprites[k].frame = sprite.newSpriteSet( font.spritesheets[v.spritesheet].sheet, v.frame, 1 )

    font.sprites[k].frame = v.frame

  end

  return font

end

– extend an object with accessor behaviors

local function accessorize( t )

  local mt = getmetatable( t )

  setmetatable( t, {

    __index = function( t, k )

      if rawget( t, ‘get_’…k ) then

        return rawget(t, ‘get_’…k )( t, k )

      elseif rawget( t, ‘raw_’…k ) then

          return rawget( t, ‘raw_’…k )

      elseif mt.__index then

        return mt.__index( t, k )

      else

        return nil

        end

    end,

    __newindex = function( t, k, v )

          if rawget( t, ‘set_’…k ) then

            rawget( t, ‘set_’…k )( t, k, v )

        elseif rawget( t, ‘raw_’…k ) then

          rawset( t, ‘raw_’…k, v )

        elseif mt.__newindex then

          mt.__newindex( t, k, v )

        else

          rawset( t, ‘raw_’…k, v )

        end

    end,

  } )

end

– extend an object with cascading removeSelf

local function removerize( t )

  local old = t.removeSelf

  t.removeSelf = function( o )

    for i = o.numChildren, 1, -1 do o[i]:removeSelf() end

    old( o )

  end

end

– Pass a font object (obtained from loadFont) and a string to render

– Return value is a DisplayObject of the rendered string

– object.font can be read/modifed

– object.text can be read/modified

– object.align can be read/modified - left/right/center (multiline not yet fully supported for non-left)

– object.input( function(text), { filter = function(), max = 32 } )

–   turns the object into a text input.

–   the callback is hit when the user presses “return” or the field losed focus.

–   this code is under development - more documentation will be added soon…

function sbFont:newString( font, text )

  local obj = display.newGroup()

  accessorize( obj )

  removerize( obj )

  obj.set_font = function( t, k, v )

    obj.raw_font = v

    if t.text then t.text = t.text end

  end

  obj.set_align = function( t, k, v )

        local w = t.contentWidth

        if t.raw_align == ‘right’ then

            for i = 1, t.numChildren do

                t[i].x = t[i].x - w

            end

        elseif t.raw_align == ‘center’ then

            for i = 1, t.numChildren do

                t[i].x = t[i].x + math.floor( w * 0.5 )

            end

        end

        t.raw_align = v

        if t.raw_align == ‘right’ then

            for i = 1, t.numChildren do

                t[i].x = t[i].x + w

            end

        elseif t.raw_align == ‘center’ then

            for i = 1, t.numChildren do

              t[i].x = t[i].x - math.floor( w * 0.5 )

            end

        elseif t.raw_align ~= ‘left’ then

            t.raw_align = ‘left’

        end

  end

  obj.set_text = function( t, k, v )

        t.raw_text = v

        for i = t.numChildren, 1, -1 do t[i]:removeSelf() end

        local oldAlign = ( t.align or ‘left’ )

        t.align = ‘left’

        local x = 0; local y = 0

        local last = ‘’; local xMax = 0; local yMax = 0

        if t.raw_font then

            for c in string.gmatch( t.raw_text…’\n’, ‘(.)’ ) do

                if c == ‘\n’ then

                    x = 0; y = y + t.raw_font.info.lineHeight

                    if y >= yMax then

                        yMax = y

                    end

                elseif t.raw_font.chars[c] then

                    if 0 + t.raw_font.chars[c].width > 0 and 0 + t.raw_font.chars[c].height > 0 then

                        --local letter = sprite.newSprite( t.raw_font.sprites[c] )

                        local letter = display.newImage( font.spritesheets[t.raw_font.sprites[ c].spritesheet ].sheet, t.raw_font.sprites[c].frame)

                        letter:setReferencePoint( display.TopLeftReferencePoint )

                        if t.raw_font.kernings[last … c] then

                            x = x + font.kernings[last … c]

                        end

                        letter.x = t.raw_font.chars[c].xoffset + x

                        letter.y = t.raw_font.chars[c].yoffset - t.raw_font.info.base + y

                        t:insert( letter )

                        last = c

                    end

                    x = x + t.raw_font.chars[c].xadvance

                    if x >= xMax then

                        xMax = x

                    end

                end

            end

          local background = display.newRect( 0, -t.raw_font.info.base, xMax, yMax )

          obj:insert( background )

          background:setFillColor( 0, 0, 0, 0 )

        end

        t.align = oldAlign

    end

    obj.font = font

    obj.align = ‘left’

  obj.text = (text or ‘’)

  return obj

end

function sbFont:destroy()

    – Nothing to Destroy, yet

end

return sbFont

[/lua]

Oh, and I did contact the original author, and he gave the community CC0 rights…

Thanks master! I found this file also during the weekend, http://ember.awirtz.com/bmf.zip ready to use in this post: http://forums.coronalabs.com/topic/4525-bitmap-font/?hl=%20bitmap%20%20fonts

now the problem is you have to use the bitmap font in the exact size it was set, right? Like we used to do in Flash. Still, using the size untouched, I get weird borders in the font when I put in the simulator if you have a second, please take a look.

This is the sprite sheet 

17qo13.png

and this is the result in the simulator:

69f6l3.png

 Look how inconsistent are the borders.

Still i think Corona should support stroke for the text.

Cheerios. A.

Does this code work for bitmap fonts? Thanks! A.

Here’s the bitmap font code… I’m planning on getting it on GitHub as some point…

[lua]

– ******************************************

– * Shoe Box/AngelCode Bitmap Font support *

– ******************************************

– Adapted from “AngelCode bitmap font support” (bmf.lua) in the CoronaSDK Community

– NOTE: This code is in a grey area as far as licencing goes, I couldn’t contact the

– orignal author, but it was released in the old portion of the Corona Labs site

– by “p120ph37”.

http://developer.coronalabs.com/forum/2011/02/05/bitmap-font

– Updates by Michael Wilson

– April 30, 2013

– 

– * Updated to a table based module

– * Moved from Sprites to Imagesheets

– * Added “path” from forum post by KenRogoway

– * Removed Input object (broken)

local sbFont = {}

local sbFont_mt = { __index = sbFont }

– Specify an Angelcode format bitmap font definition file (".FNT")

– The imagesheet that this file references need to be located in the resource directory.

– Return value is a font object that can be used when calling newString

function sbFont:load( fntFile, path )

    path = path or “”

  local function extract( s, p )

    return string.match( s, p ), string.gsub( s, p, ‘’, 1 )

  end

  local font = { info = {}, spritesheets = {}, sprites = {}, chars = {}, kernings = {} }

   local readline = io.lines( system.pathForFile( path…fntFile, system.ResourceDirectory ) )

  for line in readline do

    local t = {}; local tag;

    tag, line = extract( line, ‘^%s*([%a_]+)%s*’ )

    while string.len( line ) > 0 do

      local k, v

      k, line = extract( line, ‘^([%a_]+)=’ )

      if not k then break end

      v, line = extract( line, ‘^"([^"]*)"%s*’ )

      if not v then

        v, line = extract( line, ‘^([^%s]*)%s*’ )

      end

      if not v then break end

      t[k] = v

    end

    if tag == ‘info’ or tag == ‘common’ then

      for k, v in pairs( t ) do font.info[k] = v end

    elseif tag == ‘page’ then

      font.spritesheets[1 + t.id] = { file = t.file, frames = {} }

    elseif tag == ‘char’ then

      t.letter = string.char( t.id )

      font.chars[t.letter] = {}

      for k, v in pairs( t ) do font.chars[t.letter][k] = v end

      if 0 + font.chars[t.letter].width > 0 and 0 + font.chars[t.letter].height > 0 then

        font.spritesheets[1 + t.page].frames[#font.spritesheets[ 1 + t.page].frames + 1 ] = {

–          textureRect = { x = 0 + t.x, y = 0 + t.y, width = -1 + t.width, height = -1 + t.height },

–          spriteSourceSize = { width = 0 + t.width, height = 0 + t.height },

–          spriteColorRect = { x = 0, y = 0, width = -1 + t.width, height = -1 + t.height },

–          spriteTrimmed = true

          x = 0 + t.x, y = 0 + t.y, width = 0 + t.width, height = 0 + t.height,

        }

        font.sprites[t.letter] = {

          spritesheet = 1 + t.page,

          frame = #font.spritesheets[1 + t.page].frames

        }

      end

    elseif( tag == ‘kerning’ ) then

      font.kernings[string.char( t.first ) … string.char( t.second )] = 0 + t.amount

    end

  end

  for k, v in pairs( font.spritesheets ) do

    --font.spritesheets[k].sheet = sprite.newSpriteSheetFromData( v.file, v )

        font.spritesheets[k].sheet =graphics.newImageSheet( path…v.file, v )

  end

  for k, v in pairs( font.sprites ) do

–    font.sprites[k].frame = sprite.newSpriteSet( font.spritesheets[v.spritesheet].sheet, v.frame, 1 )

    font.sprites[k].frame = v.frame

  end

  return font

end

– extend an object with accessor behaviors

local function accessorize( t )

  local mt = getmetatable( t )

  setmetatable( t, {

    __index = function( t, k )

      if rawget( t, ‘get_’…k ) then

        return rawget(t, ‘get_’…k )( t, k )

      elseif rawget( t, ‘raw_’…k ) then

          return rawget( t, ‘raw_’…k )

      elseif mt.__index then

        return mt.__index( t, k )

      else

        return nil

        end

    end,

    __newindex = function( t, k, v )

          if rawget( t, ‘set_’…k ) then

            rawget( t, ‘set_’…k )( t, k, v )

        elseif rawget( t, ‘raw_’…k ) then

          rawset( t, ‘raw_’…k, v )

        elseif mt.__newindex then

          mt.__newindex( t, k, v )

        else

          rawset( t, ‘raw_’…k, v )

        end

    end,

  } )

end

– extend an object with cascading removeSelf

local function removerize( t )

  local old = t.removeSelf

  t.removeSelf = function( o )

    for i = o.numChildren, 1, -1 do o[i]:removeSelf() end

    old( o )

  end

end

– Pass a font object (obtained from loadFont) and a string to render

– Return value is a DisplayObject of the rendered string

– object.font can be read/modifed

– object.text can be read/modified

– object.align can be read/modified - left/right/center (multiline not yet fully supported for non-left)

– object.input( function(text), { filter = function(), max = 32 } )

–   turns the object into a text input.

–   the callback is hit when the user presses “return” or the field losed focus.

–   this code is under development - more documentation will be added soon…

function sbFont:newString( font, text )

  local obj = display.newGroup()

  accessorize( obj )

  removerize( obj )

  obj.set_font = function( t, k, v )

    obj.raw_font = v

    if t.text then t.text = t.text end

  end

  obj.set_align = function( t, k, v )

        local w = t.contentWidth

        if t.raw_align == ‘right’ then

            for i = 1, t.numChildren do

                t[i].x = t[i].x - w

            end

        elseif t.raw_align == ‘center’ then

            for i = 1, t.numChildren do

                t[i].x = t[i].x + math.floor( w * 0.5 )

            end

        end

        t.raw_align = v

        if t.raw_align == ‘right’ then

            for i = 1, t.numChildren do

                t[i].x = t[i].x + w

            end

        elseif t.raw_align == ‘center’ then

            for i = 1, t.numChildren do

              t[i].x = t[i].x - math.floor( w * 0.5 )

            end

        elseif t.raw_align ~= ‘left’ then

            t.raw_align = ‘left’

        end

  end

  obj.set_text = function( t, k, v )

        t.raw_text = v

        for i = t.numChildren, 1, -1 do t[i]:removeSelf() end

        local oldAlign = ( t.align or ‘left’ )

        t.align = ‘left’

        local x = 0; local y = 0

        local last = ‘’; local xMax = 0; local yMax = 0

        if t.raw_font then

            for c in string.gmatch( t.raw_text…’\n’, ‘(.)’ ) do

                if c == ‘\n’ then

                    x = 0; y = y + t.raw_font.info.lineHeight

                    if y >= yMax then

                        yMax = y

                    end

                elseif t.raw_font.chars[c] then

                    if 0 + t.raw_font.chars[c].width > 0 and 0 + t.raw_font.chars[c].height > 0 then

                        --local letter = sprite.newSprite( t.raw_font.sprites[c] )

                        local letter = display.newImage( font.spritesheets[t.raw_font.sprites[ c].spritesheet ].sheet, t.raw_font.sprites[c].frame)

                        letter:setReferencePoint( display.TopLeftReferencePoint )

                        if t.raw_font.kernings[last … c] then

                            x = x + font.kernings[last … c]

                        end

                        letter.x = t.raw_font.chars[c].xoffset + x

                        letter.y = t.raw_font.chars[c].yoffset - t.raw_font.info.base + y

                        t:insert( letter )

                        last = c

                    end

                    x = x + t.raw_font.chars[c].xadvance

                    if x >= xMax then

                        xMax = x

                    end

                end

            end

          local background = display.newRect( 0, -t.raw_font.info.base, xMax, yMax )

          obj:insert( background )

          background:setFillColor( 0, 0, 0, 0 )

        end

        t.align = oldAlign

    end

    obj.font = font

    obj.align = ‘left’

  obj.text = (text or ‘’)

  return obj

end

function sbFont:destroy()

    – Nothing to Destroy, yet

end

return sbFont

[/lua]

Oh, and I did contact the original author, and he gave the community CC0 rights…

Thanks master! I found this file also during the weekend, http://ember.awirtz.com/bmf.zip ready to use in this post: http://forums.coronalabs.com/topic/4525-bitmap-font/?hl=%20bitmap%20%20fonts

now the problem is you have to use the bitmap font in the exact size it was set, right? Like we used to do in Flash. Still, using the size untouched, I get weird borders in the font when I put in the simulator if you have a second, please take a look.

This is the sprite sheet 

17qo13.png

and this is the result in the simulator:

69f6l3.png

 Look how inconsistent are the borders.

Still i think Corona should support stroke for the text.

Cheerios. A.

I tried this new image sheet version of bmf vs the old version. I noticed that the kerning/letter spacing was not working quite as well in this new version. Any idea why?

btw i modified the old bmf to support resizing of the input font. The idea is to create a font bigger than you will ever need, record the size of the font, then supply the original size of the font along side the desired size of the font you need and the returned display object will be scaled appropriately. I would think that as long as your input font is twice as big as any font size you will require it would be suitable for hd, if it is 4X the size of the font you require , super hd.

usage (in the case of an input point size of 120 and desired size of 30):

local str = bmf.newString( bmf.loadFont("yellow.fnt",""),  "hello world",120, 30 );  

code:

module( ..., package.seeall ) -- AngelCode bitmap font support require( 'sprite' ) -- Specify an Angelcode format bitmap font definition file (".FNT") -- The spritesheet(s) that this file references need to be located in the resource directory. -- Return value is a font object that can be used when calling newString function loadFont( fntFile, path ) &nbsp;&nbsp;&nbsp; local function extract( s, p ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return string.match( s, p ), string.gsub( s, p, '', 1 ) &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; local path = path or "" &nbsp;&nbsp;&nbsp; local font = { info = {}, spritesheets = {}, sprites = {}, chars = {}, kernings = {} } &nbsp;&nbsp;&nbsp; local readline = io.lines( system.pathForFile( path .. fntFile, system.ResourceDirectory ) ) &nbsp;&nbsp;&nbsp; for line in readline do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local t = {}; local tag; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tag, line = extract( line, '^%s\*([%a\_]+)%s\*' ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while string.len( line ) \> 0 do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local k, v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; k, line = extract( line, '^([%a\_]+)=' ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not k then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v, line = extract( line, '^"([^"]\*)"%s\*' ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not v then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v, line = extract( line, '^([^%s]\*)%s\*' ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not v then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[k] = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if tag == 'info' or tag == 'common' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for k, v in pairs( t ) do font.info[k] = v end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif tag == 'page' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; font.spritesheets[1 + t.id] = { file = t.file, frames = {} } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif tag == 'char' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.letter = string.char( t.id ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; font.chars[t.letter] = {} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for k, v in pairs( t ) do font.chars[t.letter][k] = v end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if 0 + font.chars[t.letter].width \> 0 and 0 + font.chars[t.letter].height \> 0 then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; font.spritesheets[1 + t.page].frames[#font.spritesheets[ 1 + t.page].frames + 1 ] = { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --textureRect = { x = 0 + t.x, y = 0 + t.y, width = -1 + t.width, height = -1 + t.height }, --CLF removed the -1, it was causing issues with fonts with borders &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; textureRect = { x = 0 + t.x, y = 0 + t.y, width = t.width, height = t.height }, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spriteSourceSize = { width = 0 + t.width, height = 0 + t.height }, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spriteColorRect = { x = 0, y = 0, width = -1 + t.width, height = -1 + t.height }, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spriteTrimmed = true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; font.sprites[t.letter] = { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spritesheet = 1 + t.page, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; frame = #font.spritesheets[1 + t.page].frames &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif( tag == 'kerning' ) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; font.kernings[string.char( t.first ) .. string.char( t.second )] = 0 + t.amount &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; for k, v in pairs( font.spritesheets ) do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; font.spritesheets[k].sheet = sprite.newSpriteSheetFromData( path..v.file, v ) &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; for k, v in pairs( font.sprites ) do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; font.sprites[k] = sprite.newSpriteSet( font.spritesheets[v.spritesheet].sheet, v.frame, 1 ) &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; return font end -- extend an object with accessor behaviors local function accessorize( t ) &nbsp;&nbsp;&nbsp; local mt = getmetatable( t ) &nbsp;&nbsp;&nbsp; setmetatable( t, { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \_\_index = function( t, k ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if rawget( t, 'get\_'..k ) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return rawget(t, 'get\_'..k )( t, k ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif rawget( t, 'raw\_'..k ) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return rawget( t, 'raw\_'..k ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif mt.\_\_index then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return mt.\_\_index( t, k ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return nil &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \_\_newindex = function( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if rawget( t, 'set\_'..k ) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rawget( t, 'set\_'..k )( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif rawget( t, 'raw\_'..k ) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rawset( t, 'raw\_'..k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif mt.\_\_newindex then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mt.\_\_newindex( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rawset( t, 'raw\_'..k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end, &nbsp;&nbsp;&nbsp; } ) end -- extend an object with cascading removeSelf local function removerize( t ) &nbsp;&nbsp;&nbsp; local old = t.removeSelf &nbsp;&nbsp;&nbsp; t.removeSelf = function( o ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = o.numChildren, 1, -1 do o[i]:removeSelf() end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; old( o ) &nbsp;&nbsp;&nbsp; end end -- Pass a font object (obtained from loadFont) and a string to render -- Return value is a DisplayObject of the rendered string -- object.font can be read/modifed -- object.text can be read/modified -- object.align can be read/modified - left/right/center (multiline not yet fully supported for non-left) -- object.input( function(text), { filter = function(), max = 32 } ) -- turns the object into a text input. -- the callback is hit when the user presses "return" or the field losed focus. -- this code is under development - more documentation will be added soon... function newString( font, text ,origsize, newsize) &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; local finalScale&nbsp; = 100/origsize \*newsize/100; &nbsp;&nbsp;&nbsp; local obj = display.newGroup() &nbsp;&nbsp;&nbsp; accessorize( obj ) &nbsp;&nbsp;&nbsp; removerize( obj ) &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.set\_font = function( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.raw\_font = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if t.text then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.text = t.text &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; -- Set the alignment of the object &nbsp;&nbsp;&nbsp; obj.set\_align = function( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local w = t.contentWidth &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if t.raw\_align == 'right' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = 1, t.numChildren do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i].x = t[i].x - w &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif t.raw\_align == 'center' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = 1, t.numChildren do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i].x = t[i].x + math.floor( w \* 0.5 ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.raw\_align = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if t.raw\_align == 'right' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = 1, t.numChildren do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i].x = t[i].x + w &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif t.raw\_align == 'center' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = 1, t.numChildren do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i].x = t[i].x - math.floor( w \* 0.5 ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif t.raw\_align ~= 'left' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.raw\_align = 'left' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; -- Set the text for the object &nbsp;&nbsp;&nbsp; obj.set\_text = function( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( v == t.raw\_text ) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.raw\_text = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = t.numChildren, 1, -1 do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i]:removeSelf() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local oldAlign = ( t.align or 'left' ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.align = 'left' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local x = 0; local y = 0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local last = ''; local xMax = 0; local yMax = 0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if t.raw\_font then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for c in string.gmatch( t.raw\_text..'\n', '(.)' ) do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if c == '\n' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x = 0; y = y + t.raw\_font.info.lineHeight &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if y \>= yMax then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yMax = y &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif t.raw\_font.chars[c] then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if 0 + t.raw\_font.chars[c].width \> 0 and 0 + t.raw\_font.chars[c].height \> 0 then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local letter = sprite.newSprite( t.raw\_font.sprites[c] ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if t.raw\_font.kernings[last .. c] then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x = x + font.kernings[last .. c] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t:insert( letter ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; letter:setReferencePoint( display.TopLeftReferencePoint ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; letter.x = t.raw\_font.chars[c].xoffset + x &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; letter.y = t.raw\_font.chars[c].yoffset - t.raw\_font.info.base + y &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; last = c &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --x = x + t.raw\_font.chars[c].xadvance &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x = x + t.raw\_font.chars[c].xadvance + (t.raw\_font.info.outline or 0) --CLF added support for outlines &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if x \>= xMax then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xMax = x &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local background = display.newRect( 0, -t.raw\_font.info.base, xMax, yMax ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; background.isBackground = true --CLF Added to support tinting of font. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj:insert( background ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; background:setFillColor( 0, 0, 0, 0 ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.align = oldAlign &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.input = function( f, args ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- spawn the text field invisibly &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local field &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- Handle character insertion/deletion &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local function char() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- check if any character has been added or deleted &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if field.text ~= '--' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if string.len( field.text ) \< 2 then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- backspace was pressed &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if string.len( obj.text ) \> 0 then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.text = string.sub( obj.text, 1, -2 ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- some other key was pressed &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.text = obj.text..string.sub( field.text, 3 ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; field.text = '--' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if args.filter then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.text = string.sub( args.filter( obj.text ), 1, (args.max or 32) ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.text = string.sub( obj.text, 1, (args.max or 32) ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Runtime:addEventListener( 'enterFrame', char ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- Handle the "done" phase &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local function done( e ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if e.phase == 'submitted' or e.phase == 'ended' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; native.setKeyboardFocus( nil ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; field:removeSelf() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Runtime:removeEventListener( 'enterFrame', char ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f( text ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; field = native.newTextField( 0, 0, 240, 24, done ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; field.text = '--' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; field.isVisible = false &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; native.setKeyboardFocus( field ) &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; obj.font = font &nbsp;&nbsp;&nbsp; obj.align = 'left' &nbsp;&nbsp;&nbsp; obj.text = (text or '') &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.xScale = finalScale; &nbsp;&nbsp;&nbsp; obj.yScale = finalScale; &nbsp;&nbsp;&nbsp; return obj end function newParagraph(font, text, width) &nbsp;&nbsp;&nbsp; local obj = display.newGroup() &nbsp;&nbsp;&nbsp; accessorize( obj ) &nbsp;&nbsp;&nbsp; removerize( obj ) &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.set\_font = function( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.raw\_font = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --if t.text then t.text = t.text end &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.set\_paragraphWidth = function( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.raw\_paragraphWidth = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --if t.text then t.text = t.text end &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.set\_tint = function( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.raw\_tint = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = t.numChildren, 1, -1 do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for j = t[i].numChildren, 1, -1 do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(not t[i][j].isBackground) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if v[4] then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i][j]:setFillColor(v[1],v[2],v[3],v[4]) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i][j]:setFillColor(v[1],v[2],v[3]) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --if t.text then t.text = t.text end &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.set\_text = function(t, k, v) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --save the new raw text &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.raw\_text = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --remove all children &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = t.numChildren, 1, -1 do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i]:removeSelf() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --determine the width of a space &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local space = bmf.newString(font, " ") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local spaceWidth = space.raw\_font.info.outline\*-1 or 0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; space:removeSelf() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; space = nil &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --Create our word-wrapped paragraph. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local spaceLeft = t.raw\_paragraphWidth &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local x, y = obj.x, obj.y &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for word, spacer in string.gmatch(v, "([^%s%-]+)([%s%-]\*)") do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local w = bmf.newString(font, word..spacer) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --print(w.width,"sw" , spaceWidth, "sl", spaceLeft) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(w.width + spaceWidth) \> spaceLeft then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spaceLeft = t.raw\_paragraphWidth - w.width - spaceWidth &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y = y + w.raw\_font.info.lineHeight &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x = obj.x &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; w.x = x &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; w.x = x + t.raw\_paragraphWidth - spaceLeft &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spaceLeft = spaceLeft - w.width - spaceWidth &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; w.y = y &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj:insert(w) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.paragraphWidth = width or display.viewableContentWidth &nbsp;&nbsp;&nbsp; obj.text = text &nbsp;&nbsp;&nbsp; obj.font = font &nbsp;&nbsp;&nbsp; obj.tint = {255,255,255} &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; return obj end &nbsp;

I tried this new image sheet version of bmf vs the old version. I noticed that the kerning/letter spacing was not working quite as well in this new version. Any idea why?

btw i modified the old bmf to support resizing of the input font. The idea is to create a font bigger than you will ever need, record the size of the font, then supply the original size of the font along side the desired size of the font you need and the returned display object will be scaled appropriately. I would think that as long as your input font is twice as big as any font size you will require it would be suitable for hd, if it is 4X the size of the font you require , super hd.

usage (in the case of an input point size of 120 and desired size of 30):

local str = bmf.newString( bmf.loadFont("yellow.fnt",""),&nbsp; "hello world",120, 30 ); &nbsp;

code:

module( ..., package.seeall ) -- AngelCode bitmap font support require( 'sprite' ) -- Specify an Angelcode format bitmap font definition file (".FNT") -- The spritesheet(s) that this file references need to be located in the resource directory. -- Return value is a font object that can be used when calling newString function loadFont( fntFile, path ) &nbsp;&nbsp;&nbsp; local function extract( s, p ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return string.match( s, p ), string.gsub( s, p, '', 1 ) &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; local path = path or "" &nbsp;&nbsp;&nbsp; local font = { info = {}, spritesheets = {}, sprites = {}, chars = {}, kernings = {} } &nbsp;&nbsp;&nbsp; local readline = io.lines( system.pathForFile( path .. fntFile, system.ResourceDirectory ) ) &nbsp;&nbsp;&nbsp; for line in readline do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local t = {}; local tag; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tag, line = extract( line, '^%s\*([%a\_]+)%s\*' ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while string.len( line ) \> 0 do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local k, v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; k, line = extract( line, '^([%a\_]+)=' ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not k then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v, line = extract( line, '^"([^"]\*)"%s\*' ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not v then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v, line = extract( line, '^([^%s]\*)%s\*' ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not v then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[k] = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if tag == 'info' or tag == 'common' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for k, v in pairs( t ) do font.info[k] = v end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif tag == 'page' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; font.spritesheets[1 + t.id] = { file = t.file, frames = {} } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif tag == 'char' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.letter = string.char( t.id ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; font.chars[t.letter] = {} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for k, v in pairs( t ) do font.chars[t.letter][k] = v end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if 0 + font.chars[t.letter].width \> 0 and 0 + font.chars[t.letter].height \> 0 then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; font.spritesheets[1 + t.page].frames[#font.spritesheets[ 1 + t.page].frames + 1 ] = { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --textureRect = { x = 0 + t.x, y = 0 + t.y, width = -1 + t.width, height = -1 + t.height }, --CLF removed the -1, it was causing issues with fonts with borders &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; textureRect = { x = 0 + t.x, y = 0 + t.y, width = t.width, height = t.height }, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spriteSourceSize = { width = 0 + t.width, height = 0 + t.height }, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spriteColorRect = { x = 0, y = 0, width = -1 + t.width, height = -1 + t.height }, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spriteTrimmed = true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; font.sprites[t.letter] = { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spritesheet = 1 + t.page, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; frame = #font.spritesheets[1 + t.page].frames &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif( tag == 'kerning' ) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; font.kernings[string.char( t.first ) .. string.char( t.second )] = 0 + t.amount &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; for k, v in pairs( font.spritesheets ) do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; font.spritesheets[k].sheet = sprite.newSpriteSheetFromData( path..v.file, v ) &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; for k, v in pairs( font.sprites ) do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; font.sprites[k] = sprite.newSpriteSet( font.spritesheets[v.spritesheet].sheet, v.frame, 1 ) &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; return font end -- extend an object with accessor behaviors local function accessorize( t ) &nbsp;&nbsp;&nbsp; local mt = getmetatable( t ) &nbsp;&nbsp;&nbsp; setmetatable( t, { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \_\_index = function( t, k ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if rawget( t, 'get\_'..k ) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return rawget(t, 'get\_'..k )( t, k ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif rawget( t, 'raw\_'..k ) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return rawget( t, 'raw\_'..k ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif mt.\_\_index then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return mt.\_\_index( t, k ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return nil &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \_\_newindex = function( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if rawget( t, 'set\_'..k ) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rawget( t, 'set\_'..k )( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif rawget( t, 'raw\_'..k ) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rawset( t, 'raw\_'..k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif mt.\_\_newindex then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mt.\_\_newindex( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rawset( t, 'raw\_'..k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end, &nbsp;&nbsp;&nbsp; } ) end -- extend an object with cascading removeSelf local function removerize( t ) &nbsp;&nbsp;&nbsp; local old = t.removeSelf &nbsp;&nbsp;&nbsp; t.removeSelf = function( o ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = o.numChildren, 1, -1 do o[i]:removeSelf() end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; old( o ) &nbsp;&nbsp;&nbsp; end end -- Pass a font object (obtained from loadFont) and a string to render -- Return value is a DisplayObject of the rendered string -- object.font can be read/modifed -- object.text can be read/modified -- object.align can be read/modified - left/right/center (multiline not yet fully supported for non-left) -- object.input( function(text), { filter = function(), max = 32 } ) -- turns the object into a text input. -- the callback is hit when the user presses "return" or the field losed focus. -- this code is under development - more documentation will be added soon... function newString( font, text ,origsize, newsize) &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; local finalScale&nbsp; = 100/origsize \*newsize/100; &nbsp;&nbsp;&nbsp; local obj = display.newGroup() &nbsp;&nbsp;&nbsp; accessorize( obj ) &nbsp;&nbsp;&nbsp; removerize( obj ) &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.set\_font = function( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.raw\_font = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if t.text then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.text = t.text &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; -- Set the alignment of the object &nbsp;&nbsp;&nbsp; obj.set\_align = function( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local w = t.contentWidth &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if t.raw\_align == 'right' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = 1, t.numChildren do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i].x = t[i].x - w &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif t.raw\_align == 'center' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = 1, t.numChildren do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i].x = t[i].x + math.floor( w \* 0.5 ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.raw\_align = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if t.raw\_align == 'right' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = 1, t.numChildren do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i].x = t[i].x + w &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif t.raw\_align == 'center' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = 1, t.numChildren do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i].x = t[i].x - math.floor( w \* 0.5 ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif t.raw\_align ~= 'left' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.raw\_align = 'left' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; -- Set the text for the object &nbsp;&nbsp;&nbsp; obj.set\_text = function( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( v == t.raw\_text ) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.raw\_text = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = t.numChildren, 1, -1 do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i]:removeSelf() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local oldAlign = ( t.align or 'left' ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.align = 'left' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local x = 0; local y = 0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local last = ''; local xMax = 0; local yMax = 0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if t.raw\_font then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for c in string.gmatch( t.raw\_text..'\n', '(.)' ) do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if c == '\n' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x = 0; y = y + t.raw\_font.info.lineHeight &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if y \>= yMax then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yMax = y &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif t.raw\_font.chars[c] then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if 0 + t.raw\_font.chars[c].width \> 0 and 0 + t.raw\_font.chars[c].height \> 0 then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local letter = sprite.newSprite( t.raw\_font.sprites[c] ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if t.raw\_font.kernings[last .. c] then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x = x + font.kernings[last .. c] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t:insert( letter ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; letter:setReferencePoint( display.TopLeftReferencePoint ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; letter.x = t.raw\_font.chars[c].xoffset + x &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; letter.y = t.raw\_font.chars[c].yoffset - t.raw\_font.info.base + y &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; last = c &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --x = x + t.raw\_font.chars[c].xadvance &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x = x + t.raw\_font.chars[c].xadvance + (t.raw\_font.info.outline or 0) --CLF added support for outlines &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if x \>= xMax then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xMax = x &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local background = display.newRect( 0, -t.raw\_font.info.base, xMax, yMax ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; background.isBackground = true --CLF Added to support tinting of font. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj:insert( background ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; background:setFillColor( 0, 0, 0, 0 ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.align = oldAlign &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.input = function( f, args ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- spawn the text field invisibly &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local field &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- Handle character insertion/deletion &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local function char() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- check if any character has been added or deleted &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if field.text ~= '--' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if string.len( field.text ) \< 2 then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- backspace was pressed &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if string.len( obj.text ) \> 0 then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.text = string.sub( obj.text, 1, -2 ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- some other key was pressed &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.text = obj.text..string.sub( field.text, 3 ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; field.text = '--' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if args.filter then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.text = string.sub( args.filter( obj.text ), 1, (args.max or 32) ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.text = string.sub( obj.text, 1, (args.max or 32) ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Runtime:addEventListener( 'enterFrame', char ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- Handle the "done" phase &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local function done( e ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if e.phase == 'submitted' or e.phase == 'ended' then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; native.setKeyboardFocus( nil ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; field:removeSelf() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Runtime:removeEventListener( 'enterFrame', char ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f( text ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; field = native.newTextField( 0, 0, 240, 24, done ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; field.text = '--' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; field.isVisible = false &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; native.setKeyboardFocus( field ) &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; obj.font = font &nbsp;&nbsp;&nbsp; obj.align = 'left' &nbsp;&nbsp;&nbsp; obj.text = (text or '') &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.xScale = finalScale; &nbsp;&nbsp;&nbsp; obj.yScale = finalScale; &nbsp;&nbsp;&nbsp; return obj end function newParagraph(font, text, width) &nbsp;&nbsp;&nbsp; local obj = display.newGroup() &nbsp;&nbsp;&nbsp; accessorize( obj ) &nbsp;&nbsp;&nbsp; removerize( obj ) &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.set\_font = function( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.raw\_font = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --if t.text then t.text = t.text end &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.set\_paragraphWidth = function( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.raw\_paragraphWidth = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --if t.text then t.text = t.text end &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.set\_tint = function( t, k, v ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.raw\_tint = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = t.numChildren, 1, -1 do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for j = t[i].numChildren, 1, -1 do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(not t[i][j].isBackground) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if v[4] then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i][j]:setFillColor(v[1],v[2],v[3],v[4]) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i][j]:setFillColor(v[1],v[2],v[3]) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --if t.text then t.text = t.text end &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.set\_text = function(t, k, v) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --save the new raw text &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.raw\_text = v &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --remove all children &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = t.numChildren, 1, -1 do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i]:removeSelf() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --determine the width of a space &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local space = bmf.newString(font, " ") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local spaceWidth = space.raw\_font.info.outline\*-1 or 0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; space:removeSelf() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; space = nil &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --Create our word-wrapped paragraph. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local spaceLeft = t.raw\_paragraphWidth &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local x, y = obj.x, obj.y &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for word, spacer in string.gmatch(v, "([^%s%-]+)([%s%-]\*)") do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local w = bmf.newString(font, word..spacer) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --print(w.width,"sw" , spaceWidth, "sl", spaceLeft) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(w.width + spaceWidth) \> spaceLeft then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spaceLeft = t.raw\_paragraphWidth - w.width - spaceWidth &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y = y + w.raw\_font.info.lineHeight &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x = obj.x &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; w.x = x &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; w.x = x + t.raw\_paragraphWidth - spaceLeft &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spaceLeft = spaceLeft - w.width - spaceWidth &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; w.y = y &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj:insert(w) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; obj.paragraphWidth = width or display.viewableContentWidth &nbsp;&nbsp;&nbsp; obj.text = text &nbsp;&nbsp;&nbsp; obj.font = font &nbsp;&nbsp;&nbsp; obj.tint = {255,255,255} &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; return obj end &nbsp;