freetype
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [ft] Using SVG Font Glyph Data In FreeType


From: Tom Bishop, Wenlin Institute
Subject: Re: [ft] Using SVG Font Glyph Data In FreeType
Date: Thu, 8 Apr 2010 10:58:46 -0700

On Apr 8, 2010, at 7:05 AM, Werner LEMBERG wrote:

> 
>> If I understand Andy correctly, he'd like to map these primitive
>> outline commands to the corresponding FreeType rules (the
>> FT_outline_Functs structures) and then hand off the set of rules for
>> FreeType to work its magic on. I've had a look at
>> http://freetype.sourceforge.net/freetype2/docs/tutorial/example3.cpp
>> but it seems incomplete for the purpose of what he wants to do, as
>> it seems to demonstrate how to deal with a purely line data shape,
>> rather than one consisting of curve data.
> 
> It's trivial for conic and cubic splines, too.  You just have to set
> the proper flags in the `tags' array.  I think this is quite well
> documented.


For what it might be worth, below are some snippets of code I wrote for 
converting an SVG path into an FT_Outline. Anyone is welcome to use it, but it 
only supports a very limited subset of SVG (always d='M...z', with only L and C 
between; only a single contour), and it's not a complete program (it's 
extracted from a large program).

It still seems to me that the FreeType side is easy (given the existence of 
FreeType), but to do the SVG side correctly (not only a subset like here), it 
would make more sense to use an existing SVG library rather than re-implement 
it from scratch.

Tom

#define ON_CURVE  1 /* bit 0 set */
#define OFF_CURVE 2 /* bit 1 set: off curve, 3rd-order (cubic) */

typedef FT_F26Dot6 OLXY; /* x, y coordinates for outline (OL) */
typedef FT_Byte OLFlag; /* flag for each point (OFF_CURVE or ON_CURVE) */
typedef FT_Vector OLPoint;

typedef struct {
        #define MAX_POINTS_PER_OUTLINE 100
        OLPoint p[MAX_POINTS_PER_OUTLINE];
        OLFlag f[MAX_POINTS_PER_OUTLINE]; // flags
        OLXY hengRadius, shuRadius;
        unsigned short n; // number of points
        unsigned short strokeType, head, tail;
} OLInfo;

void OLAddP(OLInfo *oli, OLPoint p, OLFlag flag)
{
        OLAdd(oli, p.x, p.y, flag);
} // OLAddP

void OLAdd(OLInfo *oli, OLXY x, OLXY y, OLFlag flag)
{
        if (oli->n < MAX_POINTS_PER_OUTLINE) {
                oli->p[oli->n].x = x;
                oli->p[oli->n].y = y;
                oli->f[oli->n] = flag;
                oli->n++;
        }
} // OLAdd

int GetOutlineFromSVG_Path(OLInfo *oli, OLPoint *refPoints, char *d)
/*  Given d (data) like a "d" attribute of an SVG "path" element
    (but we only support a subset, such as "M", "L", and "C" commands).
    Fill in oli with the outline which can then be turned into FT_Outline.
    refPoints: Two reference points for bounding rectangle, into which
    the path is scaled.

Example: d='M28.2969,64.5156
            L22.2500,66.0312
            L18.2188,60.4844
            L72.7188,60.4844
            L80.2656,50.4375
            C88.6719,53.8594 94.0469,60.4844 96.0938,64.5156
            L28.2969,64.5156
            z'

    Wenlin's CDL-generated SVG always has d='M...z', with only L and C between.
*/
{
        static char xyFormat[] = "%f , %f%n";
        OLPoint topLeft = refPoints[0], bottomRight = refPoints[1];
        size_t ofs = 0;
        int n;

        /* Scale the coordinates. To begin with, the path coordinates are
            between 0 and GRID_SIZE, where (0, 0) maps to topLeft and
            (GRID_SIZE, GRID_SIZE) maps to bottomRight. Also need to flip since
            SVG/CDL y increases downward but FreeType y increases upward. */
        float height = (float) (topLeft.y - bottomRight.y);
        float width  = (float) (bottomRight.x - topLeft.x);
        float fx, fy;
        #define SVG_FT_X(fx) topLeft.x + (OLXY)((fx/GRID_SIZE)*width + 
FT_HALF_PIXEL)
        #define SVG_FT_Y(fy) bottomRight.y + (OLXY)((1.0-(fy/GRID_SIZE))*height 
+ FT_HALF_PIXEL)

        if (d[ofs++] != 'M') { // 'M' = "moveto"
                return NO;
        }
        if (sscanf(d + ofs, xyFormat, &fx, &fy, &n) != 2) {
                return NO;
        }
        ofs += n;
        OLAdd(oli, SVG_FT_X(fx), SVG_FT_Y(fy), ON_CURVE);
        while (d[ofs] != 'z') { // 'z' = "closepath"
                switch (d[ofs]) {
                case 'L': // 'L' = "lineto" (absolute)
                        ++ofs;
                        if (sscanf(d + ofs, xyFormat, &fx, &fy, &n) != 2) {
                                return NO;
                        }
                        ofs += n;
                        OLAdd(oli, SVG_FT_X(fx), SVG_FT_Y(fy), ON_CURVE);
                        break;
                case 'C': // 'C' = "(cubic) curveto" (absolute)
                        ++ofs;
                        if (sscanf(d + ofs, xyFormat, &fx, &fy, &n) != 2) {
                                return NO;
                        }
                        ofs += n;
                        OLAdd(oli, SVG_FT_X(fx), SVG_FT_Y(fy), OFF_CURVE);
                        if (sscanf(d + ofs, xyFormat, &fx, &fy, &n) != 2) {
                                return NO;
                        }
                        ofs += n;
                        OLAdd(oli, SVG_FT_X(fx), SVG_FT_Y(fy), OFF_CURVE);
                        if (sscanf(d + ofs, xyFormat, &fx, &fy, &n) != 2) {
                                return NO;
                        }
                        ofs += n;
                        OLAdd(oli, SVG_FT_X(fx), SVG_FT_Y(fy), ON_CURVE);
                        break;
                case ' ':
                case '\t':
                case '\n':
                        ++ofs;
                        break;
                default:
                        return NO;
                }
        }
        return YES;
} // GetOutlineFromSVG_Path

// convert OLInfo to FT_Outline as follows:
        FT_Outline ftOutline; /* see ftimage.h */
        FT_UShort oneContour; /* must be (short), see ftimage.h */
        memset(&ftOutline, 0, sizeof(FT_Outline));
        ftOutline.points = oli->p;
        ftOutline.n_points = oli->n;
        ftOutline.n_contours = 1;
        ftOutline.contours = (short *) &oneContour; /* must be (short *), see 
ftimage.h */
        ftOutline.tags = (char *) oli->f;
        ftOutline.flags = FT_OUTLINE_HIGH_PRECISION;
        ftOutline.contours[0] = ftOutline.n_points - 1;

文林 Wenlin Institute, Inc.        Software for Learning Chinese
E-mail: address@hidden     Web: http://www.wenlin.com
Telephone: 1-877-4-WENLIN (1-877-493-6546)
☯









reply via email to

[Prev in Thread] Current Thread [Next in Thread]