03/20/2008

Cheap, High Quality Fonts in Squeak

UPDATED! On 03/20/2008 I greately enhanced colored text on colored backgrounds.

One of the very few things I don't like in Squeak is font support. I'm used to nice sub pixel rendered text. I find StrikeFonts and TTFFonts in Squeak equally ugly on LCD monitors.

I have been a long time admirer of Henrik Gedenryd's FreeType work, now continued by Andy Tween. But Andy's work requires linking the FreeType library, and a new BitBlt plugin with newer modes to work.

Something smaller and simpler needs to be done! Something that could look like this:

Why not just use StrikeFonts, but with 32bit glyphs? Why not just take already rendered glyphs from the host OS, instead of rendering them with FreeType?

 This started as an experiment. I modified existing instances of StrikeFonts to use 32bit forms for glyphs. But it didn't work. So I fixed several issues there. I wanted to import the glyphs from the OS. Using a BMP file sounded natural. But it would be cumbersome to have extra parameters for the creation of the fonts. Thanks to a suggestion from Dan Ingalls, I was able to read a StrikeFont from a bitmap such as this one:

After readint them, it was pretty easy to have a basic 32 bit font working. The issues that needed further work are colored text and black text on color (non white) backgrounds.

For black text on colored backgrounds I started experimenting with alpha blending (BitBlt rule 34). But I realized that rule 28 could do a much better work. Rule 28 takes the min value between source and destiny for each rgb component. So it will leave the background untouched except for those pixels where the font wants something darker. There, the font rules. It looks great.

For doing sub pixel AA of colored text on colored background I believe you need to render the font again. As I can't do that, I use whole pixel AA (i.e. regular AA). So I prepared color maps. For example, to render a red font, I prepared a color map that maps the different colors in the font to red with different translucency. Then I display the text with alpha blending (BitBlt rule 34).

 What's missing from a full solution, such as FreeType?
- No modeling of the fonts themselves
- No way to tweak the rendering other than editing the BMP files
- No kerning (each character has a fixed width)
- Colored text doesn't use sub pixel rendering
- Poor automatically generated italic (although you can import nice italized fonts)

Advantages over FreeType:
- Very compact. Very little complexity added to StrikeFont
- Does not need FreeTypePlugin
- Does not need new BitBlt modes
- Only Smalltalk changes. Works with stock VM on any platform
- Much less code
- Very easy to build your own glyphs or entire fonts

Advantages over TTCFonts:
- Much less Smalltalk code
- Much lower memory usage. No weak caches. Less GC stress.
- Higher performance especially when using a fonts in new color (no cache building)

Disadvantages compared with TTCFonts:
- No modeling of the fonts themselves
- No way to tweak the rendering other than editing the BMP files
- No kerning (each character has a fixed width)

You can get the code and sample fonts here. Unpack the file into an \AAFonts\ subdirectory. File in the code and execute:

       TextConstants at: #Vera put: (TextStyle fontArray: (Array
              with: (StrikeFont new buildFromForm: (Form fromFileNamed: 'AAFonts\Vera7.bmp') name: 'Vera 7')
              with: (StrikeFont new buildFromForm: (Form fromFileNamed: 'AAFonts\Vera8.bmp') name: 'Vera 8')
              with: (StrikeFont new buildFromForm: (Form fromFileNamed: 'AAFonts\Vera9.bmp') name: 'Vera 9')
              with: (StrikeFont new buildFromForm: (Form fromFileNamed: 'AAFonts\Vera10.bmp') name: 'Vera 10')
              with: (StrikeFont new buildFromForm: (Form fromFileNamed: 'AAFonts\Vera11.bmp') name: 'Vera 11')
              with: (StrikeFont new buildFromForm: (Form fromFileNamed: 'AAFonts\Vera12.bmp') name: 'Vera 12')
        ), (Array
              with: (StrikeFont new buildFromForm: (Form fromFileNamed: 'AAFonts\Vera14.bmp') name: 'Vera 14')
              with: (StrikeFont new buildFromForm: (Form fromFileNamed: 'AAFonts\Vera16.bmp') name: 'Vera 16')
              with: (StrikeFont new buildFromForm: (Form fromFileNamed: 'AAFonts\Vera18.bmp') name: 'Vera 18')

       ))

BTW, if you get my Morphic 3.0 image, it has this loaded.

I hope you like it.

 
 
  © 2006-2007 Juan M. Vuletich