Transparent Text

It's been almost three months since I posted the last Neatpad tutorial, and it's also been over a year since I started this project. During this time I have been steadily working on the migration to the Uniscribe API. Alot of issues have become apparent with the way I am rendering text in Neatpad, so this tutorial will hopefully highlight these issues and offer a solution. There isn't going to be any code-download this time as I will be incorporating the ideas presented here into subsequent tutorials (which will be about Uniscribe).

Rendering text

So before we start looking at Uniscribe I want to take a moment to re-examine the process of text rendering. This is not going to be a very in-depth discussion - rather it will be an overview of text-rendering in general. As the basis for our discussion a single letter 'F' in italics will be used, as shown below.

The image shows a black glyph, representing the lower-case italic letter 'f', drawn on top of a grey rectangular background. The grey background represents the bounding rectangle of the character. Notice how the character overhangs the rectangle on the left and right edges. These measurements are called the left-bearing and right-bearing of a glyph.

In Windows the total width of a character is also represented as three values, called the ABC width. The A-width represents the width of the left-most overhanging portion of the glyph, whilst the C-width represents the right-most overhanging portion. The B-width measures the extent of the glyph. For characters such as the lower-case 'F' above, the A and C-widths are frequently negative values, which allows the characters to be positioned closer together when displayed as part of a string. Of course when a character has a negative A or C-width, it will overlap the space occupied by it's neighbouring characters. The purpose of this short tutorial is to highlight the issue with rendering glyphs that have negative A and C-widths.

All applications (including Neatpad) render text using one of the Windows text-display APIs - usually DrawText or TextOut. Text in Windows can be drawn in one of two ways - with and without a background rectangle. Text drawn with a background fill is referred to as opaque text, whilst text drawn without is called transparent text. This text-drawing feature is controlled with the SetBkMode API, or the ETO_OPAQUE option when calling ExtTextOut.

The problem of overhanging glyphs only presents itself when breaking a string into smaller segments and rendering them individually. The issue occurs because the act of filling the background causes the overhanging portions of a glyph to be overpainted, resulting in the characters being clipped by the neighbouring background rectangles. The image below illustrates the two methods of painting text. The text is made up of six individually rendered 'F's, each in a different colour.

Clipping (opaque text)
No clipping (transparent text)

The image on the left illustrates the text drawn using an opaque background-fill mode. This is the simplest way to draw text, because the text and background is rendered in one go. This is how Neatpad currently renders text. However problems occur when text is broken up into blocks. Of course the problem is made much worse by the Italic text - for most Roman text this issue never occurs.

SetBkMode(hdc, OPAQUE);

TextOut(hdc, x, y, szText, nTextLen);

The image on the right illustrates the ideal way to display multi-coloured text. In order to render the text this way the process had to be split in two phases. Firstly, the background was drawn in it's entirety (from left-to-right). Then the text was drawn 'transparently' over the top of the background.