Esempio n. 1
0
/*
** We call this routine to emmit the PostScript code
** for the character we have loaded with load_char().
*/
void GlyphToType3::PSConvert(TTStreamWriter& stream)
{
    int i,j,k;

    assert(area_ctr == NULL);
    area_ctr=(double*)calloc(num_ctr, sizeof(double));
    memset(area_ctr, 0, (num_ctr*sizeof(double)));
    assert(check_ctr == NULL);
    check_ctr=(char*)calloc(num_ctr, sizeof(char));
    memset(check_ctr, 0, (num_ctr*sizeof(char)));
    assert(ctrset == NULL);
    ctrset=(int*)calloc(num_ctr, 2*sizeof(int));
    memset(ctrset, 0, (num_ctr*2*sizeof(int)));

    check_ctr[0]=1;
    area_ctr[0]=area(xcoor, ycoor, epts_ctr[0]+1);

    for (i=1; i<num_ctr; i++)
    {
        area_ctr[i]=area(xcoor+epts_ctr[i-1]+1, ycoor+epts_ctr[i-1]+1, epts_ctr[i]-epts_ctr[i-1]);
    }

    for (i=0; i<num_ctr; i++)
    {
        if (area_ctr[i]>0)
        {
            ctrset[2*i]=i;
            ctrset[2*i+1]=nearout(i);
        }
        else
        {
            ctrset[2*i]=-1;
            ctrset[2*i+1]=-1;
        }
    }

    /* Step thru the coutours. */
    /* I believe that a contour is a detatched */
    /* set of curves and lines. */
    for(i = j = k = 0;
        i != NOMOREOUTCTR && i < num_ctr;
        k = nextinctr(i, k), (k == NOMOREINCTR && (i = k = nextoutctr(i))))
    {
        // A TrueType contour consists of on-path and off-path points.
        // Two consecutive on-path points are to be joined with a
        // line; off-path points between on-path points indicate a
        // quadratic spline, where the off-path point is the control
        // point. Two consecutive off-path points have an implicit
        // on-path point midway between them.
        std::list<FlaggedPoint> points;

        // Represent flags and x/y coordinates as a C++ list
        for (; j <= epts_ctr[k]; j++)
        {
            if (!(tt_flags[j] & 1)) {
                points.push_back(FlaggedPoint(OFF_PATH, xcoor[j], ycoor[j]));
            } else {
                points.push_back(FlaggedPoint(ON_PATH, xcoor[j], ycoor[j]));
            }
        }

        if (points.size() == 0) {
            // Don't try to access the last element of an empty list
            continue;
        }

        // For any two consecutive off-path points, insert the implied
        // on-path point.
        FlaggedPoint prev = points.back();
        for (std::list<FlaggedPoint>::iterator it = points.begin();
             it != points.end();
             it++)
        {
            if (prev.flag == OFF_PATH && it->flag == OFF_PATH)
            {
                points.insert(it,
                              FlaggedPoint(ON_PATH,
                                           (prev.x + it->x) / 2,
                                           (prev.y + it->y) / 2));
            }
            prev = *it;
        }
        // Handle the wrap-around: insert a point either at the beginning
        // or at the end that has the same coordinates as the opposite point.
        // This also ensures that the initial point is ON_PATH.
        if (points.front().flag == OFF_PATH)
        {
            assert(points.back().flag == ON_PATH);
            points.insert(points.begin(), points.back());
        }
        else
        {
            assert(points.front().flag == ON_PATH);
            points.push_back(points.front());
        }

        // The first point
        stack(stream, 3);
        PSMoveto(stream, points.front().x, points.front().y);

        // Step through the remaining points
        std::list<FlaggedPoint>::const_iterator it = points.begin();
        for (it++; it != points.end(); /* incremented inside */)
        {
            const FlaggedPoint& point = *it;
            if (point.flag == ON_PATH)
            {
                stack(stream, 3);
                PSLineto(stream, point.x, point.y);
                it++;
            } else {
                std::list<FlaggedPoint>::const_iterator prev = it, next = it;
                prev--;
                next++;
                assert(prev->flag == ON_PATH);
                assert(next->flag == ON_PATH);
                stack(stream, 7);
                PSCurveto(stream,
                          prev->x, prev->y,
                          point.x, point.y,
                          next->x, next->y);
                it++;
                it++;
            }
        }
    }

    /* Now, we can fill the whole thing. */
    stack(stream, 1);
    stream.puts( pdf_mode ? "f" : "_cl" );

    /* Free our work arrays. */
    free(area_ctr);
    free(check_ctr);
    free(ctrset);
    area_ctr = NULL;
    check_ctr = NULL;
    ctrset = NULL;
} /* end of PSConvert() */
Esempio n. 2
0
/*
** We call this routine to emmit the PostScript code
** for the character we have loaded with load_char().
*/
void GlyphToType3::PSConvert(TTStreamWriter& stream)
{
    int j, k;

    /* Step thru the contours.
     * j = index to xcoor, ycoor, tt_flags (point data)
     * k = index to epts_ctr (which points belong to the same contour) */
    for(j = k = 0; k < num_ctr; k++)
    {
        // A TrueType contour consists of on-path and off-path points.
        // Two consecutive on-path points are to be joined with a
        // line; off-path points between on-path points indicate a
        // quadratic spline, where the off-path point is the control
        // point. Two consecutive off-path points have an implicit
        // on-path point midway between them.
        std::list<FlaggedPoint> points;

        // Represent flags and x/y coordinates as a C++ list
        for (; j <= epts_ctr[k]; j++)
        {
            if (!(tt_flags[j] & 1)) {
                points.push_back(FlaggedPoint(OFF_PATH, xcoor[j], ycoor[j]));
            } else {
                points.push_back(FlaggedPoint(ON_PATH, xcoor[j], ycoor[j]));
            }
        }

        if (points.size() == 0) {
            // Don't try to access the last element of an empty list
            continue;
        }

        // For any two consecutive off-path points, insert the implied
        // on-path point.
        FlaggedPoint prev = points.back();
        for (std::list<FlaggedPoint>::iterator it = points.begin();
             it != points.end();
             it++)
        {
            if (prev.flag == OFF_PATH && it->flag == OFF_PATH)
            {
                points.insert(it,
                              FlaggedPoint(ON_PATH,
                                           (prev.x + it->x) / 2,
                                           (prev.y + it->y) / 2));
            }
            prev = *it;
        }
        // Handle the wrap-around: insert a point either at the beginning
        // or at the end that has the same coordinates as the opposite point.
        // This also ensures that the initial point is ON_PATH.
        if (points.front().flag == OFF_PATH)
        {
            assert(points.back().flag == ON_PATH);
            points.insert(points.begin(), points.back());
        }
        else
        {
            assert(points.front().flag == ON_PATH);
            points.push_back(points.front());
        }

        // The first point
        stack(stream, 3);
        PSMoveto(stream, points.front().x, points.front().y);

        // Step through the remaining points
        std::list<FlaggedPoint>::const_iterator it = points.begin();
        for (it++; it != points.end(); /* incremented inside */)
        {
            const FlaggedPoint& point = *it;
            if (point.flag == ON_PATH)
            {
                stack(stream, 3);
                PSLineto(stream, point.x, point.y);
                it++;
            } else {
                std::list<FlaggedPoint>::const_iterator prev = it, next = it;
                prev--;
                next++;
                assert(prev->flag == ON_PATH);
                assert(next->flag == ON_PATH);
                stack(stream, 7);
                PSCurveto(stream,
                          prev->x, prev->y,
                          point.x, point.y,
                          next->x, next->y);
                it++;
                it++;
            }
        }
    }

    /* Now, we can fill the whole thing. */
    stack(stream, 1);
    stream.puts( pdf_mode ? "f" : "_cl" );
} /* end of PSConvert() */