Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
/* 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);
}
Ejemplo n.º 3
0
/* 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;
    }
}
Ejemplo n.º 4
0
/* 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);
}
Ejemplo n.º 5
0
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;
	    }
	}
    }
}
Ejemplo n.º 6
0
/* 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;
}
Ejemplo n.º 7
0
/* 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;
}