void draw_clip_arrow( int sx, int sy, int ex, int ey, int head) { struct termentry *t = term; /* Don't draw head if the arrow itself is clipped */ if (clip_point(sx,sy)) head &= ~BACKHEAD; if (clip_point(ex,ey)) head &= ~END_HEAD; clip_line(&sx, &sy, &ex, &ey); /* Call terminal routine to draw the clipped arrow */ (*t->arrow)((unsigned int)sx, (unsigned int)sy, (unsigned int)ex, (unsigned int)ey, head); }
/* And text clipping routine. */ void clip_put_text(unsigned int x, unsigned int y, char *str) { struct termentry *t = term; if (clip_point(x, y)) return; (*t->put_text) (x, y, str); }
/* Draw a contiguous line path which may be clipped. Compared to * draw_clip_line(), this routine moves to a coordinate only when * necessary. */ void draw_clip_polygon(int points, gpiPoint *p) { int i; int x1, y1, x2, y2; int pos1, pos2, clip_ret; struct termentry *t = term; if (points <= 1) return; x1 = p[0].x; y1 = p[0].y; pos1 = clip_point(x1, y1); if (!pos1) /* move to first point if it is inside */ (*t->move)(x1, y1); for (i = 1; i < points; i++) { x2 = p[i].x; y2 = p[i].y; pos2 = clip_point(x2, y2); clip_ret = clip_line(&x1, &y1, &x2, &y2); if (clip_ret) { /* there is a line to draw */ if (pos1) /* first vertex was recalculated, move to new start point */ (*t->move)(x1, y1); (*t->vector)(x2, y2); } x1 = p[i].x; y1 = p[i].y; /* The end point and the line do not necessarily have the same * status. The end point can be 'inside', but the whole line is * 'outside'. Do not update pos1 in this case. Bug #1268. * FIXME: This is papering over an inconsistency in coordinate * calculation somewhere else! */ if (!(clip_ret == 0 && pos2 == 0)) pos1 = pos2; } }
/* HBB 20020313: New routine, broken out of draw3d_point, to be used * to output a single point without any checks for hidden3d */ static GP_INLINE void draw3d_point_unconditional(p_vertex v, struct lp_style_type *lp) { unsigned int x, y; TERMCOORD(v, x, y); term_apply_lp_properties(lp); /* HBB 20010822: implemented "linetype palette" for points, too */ if (lp->use_palette) { set_color(cb2gray( z2cb(v->real_z) )); } if (!clip_point(x, y)) (term->point) (x, y, lp->p_type); }
static void clip_primitives (GL_primitive_list *pl, GLcontext *g, GL_float plane[4]) { GLrenderstate *r = g->renderstate; GL_primitive *p = pl->head, *next; pl->head = NULL; pl->tail = NULL; for ( ; p; p = next) { int bits = 0; int cull = 1; int clip = 0; int i; next = p->next; for (i = 0; i < p->nverts; i++) { int c = (vdot(p->verts[i]->position, plane) < 0.0f); cull &= c; clip |= c; bits = (bits << 1) | c; } if (cull) __glcore_destroy_primitive(p); else if (!clip) __glcore_add_primitive(pl, p); else { switch (p->nverts) { case 1: clip_point(pl, g, plane, p, bits); break; case 2: clip_line(pl, g, plane, p, bits); break; case 3: clip_triangle(pl, g, plane, p, bits); break; } } } }
/* Clip the given line to drawing coords defined by BoundingBox. * This routine uses the cohen & sutherland bit mapping for fast clipping - * see "Principles of Interactive Computer Graphics" Newman & Sproull page 65. * Return 0: entire line segment is outside bounding box * 1: entire line segment is inside bounding box * -1: line segment has been clipped to bounding box */ int clip_line(int *x1, int *y1, int *x2, int *y2) { /* Apr 2014: This algorithm apparently assumed infinite precision * integer arithmetic. It was failing when passed coordinates that * were hugely out of bounds because tests for signedness of the * form (dx * dy > 0) would overflow rather than correctly evaluating * to (sign(dx) == sign(dy)). Worse yet, the numerical values are * used to determine which end of the segment to update. * This is now addressed by making dx and dy (double) rather than (int) * but it might be better to hard-code the sign tests. */ double dx, dy; int x, y, x_intr[4], y_intr[4], count, pos1, pos2; int x_max, x_min, y_max, y_min; pos1 = clip_point(*x1, *y1); pos2 = clip_point(*x2, *y2); if (!pos1 && !pos2) return 1; /* segment is totally in */ if (pos1 & pos2) return 0; /* segment is totally out. */ /* Here part of the segment MAY be inside. test the intersection * of this segment with the 4 boundaries for hopefully 2 intersections * in. If none are found segment is totaly out. * Under rare circumstances there may be up to 4 intersections (e.g. * when the line passes directly through at least one corner). */ count = 0; dx = *x2 - *x1; dy = *y2 - *y1; /* Find intersections with the x parallel bbox lines: */ if (dy != 0) { x = (clip_area->ybot - *y2) * dx / dy + *x2; /* Test for clip_area->ybot boundary. */ if (x >= clip_area->xleft && x <= clip_area->xright) { x_intr[count] = x; y_intr[count++] = clip_area->ybot; } x = (clip_area->ytop - *y2) * dx / dy + *x2; /* Test for clip_area->ytop boundary. */ if (x >= clip_area->xleft && x <= clip_area->xright) { x_intr[count] = x; y_intr[count++] = clip_area->ytop; } } /* Find intersections with the y parallel bbox lines: */ if (dx != 0) { y = (clip_area->xleft - *x2) * dy / dx + *y2; /* Test for clip_area->xleft boundary. */ if (y >= clip_area->ybot && y <= clip_area->ytop) { x_intr[count] = clip_area->xleft; y_intr[count++] = y; } y = (clip_area->xright - *x2) * dy / dx + *y2; /* Test for clip_area->xright boundary. */ if (y >= clip_area->ybot && y <= clip_area->ytop) { x_intr[count] = clip_area->xright; y_intr[count++] = y; } } if (count < 2) return 0; /* check which intersections to use, for more than two intersections the first two may be identical */ if ((count > 2) && (x_intr[0] == x_intr[1]) && (y_intr[0] == y_intr[1])) { x_intr[1] = x_intr[2]; y_intr[1] = y_intr[2]; } if (*x1 < *x2) { x_min = *x1; x_max = *x2; } else { x_min = *x2; x_max = *x1; } if (*y1 < *y2) { y_min = *y1; y_max = *y2; } else { y_min = *y2; y_max = *y1; } if (pos1 && pos2) { /* Both were out - update both */ /* EAM Sep 2008 - preserve direction of line segment */ if ((dx*(x_intr[1]-x_intr[0]) < 0) || (dy*(y_intr[1]-y_intr[0]) < 0)) { *x1 = x_intr[1]; *y1 = y_intr[1]; *x2 = x_intr[0]; *y2 = y_intr[0]; } else { *x1 = x_intr[0]; *y1 = y_intr[0]; *x2 = x_intr[1]; *y2 = y_intr[1]; } } else if (pos1) { /* Only x1/y1 was out - update only it */ /* Nov 2010: When clip_line() and draw_clip_line() were consolidated in */ /* 2000, the test below was the only point of difference between them. */ /* Unfortunately, the wrong version was kept. Now I change it back. */ /* The effect of the wrong version (>= rather than >) was that a line */ /* from ymin to ymax+eps was clipped to ymin,ymin rather than ymin,ymax */ if (dx * (*x2 - x_intr[0]) + dy * (*y2 - y_intr[0]) > 0) { *x1 = x_intr[0]; *y1 = y_intr[0]; } else { *x1 = x_intr[1]; *y1 = y_intr[1]; } } else { /* Only x2/y2 was out - update only it */ /* Same difference here, again */ if (dx * (x_intr[0] - *x1) + dy * (y_intr[0] - *y1) > 0) { *x2 = x_intr[0]; *y2 = y_intr[0]; } else { *x2 = x_intr[1]; *y2 = y_intr[1]; } } if (*x1 < x_min || *x1 > x_max || *x2 < x_min || *x2 > x_max || *y1 < y_min || *y1 > y_max || *y2 < y_min || *y2 > y_max) return 0; return -1; }
/* Clip the given line to drawing coords defined by BoundingBox. * This routine uses the cohen & sutherland bit mapping for fast clipping - * see "Principles of Interactive Computer Graphics" Newman & Sproull page 65. * Return 0: entire line segment is outside bounding box * 1: entire line segment is inside bounding box * -1: line segment has been clipped to bounding box */ int clip_line(int *x1, int *y1, int *x2, int *y2) { int x, y, dx, dy, x_intr[4], y_intr[4], count, pos1, pos2; int x_max, x_min, y_max, y_min; pos1 = clip_point(*x1, *y1); pos2 = clip_point(*x2, *y2); if (!pos1 && !pos2) return 1; /* segment is totally in */ if (pos1 & pos2) return 0; /* segment is totally out. */ /* Here part of the segment MAY be inside. test the intersection * of this segment with the 4 boundaries for hopefully 2 intersections * in. If none are found segment is totaly out. * Under rare circumstances there may be up to 4 intersections (e.g. * when the line passes directly through at least one corner). In * this case it is sufficient to take any 2 intersections (e.g. the * first two found). */ count = 0; dx = *x2 - *x1; dy = *y2 - *y1; /* Find intersections with the x parallel bbox lines: */ if (dy != 0) { x = (clip_area->ybot - *y2) * dx / dy + *x2; /* Test for clip_area->ybot boundary. */ if (x >= clip_area->xleft && x <= clip_area->xright) { x_intr[count] = x; y_intr[count++] = clip_area->ybot; } x = (clip_area->ytop - *y2) * dx / dy + *x2; /* Test for clip_area->ytop boundary. */ if (x >= clip_area->xleft && x <= clip_area->xright) { x_intr[count] = x; y_intr[count++] = clip_area->ytop; } } /* Find intersections with the y parallel bbox lines: */ if (dx != 0) { y = (clip_area->xleft - *x2) * dy / dx + *y2; /* Test for clip_area->xleft boundary. */ if (y >= clip_area->ybot && y <= clip_area->ytop) { x_intr[count] = clip_area->xleft; y_intr[count++] = y; } y = (clip_area->xright - *x2) * dy / dx + *y2; /* Test for clip_area->xright boundary. */ if (y >= clip_area->ybot && y <= clip_area->ytop) { x_intr[count] = clip_area->xright; y_intr[count++] = y; } } if (count < 2) return 0; if (*x1 < *x2) { x_min = *x1; x_max = *x2; } else { x_min = *x2; x_max = *x1; } if (*y1 < *y2) { y_min = *y1; y_max = *y2; } else { y_min = *y2; y_max = *y1; } if (pos1 && pos2) { /* Both were out - update both */ /* EAM Sep 2008 - preserve direction of line segment */ if ((dx*(x_intr[1]-x_intr[0]) < 0) || (dy*(y_intr[1]-y_intr[0]) < 0)) { *x1 = x_intr[1]; *y1 = y_intr[1]; *x2 = x_intr[0]; *y2 = y_intr[0]; } else { *x1 = x_intr[0]; *y1 = y_intr[0]; *x2 = x_intr[1]; *y2 = y_intr[1]; } } else if (pos1) { /* Only x1/y1 was out - update only it */ /* This is about the only real difference between this and * draw_clip_line(): it compares for '>0', here */ if (dx * (*x2 - x_intr[0]) + dy * (*y2 - y_intr[0]) >= 0) { *x1 = x_intr[0]; *y1 = y_intr[0]; } else { *x1 = x_intr[1]; *y1 = y_intr[1]; } } else { /* Only x2/y2 was out - update only it */ /* Same difference here, again */ if (dx * (x_intr[0] - *x1) + dy * (y_intr[0] - *y1) >= 0) { *x2 = x_intr[0]; *y2 = y_intr[0]; } else { *x2 = x_intr[1]; *y2 = y_intr[1]; } } if (*x1 < x_min || *x1 > x_max || *x2 < x_min || *x2 > x_max || *y1 < y_min || *y1 > y_max || *y2 < y_min || *y2 > y_max) return 0; return -1; }