Building FreeType2 2.3.9 for the iPhone

When I was first looking into building FreeType for the iPhone I noticed that there were a lot of people asking questions on if this could be done and how, but there was a clear lack of specific instructions and concrete information on the topic.

It turns out that getting FreeType2 to build on the iPhone is a mostly straight forward (though somewhat lengthy) process if you can figure out how the source fits together. It should be noted that I customize the build here to include only the relevant features needed for basic TTF/OTF loading. If you need to build in some of the more advanced features for any reason check docs/INSTALL.ANY before continuing. The file docs/INSTALL.ANY goes a long way toward explaining how the source is structured, and I strongly recommend reviewing this file before trying to build it for yourself.

The first thing to do is to download and extract the FreeType2 source package. I’m using the latest at the time of writing which is version 2.3.9. I don’t suspect that the instructions here are highly version specific, but I can’t promise success with a different version.

If you browse through the source tree you may notice the make files ending in .mk and the Jamfiles. These interfere with our attempts to build and need to be deleted.

Coming from a *nix background I find issuing a recursive find and delete in the root of the extracted package to be the quickest way to take care of it all. However, If you aren’t comfortable with using the console you should do this some other way since serious damage can result if you accidentally issue the command in the wrong folder or make a typo.

find . -name "*.mk" -o -name "Jamfile" -o -name "README" | xargs rm

I include README files in the delete too because Xcode complains about not being able to build them.

The next step is to import the src and include directories from this package into your Xcode project. On my machine I do this by right clicking on the project name under “Groups & Files” and creating a new group called “FreeType”. Once created, right click on the new “FreeType” group and select Add > Existing Files…. Navigate to your extracted source package and select the include and src directories.

Importing "src" and "include" directories

Importing "src" and "include" directories

At the next dialog select “Copy items into destination group’s folder.” and “Recursively create groups.”

Select "Copy" and "Recursively create groups"

Select "Copy" and "Recursively create groups"

This is what Groups & Files should look like following import.

This is what Groups & Files should look like following import.

You should have something like this after import. (Please excuse my Jamfile, as I imported before realizing I needed to clean out the make files.)

The FreeType2 source is factored into components with each component occupying a subdirectory of src. There is also a base subdirectory which holds freetype’s core. If you take a look at docs/INSTALL.ANY you’ll see that we only need pshinter, psnames, sfnt, cff, raster, smooth, and truetype in addition to base to handle TTF loading.

By command clicking on each select the groups autofit, bdf, cache, cid, gxvalid, gzip, lzw, otvalid, pcf, pfr, psaux, tools, type1, type42, and winfonts and press the delete key. I recommend selecting Also Move to Trash, when prompted, to help keep your project directory clean.

In the base/ folder there are c files which correspond to the components we’ve just removed from the project, along with some platform specific files; these need to be disabled as well. Remove ftbdf.c, ftcid.c, ftfstype.c, ftgasp.c, ftgxval.c, ftlcdfil.c, ftmac.c, ftmm.c, ftotval.c, ftpatent.c, ftpfr.c, fttype1.c, ftwinfnt.c, ftxf86.c

These modules also need to be disabled in include/freetype/confg/ftmodule.h. Mine looks like this after commenting out the ones that have been deleted:

//FT_USE_MODULE( FT_Module_Class, autofit_module_class )
FT_USE_MODULE( FT_Driver_ClassRec, tt_driver_class )
//FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class )
FT_USE_MODULE( FT_Driver_ClassRec, cff_driver_class )
//FT_USE_MODULE( FT_Driver_ClassRec, t1cid_driver_class )
//FT_USE_MODULE( FT_Driver_ClassRec, pfr_driver_class )
//FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class )
//FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class )
//FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class )
//FT_USE_MODULE( FT_Module_Class, psaux_module_class )
FT_USE_MODULE( FT_Module_Class, psnames_module_class )
FT_USE_MODULE( FT_Module_Class, pshinter_module_class )
FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class )
FT_USE_MODULE( FT_Module_Class, sfnt_module_class )
FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class )
FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcd_renderer_class )
FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcdv_renderer_class )
//FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class )

If you tried to build at this point things would go horribly wrong. I get nearly 6000 errors and around 200 warnings, but everything is not as bad as it seems. One thing that’s apparent at this point if you’ve tried the build is that FreeType’s include directory isn’t in the search path.

To fix the include directory problem, click the app name under Targets in Groups & Files and click Info at the top of the Xcode window. Make sure that you’re editing the settings for All Configurations under the Configurations drop down box. Enter into the Build tab and scroll down to Header Search Paths under Search Paths. If you peek at the project directory you’ll notice that your src and include directories got pulled into the root of your project. Add a new search path for include/. NOTE: It probably makes sense to reorganize your project directory so that these appear in a “freetype” directory or something to that effect, but for simplicity we won’t bother with that here.

Add freetype's include directory to your include search path.

Add freetype's include directory to our include search path.

Since each time we build our app we’re building FreeType as well we need to make sure that FreeType includes the headers it needs to build the internals. Otherwise, just the include files for linking against FreeType are present during compilation, which are insufficient to build FreeType itself. Checking the bottom of include/freetype/config/ftheader.h we note that FT2_BUILD_LIBRARYneeds to be defined.

To set FT2_BUILD_LIBRARY, with the Build tab still selected we click on the Gear Icon in the lower left corner of the info window and select Add User-Defined Setting. Give the setting the name OTHER_CFLAGS and set it’s value to -DFT_BUILD_LIBRARY. We also need to set -DDARWIN_NO_CARBON to keep it from trying to use the base/ftmac.c file we deleted. So the following should be set for OTHER_CFLAGS

-DFT2_BUILD_LIBRARY -DDARWIN_NO_CARBON
Setting -DFT2_BUILD_LIBRARY in the info window.

Setting -DFT2_BUILD_LIBRARY in the info window.

At this point it should almost build for the simulator. Compilation should succeed leaving you with linker errors. It turns out that some of the c files are actually being included directly from other c files, leading to a clashing of symbol names when the two files are linked together. One resolution to this is to tell Xcode that these c files are actually header files.

To change the filetype right click the file in Groups & Files and select Get Info and change the value in the File Type to sourecode.c.h.

Changing the Xcode File Type of ftcalc.c

Changing the Xcode File Type of ftcalc.c

The following files in base/ are being used as header files and need to have their Xcode File Type changed: base/ftadvanc.c, base/ftcalc.c base/ftgloadr.c, base/ftnames.c, base/ftobjs.c, base/ftoutln.c, base/ftrfork.c, base/ftstream.c, base/fttrigon.c, base/ftutil.c.

For each component only the c file which matches the component name needs to be built and all other c files in the component directory can be treated as an include. To be specific every .c file in cff/, pshinter/, psmodule/,raster/, sfnt/, smooth/, truetype/ except cff.c, pshinter.c, psnames.c, raster.c, sfnt.c, smooth.c and truetype.c respectively.

The downside here is that Xcode will now issue a warning for each file that it does not know how to compile it. These are nothing more than a minor annoyance, and can be safely ignored.

At this point the source should build for the simulator. If you tried to build it part way through and you’re now getting linker errors you may have to clean the build.

If you try to build it for the device, though, it will fail on some inlined assembly in the FT_MulFix_arm routine in include/freetype/config/ftconfig.h around line 323 or so. Changing asm to __asm__ does the trick. It should now look like this:

  static __inline__ FT_Int32
  FT_MulFix_arm( FT_Int32  a,
                 FT_Int32  b )
  {
    register FT_Int32  t, t2;
 
    __asm__ __volatile__ (
      "smull  %1, %2, %4, %3\n\t"   /* (lo=%1,hi=%2) = a*b */
      "mov    %0, %2, asr #31\n\t"  /* %0  = (hi >> 31) */
      "add    %0, %0, #0x8000\n\t"  /* %0 += 0x8000 */
      "adds   %1, %1, %0\n\t"       /* %1 += %0 */
      "adc    %2, %2, #0\n\t"       /* %2 += carry */
      "mov    %0, %1, lsr #16\n\t"  /* %0  = %1 >> 16 */
      "orr    %0, %2, lsl #16\n\t"  /* %0 |= %2 << 16 */
      : "=r"(a), "=&r"(t2), "=&r"(t)
      : "r"(a), "r"(b) );
    return a;
  }

And that should do it. You should now be able to load fonts from resources and use FT_New_Memory_Face to load the font data into freetype.

Tags: ,

Comments (5)

More than 8 Color Vim Syntax Highlighting in GNOME Terminal

Matt Wozniski wrote an awesome little Vim plugin called CSApprox that lets Vim transparently apply GVim colorschemes in the terminal. CSApprox works by approximating the color in the GVim colorscheme to the closest availble color in your terminal, provided that your terminal supports either 88 or 256 colors.

After downloading the plugin zip and extracting it to the ~/.vim directory, I was met with a rather disappointing message:

CSApprox skipped; terminal only has 8 colors, not 88/256
Try checking :help csapprox-terminal for workarounds

Don’t worry, GNOME Terminal isn’t actually limited to 8 colors, it just evades detection. We can easily force 256 color support by setting the t_Co option in ~/.vimrc .

1
set t_Co=256

Here is a screenshot of the GVim colorscheme jellybeans.vim running inside of GNOME Terminal.

The GVim colorscheme jellybeans.vim in GNOME Terminal

The GVim colorscheme jellybeans.vim in GNOME Terminal

Pretty. No?

Edit: I need to make a minor retraction: jellybeans.vim already supports 256 color terminals, so we’re only seeing the effect of set t_Co=256 here and not CSApprox. In demoing this I picked the nicest scheme I had for GVim, not realizing it already supported 256 color vim. Enjoy anyway =).

Tags: , ,

Comments (3)

Stupid Window Manager Tricks: Adding Keyboard Toggles for Full Screen and “Always on Bottom” Windows in GNOME

Full Screen

While programming I don’t like lots of screen clutter. I tend to get distracted easily and waste a lot of time, lost, cycling back and forth endlessly through window after window. One of the ways I help myself stay focused is by making the current window full screen. Usually this just amounts to hitting F11 in GNOME Terminal, but I recently switched from Vim to GVim and left its handy F11 shortcut behind.

I was shocked to find that GVim doesn’t have a full screen option. As troublesome as this may sound it is actually no big deal because any window in GNOME can be made full screen. In fact, there’s an option in gnome-keybinding-properties for setting a keyboard shortcut to make the active window go full screen.

gnome-keybinding-properties

The gnome-keybinding-properties showing shortcut keys for the full screen toggle.

Problem solved: Now any window goes full screen with Shift+Ctrl+F12.

Always on Bottom

I experienced a related issue a few days ago when I set up an auxiliary monitor to use as a full screen terminal. Setting the full screen option and disabling the window menu in GNOME Terminal works well for this sort of thing so long as no other window happens to end up behind the terminal. It didn’t take very long to get fed up with all of the windows spawning behind the terminal. Not only was this happening more frequently than I would have liked, but I found that I missed the extra real-estate as well, often wanting to drag open windows over to the auxiliary monitor only to lose them behind the terminal window.

The solution? Making the terminal an always on bottom window. So how exactly does one go about making one of these? Always on bottom windows are fairly uncommon from a user standpoint but the underlying functionality is there. It’s just a matter of gaining access. There are a number of approaches to be employed:

A rule based window matching system like Devil’s Pie (intro) sits and monitors the running windows checking to see if any match its set of user defined rules. If it finds a match Devil’s Pie will modify the window properties as specified in the rule-set.

For example, if you wanted to pull the border and frame off of xchat2 or any window with “Firefox” in the title and make the result full screen you would do something like the snippet below.

1
2
3
4
5
6
7
(if
    (or
        (contains (window_name) "Firefox")
        (is (application_name) "xchat")
    )
    (undecorate fullscreen)
)

Check out Devil’s Pie for a complete introduction.

Lisp like rule files seemed a little overkill for my full screen terminal problem. I wanted something a bit more flexible that I could reconfigure at the push of a button. gnome-keybinding-properties doesn’t have an option for setting a shortcut key for always on bottom windows. To get around this we can make use of a program called wmctrl.

wmctrl can be used to change the properties of a target window. To identify the target you can use a the window title or the window’s handle. wmctrl -l gives a list of these.

alfred@alfred-desktop:~$ wmctrl -l
0x01200003 -1 alfred-desktop Bottom Expanded Edge Panel
0x0120003d -1 alfred-desktop Top Expanded Edge Panel
0x0140001e -1 alfred-desktop x-nautilus-desktop
0x03600003  0 alfred-desktop alfred@black: ~
0x0280001e  0 alfred-desktop NERD_tree_1 - (~) - GVIM
0x0361bb62  0 alfred-desktop alfred@alfredrossi: ~
0x03621d7c  0 alfred-desktop alfred@alfred-desktop: ~

In addition to passing a specific window handle/title, wmctrl accepts the special identifiers :SELECT:, and :ACTIVE:. Passing :SELECT: tells wmctrl that you wish to select the target window with the mouse. :ACTIVE: tells wmctrl to target which ever window is currently active. The state options are more elaborate and won’t be discussed here, for more information on these I recommend checking the man page.

As an example, the first snippet below will toggle the full screen state of whichever window is selected with the mouse. The second example does almost exactly what we want, it toggles the always on bottom state of the active window.

wmctrl -r :SELECT: -b toggle,fullscreen
wmctrl -r :ACTIVE: -b toggle,below

You can also suppress the taskbar entry for the window by passing wmctrl the option -b toggle,skip_taskbar.

In order to launch the above command we need only add a custom key binding in gnome-keybinding-properties. The result is an on-demand toggle that integrates nicely along side the window manager.

Tags: , , ,

Comments (2)