struct xobject *t1_Xform( register struct xobject *obj, /* object to transform */ register DOUBLE M[2][2]) /* transformation matrix */ { if (obj == NULL) return(NULL); if (obj->type == FONTTYPE) { register struct font *F = (struct font *) obj; F = UniqueFont(F); return((struct xobject*)F); } if (obj->type == PICTURETYPE) { /* In the case of a picture, we choose both to update the picture's transformation matrix and keep the handles up to date. */ register struct picture *P = (struct picture *) obj; register struct segment *handles; /* temporary path to transform handles */ P = UniquePicture(P); handles = PathSegment(LINETYPE, P->origin.x, P->origin.y); handles = Join(handles, PathSegment(LINETYPE, P->ending.x, P->ending.y) ); handles = (struct segment *)Xform((struct xobject *) handles, M); P->origin = handles->dest; P->ending = handles->link->dest; KillPath(handles); return((struct xobject *)P); } if (ISPATHTYPE(obj->type)) { struct XYspace pseudo; /* local temporary space */ PseudoSpace(&pseudo, M); return((struct xobject *) PathTransform((struct segment *)obj, &pseudo)); } if (obj->type == SPACETYPE) { register struct XYspace *S = (struct XYspace *) obj; /* replaced ISPERMANENT(S->flag) with S->references > 1 3-26-91 PNM */ if (S->references > 1) S = CopySpace(S); else S->ID = NEXTID; MatrixMultiply(S->tofract.normal, M, S->tofract.normal); /* * mark inverted matrix invalid: */ S->flag &= ~HASINVERSE(ON); FillOutFcns(S); return((struct xobject *) S); } return(ArgErr("Untransformable object", obj, obj)); }
/* :h3.StepBezierRecurse() - The Recursive Logic in StepBezier() The recursion involves dividing the control polygon into two smaller control polygons by finding the midpoints of the lines. This idea is described in any graphics text book and its simplicity is what caused Bezier to define his curves as he did. If the input region 'R' is NULL, the result is a path that is the 'flattened' curve; otherwise StepBezier returns nothing special. */ static struct segment * StepBezierRecurse(struct bezierinfo *I, /* Region under construction or NULL */ fractpel xA, fractpel yA, /* A control point */ fractpel xB, fractpel yB, /* B control point */ fractpel xC, fractpel yC, /* C control point */ fractpel xD, fractpel yD) /* D control point */ { if (BezierTerminationTest(xA,yA,xB,yB,xC,yC,xD,yD)) { if (I->region == NULL) return(PathSegment(LINETYPE, xD - xA, yD - yA)); else StepLine(I->region, I->origin.x + xA, I->origin.y + yA, I->origin.x + xD, I->origin.y + yD); } else { fractpel xAB,yAB; fractpel xBC,yBC; fractpel xCD,yCD; fractpel xABC,yABC; fractpel xBCD,yBCD; fractpel xABCD,yABCD; xAB = xA + xB; yAB = yA + yB; xBC = xB + xC; yBC = yB + yC; xCD = xC + xD; yCD = yC + yD; xABC = xAB + xBC; yABC = yAB + yBC; xBCD = xBC + xCD; yBCD = yBC + yCD; xABCD = xABC + xBCD; yABCD = yABC + yBCD; xAB >>= 1; yAB >>= 1; xBC >>= 1; yBC >>= 1; xCD >>= 1; yCD >>= 1; xABC >>= 2; yABC >>= 2; xBCD >>= 2; yBCD >>= 2; xABCD >>= 3; yABCD >>= 3; if (I->region == NULL) { return( Join( StepBezierRecurse(I, xA, yA, xAB, yAB, xABC, yABC, xABCD, yABCD), StepBezierRecurse(I, xABCD, yABCD, xBCD, yBCD, xCD, yCD, xD, yD) ) ); } else { StepBezierRecurse(I, xA, yA, xAB, yAB, xABC, yABC, xABCD, yABCD); StepBezierRecurse(I, xABCD, yABCD, xBCD, yBCD, xCD, yCD, xD, yD); } } return NULL; /*NOTREACHED*/ }
struct segment * t1_Phantom(struct segment *p) /* object to take the Phantom of */ { struct fractpoint pt; /* handle size will built here */ if (p == NULL) pt.x = pt.y = 0; else PathDelta(p, &pt); return(PathSegment(MOVETYPE, pt.x, pt.y)); }
inline void PathSegment(const std::string& path, std::vector<std::string>& dir) { size_t it; std::string currentpath = path; if ((it = currentpath.find_last_of(ALLSEP)) != std::string::npos && it != 0) { PathSegment(currentpath.substr(0, it), dir); if (it + 1 != currentpath.size()) dir.push_back(currentpath.substr(it + 1, currentpath.size())); } else { if (currentpath.find(OTHERSEP) != std::string::npos) currentpath.replace(currentpath.find(OTHERSEP), 1, SLASHSEP); dir.push_back(currentpath); } }
inline std::string BuildPath(const std::string& path) { std::vector<std::string> dir; PathSegment(path, dir); std::string pathtest; for (auto directory : dir) { pathtest += directory; if (TypeOfFile(pathtest) == FileType::REGULAR) return ""; if (TypeOfFile(pathtest) == FileType::INVALID) { if (Mkdir(pathtest) == false) return ""; } pathtest += SLASHSEP; } return pathtest; }