📄 regions.c
字号:
R->thresholded->origin.y -= dy; }/*From now on we will deal with dx and dy as integer pel values:*/ dx = NEARESTPEL(dx); dy = NEARESTPEL(dy); if (dx == 0 && dy == 0) return; R->xmin += dx; R->xmax += dx; R->ymin += dy; R->ymax += dy; for (edge = R->anchor; VALIDEDGE(edge); edge = edge->link) { edge->ymin += dy; edge->ymax += dy; if (dx != 0) { register int h; /* loop index; height of edge */ register pel *Xp; /* loop pointer to X values */ edge->xmin += dx; edge->xmax += dx; for (Xp = edge->xvalues, h = edge->ymax - edge->ymin; --h >= 0; ) *Xp++ += dx; } }} /*:h3.UnJumble() - Sort a Region Top to Bottom It is an open question whether it pays in general to do this.*/ void UnJumble(region) struct region *region; /* region to sort */{ register struct edgelist *anchor; /* new lists built here */ register struct edgelist *edge; /* edge pointer for loop */ register struct edgelist *next; /* ditto */ anchor = NULL; for (edge=region->anchor; VALIDEDGE(edge); edge=next) { if (edge->link == NULL) abort("UnJumble: unpaired edge?", 39); next = edge->link->link; edge->link->link = NULL; anchor = SortSwath(anchor, edge, t1_SwathUnion); } if (edge != NULL) vertjoin(anchor, edge); region->anchor = anchor; region->flag &= ~ISJUMBLED(ON);} /**/#undef NEED_OPTIMZEREGION#ifdef NEED_OPTIMZEREGIONstatic int OptimizeRegion(R) struct region *R; /* region to optimize */{ register pel *xP; /* pel pointer for inner loop */ register int x; /* holds X value */ register int xmin,xmax; /* holds X range */ register int h; /* loop counter */ register struct edgelist *e; /* edgelist pointer for loop */ R->flag |= ISRECTANGULAR(ON); for (e = R->anchor; VALIDEDGE(e); e=e->link) { xmin = MAXPEL; xmax = MINPEL; for (h = e->ymax - e->ymin, xP = e->xvalues; --h >= 0;) { x = *xP++; if (x < xmin) xmin = x; if (x > xmax) xmax = x; } if (xmin != xmax || (xmin != R->xmin && xmax != R->xmax)) R->flag &= ~ISRECTANGULAR(ON); if (xmin < e->xmin || xmax > e->xmax) abort("Tighten: existing edge bound was bad", 40); if (xmin < R->xmin || xmax > R->xmax) abort("Tighten: existing region bound was bad", 41); e->xmin = xmin; e->xmax = xmax; } R->flag |= ISOPTIMIZED(ON); return(0); }#endif /* This function is not used */ /*:h2.Miscelaneous Routines :h3.MoreWorkArea() - Allocate New Space for "edge" Our strategy is to temporarily allocate an array to hold thisunexpectedly large edge. ChangeDirection frees this array any timeit gets a shorter 'dy'.*/ /*ARGSUSED*/void MoreWorkArea(R, x1, y1, x2, y2) struct region *R; /* region we are generating */ fractpel x1,y1; /* starting point of line */ fractpel x2,y2; /* ending point of line */{ register int idy; /* integer dy of line */ idy = NEARESTPEL(y1) - NEARESTPEL(y2); if (idy < 0) idy = - idy; /* * we must add one to the delta for the number of run ends we * need to store: */ if (++idy > currentsize) { IfTrace1((RegionDebug > 0),"Allocating edge of %d pels\n", idy); if (currentworkarea != workedge) NonObjectFree(currentworkarea); currentworkarea = (pel *)Allocate(0, NULL, idy * sizeof(pel)); currentsize = idy; } ChangeDirection(CD_CONTINUE, R, x1, y1, y2 - y1);} /*:h3.BoxClip() - Clip a Region to a Rectangle BoxClip also duplicates the region if it is permanent. Note theclipping box is specified in REGION coordinates, that is, incoordinates relative to the region (0,0) point*/ struct region *BoxClip(R, xmin, ymin, xmax, ymax) register struct region *R; /* region to clip */ register pel xmin,ymin; /* upper left hand corner of rectangle */ register pel xmax,ymax; /* lower right hand corner */{ struct edgelist anchor; /* pretend edgelist to facilitate discards */ register struct edgelist *e,*laste; IfTrace1((OffPageDebug),"BoxClip of %p:\n", R); R = UniqueRegion(R); if (xmin > R->xmin) { IfTrace2((OffPageDebug),"BoxClip: left clip old %d new %d\n", (LONG) R->xmin, (LONG) xmin); R->xmin = xmin; } if (xmax < R->xmax) { IfTrace2((OffPageDebug),"BoxClip: right clip old %d new %d\n", (LONG) R->xmax, (LONG) xmax); R->xmax = xmax; } if (ymin > R->ymin) { IfTrace2((OffPageDebug),"BoxClip: top clip old %d new %d\n", (LONG) R->ymin, (LONG) ymin); R->ymin = ymin; } if (ymax < R->ymax) { IfTrace2((OffPageDebug),"BoxClip: bottom clip old %d new %d\n", (LONG) R->ymax, (LONG) ymax); R->ymax = ymax; } laste = &anchor; anchor.link = R->anchor; for (e = R->anchor; VALIDEDGE(e); e = e->link) { if (TOP(e) < ymin) { e->xvalues += ymin - e->ymin; e->ymin = ymin; } if (BOTTOM(e) > ymax) e->ymax = ymax; if (TOP(e) >= BOTTOM(e)) { discard(laste, e->link->link); e = laste; continue; } if (e->xmin < xmin) { cedgemax(BOTTOM(e) - TOP(e), e->xvalues, xmin); e->xmin = xmin; e->xmax = TYPE1_MAX(e->xmax, xmin); } if (e->xmax > xmax) { cedgemin(BOTTOM(e) - TOP(e), e->xvalues, xmax); e->xmin = TYPE1_MIN(e->xmin, xmax); e->xmax = xmax; } laste = e; } R->anchor = anchor.link; return(R);} #ifdef notdef/*:h3.CoerceRegion() - Force a TextPath Structure to Become a Region We also save the newly created region in the textpath structure, if thestructure was permanent. Then we don't have to do this again. Why notsave it all the time? Well, we certainly could, but I suspect itwouldn't pay. We would have to make this region permanent (because wecouldn't have it be consumed) and this would probably requireunnecessary CopyRegions in most cases.*/ struct region *CoerceRegion(tp) register struct textpath *tp; /* input TEXTTYPE */{ struct segment *path; /* temporary character path */ struct region *R; /* returned region */ R = Interior(path, EVENODDRULE); return(R);}#endif /*:h3.RegionBounds() - Returns Bounding Box of a Region*/ struct segment *RegionBounds(R) register struct region *R;{ register struct segment *path; /* returned path */ path = BoxPath(IDENTITY, R->ymax - R->ymin, R->xmax - R->xmin); path = Join(PathSegment(MOVETYPE, R->origin.x + TOFRACTPEL(R->xmin), R->origin.y + TOFRACTPEL(R->ymin) ), path); return(path);} /*:h2.Formatting/Dump Routines for Debug :h3.DumpArea() - Display a Region*/void DumpArea(area) register struct region *area;{ IfTrace1(TRUE,"Dumping area %p,", area); IfTrace4(TRUE," X %d:%d Y %d:%d;", (LONG) area->xmin, (LONG) area->xmax, (LONG) area->ymin,(LONG) area->ymax); IfTrace4(TRUE," origin=(%d,%d), ending=(%d,%d)\n", area->origin.x, area->origin.y, area->ending.x, area->ending.y); DumpEdges(area->anchor);} #define INSWATH(p, y0, y1) (p != NULL && p->ymin == y0 && p->ymax == y1)/*:h3.DumpEdges() - Display Run End Lists (Edge Lists)*/ static pel RegionDebugYMin = MINPEL;static pel RegionDebugYMax = MAXPEL; void DumpEdges(edges) register struct edgelist *edges;{ register struct edgelist *p,*p2; register pel ymin = MINPEL; register pel ymax = MINPEL; register int y; if (edges == NULL) { IfTrace0(TRUE," NULL area.\n"); return; } if (RegionDebug <= 1) { for (p=edges; p != NULL; p = p->link) { edgecheck(p, ymin, ymax); ymin = p->ymin; ymax = p->ymax; IfTrace3(TRUE,". at %p type=%d flag=%x", p, (LONG) p->type,(LONG) p->flag); IfTrace4(TRUE," bounding box HxW is %dx%d at (%d,%d)\n", (LONG) ymax - ymin, (LONG) p->xmax - p->xmin, (LONG) p->xmin, (LONG) ymin); } } else { for (p2=edges; p2 != NULL; ) { edgecheck(p2, ymin, ymax); ymin = p2->ymin; ymax = p2->ymax; if (RegionDebug > 3 || (ymax > RegionDebugYMin && ymin < RegionDebugYMax)) { IfTrace2 (TRUE,". Swath from %d to %d:\n", ymin, ymax); for (p=p2; INSWATH(p,ymin,ymax); p = p->link) { IfTrace4(TRUE,". . at %p[%x] range %d:%d, ", p, (LONG) p->flag, (LONG) p->xmin, (LONG)p->xmax); IfTrace1(TRUE, "subpath=%p,\n", p->subpath); } } for (y=TYPE1_MAX(ymin,RegionDebugYMin); y < TYPE1_MIN(ymax, RegionDebugYMax); y++) { IfTrace1(TRUE,". . . Y[%5d] ", (LONG) y); for (p=p2; INSWATH(p,ymin,ymax); p = p->link) IfTrace1(TRUE,"%5d ", (LONG) p->xvalues[y - ymin]); IfTrace0(TRUE,"\n"); } while (INSWATH(p2, ymin, ymax)) p2 = p2->link; } }} /*:h3.edgecheck() - For Debug, Verify that an Edge Obeys the Rules*/ /*ARGSUSED*/static int edgecheck(edge, oldmin, oldmax) struct edgelist *edge; int oldmin,oldmax;{ if (edge->type != EDGETYPE) abort("EDGE ERROR: non EDGETYPE in list", 42);/*The following check is not valid if the region is jumbled so I took itout:*//* if (edge->ymin < oldmax && edge->ymin != oldmin) abort("EDGE ERROR: overlapping swaths", 43); */ return(0); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -