Back to index

tetex-bin  3.0
Defines | Functions | Variables
paths.c File Reference
#include "types.h"
#include "objects.h"
#include "spaces.h"
#include "paths.h"
#include "regions.h"
#include "fonts.h"
#include "pictures.h"
#include "strokes.h"
#include "trig.h"

Go to the source code of this file.

Defines

#define POP(p)
#define INSERT(b, p, a)   b->link=p; p->link=a; p->last=NULL
#define CLOSEFUDGE   3 /* if we are this close, let's change last segment */

Functions

static Unclose ()
struct segmentCopyPath (struct segment *p0)
void KillPath (struct segment *p)
struct segmentt1_Loc (struct XYspace *S, DOUBLE x, DOUBLE y)
struct segmentILoc (struct XYspace *S, int x, int y)
struct segmentSubLoc (struct segment *p1, struct segment *p2)
struct segmentt1_PathSegment (int type, fractpel x, fractpel y)
struct segmentLine (struct segment *P)
struct beziersegmentBezier (struct segment *B, struct segment *C, struct segment *D)
struct hintsegmentHint (struct XYspace *S, float ref, float width, char orientation, char hinttype, char adjusttype, char direction, int label)
struct segmentJoin (struct segment *p1, struct segment *p2)
struct segmentt1_JoinSegment (struct segment *before, int type, fractpel x, fractpel y, struct segment *after)
struct segmentt1_ClosePath (struct segment *p0, int lastonly)
static struct segmentSplitPath ()
static struct segmentDropSubPath ()
static struct segmentReverseSubPath ()
struct segmentReverse (struct segment *p)
static struct segmentReverseSubPath (struct segment *p)
static struct segmentDropSubPath (struct segment *p0)
static struct segmentSplitPath (struct segment *anchor, struct segment *before)
struct segmentReverseSubPaths (struct segment *p)
static UnClose (struct segment *p0)
struct segmentPathTransform (struct segment *p0, struct XYspace *S)
void PathDelta (struct segment *p, struct fractpoint *pt)
struct segmentBoundingBox (pel h, pel w)
void QueryLoc (struct segment *P, struct XYspace *S, DOUBLE *xP, DOUBLE *yP)
void QueryPath (struct segment *path, int *typeP, struct segment **Bp, struct segment **Cp, struct segment **Dp, DOUBLE *fP)
void QueryBounds (struct segment *p0, struct XYspace *S, DOUBLE *xminP, DOUBLE *yminP, DOUBLE *xmaxP, DOUBLE *ymaxP)
struct segmentBoxPath (struct XYspace *S, int h, int w)
struct segmentDropSegment (struct segment *path)
struct segmentHeadSegment (struct segment *path)
void DumpPath (struct segment *p)

Variables

static struct segment

Define Documentation

#define CLOSEFUDGE   3 /* if we are this close, let's change last segment */
#define INSERT (   b,
  p,
  a 
)    b->link=p; p->link=a; p->last=NULL

Definition at line 446 of file paths.c.

#define POP (   p)
Value:
{ register struct segment *linkp; \
       linkp = p->link; \
       if (linkp != NULL) \
               linkp->last = p->last; \
       Free(p); \
       p = linkp; }

Definition at line 434 of file paths.c.


Function Documentation

struct beziersegment* Bezier ( struct segment B,
struct segment C,
struct segment D 
) [read]

Definition at line 341 of file paths.c.

{
/* added reference field of 1 to temporary template below 3-26-91  PNM */
       static struct beziersegment template =
                    { BEZIERTYPE, 0, 1, sizeof(struct beziersegment), 0,
                      NULL, NULL, { 0, 0 }, { 0, 0 }, { 0, 0 } };
 
       register struct beziersegment *r;  /* output segment                  */
 
       IfTrace3((MustTraceCalls),"..Bezier(%z, %z, %z)\n", B, C, D);
       ARGCHECK(!ISLOCATION(B), "Bezier: bad B", B, NULL, (2,C,D), struct beziersegment *);
       ARGCHECK(!ISLOCATION(C), "Bezier: bad C", C, NULL, (2,B,D), struct beziersegment *);
       ARGCHECK(!ISLOCATION(D), "Bezier: bad D", D, NULL, (2,B,C), struct beziersegment *);
 
       r = (struct beziersegment *)Allocate(sizeof(struct beziersegment), &template, 0);
       r->last = (struct segment *) r;
       r->dest.x = D->dest.x;
       r->dest.y = D->dest.y;
       r->B.x = B->dest.x;
       r->B.y = B->dest.y;
       r->C.x = C->dest.x;
       r->C.y = C->dest.y;
 
       ConsumePath(B);
       ConsumePath(C);
       ConsumePath(D);
       return(r);
}
struct segment* BoundingBox ( pel  h,
pel  w 
) [read]

Definition at line 1078 of file paths.c.

{
       register struct segment *path;
 
       path = PathSegment(LINETYPE, -TOFRACTPEL(w), 0);
       path = JoinSegment(NULL, LINETYPE, 0, -TOFRACTPEL(h), path);
       path = JoinSegment(NULL, LINETYPE, TOFRACTPEL(w), 0, path);
       path = ClosePath(path);
 
       return(path);
}
struct segment* BoxPath ( struct XYspace S,
int  h,
int  w 
) [read]

Definition at line 1367 of file paths.c.

{
       struct segment *path;
 
       path = Join( Line(ILoc(S, w, 0)), Line(ILoc(S, 0, h)) );
       path = JoinSegment(path, LINETYPE, -path->dest.x, -path->dest.y, NULL);
       return(ClosePath(path));
}
struct segment* CopyPath ( struct segment p0) [read]

Definition at line 123 of file paths.c.

{
       register struct segment *p,*n,*last,*anchor;
 
       for (p = p0, anchor = NULL; p != NULL; p = p->link) {
 
               ARGCHECK((!ISPATHTYPE(p->type) || (p != p0 && p->last != NULL)),
                       "CopyPath: invalid segment", p, NULL, (0), struct segment *);
 
               if (p->type == TEXTTYPE)
                       n = (struct segment *) CopyText(p);
               else
                       n = (struct segment *)Allocate(p->size, p, 0);
               n->last = NULL;
               if (anchor == NULL)
                       anchor = n;
               else
                       last->link = n;
               last = n;
       }
/*
At this point we have a chain of newly allocated segments hanging off
'anchor'.  We need to make sure the first segment points to the last:
*/
       if (anchor != NULL) {
               n->link = NULL;
               anchor->last = n;
       }
 
       return(anchor);
}
struct segment* DropSegment ( struct segment path) [read]

Definition at line 1386 of file paths.c.

{
       IfTrace1((MustTraceCalls),"DropSegment(%z)\n", path);
       if (path != NULL && path->type == STROKEPATHTYPE)
               path = CoercePath(path);
       ARGCHECK((path == NULL || !ISPATHANCHOR(path)),
                 "DropSegment: arg not a non-null path", path, path, (0), struct segment *);
       if (path->type == TEXTTYPE)
               path = CoerceText(path);
       path = UniquePath(path);
 
       POP(path);
       return(path);
}
static struct segment* DropSubPath ( ) [static, read]
static struct segment* DropSubPath ( struct segment p0) [static, read]

Definition at line 832 of file paths.c.

{
       register struct segment *p;  /* returned remainder here               */
 
       for (p = p0; p->link != NULL; p = p->link) {
               if (p->link->type == MOVETYPE)
                       break;
       }
 
       return(SplitPath(p0, p));
}

Here is the call graph for this function:

void DumpPath ( struct segment p)

Definition at line 1434 of file paths.c.

{
       register fractpel x,y;
       register fractpel lastx,lasty;
       DOUBLE roundness;
 
       IfTrace1(TRUE,"Dumping path, anchor=%x:\n", p);
       lastx = lasty = 0;
 
       for (;p != NULL; p=p->link) {
 
               IfTrace0(TRUE,". ");
               x = p->dest.x;
               y = p->dest.y;
               switch (p->type) {
 
                   case LINETYPE:
                       IfTrace1(TRUE,". line<%x> to", (LONG) p->flag);
                       IfTrace4(TRUE," (%p,%p), delta=(%p,%p)",
                                 x + lastx, y + lasty, x, y);
                       break;
 
                   case MOVETYPE:
                       IfTrace1(TRUE,"MOVE<%x> to", (LONG) p->flag);
                       IfTrace4(TRUE,"(%p,%p), delta=(%p,%p)",
                                 x + lastx, y + lasty, x, y);
                       break;
 
                   case CONICTYPE:
                   {
                       register struct conicsegment *cp = (struct conicsegment *) p;
 
                       roundness = cp->roundness;
                       IfTrace2(TRUE, ". conic to (%p,%p),",
                                                  x + lastx, y + lasty);
                       IfTrace3(TRUE," M=(%p,%p), r=%f", cp->M.x + lastx,
                                                   cp->M.y + lasty, &roundness);
                   }
                       break;
 
                   case BEZIERTYPE:
                   {
                       register struct beziersegment *bp = (struct beziersegment *) p;
 
                       IfTrace4(TRUE,". bezier to (%p,%p), B=(%p,%p)",
                                       x + lastx, y + lasty,
                                       bp->B.x + lastx, bp->B.y + lasty);
                       IfTrace2(TRUE, ", C=(%p,%p)",
                                       bp->C.x + lastx, bp->C.y + lasty);
                   }
                       break;
 
                   case HINTTYPE:
                   {
                       register struct hintsegment *hp = (struct hintsegment *) p;
 
                       IfTrace4(TRUE,". hint ref=(%p,%p), width=(%p,%p)",
                                       hp->ref.x + lastx, hp->ref.y + lasty,
                                       hp->width.x, hp->width.y);
                       IfTrace4(TRUE, ", %c %c %c %c",
                                       hp->orientation, hp->hinttype,
                                       hp->adjusttype, hp->direction);
                       IfTrace1(TRUE, ", %ld", (LONG) hp->label);
                   }
                       break;
 
                   case TEXTTYPE:
                       DumpText(p);
                       break;
 
                   default:
                       IfTrace0(TRUE, "bad path segment?");
               }
               IfTrace1(TRUE," at %x\n", p);
               lastx += x;
               lasty += y;
       }
}
struct segment* HeadSegment ( struct segment path) [read]

Definition at line 1408 of file paths.c.

{
       IfTrace1((MustTraceCalls),"HeadSegment(%z)\n", path);
       if (path == NULL)
               return(NULL);
       if (path->type == STROKEPATHTYPE)
               path = CoercePath(path);
       ARGCHECK(!ISPATHANCHOR(path), "HeadSegment: arg not a path", path, path, (0), struct segment *);
       if (path->type == TEXTTYPE)
               path = CoerceText(path);
       path = UniquePath(path);
 
       if (path->link != NULL)
               KillPath(path->link);
       path->link = NULL;
       path->last = path;
       return(path);
}
struct hintsegment* Hint ( struct XYspace S,
float  ref,
float  width,
char  orientation,
char  hinttype,
char  adjusttype,
char  direction,
int  label 
) [read]

Definition at line 382 of file paths.c.

{
/* added reference field of 1 to hintsegment template below 3-26-91 PNM */
       static struct hintsegment template = { HINTTYPE, 0, 1, sizeof(struct hintsegment), 0,
                                          NULL, NULL, { 0, 0 }, { 0, 0 }, { 0, 0 },
                                          ' ', ' ', ' ', ' ', 0};
 
       register struct hintsegment *r;
 
       r = (struct hintsegment *)Allocate(sizeof(struct hintsegment), &template, 0);
 
       r->orientation = orientation;
       if (width == 0.0)  width = 1.0;
 
       if (orientation == 'h') {
               (*S->convert)(&r->ref, S, 0.0, ref);
               (*S->convert)(&r->width, S, 0.0, width);
       }
       else if (orientation == 'v') {
               (*S->convert)(&r->ref, S, ref, 0.0);
               (*S->convert)(&r->width, S, width, 0.0);
       }
       else
               return((struct hintsegment *)ArgErr("Hint: orient not 'h' or 'v'", NULL, NULL));
       if (r->width.x < 0)  r->width.x = - r->width.x;
       if (r->width.y < 0)  r->width.y = - r->width.y;
       r->hinttype = hinttype;
       r->adjusttype = adjusttype;
       r->direction = direction;
       r->label = label;
       r->last = (struct segment *) r;
       ConsumeSpace(S);
       return(r);
}
struct segment* ILoc ( struct XYspace S,
int  x,
int  y 
) [read]

Definition at line 233 of file paths.c.

{
       register struct segment *r;
 
       IfTrace3((MustTraceCalls),"..ILoc(S=%z, x=%d, y=%d)\n",
                                    S, (LONG) x, (LONG) y);
       r = (struct segment *)Allocate(sizeof(struct segment), &movetemplate, 0);
       TYPECHECK("Loc", S, SPACETYPE, r, (0), struct segment *);
 
       r->last = r;
       r->context = S->context;
       (*S->iconvert)(&r->dest, S, (LONG) x, (LONG) y);
       ConsumeSpace(S);
       return(r);
}
struct segment* Join ( struct segment p1,
struct segment p2 
) [read]

Definition at line 457 of file paths.c.

{
       IfTrace2((MustTraceCalls && PathDebug > 1),"..Join(%z, %z)\n", p1, p2);
       IfTrace2((MustTraceCalls && PathDebug <=1),"..Join(%x, %x)\n", p1, p2);
/*
We start with a whole bunch of very straightforward argument tests:
*/
       if (p2 != NULL) {
               if (!ISPATHTYPE(p2->type)) {
 
                       if (p1 == NULL)
                               return((struct segment *)Unique(p2));
 
                       switch (p1->type) {
 
                           case REGIONTYPE:
 
                           case STROKEPATHTYPE:
                               p1 = CoercePath(p1);
                               break;
 
                           default:
                               return((struct segment *)BegHandle(p1, p2));
                       }
               }
 
               ARGCHECK((p2->last == NULL), "Join: right arg not anchor", p2, NULL, (1,p1), struct segment *);
               p2 = UniquePath(p2);
 
/*
In certain circumstances, we don't have to duplicate a permanent
location.  (We would just end up destroying it anyway).  These cases
are when 'p2' begins with a move-type segment:
*/
               if (p2->type == TEXTTYPE || p2->type == MOVETYPE) {
                       if (p1 == NULL)
                               return(p2);
                       if (ISLOCATION(p1)) {
                               p2->dest.x += p1->dest.x;
                               p2->dest.y += p1->dest.y;
                               ConsumePath(p1);
                               return(p2);
                       }
               }
       }
       else
               return((struct segment *)Unique(p1));
 
       if (p1 != NULL) {
               if (!ISPATHTYPE(p1->type))
 
                       switch (p2->type) {
 
                           case REGIONTYPE:
 
                           case STROKEPATHTYPE:
                               p2 = CoercePath(p2);
                               break;
 
                           default:
                               return((struct segment *)EndHandle(p1, p2));
                       }
 
               ARGCHECK((p1->last == NULL), "Join: left arg not anchor", p1, NULL, (1,p2), struct segment *);
               p1 = UniquePath(p1);
       }
       else
               return(p2);
 
/*
At this point all the checking is done.  We have two temporary non-null
path types in 'p1' and 'p2'.  If p1 ends with a MOVE, and p2 begins with
a MOVE, we collapse the two MOVEs into one.  We enforce the rule that
there may not be two MOVEs in a row:
*/
 
       if (p1->last->type == MOVETYPE && p2->type == MOVETYPE) {
               p1->last->flag |= p2->flag;
               p1->last->dest.x += p2->dest.x;
               p1->last->dest.y += p2->dest.y;
               POP(p2);
               if (p2 == NULL)
                       return(p1);
       }
/*
Now we check for another silly rule.  If a path has any TEXTTYPEs,
then it must have only TEXTTYPEs and MOVETYPEs, and furthermore,
it must begin with a TEXTTYPE.  This rule makes it easy to check
for the special case of text.  If necessary, we will coerce
TEXTTYPEs into paths so we don't mix TEXTTYPEs with normal paths.
*/
       if (p1->type == TEXTTYPE) {
               if (p2->type != TEXTTYPE && !ISLOCATION(p2))
                       p1 = CoerceText(p1);
       }
       else {
               if (p2->type == TEXTTYPE) {
                       if (ISLOCATION(p1)) {
                               p2->dest.x += p1->dest.x;
                               p2->dest.y += p1->dest.y;
                               Free(p1);
                               return(p2);
                       }
                       else
                               p2 = CoerceText(p2);
               }
       }
/*
Thank God!  Finally!  It's hard to believe, but we are now able to
actually do the join.  This is just invoking the CONCAT macro:
*/
       CONCAT(p1, p2);
 
       return(p1);
}
void KillPath ( struct segment p)

Definition at line 161 of file paths.c.

{
       register struct segment *linkp;  /* temp register holding next segment*/
 
       /* return conditional based on reference count 3-26-91 PNM */
       if ( (--(p->references) > 1) ||
          ( (p->references == 1) && !ISPERMANENT(p->flag) ) )
           return;
 
       while (p != NULL) {
               if (!ISPATHTYPE(p->type)) {
                       ArgErr("KillPath: bad segment", p, NULL);
                       return;
               }
               linkp = p->link;
               if (p->type == TEXTTYPE)
                       KillText(p);
               else
                       Free(p);
               p = linkp;
       }
}
struct segment* Line ( struct segment P) [read]

Definition at line 306 of file paths.c.

{
 
       IfTrace1((MustTraceCalls),"..Line(%z)\n", P);
       ARGCHECK(!ISLOCATION(P), "Line: arg not a location", P, NULL, (0), struct segment *);
 
       P = UniquePath(P);
       P->type = LINETYPE;
       return(P);
}
void PathDelta ( struct segment p,
struct fractpoint pt 
)

Definition at line 1050 of file paths.c.

{
       struct fractpoint mypoint;  /* I pass this to TextDelta               */
       register fractpel x,y;  /* working variables for path current point   */
 
       for (x=y=0; p != NULL; p=p->link) {
               x += p->dest.x;
               y += p->dest.y;
               if (p->type == TEXTTYPE) {
                       TextDelta(p, &mypoint);
                       x += mypoint.x;
                       y += mypoint.y;
               }
       }
 
       pt->x = x;
       pt->y = y;
}
struct segment* PathTransform ( struct segment p0,
struct XYspace S 
) [read]

Definition at line 962 of file paths.c.

{
       register struct segment *p;   /* to loop through path with            */
       register fractpel newx,newy;  /* current transformed position in path */
       register fractpel oldx,oldy;  /* current untransformed position in path */
       register fractpel savex,savey;  /* save path delta x,y                */
 
       p0 = UniquePath(p0);
 
       newx = newy = oldx = oldy = 0;
 
       for (p=p0; p != NULL; p=p->link) {
 
               savex = p->dest.x;   savey = p->dest.y;
 
               (*S->iconvert)(&p->dest, S, p->dest.x + oldx, p->dest.y + oldy);
               p->dest.x -= newx;
               p->dest.y -= newy;
 
               switch (p->type) {
 
                   case LINETYPE:
                   case MOVETYPE:
                       break;
 
                   case CONICTYPE:
                   {
                       register struct conicsegment *cp = (struct conicsegment *) p;
 
                       (*S->iconvert)(&cp->M, S, cp->M.x + oldx, cp->M.y + oldy);
                       cp->M.x -= newx;
                       cp->M.y -= newy;
                       /*
                       * Note roundness doesn't change... linear transform
                       */
                       break;
                   }
 
 
                   case BEZIERTYPE:
                   {
                       register struct beziersegment *bp = (struct beziersegment *) p;
 
                       (*S->iconvert)(&bp->B, S, bp->B.x + oldx, bp->B.y + oldy);
                       bp->B.x -= newx;
                       bp->B.y -= newy;
                       (*S->iconvert)(&bp->C, S, bp->C.x + oldx, bp->C.y + oldy);
                       bp->C.x -= newx;
                       bp->C.y -= newy;
                       break;
                   }
 
                   case HINTTYPE:
                   {
                       register struct hintsegment *hp = (struct hintsegment *) p;
 
                       (*S->iconvert)(&hp->ref, S, hp->ref.x + oldx, hp->ref.y + oldy);
                       hp->ref.x -= newx;
                       hp->ref.y -= newy;
                       (*S->iconvert)(&hp->width, S, hp->width.x, hp->width.y);
                       /* Note: width is not relative to origin */
                       break;
                   }
 
                   case TEXTTYPE:
                   {
                        XformText(p,S);
                        break;
                   }
 
                   default:
                       IfTrace1(TRUE,"path = %z\n", p);
                       t1_abort("PathTransform:  invalid segment");
               }
               oldx += savex;
               oldy += savey;
               newx += p->dest.x;
               newy += p->dest.y;
       }
       return(p0);
}

Here is the call graph for this function:

void QueryBounds ( struct segment p0,
struct XYspace S,
DOUBLE xminP,
DOUBLE yminP,
DOUBLE xmaxP,
DOUBLE ymaxP 
)

Definition at line 1199 of file paths.c.

{
       register struct segment *path;  /* loop variable for path segments    */
       register fractpel lastx,lasty;  /* loop variables:  previous endingpoint */
       register fractpel x,y;  /* loop variables:  current ending point      */
       struct fractpoint min;  /* registers to keep lower left hand corner   */
       struct fractpoint max;  /* registers to keep upper right hand corner  */
       int coerced = FALSE;  /* we have coerced the path from another object */
       DOUBLE x1,y1,x2,y2,x3,y3,x4,y4;  /* corners of rectangle in space X   */
 
       IfTrace2((MustTraceCalls), "QueryBounds(%z, %z,", p0, S);
       IfTrace4((MustTraceCalls), " %x, %x, %x, %x)\n",
                                  xminP, yminP, xmaxP, ymaxP);
       if (S->type != SPACETYPE) {
               ArgErr("QueryBounds:  bad XYspace", S, NULL);
               return;
       }
 
       min.x = min.y = max.x = max.y = 0;
       if (p0 != NULL) {
               if (!ISPATHANCHOR(p0)) {
                       switch(p0->type) {
                           case STROKEPATHTYPE:
      /* replaced DupStrokePath() with Dup() 3-26-91 PNM */
                               p0 = (struct segment *) DoStroke(Dup(p0));
                               /* no break here, we have a region in p0 */
                           case REGIONTYPE:
                               p0 = RegionBounds(p0);
                               break;
 
                           case PICTURETYPE:
                               p0 = PictureBounds(p0);
                               break;
 
                           default:
                               ArgErr("QueryBounds:  bad object", p0, NULL);
                               return;
                       }
                       coerced = TRUE;
               }
               if (p0->type == TEXTTYPE) {
    /* replaced CopyPath() with Dup() 3-26-91 PNM */
                       p0 = (struct segment *)CoerceText(Dup(p0));  /* there are faster ways */
                       coerced = TRUE;
               }
               if (p0->type == MOVETYPE) {
                       min.x = max.x = p0->dest.x;
                       min.y = max.y = p0->dest.y;
               }
       }
       lastx = lasty = 0;
 
       for (path = p0; path != NULL; path = path->link) {
 
               x = lastx + path->dest.x;
               y = lasty + path->dest.y;
 
               switch (path->type) {
 
                   case LINETYPE:
                       break;
 
                   case CONICTYPE:
                   {
                       register struct conicsegment *cp = (struct conicsegment *) path;
                       register fractpel Mx = lastx + cp->M.x;
                       register fractpel My = lasty + cp->M.y;
                       register fractpel deltax = 0.5 * cp->roundness * cp->dest.x;
                       register fractpel deltay = 0.5 * cp->roundness * cp->dest.y;
                       register fractpel Px = Mx - deltax;
                       register fractpel Py = My - deltay;
                       register fractpel Qx = Mx + deltax;
                       register fractpel Qy = My + deltay;
 
 
                       if (Mx < min.x) min.x = Mx;
                       else if (Mx > max.x) max.x = Mx;
                       if (My < min.y) min.y = My;
                       else if (My > max.y) max.y = My;
 
                       if (Px < min.x) min.x = Px;
                       else if (Px > max.x) max.x = Px;
                       if (Py < min.y) min.y = Py;
                       else if (Py > max.y) max.y = Py;
 
                       if (Qx < min.x) min.x = Qx;
                       else if (Qx > max.x) max.x = Qx;
                       if (Qy < min.y) min.y = Qy;
                       else if (Qy > max.y) max.y = Qy;
                   }
                       break;
 
 
                   case MOVETYPE:
                       /*
                       * We can't risk adding trailing Moves to the
                       * bounding box:
                       */
                       if (path->link == NULL)
                               goto done;  /* God forgive me                 */
                       break;
 
                   case BEZIERTYPE:
                   {
                       register struct beziersegment *bp = (struct beziersegment *) path;
                       register fractpel Bx = lastx + bp->B.x;
                       register fractpel By = lasty + bp->B.y;
                       register fractpel Cx = lastx + bp->C.x;
                       register fractpel Cy = lasty + bp->C.y;
 
                       if (Bx < min.x) min.x = Bx;
                       else if (Bx > max.x) max.x = Bx;
                       if (By < min.y) min.y = By;
                       else if (By > max.y) max.y = By;
 
                       if (Cx < min.x) min.x = Cx;
                       else if (Cx > max.x) max.x = Cx;
                       if (Cy < min.y) min.y = Cy;
                       else if (Cy > max.y) max.y = Cy;
                   }
                       break;
 
                   case HINTTYPE:
                       break;
                   default:
                       t1_abort("QueryBounds: unknown type");
               }
 
               if (x < min.x) min.x = x;
               else if (x > max.x) max.x = x;
               if (y < min.y) min.y = y;
               else if (y > max.y) max.y = y;
 
               lastx = x;   lasty = y;
       }
done:
       UnConvert(S, &min, &x1, &y1);
       UnConvert(S, &max, &x4, &y4);
       x = min.x;  min.x = max.x; max.x = x;
       UnConvert(S, &min, &x2, &y2);
       UnConvert(S, &max, &x3, &y3);
 
       *xminP = *xmaxP = x1;
       if (x2 < *xminP)  *xminP = x2;
       else if (x2 > *xmaxP)  *xmaxP = x2;
       if (x3 < *xminP)  *xminP = x3;
       else if (x3 > *xmaxP)  *xmaxP = x3;
       if (x4 < *xminP)  *xminP = x4;
       else if (x4 > *xmaxP)  *xmaxP = x4;
 
       *yminP = *ymaxP = y1;
       if (y2 < *yminP)  *yminP = y2;
       else if (y2 > *ymaxP)  *ymaxP = y2;
       if (y3 < *yminP)  *yminP = y3;
       else if (y3 > *ymaxP)  *ymaxP = y3;
       if (y4 < *yminP)  *yminP = y4;
       else if (y4 > *ymaxP)  *ymaxP = y4;
 
       if (coerced)
               Destroy(p0);
}

Here is the call graph for this function:

void QueryLoc ( struct segment P,
struct XYspace S,
DOUBLE xP,
DOUBLE yP 
)

Definition at line 1097 of file paths.c.

{
       IfTrace4((MustTraceCalls),"QueryLoc(P=%z, S=%z, (%x, %x))\n",
                                            P, S, xP, yP);
       if (!ISLOCATION(P)) {
               ArgErr("QueryLoc: first arg not a location", P, NULL);
               return;
       }
       if (S->type != SPACETYPE) {
               ArgErr("QueryLoc: second arg not a space", S, NULL);
               return;
       }
       UnConvert(S, &P->dest, xP, yP);
}
void QueryPath ( struct segment path,
int typeP,
struct segment **  Bp,
struct segment **  Cp,
struct segment **  Dp,
DOUBLE fP 
)

Definition at line 1125 of file paths.c.

{
       register int coerced = FALSE;  /* did I coerce a text path?           */
 
       IfTrace3((MustTraceCalls), "QueryPath(%z, %x, %x, ...)\n",
                                             path, typeP, Bp);
       if (path == NULL) {
               *typeP = -1;
               return;
       }
       if (!ISPATHANCHOR(path)) {
               ArgErr("QueryPath: arg not a valid path", path, NULL);
       }
       if (path->type == TEXTTYPE) {
               path = CoerceText(path);
               coerced = TRUE;
       }
 
       switch (path->type) {
 
           case MOVETYPE:
               *typeP = 0;
               *Bp = PathSegment(MOVETYPE, path->dest.x, path->dest.y);
               break;
 
           case LINETYPE:
               *typeP = (LASTCLOSED(path->flag)) ? 4 : 1;
               *Bp = PathSegment(MOVETYPE, path->dest.x, path->dest.y);
               break;
 
           case CONICTYPE:
           {
               register struct conicsegment *cp = (struct conicsegment *) path;
 
               *typeP = 2;
               *Bp = PathSegment(MOVETYPE, cp->M.x, cp->M.y);
               *Cp = PathSegment(MOVETYPE, cp->dest.x, cp->dest.y);
               *fP = cp->roundness;
           }
               break;
 
           case BEZIERTYPE:
           {
               register struct beziersegment *bp = (struct beziersegment *) path;
 
               *typeP = 3;
               *Bp = PathSegment(MOVETYPE, bp->B.x, bp->B.y);
               *Cp = PathSegment(MOVETYPE, bp->C.x, bp->C.y);
               *Dp = PathSegment(MOVETYPE, bp->dest.x, bp->dest.y);
           }
               break;
 
           case HINTTYPE:
               *typeP = 5;
               break;
 
           default:
               t1_abort("QueryPath: unknown segment");
       }
       if (coerced)
               KillPath(path);
}

Here is the call graph for this function:

struct segment* Reverse ( struct segment p) [read]

Definition at line 710 of file paths.c.

{
       register struct segment *r;    /* output path built here              */
       register struct segment *nextp;  /* contains next sub-path            */
 
       IfTrace1((MustTraceCalls),"Reverse(%z)\n", p);
 
       if (p == NULL)
               return(NULL);
 
       ARGCHECK(!ISPATHANCHOR(p), "Reverse: invalid path", p, NULL, (0), struct segment *);
 
       if (p->type == TEXTTYPE)
               p = CoerceText(p);
       p = UniquePath(p);
 
       r = NULL;
 
       do {
               nextp = DropSubPath(p);
               p = ReverseSubPath(p);
               r = Join(p, r);
               p = nextp;
 
       } while (p != NULL);
 
       return(r);
}

Here is the call graph for this function:

static struct segment* ReverseSubPath ( ) [static, read]
static struct segment* ReverseSubPath ( struct segment p) [static, read]

Definition at line 744 of file paths.c.

{
       register struct segment *r;  /* reversed path will be created here    */
       register struct segment *nextp;  /* temporary variable used in loop   */
       register int wasclosed;  /* flag, path was closed                     */
 
       if (p == NULL)
               return(NULL);
 
       wasclosed = ISCLOSED(p->flag);
       r = NULL;
 
       do {
/*
First we reverse the direction of this segment and clean up its flags:
*/
               p->dest.x = - p->dest.x;  p->dest.y = - p->dest.y;
               p->flag &= ~(ISCLOSED(ON) | LASTCLOSED(ON));
 
               switch (p->type) {
 
                   case LINETYPE:
                   case MOVETYPE:
                       break;
 
                   case CONICTYPE:
                   {
/*
The logic of this is that the new M point (stored relative to the new
beginning) is (M - C).  However, C ("dest") has already been reversed
So, we add "dest" instead of subtracting it:
*/
                       register struct conicsegment *cp = (struct conicsegment *) p;
 
                       cp->M.x += cp->dest.x;  cp->M.y += cp->dest.y;
                   }
                       break;
 
                   case BEZIERTYPE:
                   {
                       register struct beziersegment *bp = (struct beziersegment *) p;
 
                       bp->B.x += bp->dest.x;  bp->B.y += bp->dest.y;
                       bp->C.x += bp->dest.x;  bp->C.y += bp->dest.y;
                   }
                       break;
 
                   case HINTTYPE:
                   {
                       register struct hintsegment *hp = (struct hintsegment *) p;
 
                       hp->ref.x = -hp->ref.x;  hp->ref.y = -hp->ref.y;
                   }
                       break;
 
                   default:
                       t1_abort("Reverse: bad path segment");
               }
/*
We need to reverse the order of segments too, so we break this segment
off of the input path, and tack it on the front of the growing path
in 'r':
*/
               nextp = p->link;
               p->link = NULL;
               p->last = p;
               if (r != NULL)
                       CONCAT(p,r);  /* leaves result in 'p'... not what we want */
               r = p;
               p = nextp;    /* advance to next segment in input path        */
 
       } while (p != NULL);
 
       if (wasclosed)
               r = ClosePath(r);
 
       return(r);
}

Here is the call graph for this function:

struct segment* ReverseSubPaths ( struct segment p) [read]

Definition at line 871 of file paths.c.

{
       register struct segment *r;  /* reversed path will be created here    */
       register struct segment *nextp;  /* temporary variable used in loop   */
       int wasclosed;        /* flag; subpath was closed                     */
       register struct segment *nomove;  /* the part of sub-path without move segment */
       struct fractpoint delta;
 
       IfTrace1((MustTraceCalls),"ReverseSubPaths(%z)\n", p);
 
       if (p == NULL)
               return(NULL);
 
       ARGCHECK(!ISPATHANCHOR(p), "ReverseSubPaths: invalid path", p, NULL, (0), struct segment *);
 
       if (p->type == TEXTTYPE)
               p = CoerceText(p);
       if (p->type != MOVETYPE)
               p = JoinSegment(NULL, MOVETYPE, 0, 0, p);
 
       p = UniquePath(p);
 
       r = NULL;
 
       for (; p != NULL;) {
               nextp = DropSubPath(p);
               wasclosed = ISCLOSED(p->flag);
               if (wasclosed)
                       UnClose(p);
 
               nomove = SplitPath(p, p);
               r = Join(r, p);
 
               PathDelta(nomove, &delta);
 
               nomove = ReverseSubPath(nomove);
               p->dest.x += delta.x;
               p->dest.y += delta.y;
               if (nextp != NULL) {
                       nextp->dest.x += delta.x;
                       nextp->dest.y += delta.y;
               }
               if (wasclosed) {
                       nomove = ClosePath(nomove);
                       nextp->dest.x -= delta.x;
                       nextp->dest.y -= delta.y;
               }
               r = Join(r, nomove);
               p = nextp;
 
       }
 
       return(r);
}

Here is the call graph for this function:

static struct segment* SplitPath ( ) [static, read]
static struct segment* SplitPath ( struct segment anchor,
struct segment before 
) [static, read]

Definition at line 845 of file paths.c.

{
       register struct segment *r;
 
       if (before == anchor->last)
               return(NULL);
 
       r = before->link;
       r->last = anchor->last;
       anchor->last = before;
       before->link = NULL;
 
       return(r);
}

Here is the call graph for this function:

struct segment* SubLoc ( struct segment p1,
struct segment p2 
) [read]

Definition at line 261 of file paths.c.

{
       IfTrace2((MustTraceCalls),"SubLoc(%z, %z)\n", p1, p2);
 
       ARGCHECK(!ISLOCATION(p1), "SubLoc: bad first arg", p1, NULL, (0), struct segment *);
       ARGCHECK(!ISLOCATION(p2), "SubLoc: bad second arg", p2, NULL, (0), struct segment *);
       p1 = UniquePath(p1);
       p1->dest.x -= p2->dest.x;
       p1->dest.y -= p2->dest.y;
       ConsumePath(p2);
       return(p1);
}
struct segment* t1_ClosePath ( struct segment p0,
int  lastonly 
) [read]

Definition at line 607 of file paths.c.

{
       register struct segment *p,*last,*start;  /* used in looping through path */
       register fractpel x,y;  /* current position in path                   */
       register fractpel firstx,firsty;  /* start position of sub path       */
       register struct segment *lastnonhint;  /* last non-hint segment in path */
 
       IfTrace1((MustTraceCalls),"ClosePath(%z)\n", p0);
       if (p0 != NULL && p0->type == TEXTTYPE)
               return(UniquePath(p0));
       if (p0->type == STROKEPATHTYPE)
               return((struct segment *)Unique(p0));
       /*
       * NOTE: a null closed path is different from a null open path
       * and is denoted by a closed (0,0) move segment.  We make
       * sure this path begins and ends with a MOVETYPE:
       */
       if (p0 == NULL || p0->type != MOVETYPE)
               p0 = JoinSegment(NULL, MOVETYPE, 0, 0, p0);
       TYPECHECK("ClosePath", p0, MOVETYPE, NULL, (0), struct segment *);
       if (p0->last->type != MOVETYPE)
               p0 = JoinSegment(p0, MOVETYPE, 0, 0, NULL);
 
       p0 = UniquePath(p0);
 
/*
We now begin a loop through the path,
incrementing current 'x' and 'y'.  We are searching
for MOVETYPE segments (breaks in the path) that are not already closed.
At each break, we insert a close segment.
*/
       for (p = p0, x = y = 0, start = NULL;
            p != NULL;
            x += p->dest.x, y += p->dest.y, last = p, p = p->link)
       {
 
               if (p->type == MOVETYPE) {
                       if (start != NULL && (lastonly?p->link==NULL:TRUE) &&
                             !(ISCLOSED(start->flag) && LASTCLOSED(last->flag))) {
                               register struct segment *r;  /* newly created */
 
                               start->flag |= ISCLOSED(ON);
                               r = PathSegment(LINETYPE, firstx - x,
                                                         firsty - y);
                               INSERT(last, r, p);
                               r->flag |= LASTCLOSED(ON);
                               /*< adjust 'last' if possible for a 0,0 close >*/
{
 
#define   CLOSEFUDGE    3    /* if we are this close, let's change last segment */
 
       if (r->dest.x != 0 || r->dest.y != 0) {
               if (r->dest.x <= CLOSEFUDGE && r->dest.x >= -CLOSEFUDGE
                    && r->dest.y <= CLOSEFUDGE && r->dest.y >= -CLOSEFUDGE) {
                       IfTrace2((PathDebug),
                               "ClosePath forced closed by (%p,%p)\n",
                                      r->dest.x, r->dest.y);
                       lastnonhint->dest.x += r->dest.x;
                       lastnonhint->dest.y += r->dest.y;
                       r->dest.x = r->dest.y = 0;
               }
       }
}
                               if (p->link != NULL) {
                                       p->dest.x += x - firstx;
                                       p->dest.y += y - firsty;
                                       x = firstx;
                                       y = firsty;
                               }
                       }
                       start = p;
                       firstx = x + p->dest.x;
                       firsty = y + p->dest.y;
               }
               else if (p->type != HINTTYPE)
                       lastnonhint = p;
       }
       return(p0);
}
struct segment* t1_JoinSegment ( struct segment before,
int  type,
fractpel  x,
fractpel  y,
struct segment after 
) [read]

Definition at line 581 of file paths.c.

{
       register struct segment *r;  /* returned path built here              */
 
       r = PathSegment(type, x, y);
       if (before != NULL) {
               CONCAT(before, r);
               r = before;
       }
       else
               r->context = after->context;
       if (after != NULL)
               CONCAT(r, after);
       return(r);
}

Here is the call graph for this function:

struct segment* t1_Loc ( struct XYspace S,
DOUBLE  x,
DOUBLE  y 
) [read]

Definition at line 211 of file paths.c.

{
       register struct segment *r;
 
 
       IfTrace3((MustTraceCalls),"..Loc(S=%z, x=%f, y=%f)\n", S, &x, &y);
 
       r = (struct segment *)Allocate(sizeof(struct segment), &movetemplate, 0);
       TYPECHECK("Loc", S, SPACETYPE, r, (0), struct segment *);
 
       r->last = r;
       r->context = S->context;
       (*S->convert)(&r->dest, S, x, y);
       ConsumeSpace(S);
       return(r);
}
struct segment* t1_PathSegment ( int  type,
fractpel  x,
fractpel  y 
) [read]

Definition at line 288 of file paths.c.

{
       register struct segment *r;  /* newly created segment                 */
 
       r = (struct segment *)Allocate(sizeof(struct segment), &movetemplate, 0);
       r->type = type;
       r->last = r;          /* last points to itself for singleton          */
       r->dest.x = x;
       r->dest.y = y;
       return(r);
}
static Unclose ( ) [static]
static UnClose ( struct segment p0) [static]

Definition at line 927 of file paths.c.

{
       register struct segment *p;
 
       for (p=p0; p->link->link != NULL; p=p->link) { ; }
 
       if (!LASTCLOSED(p->link->flag))
               t1_abort("UnClose:  no LASTCLOSED");
 
       Free(SplitPath(p0, p));
       p0->flag &= ~ISCLOSED(ON);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

struct segment [static]
Initial value:
 { MOVETYPE, 0, 1, sizeof(struct segment), 0,
                NULL, NULL, 0, 0 }

Definition at line 204 of file paths.c.