2009-11-10

Bitmaps, Framebuffers, Drawing, and Fonts

The latest set of updates encompasses a substantial amount of fundamental changes within Woopsi. It now includes the following types of bitmap class:

BitmapBase

The most basic bitmap abstract class from which all others inherit. It defines the most fundamental properties of an immutable bitmap.

BitmapWrapper

Extends the BitmapBase with the ability to wrap around a raw u16 array and permits it to be used as a standard bitmap object.

MutableBitmapBase

Extends the BitmapBase with the ability to set the colour of a pixel at a given set of co-ordinates. Can also provide a non-const pointer to the raw u16 array. This is an abstract class from which all mutable bitmaps should inherit.

Bitmap

The standard bitmap object. Can produce a new Graphics object that has the capability of drawing to the Bitmap in the same way that the GraphicsPort draws to a gadget.

FrameBuffer

Almost identical to the Bitmap class, except it accepts a pointer to a pre-existing non-const u16 array in its constructor instead of creating the array internally. Intended as a wrapper for the framebuffer to allow it to be used as a bitmap object.

These changes supercede the changes discussed in the last post.

The drawing functions have been removed from the Bitmap class and split up into a class hierarchy:

GraphicsUnclipped

Contains all of the drawing functions previously stored in the GraphicsPort and Bitmap classes, minus any clipping code. Will draw to any instance of a class that inherits from the mutable bitmap class.

Graphics

Inherits from the GraphicsUnclipped class and adds simple clipping functions that ensure the drawing methods do not exceed the width of the bitmap being drawn to. Typically used when drawing to standard bitmap objects.

GraphicsPort

Inherits from the GraphicsUnclipped class and adds complex clipping functions that ensure the drawing methods do not attempt to draw outside the boundaries of a clipping rect, or array of clipping rects.

These changes mean that the basic drawing functions now only exist in one class, instead of being duplicated (with minor changes) in two places. The rationalisation also means that functions such as dim(), copy() and the XOR drawing methods are now available for use on bitmap objects as well as within gadgets.

In order to achieve this, the DrawBg array that previously allowed access to the framebuffer has been replaced with an array of FrameBuffer objects.

Changing these classes necessitated changes to the font system. All fonts that use unpacked bitmap data now expect to be supplied with a pointer to a bitmap object instead of a raw u16 array. Changing this required a rewrite of the rendering and clipping code in the Font and MonoFont classes.

The two standard fonts, “systemFont” and “tinyFont”, are now available as font global font objects. They are instantiated in the initWoopsiGfxMode() function in woopsifuncs.cpp.

These changes should bring a variety of benefits:

  • Fewer magic numbers flying around as bitmap width/height values are stored within bitmap objects instead of specified as parameters for every method;
  • Font bitmaps can be loaded dynamically from BMP files using BitmapIO;
  • It should be easier to add conditional compilation to the drawing methods in order to optimise SDL screen updates;
  • The drawing functions are no longer duplicated in several classes;
  • Bitmaps and the GraphicsPort have access to the same set of drawing functions.

There are a couple of new issues:

  • Blitting a bitmap to another bitmap seems to result in the occasional set of missing pixels at the start or end of the bitmap, probably resulting from the DMA hardware seeing old data (need to flush);
  • I need to check that the new structure is tidy.