Getting Started with TrueType: Basic Concepts

The author of this article, Li Songfeng, is a senior technical book translator. He has translated and published more than 40 technical and interactive design monographs. He is currently a senior expert in Web front-end development of 360 Qi Dance Company, a member of the 360 ​​Front-end Technical Committee, and a W3C AC representative.

OpenType is an extension of TrueType. The whole process of this article describes each step of TrueType from font design to font display, and these steps also apply to OpenType.

TrueType fonts may be born on paper, or they may be converted from other formats. But in the end, the font file must contain description information for each glyph. The diagram below shows the process from the original design draft, to digitized glyphs, to digitized outlines in the font file.

Figure 1 Original design draft, digitized glyphs, and digitized outlines represented by FUnit coordinates in the font file

So how are TrueType fonts applied on display devices (screens, printers)?

First, the outlines stored in the font file are scaled to the required dimensions by converting the original outlines in the font file in FUnit (Font Uint, Font Units) to device-specific pixel coordinates.

The interpreter then runs the instructions associated with the glyphs, and the result of running the instructions is to complete the grid-fit of the glyphs. The mesh adaptation is completed, and then the scan conversion program generates the final bitmap image that is rendered on the target device.

Figure 2 Font rendering process

1. Describe the outline of the glyph in the form of FUnit coordinates in the TrueType font file 2. The scaling program converts the FUnit to pixel coordinates and scales to the size required by the application 3. The outline is scaled to the new grid 4. After scaling, it is expressed in pixel coordinates Outline 5, the interpreter executes the instructions associated with glyph B, mesh adaptation 6, mesh adapted outline 7, mesh adapted outline 8, the scan converter decides which pixels to open 9, in the target Rendering position on device

glyph digitization

The outlines of glyphs contained in a font are represented by consecutive points in a virtual coordinate system.

contour

In TrueType fonts, the shape of a glyph is represented by a contour, which is represented by a point on virtual coordinates. Simple glyphs may have only one outline, and complex glyphs may have multiple outlines. Compound glyphs, on the other hand, can be composed of multiple simple glyphs. In the font file, control characters without visible outlines are mapped to glyphs without outlines.

Figure 3 A glyph consisting of a series of on-line and off-line dots

The points that make up the curve must be numbered in consecutive numbers, and whether the numbering is ascending or descending also matters, as it determines the fill pattern of the shapes that make up the glyph. In summary, if the curve is defined along an ascending number, the black space, i.e. the filled area, is always on the right.

FUnit and em block

In a TrueType font file, the position of a point is expressed in font units or FUnits. The so-called FUnit is the smallest unit of measurement in the em square, and the em square is a virtual square used to measure the size of glyphs and align glyphs. Typically, a glyph's em block contains the full length of the glyph, plus extra space to avoid overcrowding lines to lines without extra lead space when typesetting.

Figure 5 em square

In the age of metal glyphs, glyphs wouldn't stick out of the em square, but digital fonts don't have these restrictions. The em square can be made large enough to contain all glyphs, including phonetic glyphs. However, when necessary, some glyphs can also stick out to the em square. TrueType fonts support both scenarios, and it is up to the font manufacturer to decide which one to use.

Figure 6 Glyphs sticking out of the em square

The em square defines a two-dimensional coordinate network system, where the x-axis represents horizontal movement and the y-axis represents vertical movement.

FUnit and grid

Digitizing fonts begins with determining the accuracy or resolution of the points that describe the outline of the glyph. The accuracy of these points is determined by the smallest measurable length of the em grid, which is FUnit. This grid is in a two-dimensional coordinate system, and the coordinate origin is (0, 0). But this mesh is not an infinite plane, but lies between -16384 and +16384 FUnits. The choice of FUnit size is different, and the number of points in the grid is also different

The number of FUnits contained in each em grid, which is upem (FUnit per Em), is determined by the font designer or manufacturer. However, setting upem to a power of 2, such as 2048, results in the fastest contour scaling.

Figure 7 Grid coordinate system in em squares

There is no set rule for where the origin of the coordinates in the em block is placed. In practice, some conventions are usually followed. For example, Roman fonts are used for horizontal typesetting, so the y-coordinate of 0 is usually placed on the baseline of the font. As for where the 0 value of the x coordinate is placed, it is very free. It's just that choosing the usual approach may perform better.

For example, for fonts used in vertical layout, choosing the visual center point of the glyph as the origin of the x-axis can make the glyphs line up more beautifully. For horizontal typesetting fonts, the x value of the leftmost point of the font outline can also be equal to the left-side-bearing of the glyph. Such fonts print faster in PostScript printers.

Figure 8 Selection of two glyph origins: the left side of the glyph has an empty x value of 0, and the right side is the visual center with an x ​​value of 0

Next, the number of FUnits contained in each em block, that is, upem, determines the granularity of the em block. The larger the upem, the higher the precision.

Figure 9 Grid of two em squares: 8 units per em on the left side 16 units per em on the right

FUnit is a relative unit because the size it actually represents varies with the size of the em square. But the number of FUnits contained in each em, that is, upem, is a constant, no matter how big the glyph is finally rendered. When it comes to final rendering, there is another concept: ppem, that is, the number of points corresponding to each em square. The point here is an absolute size unit, that is, 1 point = 1/72 inch = 0.353 mm. If a glyph is rendered 9 points large, then each em square contains 9 points (9 x 0.353 = 3.17 mm), and when rendered 14 points large, each em square contains 14 points (14 x 0.353 = 4.94 mm) ). Since upem does not change and ppem changes, the absolute size corresponding to FUnit when rendering will naturally change.

Figure 10 M of 72 points and M of 127 points and their em squares The upem in both cases is 8

In other words, no matter how big the font is rendered, the upem in FUint will never change

Scaling glyphs

Let's take a look at how the glyph outlines in the font file are scaled to the size required by the application.

FUnit to pixel conversion

There are two values ​​that need to be calculated when FUnit is converted to pixels: one is how many pixels are equivalent to the glyph after conversion represented by FUint, and the other is the coordinates of the point in the FUnit coordinate system converted to the point in the pixel coordinate system.

For the first transformation, the final pixel value depends on how many points to render to, the target device's resolution dpi, and the FUnit of the em square, or upem. Assuming that the glyph width in the font file is 550 FUnit, the device resolution is 72ppi, the upem of the font is 2048, and the rendering is 18 points, then the pixel value of the rendered glyph is:

550×18×72ppi/(72dpi×2048upem) = 4.83px

In other words, the converted pixel value of a glyph is proportional to its own FUnit value, rendered points, and device resolution, and inversely proportional to the font's upem. Finally, 72dpi is a constant (ie 1 inch equals 72 dots).

For the second transformation, that is, the coordinates of the midpoints of the glyphs are converted from FUnits to pixels, you first need to know the number of midpoints per em after the transformation, which is ppem (proportional to the device resolution):

ppem = rendering points × device resolution / 72dpi

Assuming that you want to print at 12 pixels and the print resolution is 300dpi, then the ppem of each glyph is: 12 × 300 / 72 = 50. That is, each glyph can be rendered with 50 (ink) dots.

Then, we know that we have the following equation:

pixel coordinates/ppem = FUnit coordinates/upem

That is, the ratio of pixel coordinates to ppem is always equal to the ratio of FUnit coordinates to upem. so:

pixel coordinates = FUnit coordinates × ppem / upem

Assuming that it is still on a 300dpi laser printer and you want to print 12-point glyphs, then its ppem is 50. Correspondingly, if the coordinates of a point in the outline of the glyph are (1024, 0), and the upem of the font is 2048, the pixel coordinates corresponding to this point are (25, 0).

Glyph outline fit grid

Fitting the grid is accomplished by executing instructions. The purpose of the adaptive grid is to allow glyphs to retain or render the characteristics of the original design across different sizes and devices, in particular ensuring consistent stem heights, even spacing, and eliminating pixel dropout.

To achieve these goals, it is important to ensure that certain pixels are turned on when the glyph is pixelated. In this case, it may be necessary to alter or distort the original outline definition to produce a high-quality bitmap. This deformation of the original glyph outline is called grid-fitting.

The image below shows how the mesh fit stretches the original design:

Figure 11 Ungrid-fitted and grid-fitted outlines and bitmaps

Grid fitting is the process of stretching a glyph according to the instructions associated with the glyph. After grid adaptation, the number of points that make up the outline of the glyph remains unchanged, but the positions (coordinates) of these points are shifted.

understand instructions

The TrueType instruction set defines a number of instructions for designers to specify how to render glyphs so that they retain the characteristics of the font when scaled. In other words, directives are used to control glyph outlines when adapting the grid for different sizes or devices.

Fitting the grid means moving the points on the contour, and moving the points is called "moving". Using TrueType fonts does not necessarily require executing commands. If the resolution of the output device is high enough and the number of rendering points is large enough, high-quality glyphs can be output without running commands. However, for small rendering points, it is critical to add and run instructions to ensure readability of the output.

How does the TrueType interpreter know how to stretch glyph outlines to produce acceptable results? The relevant information is contained in the directives attached to each glyph in the font. Directives specify the design that glyphs need to preserve when they are scaled. The image below shows that when rendering a 9-point Arial lowercase m with no instructions running, a stem is lost as the stem is kept at the center of the pixel. And the diagram on the right shows that the instruction aligns the stem to the grid, thus keeping the stem intact.

Figure 12 Arial of 9-dot size before and after applying the command

TrueType interpreter

Instructions are interpreted and executed by the TrueType interpreter. Specifically, the interpreter processes the instruction stream or sequence of instructions, and the instructions take parameters from the interpreter's stack space, and then put the execution results back on the stack. There are also a few instructions that push data onto the stack, and these instructions take their arguments from the instruction stream.

All operations of the interpreter run in the context of Graphics State. Graphic State is a set of variables whose values ​​are used to direct the interpreter to run and determine the outcome of a particular instruction execution.

The operation of the interpreter can be summarized as follows:

1. The interpreter fetches an instruction from the instruction stream, that is, a sequence of ordered instruction opcodes and data. Opcodes are in bytes, and data may be single or double bytes (words). Instructions take word data from the instruction stream and also create double-byte words. The high byte appears first in the instruction stream, followed by the low byte. 2. Execute the command: If it is a push command, get the parameters from the command stream. Other instructions fetch data from the stack, and the data generated by these instructions is pushed onto the stack. The interpreter's stack is a last-in, first-out data structure. Instructions get the data they need from the last item on the stack. The instruction set contains all the instructions for pushing, popping, emptying and copying the stack. The effect of the instruction execution depends on the variables and values ​​in the Graphics State. The instruction can also modify the variables of the Graphics State. 3. Repeat the above process until all instructions are executed.

where is the command

Directives may be stored in many places in the font file. For example, it can appear in the Font Program and CVT Program, and it can also appear in the font data. The directives in the first two tables apply to the entire font, the directives in the glyph data only apply to specific glyphs.

The instructions in the Font Program will only be executed once when the application reads the font. The directives here are used to create function definitions (FDEF) and instruction definitions (IDEF). Function and directive definitions in the Font Program can be used anywhere in the font file.

The instructions in the CVT Program are executed every time the glyph is scaled, but it is only used for font-level changes, regardless of the specific glyph. Specifically, the instructions in the CVT Program are used to establish the values ​​in the Control Value Table. The purpose of Control Value Table, also known as CVT, is to assist in maintaining font consistency when running commands.

Instructions that reference a value in the CVT are called indirect instructions, and instructions that fetch values ​​from glyph data are direct instructions. CVT values ​​in TrueType font files are expressed in FUnits. When contours are converted from FUnits to pixels, the values ​​in the CVT are also converted.

When writing values ​​to the CVT, you can use the values ​​in the glyph coordinate system, or you can use the values ​​from the original FUnit. The interpreter scales these values ​​accordingly. Whereas the value read from the CVT is always in pixels.

Graphics State

Graphics State contains a table that holds variables and their values. All instructions are run in the context of Graphics State. All variables in Graphics State have default values, some of which can be modified in CVT Program. However, modifying the value of the Graphics State variable while processing a single glyph will only affect subsequent processing of the corresponding glyph.

scan converter

TrueType's scan conversion program takes the outline of a glyph and generates a bitmap image of that glyph. The scan converter has two modes. In the first mode, the scan conversion program uses a simple algorithm to determine which pixels belong to the glyph outline.

  • Rule one: If the center of a pixel falls on the outline of the glyph, the pixel opens and becomes part of the glyph.
  • Rule 2: If the contour falls exactly in the center of a pixel, then that pixel is turned on.

A point is considered a point within a glyph if it has a non-zero "winding" value. To determine the "winding" value of a point, draw a radial line from the point toward infinity. Start at 0 and subtract 1 each time a contour crosses this ray from right to left or from bottom to top. This crossover is called an "on transition". Conversely, increment by 1 whenever a contour crosses the ray from left to right or from top to bottom. This crossover is called an "off transition".

As for the orientation of the contour, it can be determined by looking at the number of the points. The directions are always from small to large. The image below illustrates how the wrap value can be used to determine whether a point is inside a glyph.

Figure 13 Determining the winding value of a point

In the figure, the point p1 has experienced a total of 4 transitions (on, off, on, off). Because the number of transitions is an even number, the winding value is 0, in other words, the point is not a point in the glyph. And p2 goes through 3 transitions (off, on, off) with a wrap value of +1, so point p2 is a point within the glyph.

Eliminate leaks

Dropout occurs when the connected part of a glyph contains two black pixels but cannot be connected by a straight line that can only connect black pixels.

Figure 14 The letter m has two leaks

TrueType directives are designed to allow scan converters to turn on the necessary pixels without having to worry about rendering sizes or how to transform them. However, after all, it is impossible for us to know in advance all the transformations that will take place in the glyph. Especially in the case of small ppem and relatively complex glyphs, pixel leakage is inevitable.

Leakage can be tested by observing the line segment connecting the centers of two adjacent pixels. If this line segment intersects both an on transition and an off transition, there is a possibility of a leak. However, a potential leak will only become a true leak if the two contours continue to advance in their respective directions, cutting off other line segments connecting the centers of adjacent pixels. If the two outlines join immediately after crossing the line segment, there will be no leaks, but one of the stems of the glyph may be shortened.

To avoid pixel leaks, font manufacturers can have scan converters use two additional rules.

  • Rule 3: If a line between the centers of two adjacent pixels (whether vertical or horizontal) intersects both an on transition and an off transition outline, and no pixel is turned on by rule 1 and rule 2, turn on the rightmost Pixel (horizontal line segment) or bottommost pixel (vertical line segment).
  • Rule 4: Rule 3 applies only when the two contour lines continue to intersect other line segments in their respective directions. This does not turn on pixels for "stubs".

Font makers or designers can choose to do simple scan conversion based on rules one and two, or use rules three and four if necessary. These choices create font-to-font differences. But directives in prePromgram affect the entire font by default, while changes in individual glyphs only affect that glyph.

Related Links

TrueType fundamentals : http://docs.microsoft.com/zh-cn/typography/opentype/spec/ttch01

Follow us

{{o.name}}
{{m.name}}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324193715&siteId=291194637