Bitmap font

82 replies [Last post]
holmes2870
User offline. Last seen 14 weeks 3 days ago. Offline
Joined: 3 Feb 2011

A little while ago there was a tool called GlyphDesigner released by 71squared. The app is for the mac and allows you to design cool effects for fonts you have on your computer. The tool is really good and I wonder you can add support for that tool so corona reads font files created by GlyphDesigner?

Replies

p120ph37
User offline. Last seen 42 weeks 1 day ago. Offline
Joined: 1 Feb 2011

Merry Christmas...

[edit]
Old code removed - see link below for latest code.
[/edit]

I don't have the registered version of Glyph Designer to test with, but it works with BMFont output, so it ought to work with Glyph Designer as well.

[edit]
After playing with Glyph Designer, I bought it and exported a font. I discovered and fixed an issue in my code that didn't like the fact that space was encoded as a 0px by 0px bitmap, and I can now say I have tested it with Glyph Designer output and it works nicely.
[/edit]

holmes2870
User offline. Last seen 14 weeks 3 days ago. Offline
Joined: 3 Feb 2011

Awesome, thanks.

I made arial32.fnt file and a .png in GlyphDesigner and tried it with your code but when I ran it in the simulator I got this error;

Runtime error
...1HGkKXNH+WWf6ydHU3uW++++TI/TemporaryItems/48/bmf.lua:71: ERROR: Invalid parameter passed to sprite.newSpriteSheetFromData(). Missing data.
stack traceback:
[C]: ?
[C]: in function
'newSpriteSheetFromData'
...1HGkKXNH+WWf6ydHU3uW++++TI/TemporaryItems/48/bmf.lua:71: in function 'loadFont'
...HGkKXNH+WWf6ydHU3uW++++TI/TemporaryItems/48/main.lua:13: in main chunk

Runtime error: ...1HGkKXNH+WWf6ydHU3uW++++TI/TemporaryItems/48/bmf.lua:71: ERROR: Invalid parameter passed to sprit
e.newSpriteSheetFromData(). Missing data.
stack traceback:
[C]: ?
[C]: in function 'newSpriteSheetFromData'
...1HGkKXNH+WWf6ydHU3uW++++TI/TemporaryItems/48/bmf.lua:71: in function 'loadFont'
...HG
kKXNH+WWf6ydHU3uW++++TI/TemporaryItems/48/main.lua:13: in main chunk

Do you have any ideas why this happen? I have the .fnt file and the .png in the same directory as the main.lua and the bmf.lua

I just copied your code and made the bmf.lua file and copied the other code into my main.lua. Do I have to make a spriteSheet out of my arial.png too? Do I have to slice the all the letters into individual sprites to make a arial32.lua spriteSheet?

How did you make it work?
David

p120ph37
User offline. Last seen 42 weeks 1 day ago. Offline
Joined: 1 Feb 2011

Here is a link to my example project, including font file:

http://ember.awirtz.com/bmf.zip

If you are having trouble, you can send me your sample project and I can take a look and see if I can figure out what is being buggy...

holmes2870
User offline. Last seen 14 weeks 3 days ago. Offline
Joined: 3 Feb 2011

I got it to work, but I had a strange problem though. I copied everything of your code exactly like in your file you posted for download and when I ran the project I got the error above, but here is the strange part...
when I made a new set of files and replaced the old ones, the project worked???

I tried the old files 20 times and they failed in simulator but when I copied the code and pasted them into new file it built fine, is that a bug in corona or something?

I wish a clean Target/All Targets option were built in Corona Simulator, just like in xcode.

p120ph37
User offline. Last seen 42 weeks 1 day ago. Offline
Joined: 1 Feb 2011

Are you perhaps using Windows?
(I wouldn't assume so if you are talking about Glyph Designer, which is a Mac program)
If so, maybe it's a Windows vs Mac end-of-line marker issue?

I tried freshly downloading and running the zip on my Mac and it doesn't have issues.

holmes2870
User offline. Last seen 14 weeks 3 days ago. Offline
Joined: 3 Feb 2011

I got a mac, I've been testing some more and it seems to be something wrong with the font I used. I made a few different fonts and there was only that one that didn't work (materhorn.fnt, 64pt). I only changed the fonts and the rest was the standard presets that starts with glyph designer.

I have no clue what the problem could be? I can sent you the font file.
David

p120ph37
User offline. Last seen 42 weeks 1 day ago. Offline
Joined: 1 Feb 2011

Thanks for sending the file.

After trial and error removing various lines from the FNT file until I isolated the problem, I discovered that the "`" (backtick) character for this font has a negative y-offset.
This confuses some of the math which calculates the spritesheet coordinates.
Also, I noticed that this FNT file has quite a few kernings, which my code currently ignores.
I'm working on updating the code to handle the negative y-offset and adding support for kernings.
In the mean time, if you delete the line for backtick (id=96) from the FNT file, you should be able to start working with your Materhorn.FNT while you are waiting for me.

p120ph37
User offline. Last seen 42 weeks 1 day ago. Offline
Joined: 1 Feb 2011

I've updated my code to support negative offsets, added kerning support, and added support for newlines.

The new code is available at the link above. I also included an Impact-based font rather than the old Futura-based one to demonstrate the kerning support. (Notice that the "W"s and "A"s interlock properly)

One other caveat that I have discovered (technically it could be considered a bug in Glyph Designer) is that if you set the spacing too low (e.g. 0), some of the character x/y coordinates end up negative. Just make sure you have spacing set to at least 1px.

holmes2870
User offline. Last seen 14 weeks 3 days ago. Offline
Joined: 3 Feb 2011

Cool, what does the dumper.lua file do?
Do I have to include that file in my projects when i use bmf?

p120ph37
User offline. Last seen 42 weeks 1 day ago. Offline
Joined: 1 Feb 2011

No, you don't. Sorry I didn't mean to include that in the zip. (removed it now)

It is a Lua library for dumping the contents of data structures to the console so I can see what's going on inside of them when debugging.

e.doussin2's picture
e.doussin2
User offline. Last seen 30 weeks 6 days ago. Offline
Joined: 4 Feb 2011

@p120ph37:
thanks for the bmf.lua file!
i got a glyph designer license now and i am using the bmf.lua file to render a big bitmap font style timer that is updated by a Runtime "enterframe" event handler.
it is a central element of my game and it looks amazing.
--> thanks so far!

the only problem i face now is that when i check for memory leaks with instruments, it seems that the graphics that are created are not deallocated and i get memory warnings/crashes after a while.
i experimented with 'object:removeSelf()' and set the variables in my code to nil, it didn't help.

this is what it looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- SHOW TIME PLAYED WITH BMP CUSTOM FONT
 
--initialize bmp font timer:
local Timestring = bmf.newString(font2, "00:00:00:00")
Timestring.x = 55
Timestring.y = 70
 
 
--update bmp font timer:
function TimestringUpdate (newString)
Timestring:removeSelf()
Timestring = nil
Timestring = bmf.newString(font2, newString)
Timestring.x = 55
Timestring.y = 70 
newString=nil
end
 
--newString parameter comes from another function 
-- this is called by a runtime "enterframe"event listener

now i think maybe it is happening inside the bmf.lua file?
when you return the font object in the newString function, is there a way to clean up the memory after it returned the object?

Big Thanks!

e.doussin2's picture
e.doussin2
User offline. Last seen 30 weeks 6 days ago. Offline
Joined: 4 Feb 2011

I edited the code a little so it only draws a new picture every 50ms.
helps a little because now it uses up the memory much slower, but doesn't solve the problem.

p120ph37
User offline. Last seen 42 weeks 1 day ago. Offline
Joined: 1 Feb 2011

Thanks for the feedback - So far I have used it mostly for fairly low-refresh things so I hadn't seen the memory leak issues. I will look into it when I get a chance. Can you provide me with the debug statements you are using to track the memory usage too?

In the mean time, I have some minor updates of my own that I've made to the BMF library while working on my own projects, which I have uploaded to the ZIP. I fixed an off-by-one issue with spritesheet alignment, added support for newlines, and added placeholder rectangles so that the text centers correctly when there are leading/trailing spaces or blank lines.

p120ph37
User offline. Last seen 42 weeks 1 day ago. Offline
Joined: 1 Feb 2011

Actually, I think I've located the issue. ( I took your example code and fed it system.getTimer() data every frame while monitoring the value of collectgarbage( 'count' ) )

It seems that Corona does not automatically free the memory used by children of a group object when the group object is removed.

As a work-around, I have overridden the 'removeSelf' method of my string objects (really just group objects under the hood) so that it removes its children before removing itself.

Your memory leak should now be gone with the latest version of the library.

Cheers!

NB: If you use the parent:remove( string ) form rather than string:removeSelf(), this will not hit my custom removeSelf method.

e.doussin2's picture
e.doussin2
User offline. Last seen 30 weeks 6 days ago. Offline
Joined: 4 Feb 2011

Wow, Great News! I will try it out Tomorrow!

e.doussin2's picture
e.doussin2
User offline. Last seen 30 weeks 6 days ago. Offline
Joined: 4 Feb 2011

ahh.. download link seems to be broken. could you check?

e.doussin2's picture
e.doussin2
User offline. Last seen 30 weeks 6 days ago. Offline
Joined: 4 Feb 2011

works like a charm:

thank you!

p120ph37
User offline. Last seen 42 weeks 1 day ago. Offline
Joined: 1 Feb 2011

I threw a few more examples and sample fonts into the demo - this should give people something decent to play with before deciding if they want to buy Glyph Designer.

Rob2
User offline. Last seen 4 weeks 4 days ago. Offline
Joined: 14 Apr 2010

This is great, very much help. As an owner of Glyph Designer who likes the look of Text Candy how can I easily convert angelcode .fnt into .lua spritesheet?

p120ph37
User offline. Last seen 42 weeks 1 day ago. Offline
Joined: 1 Feb 2011

I don't own Text Candy, and there doesn't seem to be any detailed information on the website describing the spritesheet definition format that they are using, so I don't know for sure, but I imagine it shouldn't be terribly difficult to take my .fnt parsing routine and modify it slightly to work as a Text Candy .lua file.

Incidentally, I have some new code I've been working on for my BMF library that allows you to use bitmap fonts for text input fields and to change the text or font of a label without having to destroy and recreate it entirely. Stay tuned... :-D

Rob2
User offline. Last seen 4 weeks 4 days ago. Offline
Joined: 14 Apr 2010

Thanks for the speedy response and very much looking forward to BMF developments:)

It looks like Candy are using the the standard Corona table .lua spritesheet definition as produced by Zwoptex/Texturepacker.

p120ph37
User offline. Last seen 42 weeks 1 day ago. Offline
Joined: 1 Feb 2011

Thanks for the info.

I looked at how Zwoptex structures its .lua file and it's pretty straightforward.
So to use AngelCode-style .fnt files as font definitions for TextCandy, you should be able to just save this code snippet with the same base name as your myfont.png and myfont.fnt files (e.g. myfont.lua) and use that as your TextCandy definition file.

1
2
3
4
5
module( ... )
require( 'bmf' )
function getSpriteSheetData()
  return bmf.loadFont( _M._NAME ).spritesheets[0]
end

Let me know if that works out for you - I haven't actually tested it yet.

Rob2
User offline. Last seen 4 weeks 4 days ago. Offline
Joined: 14 Apr 2010

Thanks again http://developer.anscamobile.com/forum/2011/03/19/new-candy-tool-text-candy-corona-50-coupon-inside#comment-28723 is posted as a tutorial for creating fonts
I haven't bought Candy yet as I was hoping to purchase both products together:) but I guess I will just have to take the plungette now and pay a pal!

Your BMF lib takes kerning into account? I don't think text Candy does.

p120ph37
User offline. Last seen 42 weeks 1 day ago. Offline
Joined: 1 Feb 2011

Right - from the settings I they describe in the documentation, it doesn't seem that TextCandy handles kerning or any sort of character overlap for that matter.

Also, my example probably won't work as-is... I forgot that in the version of my BMF library that's on the server right now I'm destroying the spritesheet definition once the spritesheet is loaded so it's no longer accessible after loadFont has completed.

Plus you probably want to get additional information from the .fnt file besides just the sprite locations - like the line height and the space width and y-offsets.

p120ph37
User offline. Last seen 42 weeks 1 day ago. Offline
Joined: 1 Feb 2011

I've updated the library so it doesn't destroy the spritesheet definition.

I've also included a sneak-peek at a few new features that I haven't had a chance to show off in the demo yet:

object.text and object.font are now properties which can be read/written after the object is created.
object.align allows some rudimentary text alignment options.
object.input() allows you to use a text object as an input field - no more ugly white input boxes! (this is still a bit in development - expect more detailed documentation soon...)

Finally, I've posted to the TextCandy thread with some ideas on integration - we'll see if X-Pressive wants to help with that.

Rob2
User offline. Last seen 4 weeks 4 days ago. Offline
Joined: 14 Apr 2010

Thanks very much for all your help with this, I still have a tonne to learn but hopefully I will get there. :)

lyssagale12
User offline. Last seen 47 weeks 6 days ago. Offline
Joined: 22 Jun 2011

You can Download Computer Fonts which you required and upload in your system.

vitalyx's picture
vitalyx
User offline. Last seen 4 weeks 3 hours ago. Offline
Joined: 11 Apr 2011

p120ph37, thanks for sharing! But do you have any updates for this? When navigating away from the scene that uses BMF fonts the simulator hangs for me with 100% CPU. I'm using the Director class to manage scenes, so maybe this has something to do with Director's cleangroups() method.
Also, I noticed there is 1px clipping at the bottom with the font I generated with BMFFont.

EDIT: I found the reason for trimming, changed code on line 40 to:

1
textureRect = { x = 0 + t.x, y = 0 + t.y, width = -1 + t.width, height = t.height }, -- removed "-1" for "height"

But the simulator still hangs. Will keep looking.

p120ph37
User offline. Last seen 42 weeks 1 day ago. Offline
Joined: 1 Feb 2011

@vitalyx

Hi,
Sorry I haven't updated the code in a while. One of the tricks in my BMF implementation was that I had to clean out the contents of the group objects as they were destroyed since Corona at the time I wrote the code had a bug which would leak memory if I didn't. I understand that has been fixed in the more recent builds, but I haven't had a chance to try it out yet. You might try removing that part of my code and see if it helps your issue. As far as coordinates and the 1px clipping, I did most of my testing with the fonts from Glyph Designer, so it may be possible that BMFFont uses slightly different coordinate numbering - I'll have to look into that at some point, but if you have it working for your particular font, great! If you do decide that BMF fonts are a good option in Corona and if you have a Mac available, I would highly recommend trying out Glyph Designer... ;-)

I can't promise anything on timeframes, but I'll try to get back to this library sometime soon to update it and release a couple of extras I've been working on for it.

vitalyx's picture
vitalyx
User offline. Last seen 4 weeks 3 hours ago. Offline
Joined: 11 Apr 2011

Hi p120ph37, thanks for your reply. I will be looking forward to this update. Till then I will probably put up a tiny module of my own, since my only need for now is displaying outlined numbers, so no worries.

vitalyx's picture
vitalyx
User offline. Last seen 4 weeks 3 hours ago. Offline
Joined: 11 Apr 2011

I decided to dive into your code instead and understand what it does.
Pretty clever, but quite hard to read, IMO.
I've modified the newString() function.
Now there is no need for accessorize/removerize functions, behavior looks the same (though, I haven't done much testing), there is less code and it's easier to understand.

Here it is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
function newString(sFont, sText)
    local obj = display.newGroup()
 
    local font, text, align
 
    function obj:getFont()
        return font
    end
 
    function obj:getText()
        return text
    end
 
    function obj:getAlign()
        return align
    end
 
    function obj:setAlign(a)
        align = a
        local width = self.contentWidth
        if a == "right" then
            for i = 1, self.numChildren do
                self[i].x = self[i].x + width
            end
        elseif a == "center" then
            for i = 1, self.numChildren do
                self[i].x = self[i].x - math.floor(width * 0.5)
            end
        end
    end
 
    function obj:setText(t)
        if type(t) ~= "string" then return end
 
        text = t
        for i = self.numChildren, 1, -1 do self[i].removeSelf() end
        local x, y, xMax, yMax = 0, 0, 0, 0
        local last = ""
 
        for c in string.gmatch(text .. "\n", "(.)") do
            if c == "\n" then
                x = 0
                y = y + font.info.lineHeight
                if y >= yMax then yMax = y end
            elseif font.chars[c] then
                if 0 + font.chars[c].width > 0 and 0 + font.chars[c].height > 0 then
                    local letter = sprite.newSprite(font.sprites[c])
                    letter:setReferencePoint(display.TopLeftReferencePoint)
                    if font.kernings[last .. c] then
                        x = x + font.kernings[last .. c]
                    end
                    letter.x = font.chars[c].xoffset + x
                    letter.y = font.chars[c].yoffset - font.info.base + y
                    self:insert(letter)
                    last = c
                end
                x = x + font.chars[c].xadvance
                if x >= xMax then xMax = x end
            end
        end
 
        local background = display.newRect(0, -font.info.base, xMax, yMax)
        obj:insert(background)
        background:setFillColor(0, 0, 0, 0)
 
        self:setAlign(align)
    end
 
    function obj:setFont(f)
        font = f
        self:setText(text)
    end
 
    align = "left"
    text = sText
    obj:setFont(sFont)
 
    return obj
end

p120ph37
User offline. Last seen 42 weeks 1 day ago. Offline
Joined: 1 Feb 2011

@vitalyx:

That's similar to what I had at first. I added the "accessor" functionality so that it would behave more like the native text strings where you can change the displayed text by just setting the value of the "text" attribute rather than by calling a method. The idea was to make it usable as a drop-in replacement for the native text objects. Removing that layer of abstraction will certainly make the code easier for you to understand and work on if you want to learn how it works though!

vitalyx's picture
vitalyx
User offline. Last seen 4 weeks 3 hours ago. Offline
Joined: 11 Apr 2011

Oh, I see :) Well, maybe this will make it easier for somebody else who is curious what's going on there. As I rarely just copy-paste other people's code and usually try to at least understand it. But most of the time modify it to suit the needs of my project or just to make it conform with the rest of the code better.

BTW, the above code appears to work fine with the Director class, so if somebody had this same problem, this is worth noting.

Also, I haven't figured out how alignment works.
I would expect "right" to look like this:

1
2
3
abcdefg
  abcde
    abc

and "center" like this:
1
2
3
abcdefg
 abcde
  abc

But it's not the case. Not important for my particular project, but again, worth noting.

chris.l.frederick's picture
chris.l.frederick
User offline. Last seen 3 weeks 5 days ago. Offline
Joined: 14 May 2011

@p12Oph37

I've added some new features I needed to this library, hopefully it's helpful. Would you be game for adding this code to github so we can manage changes easier? I haven't tested this fully yet, but it does seem to work for my project.

My changes:

  • Added a newParagraph function with word-wrapping
  • Added support for tinting paragraphs (requires build 614+)
  • Fixed display issue (spacing) for fonts that use the outline effect
  • Fixed issue that caused some fonts height/width to be off by one pixel
  • Soon I'll be adding:

  • Support for defining a callback function for each word in a paragraph
  • The ability to tint a single word
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    
    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 )
      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( 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 }, --CLF removed the -1, it was causing issues with fonts with borders
                      textureRect = { x = 0 + t.x, y = 0 + t.y, width =  t.width, height = 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
            }
            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 )
      end
      for k, v in pairs( font.sprites ) do
        font.sprites[ k ] = sprite.newSpriteSet( font.spritesheets[ v.spritesheet ].sheet, v.frame, 1 )
      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 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 ] )
                                                    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 
                                            x = x + t.raw_font.chars[ c ].xadvance + (t.raw_font.info.outline or 0) --CLF added support for outlines
                                            if x >= xMax then
                                                    xMax = x
                                            end
                                    end
                            end
                      local background = display.newRect( 0, -t.raw_font.info.base, xMax, yMax )
                      background.isBackground = true --CLF Added to support tinting of font.
                      obj:insert( background )
                      background:setFillColor( 0, 0, 0, 0 )
                    end
                    t.align = oldAlign
            end
            obj.input = function( f, args )
                    -- spawn the text field invisibly
                    local field
                    local function char()
                            -- check if any character has been added or deleted
                            if field.text ~= '--' then
                                    if string.len( field.text ) < 2 then
                                            -- backspace was pressed
                                            if string.len( obj.text ) > 0 then
                                                    obj.text = string.sub( obj.text, 1, -2 )
                                            end
                                    else
                                            -- some other key was pressed
                                            obj.text = obj.text..string.sub( field.text, 3 )
                                    end
                                    field.text = '--'
                                    if args.filter then
                                            obj.text = string.sub( args.filter( obj.text ), 1, (args.max or 32) )
                                    else
                                            obj.text = string.sub( obj.text, 1, (args.max or 32) )
                                    end
                            end
                    end
                    Runtime:addEventListener( 'enterFrame', char )
                    local function done( e )
                            if e.phase == 'submitted' or e.phase == 'ended' then
                                    native.setKeyboardFocus( nil )
                                    field:removeSelf()
                                    Runtime:removeEventListener( 'enterFrame', char )
                                    f( text )
                            end
                    end
                    field = native.newTextField( 0, 0, 240, 24, done )
                    field.text = '--'
                    field.isVisible = false
                    native.setKeyboardFocus( field )
            end
            obj.font = font
            obj.align = 'left'
      obj.text = (text or '')
      return obj
    end
     
    function newParagraph(font, text, width)                
                    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_paragraphWidth =        function( t, k, v )
                                                                                    obj.raw_paragraphWidth = v
                                                                                    --if t.text then t.text = t.text end
                                                                            end                                                                     
                    obj.set_tint =  function( t, k, v )
                                                                    obj.raw_tint = v
                                                                    for i = t.numChildren, 1, -1 do 
                                                                            for j = t[i].numChildren, 1, -1 do
                                                                                    if(not t[i][j].isBackground) then
                                                                                            if v[4] then
                                                                                                    t[i][j]:setFillColor(v[1],v[2],v[3],v[4])
                                                                                            else
                                                                                                    t[i][j]:setFillColor(v[1]-i*2,math.random(1,255),v[3])
                                                                                            end
                                                                                    end
                                                                            end
                                                                    end
                                                                    --if t.text then t.text = t.text end
                                                            end
                    obj.set_text = function(t, k, v)
                            --save the new raw text
                            t.raw_text = v
                            
                            --remove all children
                            for i = t.numChildren, 1, -1 do t[i]:removeSelf() end
                            
                            --determine the width of a space
                            local space = bmf.newString(font, " ")
                            local spaceWidth =  space.raw_font.info.outline*-1 or 0
                            space:removeSelf()
                            space = nil
                            
                            --Create our word-wrapped paragraph.
                            local spaceLeft = t.raw_paragraphWidth
                            local x, y = obj.x, obj.y
                            
                            for word, spacer in string.gmatch(v, "([^%s%-]+)([%s%-]*)") do
                                    local w = bmf.newString(font, word..spacer)
                                    print(w.width,"sw" , spaceWidth, "sl", spaceLeft)
                                    if(w.width + spaceWidth) > spaceLeft then
                                            spaceLeft = t.raw_paragraphWidth - w.width - spaceWidth
                                            y = y + w.raw_font.info.lineHeight
                                            x = obj.x
                                            w.x = x
                                    else
                                            w.x = x + t.raw_paragraphWidth - spaceLeft
                                            spaceLeft = spaceLeft - w.width - spaceWidth
                                    end
     
                                    w.y = y
                                    
                                    obj:insert(w)
                            end
                    end
                    
                    obj.paragraphWidth = width or display.viewableContentWidth
                    obj.text = text
                    obj.font = font
                    obj.tint = {255,255,255}
                    
            return obj
    end

    chris.l.frederick's picture
    chris.l.frederick
    User offline. Last seen 3 weeks 5 days ago. Offline
    Joined: 14 May 2011

    Ack, Line 246 was full of silliness, if you wanted random purple tinting leave it alone, otherwise it should read:

    t[i][j]:setFillColor(v[1],v[2],v[3])

    KenRogoway's picture
    KenRogoway
    User is online Online
    Joined: 17 Jan 2011

    First, a big thanks for this code. Very nice and appreciated.

    Second, there appears to be an issue with alignment. If I use newString() with a short text string, then later change the string to be much longer, it doesn't align properly. It aligns to the right even though the default is "left" in the bmf code. I have also tried "center", etc for bmf alignment, but since this applies it EVERY TIME I call that, it just moves the text over more and more.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
      -- This part works fine
      local statusMsg = bmf.newString( ImpactBold24, "Message" )
      myGroup:insert( statusMsg )
      statusMsg:setReferencePoint( display.TopCenterReferencePoint )
      statusMsg.x = display.contentCenterX
      statusMsg.y = display.contentCenterY
     
      -- This will set the text correctly, but it will no
      -- longer be centered on the screen in the X direction
      statusMsg.text = "Much Longer Message"
      statusMsg:setReferencePoint( display.TopCenterReferencePoint )
      statusMsg.x = display.contentCenterX
      statusMsg.y = display.contentCenterY

    I can provide a simple text app if needed, but you can duplicate this easily enough by doing what I have done above.

    Hopefully the bmf code is still being supported either by the original author or by Chris.

    Jadynut's picture
    Jadynut
    User offline. Last seen 4 days 19 hours ago. Offline
    Joined: 7 Jul 2011

    Hi all,

    anyone realized that the loaded font can't be nil and will keep stay in the memory ?

    my code is like this,
    local hudText = bmf.loadFont( 'hudText.fnt' )

    And i have tried to nil the handler, even its children in the hudText manually,
    but the memory didn't get freed, 15kb mem will be used all the time.

    Anyone know a better way to unload the font?

    vitalyx's picture
    vitalyx
    User offline. Last seen 4 weeks 3 hours ago. Offline
    Joined: 11 Apr 2011

    @Sun.Jiajie hudText:dispose()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    
    module(..., package.seeall)
     
    local sprite = require "sprite"
     
    function loadFont(fntFile)
        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(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 = t.width, height = 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
                    }
                    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 )
        end
        for k, v in pairs( font.sprites ) do
            font.sprites[ k ] = sprite.newSpriteSet( font.spritesheets[ v.spritesheet ].sheet, v.frame, 1 )
        end
     
        function font:dispose()
            for k in pairs( self.spritesheets ) do
                self.spritesheets[ k ].sheet:dispose()
            end
        end
     
        return font
    end
     
    function newString(sFont, sText)
        local obj = display.newGroup()
     
        local font, text
     
        function obj:getFont()
            return font
        end
     
        function obj:getText()
            return text
        end
     
        function obj:setText(t)
            if type(t) ~= "string" then return end
     
            text = t
            for i = self.numChildren, 1, -1 do self[i].removeSelf() end
            local x, y = 0, 0
            local last = ""
     
            for c in string.gmatch(text .. "\n", "(.)") do
                if c == "\n" then
                    x = 0
                    y = y + font.info.lineHeight
                elseif font.chars[c] then
                    if 0 + font.chars[c].width > 0 and 0 + font.chars[c].height > 0 then
                        local letter = sprite.newSprite(font.sprites[c])
                        letter:setReferencePoint(display.TopLeftReferencePoint)
                        if font.kernings[last .. c] then
                            x = x + font.kernings[last .. c]
                        end
                        letter.x = font.chars[c].xoffset + x
                        letter.y = font.chars[c].yoffset - font.info.base + y
                        self:insert(letter)
                        last = c
                    end
                    x = x + font.chars[c].xadvance
                end
            end
        end
     
        function obj:setFont(f)
            font = f
            self:setText(text)
        end
     
        text = sText
        obj:setFont(sFont)
     
        return obj
    end

    Jadynut's picture
    Jadynut
    User offline. Last seen 4 days 19 hours ago. Offline
    Joined: 7 Jul 2011

    hi @ vitalyx

    i even updated the font:dispose() function , but the mem didn't have any change, really wierd

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    function font:dispose()
            for k,v in pairs( self.spritesheets ) do
                    self.spritesheets[ k ].sheet:dispose()
                     self.spritesheets[ k ].sheet = nil
            end
            
            for k,v in pairs(self.info) do
                    k = nil
            end
            
            for k,v in pairs(self.chars) do
                    for i,u in pairs(self.chars[k]) do
                            self.chars[k][i] = nil
                    end
                    
                    self.chars[k] = nil
                    
            end
            
            for k,v in pairs(self.sprites) do
                    self.sprites[k] = nil
            end
            
            collectgarbage( "collect" )
    end

    vitalyx's picture
    vitalyx
    User offline. Last seen 4 weeks 3 hours ago. Offline
    Joined: 11 Apr 2011

    hi @Sun.Jiajie Sorry, can't confirm.

    Just spend some time switching scenes in my game (from one that utilizes a bitmap font to one that don't and back). Here's the result:

    squeraud
    User offline. Last seen 5 weeks 4 days ago. Offline
    Joined: 24 Dec 2011

    Hi everyone,

    i recently released a new bitmap font generator for OSX: bmGlyph (http://www.bmglyph.com).

    the export format is compatible with the bmf project posted above.

    however, a bmGlyph user reported some difficulties using HD and SD font format (which is automatically generated by bmGyph), and after looking at it, i made a quick fix to the code.

    this will work only for iPhone/iPhone4 (actually it depends on the scale factor), but it should be pretty easy to adpat it to other scale factor.

    here is what i do:

    1
    2
    3
    4
    5
    6
    7
    8
    
    local bmglyphfnt
    if display.contentScaleX == 0.5 then
     bmglyphfnt = bmf.loadFont( 'testbmglyph-hd.fnt' )
    else
     bmglyphfnt = bmf.loadFont( 'testbmglyph.fnt' )
    end
     
    local string = bmf.newString(bmglyphfnt, "Loading ... ")

    in bmf.lua, i changed the set_text function ad follow:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    
    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
                            if display.contentScaleX == .5 then 
                                    t.raw_font.info.lineHeight = t.raw_font.info.lineHeight /2
                            end
                            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 ] )
                                                     
     
                                                    letter:setReferencePoint( display.TopLeftReferencePoint )
                                                    if t.raw_font.kernings[ last .. c ] then
                                                            x = x + font.kernings[ last .. c ]
                                                    end
                                                    
                                                    if display.contentScaleX == .5 then --scale the highres spritesheet if you're on a retina device.
                                                            letter.xScale = .5
                                                            letter.yScale = .5
                                                            letter.x = t.raw_font.chars[ c ].xoffset/2 + x
                                                            letter.y = t.raw_font.chars[ c ].yoffset/2 - t.raw_font.info.base + y
                                                    else
                                                            letter.x = t.raw_font.chars[ c ].xoffset + x
                                                        letter.y = t.raw_font.chars[ c ].yoffset - t.raw_font.info.base + y
                                                    end
                                                    
                                                    t:insert( letter )
                                                    last = c
                                            end
                                            if display.contentScaleX == .5 then 
                                                    x = x + t.raw_font.chars[ c ].xadvance/2
                                            else
                                                    x = x + t.raw_font.chars[ c ].xadvance
                                            end
                                            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

    the text displayed is now using the HD texture on iPhone4 and SD on iPhone.

    i'm not sure it is the right way to deal with hd and sd textures on Corona, feel free to correct it. but at least it works :)

    hope that helps!

    vitalyx's picture
    vitalyx
    User offline. Last seen 4 weeks 3 hours ago. Offline
    Joined: 11 Apr 2011

    Congrats, squeraud! Looks like an awesome app :) Too bad we don't have something like this for Windows. Sure, we have BMFont, but it is more basic. Will be using your app in a virtual machine.

    jkrassman's picture
    jkrassman
    User offline. Last seen 7 hours 15 min ago. Offline
    Joined: 4 Aug 2011

    Hi, I am having a small group that contains 1 background image (Square) and one bitMap font.

    The problem is that I have no clue how I should center the bitMap above my image? I was trying to do it manually but the text doesn't align perfect in that way.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    level[i]   = display.newGroup()
                    
                    level[i]:insert(display.newImage( "level.png" ))
                    
                    local bmglyphfnt
                    if display.contentScaleX == 0.5 then
                            bmglyphfnt = bmf.loadFont( 'hobo-hd.fnt' )
                    else
                            bmglyphfnt = bmf.loadFont( 'hobo.fnt' )
                    end
     
                    local string = bmf.newString(bmglyphfnt, i)
                    string.x = 10; 
                    string.y = 80
                    level[i]:insert(string)

    Kind regards, Joakim

    KenRogoway's picture
    KenRogoway
    User is online Online
    Joined: 17 Jan 2011

    Try this:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
      -- Only need to do this once
      local bmglyphfnt
      if display.contentScaleX == 0.5 then
        bmglyphfnt = bmf.loadFont( 'hobo-hd.fnt' )
      else
        bmglyphfnt = bmf.loadFont( 'hobo.fnt' )
      end
     
      local level = {}
     
      for i=1,NUM_LEVELS do
        level[i] = display.newGroup()
                    
        level[i]:insert(display.newImage( "level.png" ))
     
        local string = bmf.newString( bmglyphfnt, string.format("%d", i) )
        level[i]:insert(string)
        string:setReferencePoint( display.TopLeftReferencePoint )
        string.x = 0.5*( level[i].contentWidth - string.contentWidth )
        string.y = 0.5*( level[i].contentHeight - string.contentHeight )
      end

    Antheor
    User offline. Last seen 6 hours 4 min ago. Offline
    Joined: 22 Sep 2010

    Just to add my thought : TextCandy does the job perfectly well with no mem troubles, and supports glyph designer.

    squeraud
    User offline. Last seen 5 weeks 4 days ago. Offline
    Joined: 24 Dec 2011

    hi,

    you will probably need to get the baseline of the font (assuming that you want to center only numbers which or not going under the baseline of the font)

    check in the fnt file, at the top, the lineheight and baseline values. the non-inverted baseline value will be 'lineheight - baseline'. now you should only have to get the center of your level.png and shift the string position like this:

    1
    2
    3
    
    ...
    string.x = level.width/2 - string.width/2
    string.y = level.height/2 + string.height/2 - baseline

    jkrassman's picture
    jkrassman
    User offline. Last seen 7 hours 15 min ago. Offline
    Joined: 4 Aug 2011

    Thanks, @KenRogoway!

    That did the stuff and it was not so hard to understand!

    Joakim

    jkrassman's picture
    jkrassman
    User offline. Last seen 7 hours 15 min ago. Offline
    Joined: 4 Aug 2011

    Hi again,

    I want to keep my things in places so it looks tidy in my main directory.

    But I can't place my font files in a folder? Any suggestions?

    Regards, Joakim

    KenRogoway's picture
    KenRogoway
    User is online Online
    Joined: 17 Jan 2011

    You CAN place your fonts in a folder. I do. When you call the function to add the font just do something like this:

    1
    2
    3
    4
    5
    
    FONT_DIR = "Fonts/"
     
    Calibri48BoldBlack = bmf.loadFont( 'CalibriBold_Black48.fnt', FONT_DIR )
     
    bmf.newString( Calibri48BoldBlack, "Text Message" )

    jkrassman's picture
    jkrassman
    User offline. Last seen 7 hours 15 min ago. Offline
    Joined: 4 Aug 2011

    Great that seems straight forward, but I am getting "Cannot create path for resource file 'hobo-hd.fnt'. File does not exist" error. The fonts are in a folder "fonts" in the root directory of the project.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    local bmglyphfnt
     
    local FONT_DIR = "fonts/"
    if display.contentScaleX == 0.5 then
            bmglyphfnt = bmf.loadFont( 'hobo-hd.fnt',FONT_DIR )
            bmglyphfnt1 = bmf.loadFont( 'badaboom-hd.fnt',FONT_DIR )
    else
            bmglyphfnt = bmf.loadFont( 'hobo.fnt',FONT_DIR )
            bmglyphfnt1 = bmf.loadFont( 'badaboom.fnt',FONT_DIR )
    end

    Any suggestions?

    Joakim

    Viewing options

    Select your preferred way to display the comments and click "Save settings" to activate your changes.