next up previous contents index
Next: Loading Fonts Explicitly Up: Using t1lib Previous: The t1lib-Logfile   Contents   Index


Generating Bitmaps

At this point, you are able to generate a bitmap. As said before, a character- or string-bitmap is given to the user as an object of type GLYPH. We should briefly explain GLYPH here. The type is defined by
typedef struct
{
  char *bits; 
  struct          
  {
    int ascent;
    int descent;
    int leftSideBearing;
    int rightSideBearing;
    int advanceX;
    int advanceY;
  } metrics;
  void *pFontCacheInfo;
  unsigned long bpp;
} GLYPH;
bits is a pointer to the bitmap data. The bitmap is organized in lines, starting with the uppermost line. Each bitmap pixel is usually represented by one bit. If the width of the bitmap is not an integer multiple of 8, the lines are padded with zeros, so that each line starts at a byte boundary. Note that the bitmap has no margins taken into account. The bitmap occupies the minimum area the character needs to be painted.

The bitmap pointer may also be the NULL-pointer. In this case, the glyph contains no foreground pixels. The metrics of the corresponding glyph should be valid, though. Typically, this appears for the space character as well as in situations where an undefined or unencoded character had been substituted by the .notdef-character within the rastering functions.

Note that the pixmap-entry which has been present in version 0.3-beta, has been removed with version 0.4-beta. See the discussion on the X11-interface in [*] for an explanation of this.

The struct metrics contains metric information that is needed to position the character and to describe the character origin with respect to the bitmap. The members in detail:

As seen, the width of the bitmap is given as the difference between rightSideBearing and leftSideBearing and the values metrics.leftSideBearing, metrics.descent,
metrics.rightSideBearing and metrics.ascent effectively describe the bounding box of the glyph.

The entry pFontCacheInfo is not currently used but will probably later when font caching is really implemented. Moreover, there's a certain chance that some other entry will be added in future releases.

The member bpp is used to store the depth of the bitmap. For true bitmaps, it is always 1. See [*] for an explanation.

There are three basic functions which produce pointer to glyph objects. In order to generate the glyph for a single character you would use the function

 GLYPH *T1_SetChar( int FontID, char charcode, 
                    float size, T1_TMATRIX *transform)

to 0pt \fbox{$\mathcal{F}()\Rightarrow$} As in most other functions, FontID is a valid identification number of a font. It can range from 0 to $n-1$, where $n$ is number of fonts declared in the font database file.

The second argument charcode determines the character that will be rasterized. As mentioned earlier, the encoding mechanism is used for accessing the output character. This means, if 'A' is given as the character code, the machine representation of 'A' is used as an index into the current encoding vector. In this encoding vector, the characters' name is looked up. Encoding vectors may be changed by the user (see [*]).

The parameter size is interpreted in Postscript's bigpoint-unit (bp). By default, 1 bp equals one device pixel.

transform specifies the transformation that will be applied to the character before rastering. If this pointer is NULL, no transformation is used. Otherwise it should point to a valid t1lib-transformation matrix. Please refer to [*] for information on how to easily create T1_TMATRIX matrices. Hinting is only performed if the transformation is a pure rotation and if the the angle is one of 0, 90, 180 or 270 degrees. Otherwise font level and character level hinting information is ignored.

Bitmaps of transformed characters are never saved in cache memory since I assume that they are rarely needed. The overhead to manage transformed characters in cache would be overkill and would significantly increase memory consuming. Anyhow, this would only work for some dedicated transformations.

T1_SetChar() in fact does some more things than simply rastering the specified character:

Some words concerning memory management: The memory used by the GLYPH-structure is static in this function. The memory required for the bitmap is also allocated by the function itself. This means, the user doesn't need to free any memory by himself. Every time T1_SetChar() is called, it starts by giving the memory needed for the last generated glyph free or respectively setting metric values to 0. Thus, do not free the returned glyph pointer since later T1_SetChar() will free memory that is no more allocated and probably used for some other purpose. If you really like to free the memory, set the pointer to NULL afterwards.

If an error occurs at some point, T1_SetChar() returns a NULL-pointer to the user.

Frequently it is advantageous to raster a series of characters at once. This has the advantage that internal accuracy may be used and the overhead for the user is minimal. For such cases, the function

 GLYPH *T1_SetString( int FontID, char *string, int len, 
                      long spaceoff, int modflag, 
                      float size, T1_TMATRIX *transform)

to 0pt \fbox{$\mathcal{F}()\Rightarrow$} is provided. It can be considered an extended version of T1_SetChar(). The same as said above applies to the arguments FontID, size and transform. But a few additional arguments are needed here.

string is a series of bytes representing the indices into the current encoding vector. The len-parameter is needed because we cannot imply that string is always an object like a string in C. For example, the Computer Modern Roman fonts contain the uppercase Greek Gamma (�) at position 0 in their internal encoding. In a string to be typeset the value 0 is thus a valid value and deserves no special treatment. Hence, we cannot not use the C-function strlen() to compute the length of the string. However, since in most usual encodings the special value 0 is not encoded (``.notdef''), it makes sense to switch between standard situations and non-standard situations:

The spaceoff parameter is important for word processing purposes. The value specified here is interpreted as an offset to the space width used during rastering. It is interpreted in charspace units, i.e., $1/1000$ bp. Every time a space character is requested, this amount of horizontal escapement is added to the natural spacewidth of the current font. Note that the space character itself is actually not rastered. All requests to the character with the charactername ``space'' are caught by t1lib and converted to a simple horizontal escapement. For computation of the resulting spacewidth, the width of the space-character is taken from the AFM data and merged with the specified offset, which may also be negative.5

The modflag argument may be used to specify some option to the rastering function. It is generally 0 or an OR'ed combination of the following names:

For a description of underlining and such, see [*]. Notice also that the modflag argument is a replacement of the kerning argument from pre-0.7 versions of t1lib.

Concerning glyph-memory considerations, the same applies as said under the description of T1_SetChar(): Never free a pointer to memory which was returned by T1_SetString(). Or, alternatively, if freeing the pointer cannot be avoided set it to NULL after freeing it.6

There are two generic ways how a string-glyph can be produced. The first is to take the paths of all characters needed, concatenate them, insert space and kerning amounts as needed and raster the resulting whole path. This will yield the best results since the average position accuracy of the pixels will be optimal. This applies especially for rotated strings. The drawback is, that every character must be rastered every time it is needed. There is no way to access the bitmap data of a character inside a rastered string separate from others. And the caching of string-glyphs at this programming level doesn't make any sense. So this principle takes significantly longer than concatenating bitmaps from a cache area. However, it is done when the specified rotation angle is not equal to $0^\circ$ or when even further transformation are to be applied. This condition should limit the total number of situations when this happens to an amount we can easily bear.

If the transform-argument is NULL we know transformations or rotation should not be applied and another approach is used. We are then able to construct the resulting bitmap by adjusting already existent bitmaps into proper positions. If a character does not already exist in the cache, it is generated just the way T1_SetChar() works. The calculation of the character-bitmap positions in the output bitmap is done with char space-precision. Nonetheless, there may be differences in the output compared with output of the above method. These are caused by the fact that rounding to pixel accuracy has already been achieved when generating the character bitmap. Thus, the output of the above principle should always be better since the positions of the black pixels are rounded with respect to the whole string, and not with respect to a single character glyph. On the other hand, concatenating character glyphs takes significantly less time than rastering a complete string. Theoretically, differences of up to two pixels horizontal shift may appear in the output of the two principles. You can check the effect by running the program xglyph. Specify a string of enough length and raster it at angle $0^\circ$. Then specify a very small angle from 0 different, say, $0.001^\circ$, and raster the string again with the new setting. You might find that the representation of the string is a little different now.

The third function that creates a glyph object is

 GLYPH* T1_SetRect( int FontID, float size,
                    float width, float height,
                    T1_TMATRIX *transform)

to 0pt \fbox{$\mathcal{F}()\Rightarrow$} Calling this function yields a filled rectangle. It is intended for situations where a TEX-style \vrule would be appropriate, or, for equations in mathematical typesetting.

First, the argument FontID identifies a valid font. At this time, it is not obvious why a valid font is required in order to create a rectangular glyph. The reason is, that some of the parameters that are associated to a particular font are also relevant for creating rectangles in the context of that font. Hence, specifying a font identifier in this case is a means of stating ``draw a rectangle that visually fits to the style of the font FontID''. Aside from this, I assume that each application that uses t1lib deals with at least one font so that the FontID parameter actually does not hurt.

The size of the rectangle is to be specified in charspace units by means of the parameters width and height, and is moreover subject to scaling through the parameter size. By definition, the typographical fundamental area of a font, known as the em-square, is just as high and as wide as the design size of the font. In charspace units, this rectangle exactly maps to a $1000 \times 1000$ grid. Or alternatively spoken, one charspace unit is 0.001bp (Big Point). For example, in order to draw an em-square for some font at 13 points, the correct parameters are size $= 13$, width $= 1000$ and height $= 1000$. If absolute physical dimensions are desired, the scaling explicitly must be calculated by the user. For instance, in order to produce a $ 1 \mathrm{cm} \times 1 \mathrm{cm}$ square we find

\begin{displaymath}
h = w = 1\mathrm{cm} \frac{72\mathrm{bp}/\mathrm{in} \times
...
...bp}}{2.54\mathrm{cm}/\mathrm{in}}
\approx 28346\;\mathrm{cs.}
\end{displaymath}

Here ``cs'' designates charspace units and size is assumed to be $1$. Note that still the device resolution must be properly setup in order to make the dimensions appear accurately on the device.

The parameter transform is a pointer to a t1lib transformation matrix. If it is NULL, the current transformation of the font in question is used. Depending on the kind of actual transformation, the rectangle might also image as a nonrectangular shape. This happens, if the current font is slanted, then the rectangle will be skewed.

Glyphs produced by the rectangle function are never cached because there is no means in doing so. With respect to memory management, the same applies as for T1_SetChar() and T1_SetString(). Since rectangles rarely are used to produce normal text flow, the glyphs produced by the rectangle function do not cause any escapement.

If two glyphs with arbitrary orientation exist,

 GLYPH *T1_ConcatGlyphs( GLYPH *glyph1, GLYPH *glyph2,
                         int x_off, int y_off, int modflag)

to 0pt \fbox{$\mathcal{F}()\Rightarrow$} can be used to concatenate them. First the size of the resulting glyph is computed and its metric values are filled. Then, the two glyphs are placed at their appropriate positions in the newly created bitmap. In order to be able to work, the following conditions must be met:
  1. Either glyph must be different from NULL.
  2. Both glyphs must have identical bpp-values. If antialiased and non-antialiased glyphs are to be concatenated, have a look at
  3. There must be enough memory for the new glyph (naturally).
The quantities x_off and y_off describe the $x$- and $y$-component of an optional offset to be inserted between the two glyphs. This offset is interpreted as device pixels. The modflag argument is used to specify the direction in which the two glyphs are to be concatenated. That is, only the bit T1_LEFT_TO_RIGHT / T1_RIGHT_TO_LEFT is respected by this function.

If problems occur, NULL is returned. It is generally not recommended to produce large glyphs with this function because the char space precision in placing the character bitmaps is lost. For example, three times rounding up an advance by 0.3 pixels accumulates to 1 pixel position error. A similar effect shows up when two rotated and underlined glyphs are concatenated with this function. There might be a slight shift in the baseline at the point where the two glyphs touch.

A dilemma occurs, if two antialiased bitmaps have distinct background colors. Then, it is not clear what the transparent color is. T1_ConcatGlyphs() always assumes the current background color to be transparent.

There is one more function that generates pointers to glyphs:

 GLYPH *T1_CopyGlyph(GLYPH *glyph)

to 0pt \fbox{$\mathcal{F}()\Rightarrow$} As mentioned earlier, the user doesn't have the possibility of keeping the glyphs longer than to the next call of the respective rastering function. If someone wants to keep a bitmap some time longer, T1_CopyGlyph() may be used to copy the glyph to another area which is then completely under user's control. This function simply does the following:

Return value is the pointer to the allocated glyph-structure. If something goes wrong, NULL is returned to indicate an error. A glyph pointer, returned by a call to this function should be freed by a call to T1_FreeGlyph() (see [*]).


next up previous contents index
Next: Loading Fonts Explicitly Up: Using t1lib Previous: The t1lib-Logfile   Contents   Index
2004-10-04