programming4us
programming4us
MULTIMEDIA

iPhone 3D Programming : Drawing an FPS Counter (part 1) - Generating a Glyphs Texture with Python

- How To Install Windows Server 2012 On VirtualBox
- How To Bypass Torrent Connection Blocking By Your ISP
- How To Install Actual Facebook App On Kindle Fire
8/25/2011 3:15:28 PM
Rather than demonstrating text rendering with yet another goofy toy application, let’s do something useful for a change. Overlaying a frames-per-second counter in one corner of the iPhone screen provides a quick and easy way of evaluating graphics performance; see Figure 1.
Figure 1. FPS counter



Before writing any application code, you’d need to generate an image that contains bitmaps for the numbers zero through nine, as depicted in Figure 2. (Don’t bother trying to create this yet; you’ll see a way to automate this shortly.)
Figure 2. Numerals in a 128x32 luminance texture


You probably already guessed that you need to store off the bounding box of each glyph in order to compute the appropriate texture coordinates. Thinking about this a bit more, you’ll realize a mere bounding box is not enough. When you’re writing a sentence on ruled paper, some parts of letters extend below the baseline, like the descender of the lowercase p. And, in the case of the rather artsy font shown in Figure 3, the type designer wants the 9 numeral to be vertically offset from the other letters. Further complicating matters is the fact that the bounding boxes of glyphs can overlap in the destination image. In Figure 3, observe how the descender of the letter p extends right below the letter i.

Figure 3. Simple text layout with baseline


It turns out that associating a specific set of glyph metrics with each character supplies enough information to achieve the simple text layout shown in Figure 3. A popular naming convention for these metrics is described in Figure 4; in this diagram, the origin represents the current pen position.

Figure 4. Glyph metrics: bearing and advance vectors; width and height lengths


To summarize, the four glyph metrics are as follows:


Bearing vector

2D vector describing the offset from the pen position.


Advance vector

2D vector describing how to advance the pen to the next position after rendering the current glyph. The y component is always zero for Latin-based alphabets.


Width

The horizontal length of the glyph.


Height

The vertical length of the glyph.

Using these metrics, Example 1 the pseudocode for a simple text layout algorithm.

Example 1. Simple text layout algorithm
void RenderText(string s, vec2 p)
{
for each character c in s
{
metrics m = GlyphTable[c].Metrics
vec2 topLeft = GlyphTable[c].Position
box source = box(topLeft, m.Width, m.Height)
box dest = box(p + m.BearingVector, m.Width, m.Height)
Blit(source, dest)
p += m.AdvanceVector
}
}

1. Generating a Glyphs Texture with Python

Before writing any application code, we need to choose a way of generating a glyphs texture and a set of metrics for each glyph.

Leveraging Quartz is perhaps the most obvious way of generating a glyphs texture . This can be done at runtime when your application first starts up. This might slow down your startup time by a tiny amount, but it has the benefit of shrinking the size of the application bundle.

My preference is to generate the glyphs texture as a build step, mostly because it simplifies my application code. Build steps take place in Xcode rather than the iPhone execution environment, which brings a much richer tool set to the table. This is a perfect use case for a scripting language, and Python comes to mind first.


Note:

There are many ways of generating a glyphs texture; here I’m giving an overview of my favorite. Take it only as a high-level example.


Given that we’re using Python in a build step, we need to find some useful Python modules for image manipulation and image generation. At the time of this writing, the Python Imaging Library (PIL) is the most popular imaging manipulation module, and it provides excellent support for manipulating PNG images at a low level. However, it’s not quite enough on its own because it doesn’t provide direct access to the glyph metrics that we need. Another popular library is Cairo, which has a well-maintained Python binding called pycairo. Cairo is robust and fast, and it’s used as the rendering backend in Firefox, Mono, and GTK. So, let’s go with PIL (http://www.pythonware.com/products/pil/) and pycairo (http://www.cairographics.org/pycairo/).

Installing Python Modules

The copy of Python that’s installed on Mac OS X won’t have these modules installed by default, so you’ll have to do a little bit of prep to install them.

First, install the Python Imaging Library. Go here to download the source: http://www.pythonware.com/products/pil/. At the time of this writing, the 1.1.7 version of PIL was the most recent and worked well. Make sure you download the version for Python 2.6 to ensure that the script will work. Extract the tarball (you can double-click it to extract it), open the Terminal, and cd to the top-level directory of the source code distribution. Next, execute the following command:

sudo python setup.py install

Next, install pycairo. Download the source from here: http://www.cairographics.org/ (the script was tested with version 1.8.8). Extract the tarball, open the Terminal, and cd to the top-level directory of the source code distribution. Next, execute the following commands:

./configure \
--prefix=/System/Library/Frameworks/Python.framework/Versions/2.6
make
sudo make install

You’ll also need to install Cairo itself since pycairo is only a thin wrapper; build instructions and downloads are available from http://www.cairographics.org/download/.


Rather than packaging the glyphs texture as a PNG or PVR file, let’s serialize the data to a C header file. Since it’s a single-channel texture, the amount of data is relatively small. The header file will also provide a convenient place to store the glyph metrics. We’ll simply have our Python script spawn PVRTexTool for generating the header file from the image. We’ll still generate a PNG file for preview purposes, but we won’t include it in the application bundle. See Example 7-2 for the complete Python script that generates Figure 2.

Example 2. CreateNumerals.py
import cairo
import os
from PIL import Image

# Create a Cairo image surface:
imagesize = (256,32)
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, *imagesize)
cr = cairo.Context(surface)
padding = 3

# Choose a font (look in /Library/Fonts) and set up the transforms.
cr.select_font_face("Apple Chancery",
cairo.FONT_SLANT_NORMAL,
cairo.FONT_WEIGHT_BOLD)
cr.set_font_size(32)
cr.set_source_rgb(1,1,1)

# Create a string for appending the glyph metrics to the texture file:
glyphs = '''
struct GlyphPosition {
int X;
int Y;
};\n
struct GlyphMetrics {
int XBearing;
int YBearing;
int Width;
int Height;
int XAdvance;
int YAdvance;
};\n
struct Glyph {
GlyphPosition Position;
GlyphMetrics Metrics;
};\n
static const Glyph NumeralGlyphs[] = {\n'''

# Render glyphs '0' through '9' and write out their extents:
x, y = 0, 0
for character in '0123456789':
extents = cr.text_extents(character)
x_bearing, y_bearing, width, height, x_advance, y_advance = extents
glyphs += ' {{ %d, %d }, ' % (x, y)
glyphs += '{ %d, %d, %d, %d, %d, %d }},\n' % extents
cr.save()
cr.translate(x, -y_bearing)
cr.text_path(character)
cr.fill()
cr.restore()
x += width + padding
glyphs += '};\n'

# Extract the alpha channel and open it up for a quick preview:
surface.write_to_png("NumeralsTexture.png")
image = Image.open("NumeralsTexture.png")
image.load()
image.split()[3].save("NumeralsTexture.png")
os.system("open NumeralsTexture.png")

# Serialize the image data to a C header file:
os.system('PVRTexTool -h -yflip1 -fOGL8 -iNumeralsTexture.png')

# Write to the header file:
headerFile = open('NumeralsTexture.h', 'a')
headerFile.write(glyphs)
headerFile.close()




Note:

For this to work, you must either put the location of PVRTexTool into your shell’s PATH environment variable or copy PVRTexTool into one of your PATH entries, such as /usr/local/bin. If you’ve extracted the Khronos SDK into your current directory, you could copy the file and mark it executable with these commands:

cd SDKPackage/Utilities/PVRTexTool/PVRTexToolCL/MacOS
sudo cp PVRTexTool /usr/local/bin
sudo chmod +x /usr/local/bin/PVRTexTool
cd -

Other  
 
Top 10
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
REVIEW
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
programming4us programming4us
programming4us
 
 
programming4us