next up previous contents index
Next: Logical Fonts Up: Interface to Outlines Previous: Using Outlines   Contents   Index


Manipulation of Outlines

t1lib provides some limited further functionality to process outlines. First of all, a user would expect a character to be defined in a coordinate system in which $x$ points to the right and $y$ points up. Further, a representation of the glyph where all points are specified in absolute coordinates would be advantageous for manipulating outline-points. This is because most transformations, linear or nonlinear, need to have an absolute $x$-value to compute an $y$-value or vice versa. The function

 void T1_AbsolutePath( T1_OUTLINE *rpath)

to 0pt \fbox{$\mathcal{F}()\Rightarrow$} does exactly what has been described just before, (a) conversion of relative coordinates into absolute coordinates and (b) inverting the $y$-direction.

Once a path has been converted into an absolute path, it is suitable for possibly nonlinear manipulation.14As an example of what can be done, have a look at figure [*].

Figure: A string with nonlinearly scaled coordinates.
\includegraphics[scale=1.0]{manipulate}

The string displayed has been generated by essentially applying the transformation $y'= y(1+cx^2)$, with appropriate $c$. To allow such transformations by the user, t1lib provides the function

 void T1_ManipulatePath( T1_OUTLINE *path,
                         void (*manipulate)(long *x,long *y, int type))

to 0pt \fbox{$\mathcal{F}()\Rightarrow$} Here, path should be an absolute path as described above. Notice that t1lib has no way to check whether the path is relative or absolute, this is in the responsibility of the user. The second argument is a pointer to a function that has a return type of void and that expects three arguments: two pointers to long-values one integer type. T1_ManipulatePath() works by iterating through all outline points of path and calling the function *manipulate() for each outline point. When the function *manipulate() is called, x and y are pointers to the $x$- and $y$-coordinates respectively of the outline point to be processed. That way, *manipulate() can alter the outline points arbitrarily. The type-argument will be set to the segment type by T1_ManipulatePath(). As described earlier, the segment type can be one of T1_PATHTYPE_MOVE, T1_PATHTYPE_LINE and T1_PATHTYPE_BEZIER. Of course, the function manipulate() has to be written by the user. To make it clear, we consider a function which stretches an outline horizontally by 1.5. The code fragment for this could be:
     .
     .
     .
void h_stretch( long *x, long *y, int type)
{
  double dx;

  dx=(double)*x;
  dx *=1.5;       /* scale x coordinate by 1.5 */
  *x=(long)dx;
}
     .
     .
     .
T1_OUTLINE *path=NULL;
path=T1_GetStringOutline(FontID,(char *)SomeString,
                         0,0,T1_KERNING,20.0,NULL);
T1_AbsolutePath( path);
T1_ManipulatePath( path, &h_stretch);
T1_RelativePath( path);
glyph=T1_FillOutline( path, Modflag);
     .
     .
     .

As the example above already has shown, an absolute path, manipulated or not, must converted back to a relative path before it finally can be interpreted by the rasterizer. This conversion is done using

 void T1_RelativePath( T1_OUTLINE *apath)

to 0pt \fbox{$\mathcal{F}()\Rightarrow$} As already mentioned with respect to T1_AbsolutePath(), t1lib cannot check whether the path specified is really absolute. The user has to take care for this.

A few general comments about manipulating paths are appropriate. Although the mechanism implemented by T1_ManipulatePath() allows arbitrary manipulation of path points, one must be very careful in doing so. Figure [*] exhibits some of the problems that may arise. A text string aligned to a sine function is displayed.

Figure: The string ``Text aligned along a sine wave function'' using a period of (a) 500, (b) 200, (c) 100, (d) 50 pixels and (e) again 500 pixels with underlining. The sine amplitude was 30 pixels (in screen resolution).
a) \includegraphics[scale=0.5]{outlineproblems1}

b) \includegraphics[scale=0.5]{outlineproblems2}

c) \includegraphics[scale=0.5]{outlineproblems3}

d) \includegraphics[scale=0.5]{outlineproblems4}

e) \includegraphics[scale=0.5]{outlineproblems5}


In part (a), a pleasing smooth text flow is shown and this also applies for (b) where the period of the sine has been reduced to 200 pixels. In (c), where the period has been reduced to 100 pixels, some artefacts already show up. For example, the top bar of the uppercase ``T'' has noticeable variance in thickness. In (d), where the period has been reduced again, the result is hardly readable. Another artefact appears in figure [*] (e): since the underlining rule is defined by four points only, these points and nothing else is transformed with the result that the out coming line is still straight and not curved as we would like. From this discussion we conclude, that such transformations can only be done with reasonable results if the maximum distance between the outline points of a shape is small compared to the variance of the outline points that the transformation results in. This rule, although being very fuzzy and non-mathematical, should give a good estimation of which transformations are valid.

Another completely independent topic is that, at the level where t1lib provides outlines, their representation is strictly descriptive with respect to points and their connections. There are no such things like closepath-segments which would take care that a path is really closed, no matter what the transformation had been. This means, that identical points $P_1 = P_2$ have to be transformed to identical points $P_1'=P_2'$, no matter where they appear in the outline. However, if the transformation is done by by a function $(x',y')=f(x,y)$ as suggested, this should never be a problem.

Finally, one should remember that all computations in the user function manipulate() have to be done in units of fractional pixels, rather than in pixels. When designing a sine wave as in figure [*], this must be taken into account with respect to periodicity.


next up previous contents index
Next: Logical Fonts Up: Interface to Outlines Previous: Using Outlines   Contents   Index
2004-10-04