It's all in the Comments

Anyone reading this blog but ignoring the comments is missing out on all the intelligent posts at the moment. For anyone who has missed out, the enigmatic Steven seems to have joined the burgeoning ranks of Woopsi developers, and is currently engaged in ripping PALib apart and re-assembling the pieces Woopsi needs into what seems to be becoming a new abstraction layer.

Marvellous stuff.

This will make Woopsi independent from PALib, opening the door for any libnds developers to make use of it.

In other news, again based on conversations in the comments, I’ve split the Font class into FontBase and Font classes. The FontBase implements almost everything needed for a font; the Font class rounds it off by adding a 16-bit bitmap into the mix. In addition to this, Woopsi also has a MonoFont class. This allows for 1-bit bitmaps to be used as fonts, saving 15 bits per pixel. These bitmaps need to be arrays of unsigned shorts, with each bit representing a visible (1) or invisible (0) pixel.

Whilst playing with the font classes, I thought I’d have a go at implementing const-correctness. This is the mildly controversial technique of enforcing an API - if a parameter passed into a function shouldn’t be changed within that function, it should be passed in as a const. It’s controversial because it can make programming a little more fiddly, and has led to the creation of the “mutable” keyword (that lets const values become non-const, which seems like something of a waste of effort to me). The benefits far outweigh the cons, though, so it seems like something I’ll definitely need to implement throughout the codebase.

Back in the mists of time when I first picked up C++ I seemed to have the const stuff sorted, or so it seems from looking at my old code. I’ve just forgotten it over the intervening years.

The Gadget::GadgetType enum is history. Since I refactored the code it’s no longer used anywhere, and as Jeff pointed out in the first place, when you’re trying to allow subclassing it’s an approach that simply won’t work. I think the SimpleScreen and SimpleWindow classes are going to have to go the same way.

GraphicsPort now has a drawRect() function. It’s pretty much a copy-and-past of drawXORRect().

Lastly, there’s a new Animation class. Not tested yet - I’ll get around to making an AnimatedButton soon - but it allows bitmaps to be linked together to produce animations. The developer can play, stop and pause the animation, move through it to a different frame, set its playback speed, and make individual frames appear on-screen for longer than the playback speed typically allows. Animations can either not loop, loop with a wraparound, or ping-pong.


Jeff on 2007-12-13 at 20:44 said:

What I find most confusing about ‘const’ and typically do wrong by habit, is putting it on the left. ie, if you have a function that takes a pointer to const characters, it should be declared

func(char const *)

The C++ standard is a bit slack in this regard and says words to the effect that “const applies to the expression to its left, unless it is the left-most in which case it applies to its right”.

Unfortunately, I got into the habit of writing “const char *” because I read it as ‘constant character’ pointer.

constant ‘character pointer’ which is actually supposed to be ‘char * const’ but I have yet to see too many places where its really all that useful. This is a variable whose value you are not allowed to change, and those just don’t come up all that often, I find.

There are a couple of other gotchas that I noticed in Woopsi, I think it was Window and Screen titles - the object just keeps a literal pointer to the value passed in at constructor time rather than copying it. Since most people create these things from string literals, they’ll probably be fine. But if someone were to read their UI from an external file, they might find random crashes happening if they read/createwith/free those strings.

Steven on 2007-12-13 at 21:30 said:

OK so I’ve got a patch to remove the dependance on PALib - and I appologise now for the insaine speed of the pong window…..


Enjoy :D

ant on 2007-12-14 at 00:24 said:

Patch works OK - any reason for the huge speed boost? Looks like the vsync has gone out in DeSMuME.

EDIT: Ah, yes - adding more VBL waits doesn’t affect the speed - looks like the function is broken?

Steven on 2007-12-14 at 00:26 said:

I’ve got no idea…. even on hardware it’s insaine…

ant on 2007-12-14 at 00:31 said:

Got it. The function was doing this:

if( !( keysHeld() & KEY_LID ) ) { return 0; }

When it needed to do this:

if( !( keysHeld() & KEY_LID ) ) { swiWaitForVBlank(); return 0; }

Looks fantastic. I’ll need to tidy up the style a little to match the rest of the code, but this is definitely going in!

Steven on 2007-12-14 at 00:43 said:

Actually looking at that code you don’t even need the returns (I merged 2 PA functions into that one).

ant on 2007-12-14 at 01:00 said:

Looks like there’s another bug in here somewhere - dragging and releasing a window sometimes causes the window to jump down about 50 pixels. I wonder if the stylus-up isn’t being read quick enough?

Steven on 2007-12-14 at 13:59 said:

I’ve started tring to implement another font class, but I don’t think the current implementation is very helpful to non bitmap based fonts. I think you may have to move the drawing of the font data from the text writer class and move it into the font class, or provide some other way for the font class to provide the information about the font.

Steven on 2007-12-14 at 14:00 said:

Gah I should proof read before posting - I meant that the current implementation is set more towards a bitmap font, than a non bitmap font.

ant on 2007-12-14 at 14:26 said:

The font system is definitely set up for bitmap fonts. I could extract that sort of thing into a new BitmapFont class. What kind of functionality do you need in the base class?

Steven on 2007-12-14 at 18:53 said:

I thought that the font class would deal with everything font related, and I’ve only had a quick glace at how you have things setup at the moment.

The main problem that I can see you having is what will happen if you add the ability to use other font formats, I know you said you were going to add the ability to use Amiga fonts at some point, and I know from experience that not all the amiga fonts were bitmap based.

I think you may have to move the code that deals with drawing the characters into the base class.

What I think you could use for the font classes:

baseFont -----> bitmapFont -----> monoFont

baseFont -----> outlineFont

And the baseFont class has a drawChar( const bitmap, x, const y, const letter) code that then draws the font at the x,y position and updates the x co-ord with the kerning of the font. This change will mean that you will be able to add monospaced and proportional fonts into the system with ease. Adding a getLineHeight() function to the baseFont will also allow different height fonts.

Clipping of the string would be dealt with at the text writer level, and clipping of a single letter at the font draw char level. This would then allow you to add a fontBMF (for the BMF fonts out there), fontBMP (this is close to what your using now for the normal font), fontAmiga (for the amiga fonts), fontFreeType (to add true type fonts at any size).

So basically all you need to add to the base class is:

drawChar() getLineHeight() setLineHeight() - this would only be used on the amiga and free type fonts, unless you added font scaling into your drawing code for bitmap fonts.

ant on 2007-12-14 at 19:52 said:

I wasn’t intending to support Amiga Compugraphic (AGFA) fonts, just bitmap fonts.

Hmm, I’m undecided about this. On the one hand, it’s a fairly easy switch to make. On the other, I’m dubious about the practicality and usefulness of outline font support. It’s not something I’d write, but I don’t gain anything by not making the font system generic enough for someone else to add it. Proportional fonts would be good, and I can see that this would help.

I’ll look into it and see what I come up with.

Jeff on 2007-12-14 at 22:16 said:

4MB of main memory, guys. Don’t lose sight of that. This isn’t about building a tech-demo, its about a real usable application framework.

I agree that the Font could be doing the drawChar() rather than the Textwriter, but I suspect you’ll find that you’ll get way better performance from kerning info if the Font gets to draw a string of characters in one go - after all, if you’re doing kerning, the next logical step is ligatures. Which of course complicate up the ability to draw a text insertion cursor.

ant on 2007-12-14 at 22:53 said:

Memory is always a problem, definitely. For the moment I’m going to concentrate on other areas - the font system works and it’s good enough.

Jeff on 2007-12-14 at 22:55 said:

On a different topic, what happened to Gadget::drawIntOutline() ?

Jeff on 2007-12-14 at 23:09 said:

Sigh, gotta remember to refresh the main page every time I come back.

ant on 2007-12-14 at 23:10 said:

See the latest post. I’ve been meaning to delete it for ages. Finally got around to it. You should do this instead:

GraphicsPort* port = newInternalGraphicsPort(clipRect); // Your code goes here // Draw the border port->drawBevelledRect(0, 0, _width, _height); delete port;