📄 paths.c
字号:
} 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: abort("QueryPath: unknown segment", 26); } if (coerced) KillPath(path);}/*:h3.QueryBounds() - Return the Bounding Box of a Path Returns the bounding box by setting the user's variables.*/ void QueryBounds(p0, S, xminP, yminP, xmaxP, ymaxP) register struct segment *p0; /* object to check for bound */ struct XYspace *S; /* coordinate space of returned values */ DOUBLE *xminP,*yminP; /* lower left hand corner (set by routine) */ DOUBLE *xmaxP,*ymaxP; /* upper right hand corner (set by routine) */{ 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(%p, %p,", p0, S); IfTrace4((MustTraceCalls), " %p, %p, %p, %p)\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: abort("QueryBounds: unknown type", 27); } 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);}/*:h3.BoxPath()*/struct segment *BoxPath(S, h, w) struct XYspace *S; int h,w;{ 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));} /*:h3.DropSegment() - Drop the First Segment in a Path This routine takes the path and returns a new path that is one segmentshorter. It can be used in conjunction with QueryPath(), for example,to ask about an entire path.*/ struct segment *DropSegment(path) register struct segment *path;{ IfTrace1((MustTraceCalls),"DropSegment(%p)\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);}/*:h3.HeadSegment() - Return the First Segment in a Path This routine takes the path and returns a new path consists of thefirst segment only.*/ struct segment *HeadSegment(path) register struct segment *path; /* input path */{ IfTrace1((MustTraceCalls),"HeadSegment(%p)\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);} /*:h2.Path Debug Routines :h3.DumpPath() - Display a Path on the Trace File removed by RMz, 1999-06-07 *//*void DumpPath(p) register struct segment *p;{ register fractpel x,y; register fractpel lastx,lasty; DOUBLE roundness; IfTrace1(TRUE,"Dumping path, anchor=%p:\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," (%d,%d), delta=(%d,%d)", x + lastx, y + lasty, x, y); break; case MOVETYPE: IfTrace1(TRUE,"MOVE<%x> to", (LONG) p->flag); IfTrace4(TRUE,"(%d,%d), delta=(%d,%d)", x + lastx, y + lasty, x, y); break; case CONICTYPE: { register struct conicsegment *cp = (struct conicsegment *) p; roundness = cp->roundness; IfTrace2(TRUE, ". conic to (%d,%d),", x + lastx, y + lasty); IfTrace3(TRUE," M=(%d,%d), r=%p", cp->M.x + lastx, cp->M.y + lasty, &roundness); } break; case BEZIERTYPE: { register struct beziersegment *bp = (struct beziersegment *) p; IfTrace4(TRUE,". bezier to (%d,%d), B=(%d,%d)", x + lastx, y + lasty, bp->B.x + lastx, bp->B.y + lasty); IfTrace2(TRUE, ", C=(%d,%d)", bp->C.x + lastx, bp->C.y + lasty); } break; case HINTTYPE: { register struct hintsegment *hp = (struct hintsegment *) p; IfTrace4(TRUE,". hint ref=(%d,%d), width=(%d,%d)", 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, ", %d", (LONG) hp->label); } break; case TEXTTYPE: DumpText(p); break; default: IfTrace0(TRUE, "bad path segment?"); } IfTrace1(TRUE," at %p\n", p); lastx += x; lasty += y; }} */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -