⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 regions.c

📁 source code: Covert TXT to PDF
💻 C
📖 第 1 页 / 共 5 页
字号:
a call back to the REGIONS module.:li.ChangeDirection will call whatever function is in the regionstructure; for Interior, this function is 'newfilledge'.:li.Newfilledge will call NewEdge to create a new edgelist structure,then, call SortSwath to sort it onto the linked list being built atthe region "anchor".:eol. By making the function called by ChangeDirection be a parameter of theregion, we allow the same ChangeDirection logic to be used by stroking.*/ /*SHARED LINE(S) ORIGINATED HERE*/ struct region *Interior(p, fillrule)       register struct segment *p;    /* take interior of this path          */       register int fillrule;         /* rule to follow if path crosses itself */{       register fractpel x,y;  /* keeps ending point of path segment         */       fractpel lastx,lasty; /* previous x,y from path segment before        */       register struct region *R;  /* region I will build                    */       register struct segment *nextP; /* next segment of path */       struct fractpoint hint; /* accumulated hint value */       char tempflag;        /* flag; is path temporary?                     */       char Cflag;           /* flag; should we apply continuity?            */        IfTrace2((MustTraceCalls),".  INTERIOR(%p, %d)\n", p, (LONG) fillrule);        if (p == NULL)               return(NULL);/*Establish the 'Cflag' continuity flag based on user's fill rule andour own 'Continuity' pragmatic (0: never do continuity, 1: do whatuser asked, >1: do it regardless).*/       if (fillrule > 0) {               Cflag = Continuity > 0;               fillrule -= CONTINUITY;       }       else               Cflag = Continuity > 1;        ARGCHECK((fillrule != WINDINGRULE && fillrule != EVENODDRULE),                       "Interior: bad fill rule", NULL, NULL, (1,p), struct region *);        if (p->type == TEXTTYPE)/*             if (fillrule != EVENODDRULE)               else */                       return((struct region *)UniquePath(p));       if (p->type == STROKEPATHTYPE){	 if (fillrule == WINDINGRULE)	   return((struct region *)DoStroke(p));	 else	   p = CoercePath(p);       }               R = (struct region *)Allocate(sizeof(struct region), &EmptyRegion, 0);        ARGCHECK(!ISPATHANCHOR(p), "Interior:  bad path", p, R, (0), struct region *);       ARGCHECK((p->type != MOVETYPE), "Interior:  path not closed", p, R, (0), struct region *);  /* changed definition from !ISPERMANENT to references <= 1 3-26-91 PNM */       tempflag =  (p->references <= 1); /* only first segment in path is so marked */       if (!ISPERMANENT(p->flag)) p->references -= 1;        R->newedgefcn = newfilledge;/*Believe it or not, "R" is now completely initialized.  We are countingon the copy of template to get other fields the way we want them,namely:ol.:li.anchor = NULL:li.xmin, ymin, xmax, ymax, to minimum and maximum values respectively.:eol.Anchor = NULL is veryimportant to ChangeDirection.See :hdref refid=CD.. To minimize problems of "wrapping" in our pel arithmetic, we keep anorigin of the region which is the first move.  Hopefully, that keepsnumbers within plus or minus 32K pels.*/       R->origin.x = 0/*TOFRACTPEL(NEARESTPEL(p->dest.x))*/;       R->origin.y = 0/*TOFRACTPEL(NEARESTPEL(p->dest.y))*/;       lastx = - R->origin.x;       lasty = - R->origin.y;/*ChangeDirection initializes other important fields in R, such aslastdy, edge, edgeYstop, edgexmin, and edgexmax.  The first segmentis a MOVETYPE, so it will be called first.*//*The hints data structure must be initialized once for each path.*/        if (ProcessHints)               InitHints(); /* initialize hint data structure */        while (p != NULL)  {                x = lastx + p->dest.x;               y = lasty + p->dest.y;                IfTrace2((HintDebug > 0),"Ending point = (%d,%d)\n",			x,			y);                nextP = p->link; /*Here we start the hints processing by initializing the hint value tozero.  If ProcessHints is FALSE, the value will remain zero.Otherwise, hint accumulates the computed hint values.*/                hint.x = hint.y = 0; /*If we are processing hints, and this is a MOVE segment (other thanthe first on the path), we need to close (reverse) any open hints.*/                if (ProcessHints)                       if ((p->type == MOVETYPE) && (p->last == NULL)) {                               CloseHints(&hint);                               IfTrace2((HintDebug>0),"Closed point= (%d,%d)\n",					x+hint.x,					y+hint.y);                       } /*Next we run through all the hint segments (if any) attached to thissegment.  If ProcessHints is TRUE, we will accumulate computed hintvalues.  In either case, nextP will be advanced to the first non-HINTsegment (or NULL), and each hint segment will be freed if necessary.*/                while ((nextP != NULL) && (nextP->type == HINTTYPE))  {                       if (ProcessHints)                               ProcessHint(nextP, x + hint.x, y + hint.y, &hint);		                              {                               register struct segment *saveP = nextP;                                nextP = nextP->link;                               if (tempflag)                                       Free(saveP);                       }               } /*We now apply the full hint value to the ending point of the path segment.*/	       /*  printf("Applying hints (x=%d,y=%d)\n", hint.x, hint.y);*/                x += hint.x;               y += hint.y;                IfTrace2((HintDebug>0),"Hinted ending point = (%d,%d)\n", 			x, y);                switch(p->type) {                    case LINETYPE:                       StepLine(R, lastx, lasty, x, y);                       break;                    case CONICTYPE:                   { /*For a conic curve, we apply half the hint value to the conic midpoint.*/                    }                       break;                    case BEZIERTYPE:                   {                       register struct beziersegment *bp = (struct beziersegment *) p; /*For a Bezier curve, we apply the full hint value to the Bezier C point.*/                        StepBezier(R, lastx, lasty,                                 lastx + bp->B.x, lasty + bp->B.y,                                 lastx + bp->C.x + hint.x,                                 lasty + bp->C.y + hint.y,                                 x, y);                   }                       break;                    case MOVETYPE:/*At this point we have encountered a MOVE segment.  This breaks thepath, making it disjoint.*/                       if (p->last == NULL) /* i.e., not first in path */                               ChangeDirection(CD_LAST, R, lastx, lasty, (fractpel) 0);                        ChangeDirection(CD_FIRST, R, x, y, (fractpel) 0);/*We'll just double check for closure here.  We forgive an appendedMOVETYPE at the end of the path, if it isn't closed:*/                       if (!ISCLOSED(p->flag) && p->link != NULL)                               return((struct region *)ArgErr("Fill: sub-path not closed", p, NULL));                       break;                    default:                       abort("Interior: path type error", 30);               }/*We're done with this segment.  Advance to the next path segment inthe list, freeing this one if necessary:*/               lastx = x;  lasty = y;                if (tempflag)                       Free(p);               p = nextP;       }       ChangeDirection(CD_LAST, R, lastx, lasty, (fractpel) 0);       R->ending.x = lastx;       R->ending.y = lasty;/*Finally, clean up the region's based on the user's 'fillrule' request:*/       if (Cflag)             ApplyContinuity(R);       if (fillrule == WINDINGRULE)             Unwind(R->anchor);       return(R);}/*:h4.Unwind() - Discards Edges That Fail the Winding Rule Test The winding rule says that upward going edges should be paired withdownward going edges only, and vice versa.  So, if two upward edgesor two downward edges are nominally left/right pairs, Unwind() shoulddiscard the second one.  Everything should balance; we should discardan even number of edges; of course, we abort if we don't.*/static int Unwind(area)       register struct edgelist *area;  /* input area modified in place      */{       register struct edgelist *last=NULL,*next;  /* struct before and after current one */       register int y;       /* ymin of current swath                        */       register int count,newcount;  /* winding count registers              */        IfTrace1((RegionDebug>0),"...Unwind(%p)\n", area);        while (VALIDEDGE(area)) {                count = 0;               y = area->ymin;                do {                       next = area->link;                        if (ISDOWN(area->flag))                               newcount = count + 1;                       else                               newcount = count - 1;                        if (count == 0 || newcount == 0)                               last = area;                       else                               discard(last, next);                        count = newcount;                       area = next;                } while (area != NULL && area->ymin == y);                if (count != 0)                       abort("Unwind:  uneven edges", 31);       }       /* We retunr a value for ANSI-C-compiler */       return(0);       }/*:h3."workedge" Array This is a statically allocated array where edges are builtbefore being copied into more permanent storage by NewEdge().*/ #ifndef   MAXEDGE#define   MAXEDGE     1000#endif static pel workedge[MAXEDGE];static pel *currentworkarea = workedge;static pel currentsize = MAXEDGE; /*:h3 id=cd.ChangeDirection() - Called When Y Direction Changes The rasterizing routines call this entry point when they detecta change in Y.  We then build the current edge and sort it intoemerging edgelist at 'anchor' by calling whatever "newedgefcn"is appropriate.*/ void ChangeDirection(type, R, x, y, dy)       int type;             /* CD_FIRST, CD_CONTINUE, or CD_LAST            */       register struct region *R;  /* region in which we are changing direction */       fractpel x,y;         /* current beginning x,y                        */       fractpel dy;          /* direction and magnitude of change in y       */{       register fractpel ymin,ymax;  /* minimum and maximum Y since last call */       register fractpel x_at_ymin,x_at_ymax;  /* their respective X's       */       register pel iy;      /* nearest integer pel to 'y'                   */       register pel idy;     /* nearest integer pel to 'dy'                  */       register int ydiff;   /* allowed Y difference in 'currentworkarea'    */        IfTrace4((RegionDebug>0),"Change Y direction (%d) from (%d,%d), dy=%d\n",                                         (LONG) type, x, y, dy);        if (type != CD_FIRST) {                if (R->lastdy > 0) {                       ymin = R->firsty;                       x_at_ymin = R->firstx;                       ymax = y;                       x_at_ymax = x;               }               else {                       ymin = y;                       x_at_ymin = x;                       ymax = R->firsty;                       x_at_ymax = R->firstx;               }                if (ymax < ymin)                       abort("negative sized edge?", 32);                 (*R->newedgefcn)(R, R->edgexmin, R->edgexmax, ymin, ymax,                                   R->lastdy > 0, x_at_ymin, x_at_ymax);        }        R->firsty = y;       R->firstx = x;       R->lastdy = dy;        iy = NEARESTPEL(y);       idy = NEARESTPEL(dy);       if (currentworkarea != workedge && idy < MAXEDGE && idy > -MAXEDGE) {               NonObjectFree(currentworkarea);               currentworkarea = workedge;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -