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]