Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Looking for feedback/suggestions on my free bitmap font library (bit like TextCandy ...)
Started by paulscottrobson May 08 2014 01:11 PM

* * * * * 1 votes
125 replies to this topic
[TOPIC CONTROLS]
Page 3 of 6 1 2 3 4 5 »
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#51

paulscottrobson

[GLOBAL: userInfoPane.html]
paulscottrobson
  • Contributor

  • 456 posts
  • Corona SDK

Hi. I've got Glyph Designer and the demo version of bmglyph so I have been experimenting.

 

With respect to padding, I've yet to find anything that is anything other than 0,0,0,0. I'm not quite sure what you mean ?

 

BmGlyph - I tried your settings and yes, it does look terrible. The output from bmglyph (the small fonts) is awful though :(  Viewing it in a image viewer it does look all blurry. If you have a font that looks okay on the .png but doesn't work can you send it to me ?

 

I can only do it on 50 pt size mind. I found that simply calling the font bmgfont@4x or whatever worked fine, even when it was scaled down. 

 

I don't quite see how bmGlyph is going to work - it generates three different font file bmgfont.fnt bmgfont@2x.fnt and bmgfont@4x.fnt so there isn't likely to be much in the way of auto detection.

 

You were right about the alignment. I think it's right now - I made a font from straight Arial and it looks like it is matching  up as it does in LibreOffice, at various scales, so I think it's right - it's certainly a lot closer than it was. 

 

The font image name is part of the .fnt file, so it doesn't matter what it is as long as its consistent.



[TOPIC: post.html]
#52

richard9

[GLOBAL: userInfoPane.html]
richard9
  • Corona Geek

  • 1,118 posts
  • Enterprise

Padding

Padding applies a border around every glyph. So a padding of two adds a 2px transparent gap around A, B, C, etc. This can be important sometimes because there are situations (especially if Corona is not using GL_NEAREST) where the sprites will bleed and the edge of one glyph ends up on another.

 

You can set the padding directly in bmGlyph. The only thing I'm not sure about is that it's a single value (not 4) so not sure exactly what the .fnt translation of that number means, except perhaps -2,-2,2,2

 

bmglyph files

I don't think you need to worry about the @2x/@4x .fnt files. TexturePacker does the same thing with .lua. AFAIK corona only needs the base file to calculate the differences, since internally what graphics.* does is use all numbers from 1x to calculate 4x.

 

Just checked my project, and the 1x file was also awful in my case. But I re-ran the publish and now it looks alright in the PNG file. Not great, but not super hazy. And I have another test that seems to look alright at all three. You can grab them here, temporarily. (They're both the same font, one has no stroke)  Still can't get anything but 1x haze in the simulator, though.



[TOPIC: post.html]
#53

paulscottrobson

[GLOBAL: userInfoPane.html]
paulscottrobson
  • Contributor

  • 456 posts
  • Corona SDK

Ah, right. I wasn't quite sure what these things actually meant :) I'll fix that today, that isn't particularly difficult. 

 

I think the problem with bmGlyph is it just produces smaller font files than GlyphDesigner does by default - I'm not sure there's anything wrong with the code (except the bleeding issue you mention above) other than it's trying to scale things up too much. If I run in 320 x 480 and pick iPad Retina that means a scale-up of 4x before you even do anything else. 

 

This https://coronalabs.com/blog/2012/03/22/developing-for-ipad-retina-display/ should work though I haven't tried it.



[TOPIC: post.html]
#54

paulscottrobson

[GLOBAL: userInfoPane.html]
paulscottrobson
  • Contributor

  • 456 posts
  • Corona SDK

Have you ever managed to actually generate a padded font ? There's a padding and bounding box option on bmGlyph but it doesn't affect the padding setting irrespective of what it is set to.  The Glyph Designer one does seem to work though.



[TOPIC: post.html]
#55

jonathan.simananda

[GLOBAL: userInfoPane.html]
jonathan.simananda
  • Contributor

  • 105 posts
  • Corona SDK

sorry for bumping out of discussion, but does this library able to do than just animated moving text? like for example, a typewriting effect dialog that appears in RPGs? would love to try this when I have the time though :)



[TOPIC: post.html]
#56

paulscottrobson

[GLOBAL: userInfoPane.html]
paulscottrobson
  • Contributor

  • 456 posts
  • Corona SDK

No problem. Yes it can (this is what Richard 9 wants). If you look at the main.lua file which is a placeholder for others comment out all except require("main_roll") and run it, it rolls out some text - this particular interpretation also allows 'events' in the text, in this case the speed changes (and it print 'shake' to the console). The file is some support classes (one does the roll out, one does the events/animation and one puts the whole thing together, then there is a sample class and showing how it works.

 

It's a cheat though ; it is an 'animation' which progressively reveals the text. The whole text is always there, it's just the bits that haven't been revealed yet have an alpha of zero :)



[TOPIC: post.html]
#57

jonathan.simananda

[GLOBAL: userInfoPane.html]
jonathan.simananda
  • Contributor

  • 105 posts
  • Corona SDK

can you explain how the animation work? dos it animate the bits of text one by one, or is it something else? Because i worry about the performance of the device, as sometimes animations can be quite heavy in Corona. But hell, I'll even try this asap. this really intrigues me :)



[TOPIC: post.html]
#58

paulscottrobson

[GLOBAL: userInfoPane.html]
paulscottrobson
  • Contributor

  • 456 posts
  • Corona SDK

At heart all if it is a display group with a collection of bitmaps, which are by default arranged in a line or multiple lines, you can left, centre and right justify them. This is their 'normal' state and to the system that is what they are. So if you animate them the anchor points don't move (as opposed to if you use transition.to on it)

 

The animation is driven by the concept of modifiers. For each displayed character you can change specific features - position offset, scale and rotation, alpha pretty much to anything you like. The 'modifier' receives a table saying which character, word, line etc. it is on and the modifiers work out what to do. So if you want your third word to be twice as big your modifier would have something like.

if info.wordIndex == 3 then modifier.xScale = 2, modifier.yScale = 2 end

Something like the wobble modifier just sticks a few small random numbers in the modifier.

 

Animation is basically a time adjusted modifier. There are two values used for this, an elapsed time since the string was created, and a 'position' function which is a percentage of width when static, but when modified this moves along.

 

If you don't animate the text but just shape it, the modifier is applied once and then nothing else happens, so there are no performance issues other than the time Corona takes to render the font bitmaps.

 

If you animate it, then at a given rate (you can change this) the bitmaps are continually re-modified, so you can then use the time features  to make it move. This obviously has resource implications, because everything is repositioned and recalculated. If it was (say) used in an arcade game for the score it would be fine static - to the system it's just more bitmap images - but animated might slow things down to much especially on low end Android hardware.

 

In general though it's fine. I've got an ultra cheapie 7" tablet - the worst I could find - and it seems to cope fine.

 

So the roll out modifier is something like:

if info.elapsedTime/1000 > info.index then modifier.alpha = 1 else modifier.alpha = 0 end

So every one second, the elapsed time reveals one more character (index is the character number it is enquiring about) after 1 second, index 1 is shown, after 2 seconds 1 and 2, after 3 seconds 1,2, and 3 etc. Modifiers can be functions (simpler) or classes (useful where you have state - e.g. the main_roll.lua file has a speed state).

 

You don't have to use modifiers, you can just write things like:

b = display.newBitmapString("Hello world",160,240,"retroFont",42):setModifier("curve"):animate()

and it will create the string, and curve it and animate that curve. The built in named effects are just a few modifiers I've written, most of them are a couple of lines of code.

 

Note, this chaining approach is a shorthand for:

b = display.newBitmapString("Hello world",160,240,"retroFont",42)
b:setModifier("curve")
b:animate() 

There is one down side, which I haven't come up with an answer to yet. You can treat it exactly as a display.newGroup() object - it is one - except for the following problem:

 

If you animate a font, it adds an enterFrame listener so it can animate. This creates an external reference to the bitmap object, and I haven't figured out how to autoRemove this listener.

 

You can remove the bitmap string just with bitmap:removeSelf() and it tidies up after itself, you can turn the animation off with bitmap:stop() and same thing happens,  but Composer/Storyboard's garbage collection doesn't seem to have a finaliser.

 

So if you do purge an animated string this way, it will still be there (non visible) because of the enterFrame reference.

 

If you turn the animation off in the exit phase of the Scene managers, or remove the string, it works fine. If you don't animate it it works fine, it's just like any other graphic.



[TOPIC: post.html]
#59

jonathan.simananda

[GLOBAL: userInfoPane.html]
jonathan.simananda
  • Contributor

  • 105 posts
  • Corona SDK

which means, even though i removed the text, the enter frame listener is still there, and probably (and will, in my opinion) cause something unexpected under Corona hood.

 

does removing the object clean entirely all listeners attached to it? As I understand, you also need to kill the listeners, and I don't have any idea how to remove an enterFrame listener.

 

Quite splendid though. i'll follow the progress updates. I'll give feedback as soon as I able to use it. the library one is to use right, now the demo one?



[TOPIC: post.html]
#60

paulscottrobson

[GLOBAL: userInfoPane.html]
paulscottrobson
  • Contributor

  • 456 posts
  • Corona SDK

It appears not. You don't need to remove this listener though, just stop the animation with the :stop() method or remove the bitmap with :removeSelf().

 

The font-demo is usually slightly out of date ; the best one to use is the font-manager which has an assortment of simple demos that can be changed by editing the main.lua file.



[TOPIC: post.html]
#61

jonathan.simananda

[GLOBAL: userInfoPane.html]
jonathan.simananda
  • Contributor

  • 105 posts
  • Corona SDK

okay, I'll give feedback as soon as I try it! :)



[TOPIC: post.html]
#62

richard9

[GLOBAL: userInfoPane.html]
richard9
  • Corona Geek

  • 1,118 posts
  • Enterprise

...you're absolutely right. bmGlyph is not passing on the padding. Bah!

 

Well, I give in. I'll switch to Glyph Designer tomorrow morning and report in based on what I find.



[TOPIC: post.html]
#63

richard9

[GLOBAL: userInfoPane.html]
richard9
  • Corona Geek

  • 1,118 posts
  • Enterprise

...I posted and yet it's not there?

 

Anyway, you're right. Glyph designer worked, though there is some suspicious x-spacing. I wish there was a way to edit that in the Glyph Designer...

 

The bigger problem with Glyph Designer is working from large assets. Ideally you want your "core" asset to be the small one, because 2x, 3x, 4x can be multiples. If your big asset is core, then you need to make sure the entire rest of your project does the same. It may not seem like a big deal now but with @3x gaining in importance (it seems likely it will be the new iPhone resolution) assets will look sloppy at a res that can't be evenly divided.



[TOPIC: post.html]
#64

richard9

[GLOBAL: userInfoPane.html]
richard9
  • Corona Geek

  • 1,118 posts
  • Enterprise

Ugh, so for some reason my project didn't have a config.lua. That being said, 

 

a ) The font is still highly blurry with one present

b ) @2x and @4x assets don't seem to legible at all, as if they're using either completely busted export details or perhaps the details of the 1x sheet. 

 

Glyph Designer looks perfect though. Hmm.



[TOPIC: post.html]
#65

paulscottrobson

[GLOBAL: userInfoPane.html]
paulscottrobson
  • Contributor

  • 456 posts
  • Corona SDK

I do wonder if it is mostly to do with BmGlyph and its settings. In *theory* they should do the same thing, and produce the same output, pretty much.  All the library is doing, pretty much, is treating them as a sprite sheet and creating and animating those sprites. That bit is actually relatively straightforward. 

 

Unless BmGlyph have wired it up in a really weird fashion it shouldn't make any difference on 2x 4x and (1x) other than obvious things like the resolution and sheet size. From what I can see, what it does is create three fonts with the three different names. 

 

Having used both of them Glyph Designer is more expensive, but it is a much better program in the way it is built.



[TOPIC: post.html]
#66

richard9

[GLOBAL: userInfoPane.html]
richard9
  • Corona Geek

  • 1,118 posts
  • Enterprise

The bmGlyph author sent me a working project and output files. It does appear to work well, at least, using his assets and the bmf.lua font controller he built. He says he sent you a message a few days ago and hasn't heard back? (From talking with him he's clearly motivated to make sure his stuff is working cross-library. And with fontmanager, it's not; I'm reliably getting a hazy 1x and broken 2x/4x with everything bmGlyph outputs.)

 

You need not be confused by the multi-file output, by the way; display.newSprite uses the information given from the 1x asset, and them multiplies it as necessary if 2x or 4x assets are needed according to config.lua. The @2x/@4x fnt files are not used unless you choose to sub them in through code.

 

Anyway, I think Glyph Designer has a strong, consistent presentation but it just is missing some very important features right now that bmGlyph has:

  • Substitute image for glyph
  • Custom x-spacing per glyph (I have to edit the Glyph Designer .fnt file manually to do this...)
  • A build wizard for automatic 1x/2x/4x/etc output.
  • .lua instead of .fnt support if you want to roll that way

That being said, something is fishy with the numbers. I've dropped a sample export (1x,2x,4x textures + .fnt file) into dropbox if you want to give it a quick look. If the problem is on his end, I have to think there's something wrong with the glyph coordinates, but I'm just not experienced enough with the format to see any tell-tale problems.



[TOPIC: post.html]
#67

paulscottrobson

[GLOBAL: userInfoPane.html]
paulscottrobson
  • Contributor

  • 456 posts
  • Corona SDK

Hi. Can you forward my email address to him (paul@robsons.org.uk). I don't recall having an email from him but I might have deleted it accidentally. I will try to contact them direct.

 

I have made some progress, I have got the FM using the correct sprite sheet  - because I wasn't setting sheetContentWidth and sheetContentHeight it always picked up the 1x display.

 

But there is another problem.

 

The .fnt file (your dropbox one) only has one layout of fonts. 

 

However, if you look at newTest.png and newTest@2x.png, they are different layouts - different characters in different positions - it isn't just a 'scaled up' version of newTest.png (which is, I think, how it's supposed to work).

 

So there must either be some way of generating alternate .fnt file - otherwise I have no idea where the characters are - or alternatively some way of getting bmGlyph to use the same layout for every png file, just scaled to suit.



[TOPIC: post.html]
#68

paulscottrobson

[GLOBAL: userInfoPane.html]
paulscottrobson
  • Contributor

  • 456 posts
  • Corona SDK

Thanks to Stephane at bmGlyph I now have more idea :) 

 

The problem with bmGlyph is that as I suggested there is only one .fnt file - there should be three pairs, of .fnt files, usually called font.fnt font@2x.fnt and font@4x.fnt.

 

The way FM now works is it picks up a file appropriate for the scale. There is a calculation in the retina code tutorial which works out what the 'preferred scale' is - this returns a value between 1,2,3 and 4. 1 is a 320x480 iPhone, 4 a Retina iPad (2048x1536 ?)

 

What it does is to look for these backwards - so for a retina iPad it will start @4x (at font@4x.fnt) and work its way down until it finds a .fnt/.png file that exist. For a basic iPhone it will go straight to the 1 x scale file (e.g. font.fnt). So it pretty much picks the best available. You can override this, if you put font@4x in the font name it will use the 4x font irrespective of what else is there.

 

You still have the basic issue though that a 1x font has to look okay on the device it is running on. If bmGlyph or Glyph Designer produces a rather smallish font which is quite pixellated it's going to stay looking pixellated. It is a trade off with texture memory.

 

The other change is that I have extended UTF-8 decoding so it uses up to the six byte character maximum, if anyone should want this.

 

Padding is still in the pipeline.



[TOPIC: post.html]
#69

jonathan.simananda

[GLOBAL: userInfoPane.html]
jonathan.simananda
  • Contributor

  • 105 posts
  • Corona SDK

can i use this with starter Corona SDK? I'm getting a few error when running the demo



[TOPIC: post.html]
#70

paulscottrobson

[GLOBAL: userInfoPane.html]
paulscottrobson
  • Contributor

  • 456 posts
  • Corona SDK

Don't know - what errors are you getting ? 



[TOPIC: post.html]
#71

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

The standard Corona way to handle dynamic scale naming is to have a base-name and let the imageSuffix in config.lua decide which suffix to use. Instead of having a forced naming convention, I've modified the code somewhat so that it uses the imageSuffix extensions found in config.lua.

 

First I require("config") at the top of the module to get the imageSuffix table.

 

In the code below, I've made 3 modifications delimited by:

-->> modification (n) >>>>>>>>>>>>>>>

some code here

--<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

 

I've done some initial testing and it seems to work well.

require ("config")
.
. 
.
function BitmapFont:loadFont(fontName)
    local options = { frames = {} }                                                         
    local spriteCount = 1                                                                   
    local imageFile = nil                                                                   
    local charData = {}                                                                     
    local source = io.lines(self:getFontFile(fontName))                                     
    self.padding = { 0,0,0,0 }                                                              

    for l in source do 
        -->>> modification 1 >>>>>>>>>>>>>>>>>>>> 
        local page = l:match('^%s*page%s*id%s*=%s*(%d+)%s*file%s*=%s*%"(.*)%"$') 
        local fileName = fontName .. self.suffix .. ".png"
        --<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

        if page ~= nil then                                                                
            assert(page == "0","We do not support font files with page > 0. If you have one contact the author")
            imageFile = BitmapFont.fontDirectory .. "/" .. fileName                        
        end
        if l:match("^%s*char%sid") ~= nil then                                             
                                                                                           
            local x,y,w,h = l:match("x%s*=%s*(%d+)%s*y%s*=%s*(%d+)%s*width%s*=%s*(%d+)%s*height%s*=%s*(%d+)%s*")
            assert(h ~= nil,"Failure to read line in .fnt file, contact author")           
            local optionsEntry = { x = x*1, y = y*1, width = w*1, height = h*1 }           
            options.frames[spriteCount] = optionsEntry                                     

                                                                                           
            local charID,xOffset,yOffset,xAdvance = l:match("id%s*=%s*(%d+).*xoffset%s*=%s*([%-%d]+).*yoffset%s*=%s*([%-%d]+).*xadvance%s*=%s*([%-%d]+)")
            assert(xAdvance ~= nil,"Failure to read line in .fnt file, contact author")
            local charInfo = { width = xAdvance*1, xOffset = xOffset*1, yOffset = yOffset*1}
            charInfo.spriteID = spriteCount                                                 
            charInfo.frame = optionsEntry                                                   
            charInfo.height = optionsEntry.height                                           
            assert(charData[charID] == nil,"Duplicate character code, contact author")
            charData[charID*1] = charInfo                                                   
            spriteCount = spriteCount + 1                                                   
        end
        if l:match("padding") ~= nil then 
            self.padding[1],self.padding[2],self.padding[3],self.padding[4] =               
                l:match("padding%s*%=%s*([%d+])%s*%,%s*([%d+])%s*%,%s*([%d+])%s*%,%s*([%d+])")
            assert(self.padding[4] ~= nil,"Bad padding parameter format")                   
            for i = 1,4 do self.padding[i] = self.padding[i] * 1 end                        
        end
    end

    assert(imageFile ~= nil,"No image file in fnt file, contact the author")                
    self.imageSheet = graphics.newImageSheet(imageFile,options)                             
    assert(self.imageSheet ~= nil,"Image file " .. imageFile .. "failed to load for fnt file ".. fontName)  
    return charData
end

--//%   Get font file name, scaling for display size and checking for @nx files.
--//    @fontFile   [string]        Base name of font file. May use @4x tags to force high res font
--//    @return     [string]        Path of font file.

function BitmapFont:getFontFile(fontFile)
    -->> modification 2 >>>>>>>>>>>>>>>>>>>>>>
    --// TODO: Work out scale, check if 4x, 3x 2x 1x exist and use them if they do.
    --// TODO: Explain in docs what it actually does.
    -- local scaleFactor = 1 / display.contentScaleX
    -- if fontFile:match("%@%d+x$") == nil then                                             
    --  local deviceWidth = ( display.contentWidth - (display.screenOriginX * 2) ) /        
    --                                                                      display.contentScaleX
    --  scaleFactor = math.floor( deviceWidth / display.contentWidth )
    --  scaleFactor = math.max(scaleFactor,1)                                               
    --  while scaleFactor > 1 and self:getFileNameScalar(fontFile,scaleFactor) == nil do    
    --          scaleFactor = scaleFactor - 1                                               
    --  end
    -- end

    self.fontScalar = 1 / display.contentScaleX                                             
    --<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    return self:getFileNameScalar(fontFile,scaleFactor)                                     
end 

--//%   Create a full file name for a font scaled by a particular amount (so 2 => @2x etc.)
--//    @fontFile   [string]        Base name of font file
--//    @fontScalar [number]        Possible scalar size 2,3,4 etc.
--//    @return     [string]        Path of font file.

function BitmapFont:getFileNameScalar(fontFile,fontScalar)
    -->> modification 3 >>>>>>>>>>>>>>>>>>>>>>>
    local suffix = ""
    local selectedScale = -1

    for k, v in pairs(application.content.imageSuffix) do                                   
        if (self.fontScalar >= v) and (v > selectedScale) then                              
            selectedScale = v
            suffix = k
        end
    end

    fontFile = fontFile .. suffix
    self.suffix = suffix
    --<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    return system.pathForFile(BitmapFont.fontDirectory .. "/" ..                            
                                                fontFile .. ".fnt", system.ResourceDirectory)
end 


[TOPIC: post.html]
#72

paulscottrobson

[GLOBAL: userInfoPane.html]
paulscottrobson
  • Contributor

  • 456 posts
  • Corona SDK

Thanks - it's much appreciated - do you want to push that or shall I do it ?



[TOPIC: post.html]
#73

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

I'm still testing it to see if there are any unwanted side-effects to my changes.

Did you see if my changes have broken something in your object logic or not?

 

I can do the push when I'm done. Do you want me to fork it and create a separate branch with a pull request?



[TOPIC: post.html]
#74

richard9

[GLOBAL: userInfoPane.html]
richard9
  • Corona Geek

  • 1,118 posts
  • Enterprise

Not sure if any upgrades have been done here since June, but I did notice that the github version fires a warning if you don't have @2x/@4x files now?

 

Guess I need to dig in and find a way to disable that...(GL_NEAREST doesn't require different size assets; it's strictly optional and silently just does Corona scaling otherwise)



[TOPIC: post.html]
#75

paulscottrobson

[GLOBAL: userInfoPane.html]
paulscottrobson
  • Contributor

  • 456 posts
  • Corona SDK

I have merged Ingemar's changes to use config.lua to use imageSuffix - I added an or {} so that it still works if there isn't an Image suffix. AFAICS the changes work fine.




[topic_controls]
Page 3 of 6 1 2 3 4 5 »
 
[/topic_controls]