Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » feature request + patch (5.1 branch): al_create_std_bitmap_font

Credits go to Audric, Elias, Evert, Matthew Leverton, torhu, and weapon_S for helping out!
This thread is locked; no one can reply to it. rss feed Print
feature request + patch (5.1 branch): al_create_std_bitmap_font
Dennis
Member #1,090
July 2003
avatar

--- update 3, July 4th 2012 ---
I've submitted the patch (in GIT format for the 5.1 branch) to the mailing list.

--- update 2, July 3rd 2012 ---
[1] new patch (with simple Tri-add-rem upscaling algo)
modified ex_font to demonstrate usage, as seen in screenshot below:
{"name":"606238","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/3\/e3c167e6d3048ca8c86be332a285e03e.png","w":804,"h":661,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/3\/e3c167e6d3048ca8c86be332a285e03e"}606238
just for reference a full 2x and 5x scaled set:
{"name":"606236","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/a\/1a99836365909a00fa01f3b453f9479f.png","w":578,"h":182,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/a\/1a99836365909a00fa01f3b453f9479f"}606236
{"name":"606237","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/a\/3a4d8a8e361a8c56ea68084cf5fbdf8c.png","w":1445,"h":455,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/a\/3a4d8a8e361a8c56ea68084cf5fbdf8c"}606237
--- end of update 2 ---

--- update 1 ---
[2] link to new attached patch: implemented 'al_create_builtin_font(unsigned int scale)' in the font addon and modified ex_font to demonstrate usage, see also the screenshot below:
{"name":"606203","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/a\/5a8ac1337f2248653955c17c0f7b2db2.png","w":894,"h":482,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/a\/5a8ac1337f2248653955c17c0f7b2db2"}606203
--- end of update 1 ---

--- original post ---
[3] link to attached patch: implemented 'al_create_std_bitmap_font' in the font addon and modified ex_font to demonstrate usage

I humbly request to include this in the 5.1 branch.

stdfont.c said:

contains a ported binary version of the Allegro 4 internal standard font
and a function to create an Allegro 5 bitmap font from the binary data
for use in environments where no external bitmap font or true type font is available

--- end of original post ---

Evert
Member #794
November 2000
avatar

I think this could be an extra addon, something like "allegro_standard_font" or similar. This seems to me to fit nicely with Allegro 5's modular design.

Apart from that technical detail, this seems like a good idea. Not sold on the A4 font though; it's a bit small at today's resolutions. Would it be possible to embed a TTF font?

Dennis
Member #1,090
July 2003
avatar

Embedding a TTF font should not be a problem in theory as long as there is some internal function which can read a TTF font from a memory address instead of from a given filename.

I could then just write a small tool which reads a TTF file and generates a byte array in C code which I could then paste into the source and read the TTF font from there.

The embedded TTF font should be royalty free, not GNU'ed or otherwise license contaminated and most importantly it should be as small as possible (bytesize not font-size).

Evert said:

Not sold on the A4 font though; it's a bit small at today's resolutions.

My personal motivation for wanting it is to be able to quickly display some debugging information on screen near relevant in game objects without having to rely on external data.

I could add a scaling parameter to the function in the OP. It would look blocky but it would be bigger.

Matthew Leverton
Supreme Loser
January 1999
avatar

I dislike the name, but I don't see why it cannot be part of the regular font add-on. I don't really see a reason for an add-on that is full of embedded fonts. IMO, you either want a quick and dirty one for debugging or you want the full control of loading external TTFs.

Elias
Member #358
May 2000

Yes, the intended use case of this should probably be some quick debug messages during development - not the font to use in your game/application.

We may want an API to load a system font for that instead. Which probably would then be something like al_get_standard_font("Arial 12pt").

In light of that, I suggest changing the name to al_create_builtin_font (or similar). Also about the patch, I think it does not follow our style conventions.

--
"Either help out or stop whining" - Evert

torhu
Member #2,727
September 2002
avatar

I bet I'm not the only one using the a4_font.tga that comes with the Allegro 5 examples for my games. On my monitor it's a good size both for debug info printing and other text. It does the job, but a better looking font wouldn't hurt either.

An easily available font for use early in the project, for debugging, or just when you can't be bothered to find something else would be handy.

Dennis
Member #1,090
July 2003
avatar

I only found one public domain font: http://tulrich.com/fonts/

The regular font face of that is about 160KB in .ttf and 140KB in .otf format.

It might be possible to reduce that size to about 80KB to 95KB by storing it in a compressed form inside the code and the decompressing it in memory and loading it from there.

However, that still seems huge for an embedded font.

The A4 font only takes up 8 byte per character and the tiny display-size problem could be fixed by adding a scaling parameter to the function from the patch.

Elias said:

In light of that, I suggest changing the name to al_create_builtin_font (or similar). Also about the patch, I think it does not follow our style conventions.

Where can I find a copy of the style conventions? (are you referring to the local variable names inside the function?)

Next up...
I will rename the routine to al_create_builtin_font.
I will add a parameter to allow scaling it up in integral increments on creation time (e.g. 1(default), 2, 3, ...).
I will fix the code to follow the style conventions (if I can find them).

Quote:

We may want an API to load a system font for that instead. Which probably would then be something like al_get_standard_font("Arial 12pt").

That's outside the scope and purpose of this builtin font though but a good idea.
That should probably go right into the TTF addon:
a function to enumerate available TTF fonts on the system (filename, font name pairs)
a function to load a system font (already there if the enumeration function delivers full filenames (including path))

Under Windows all fonts are stored under <WindowsInstallDir>/Fonts but maybe FreeType already has a function to enumerate system fonts?

Audric
Member #907
January 2001

Freefont itself doesn't know.
You can check here the locations for a handful of OSes (OSX, Beos, Haiku,..)
http://code.google.com/p/grafx2/source/browse/trunk/src/text.c#292

weapon_S
Member #7,859
October 2006
avatar

Dennis
Member #1,090
July 2003
avatar

Dennis said:

I will rename the routine to al_create_builtin_font.
I will add a parameter to allow scaling it up in integral increments on creation time (e.g. 1(default), 2, 3, ...).
I will fix the code to follow the style conventions (if I can find them).

Done. See updated main post (includes screenshot). I hope I didn't miss any important style convention from the A4 hackers guide.

With the link Audric provided I'll look into starting with a new function for the TTF Addon soon(ish) but that will be a separate patch.

Elias
Member #358
May 2000

Is the scale parameter useful? You can achieve the exact same effect by drawing it at twice the size, it seems.

--
"Either help out or stop whining" - Evert

Dennis
Member #1,090
July 2003
avatar

I did not find a scale or size parameter in any of the text drawing routines and I was not aware of al_scale_transform when I wrote it.

I think it does not hurt to have it though now that it's already there.

The documentation could include a hint that scaling can be achieved by other means and that using the scaling parameter in the creation routine will cause the font to use up more texture memory as you pointed out in IRC.

Using a combination of both al_scale_transform and a different scale on creation time may yield some interesting results though.

Depending on how interpolation works, drawing a 2x or higher scaled(at creation time) version at less than 0.5 size (using al_scale_transform) may lead to cleaner or dirtier rendering output.

EDIT:
Maybe I should attempt to implement something like http://en.wikipedia.org/wiki/Hqx for the scaling. Thoughts?

Elias
Member #358
May 2000

A HQX addon would be interesting I guess. But it would be a separate addon and simply scale one bitmap to another.

Maybe more useful than just doing an offline scale would be a new shader example which uses a real-time HQX shader. That's a bit of work though :P

--
"Either help out or stop whining" - Evert

Dennis
Member #1,090
July 2003
avatar

I started thinking about a simple up-scaling smoothing algorithm for this special monochrome (1 bit) case for scaling the available font data bits into something less blocky.

It won't be able to generate nice curves, nor would it be able to get any non-multiple of 45 degrees lines corrected or even nicely extrapolated but I think the result would be good enough to make looking at it more tolerable than looking at blocky fat pixels.

The basic idea is to test around a given target (fat)pixel for intersecting "lines" and then slapping one or more of 8 different (scaled) triangles into the (fat)pixel in a lower pixel resolution.

I fixed my thoughts in the following (not yet complete) diagram:
{"name":"606204","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/9\/29d5be62ba7307f101afc39d1af302af.png","w":537,"h":618,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/9\/29d5be62ba7307f101afc39d1af302af"}606204

I'd basically have four different tests in four different orientations each. Each test would have to check at most 6 bits. Some tests must have precedence over others. Each test must specify which of the eight triangles to render into the gap to iron it out. There'd be a few special test cases as well.

----
append (July 1st 2012):
Thought about it some more and I will implement some up-scaling de-blockification according to the following draft:
{"name":"606224","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/a\/9a6e2f16de2a8d54a94ba9ee60e82213.png","w":256,"h":256,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/a\/9a6e2f16de2a8d54a94ba9ee60e82213"}606224

append 2 (additional notes(view with monospaced font) to the above image and the algorithm)

+------------------------------------------+
|Monochrome Font Upscaling Algo v.1.0 draft|
|"Tri-add-rem" by Dennis-Busch@gmx.net     |
|July 1st 2012                             |
+------------------------------------------+

(see also "Tri-add-rem-draft10b.png")

Short description:
------------------
Examine bits around source pixel and reshape scaled target "pixel"(square) by adding or removing one or more of four triangles to/from the 

target square.

Random thought: Could easily be adapted for achieving differently styled result by using other shapes than triangles, e.g. cirlce 

sections.

triangles 0 to 3:
-----------------
(the sides on the right angle are supposed to be even in length and their length is half the target square side length)
+--+ +--+ +       +
| /   \ | |\     /|
|/     \| | \   / |
+       + +--+ +--+
 t0   t1   t2   t3

Bits around target square/source pixel:
---------------------------------------
bit 0, bit 1, bit 2
bit 3, ts/sp, bit 4
bit 5, bit 6, bit 7
(ts = target square, sp = source pixel)


A test case(rule) includes the following information:
-----------------------------------------------------
  a.) an "apply only on scale factor 3 or more" bit (to prevent erasing/adding 
      full squares on scaling factor 2 for some otherwise generic rules) 

  b.) a "stop bit" to specify that no other rule should be tested if this rule
      applies (rule tests must be sorted so that rules with higher precedence will be
      tested first)

  c.) the bit pattern (set, un-set, don't care) which the bits around the source pixel
      must represent in order to apply the triangle operations to the target square
      (need two bits per bit in the pattern to represent the "don't care" setting)

  d.) four triangle bits specifying which triangles to apply(add/remove)
      (if sp is set they will be removed otherwise they will be added)

So there will be 22 bits per rule, so each rule needs 3 bytes to be stored:
a,b,d can be stored together in one byte and c can be stored in two bytes
00ddddba | cccccccc (set/unset bits) | cccccccc (don't care bits)
       1          1                           1 (least significant bit)
  0123     01234567                    01234567 (triangle numbers, surrounding bit numbers)

rules for 'set' source pixel (only remove triangles):
-----------------------------------------------------
example for the first non-exclusive rule in the diagram on the image file
00101000 | 00001000 | 00000000 (left 'line' ending)
  0123ba | 01234567 | 01234567

example for the first exclusive rule in the image file
00111111 | 00000000 | 00000000 (single square surrounded by unset bits)
  0123ba | 01234567 | 01234567

todo: add rules

rules for 'unset' source pixel (only add triangles):
----------------------------------------------------
example for the second exclusive rule in the image file
00111111 | 01011010 | 10100101 (empty square surrounded by set/don't care bits)
  0123ba | 01234567 | 01234567

todo: add rules

weapon_S
Member #7,859
October 2006
avatar

Dennis
Member #1,090
July 2003
avatar

Have you ever wasted two days implementing a complicated algorithm until you realized you can achieve the same effect with a MUCH SIMPLER method? No? Well, I just did that. :D

As I was adding more and more of those rules I realized I can base all of that on much simpler rules:
I only need to determine for each triangle whether to draw it or remove it.
This can be done by examining the three pixels neighboring the triangle:

If the center pixel is set and the three neighbor pixels of a triangle are empty, remove that triangle.

If the center pixel is not set and the orthogonal neighbor pixels of a triangle are filled, add that triangle.

In both cases, if there are at least two triangles being added or removed, make them slightly smaller.

Simple.

And I already had this very complicated system (complete with lookup table and rule definitions in place... :X ).

Overly complex code[1] and image below are included just for laughs: XD :P
(I will rewrite that with the simple rules from above.)
{"name":"606234","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/c\/8c15d6b58d7710819af79d811e0969a0.png","w":256,"h":256,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/c\/8c15d6b58d7710819af79d811e0969a0"}606234

--- append ---
Updated main post with new simple up-scaling implementation and patch.

Go to: