Пример #1
0
static void print_parameter(int mode, char *ptr)
{

#define INSIDE(p,t) (ptr >= (char *) t && ptr < ((char *) t) + sizeof(t))

    /*
     * This is gross, but the best we can do on short notice.
     */
    if (INSIDE(ptr, time_table))
	print_time(mode, (CONFIG_TIME_TABLE *) ptr);
    if (INSIDE(ptr, bool_table))
	print_bool(mode, (CONFIG_BOOL_TABLE *) ptr);
    if (INSIDE(ptr, int_table))
	print_int(mode, (CONFIG_INT_TABLE *) ptr);
    if (INSIDE(ptr, str_table))
	print_str(mode, (CONFIG_STR_TABLE *) ptr);
    if (INSIDE(ptr, str_fn_table))
	print_str_fn(mode, (CONFIG_STR_FN_TABLE *) ptr);
    if (INSIDE(ptr, str_fn_table_2))
	print_str_fn_2(mode, (CONFIG_STR_FN_TABLE *) ptr);
    if (INSIDE(ptr, raw_table))
	print_raw(mode, (CONFIG_RAW_TABLE *) ptr);
    if (INSIDE(ptr, nint_table))
	print_nint(mode, (CONFIG_NINT_TABLE *) ptr);
    if (msg_verbose)
	vstream_fflush(VSTREAM_OUT);
}
Пример #2
0
void clipline(dcpt winmin,dcpt winmax,wcpt2 p1,wcpt2 p2)
{
	unsigned char encode(wcpt2,dcpt,dcpt);
	unsigned char code1,code2;
	int done = 0 , draw = 0;
	float m;
	void swapcode(unsigned char *c1,unsigned char *c2);
	void swappts(wcpt2 *p1,wcpt2 *p2);

	while(!done)
	{
		code1 = encode(p1,winmin,winmax);
		code2 = encode(p2,winmin,winmax);
		if(ACCEPT(code1,code2))
		{
			draw = 1;
			done = 1;
		}
		else if(REJECT(code1,code2))
			done = 1;
		else if(INSIDE(code1))
		{
				swappts(&p1,&p2);
				swapcode(&code1,&code2);
		}
		if(code1 & LEFT_EDGE)
		{
				p1.y += (winmin.x - p1.x) *  (p2.y - p1.y) / (p2.x - p1.x);
				p1.x = winmin.x;
		}
		else if(code1 & RIGHT_EDGE)
		{
				p1.y += (winmax.x - p1.x) *  (p2.y - p1.y) / (p2.x - p1.x);
				p1.x = winmax.x;
		}
		else if(code1 & TOP_EDGE)
		{
			if(p2.x != p1.x)
				p1.x += (winmin.y - p1.y) *  (p2.x - p1.x) / (p2.y - p1.y);
				p1.y = winmin.y;
		}
		else if(code1 & BOTTOM_EDGE)
		{
			if(p2.x != p1.x)
				p1.x += (winmax.y - p1.y) *  (p2.x - p1.x) / (p2.y - p1.y);
				p1.y = winmax.y;
		}
    }
    if(draw)
    {
	setcolor(5);
	line(p1.x,p1.y,p2.x,p2.y);
    }
}
Пример #3
0
static void
handle_frame0 (APP *a, XEvent *event)
{
    XButtonPressedEvent *bevent;

    switch (event->type) {
	case ButtonPress:
	    bevent = (XButtonPressedEvent *)event;
	    switch (bevent->button & 0xFF) {
		case Button1:
		    /*printf("handle0: b1\n");*/
		    if (INSIDE(bevent->x, bevent->y, 4, 4, 10, 10)) {
			/*printf("next: %d %d\n", bevent->x, bevent->y);*/
			break;
		    }
		    if (INSIDE(bevent->x, bevent->y, 50, 4, 56, 10)) {
			/*printf("quit: %d %d\n", bevent->x, bevent->y);*/
			((DOCKAPP *)a)->quit = True;
			break;
		    }
		    if (INSIDE(bevent->x, bevent->y, 1, 1, 59, 13)) {
			/*printf("time: %d %d\n", bevent->x, bevent->y);*/
			SWITCH_FRAME(a, 1);
			break;
		    }
		    if (INSIDE(bevent->x, bevent->y, 1, 16, 59, 27)) {
			/*printf("cpu : %d %d\n", bevent->x, bevent->y);*/
			SWITCH_FRAME(a, 2);
			break;
		    }
		    if (INSIDE(bevent->x, bevent->y, 1, 30, 29, 41)) {
			/*printf("wifi: %d %d\n", bevent->x, bevent->y);*/
			SWITCH_FRAME(a, 3);
			break;
		    }
		    if (INSIDE(bevent->x, bevent->y, 32, 30, 59, 41)) {
			/*printf("temp: %d %d\n", bevent->x, bevent->y);*/
			SWITCH_FRAME(a, 4);
			break;
		    }
		    if (INSIDE(bevent->x, bevent->y, 1, 44, 59, 59)) {
			/*printf("batt: %d %d\n", bevent->x, bevent->y);*/
			SWITCH_FRAME(a, 5);
			break;
		    }
		    break;
		case Button2:
		    /*printf("handle0: b2\n");*/
		    break;
		case Button3:
		    /*printf("handle0: b3\n");*/
		    break;
	    }
	    break;
    }
}
Пример #4
0
Intersection PlanoY::Intercepta(const Raio& r_vis, IntersectionMode mode, float threshold)
{
  float x,z;

  float t = (a - r_vis.Y0()) / r_vis.Dy();

  Intersection lastIntersection;
  if ( t <0)
    return lastIntersection;

  x = r_vis.X0() +  t * r_vis.Dx();
  if (INSIDE(x,bmin,bmax))
  {
    z = r_vis.Z0() + t *r_vis.Dz();
    if (INSIDE(z,cmin,cmax))
    {
        lastIntersection.setValues(this, t);
        return lastIntersection;
    }
  }
  return lastIntersection;
}
Пример #5
0
/* html_path:
 * Return a box in a table containing the given endpoint.
 * If the top flow is text (no internal structure), return 
 * the box of the flow
 * Else return the box of the subtable containing the point.
 * Because of spacing, the point might not be in any subtable.
 * In that case, return the top flow's box.
 * Note that box[0] must contain the edge point. Additional boxes
 * move out to the boundary.
 *
 * At present, unimplemented, since the label may be inside a
 * non-box node and we need to figure out what this means.
 */
int html_path(node_t * n, port* p, int side, box * rv, int *k)
{
#ifdef UNIMPL
    point p;
    tbl_t *info;
    tbl_t *t;
    box b;
    int i;

    info = (tbl_t *) ND_shape_info(n);
    assert(info->tbls);
    info = info->tbls[0];	/* top-level flow */
    assert(IS_FLOW(info));

    b = info->box;
    if (info->tbl) {
	info = info->tbl;
	if (pt == 1)
	    p = ED_tail_port(e).p;
	else
	    p = ED_head_port(e).p;
	p = flip_pt(p, GD_rankdir(n->graph));	/* move p to node's coordinate system */
	for (i = 0; (t = info->tbls[i]) != 0; i++)
	    if (INSIDE(p, t->box)) {
		b = t->box;
		break;
	    }
    }

    /* move box into layout coordinate system */
    if (GD_flip(n->graph))
	b = flip_trans_box(b, ND_coord_i(n));
    else
	b = move_box(b, ND_coord_i(n));

    *k = 1;
    *rv = b;
    if (pt == 1)
	return BOTTOM;
    else
	return TOP;
#endif
    return 0;
}
Пример #6
0
static Eterm
check_process_code(Process* rp, Module* modp)
{
    Eterm* start;
    char* mod_start;
    Uint mod_size;
    Eterm* end;
    Eterm* sp;
#ifndef HYBRID /* FIND ME! */
    ErlFunThing* funp;
    int done_gc = 0;
#endif

#define INSIDE(a) (start <= (a) && (a) < end)
    if (modp == NULL) {		/* Doesn't exist. */
	return am_false;
    } else if (modp->old_code == NULL) { /* No old code. */
	return am_false;
    }

    /*
     * Pick up limits for the module.
     */
    start = modp->old_code;
    end = (Eterm *)((char *)start + modp->old_code_length);
    mod_start = (char *) start;
    mod_size = modp->old_code_length;

    /*
     * Check if current instruction or continuation pointer points into module.
     */
    if (INSIDE(rp->i) || INSIDE(rp->cp)) {
	return am_true;
    }

    /*
     * Check all continuation pointers stored on the stack.
     */
    for (sp = rp->stop; sp < STACK_START(rp); sp++) {
	if (is_CP(*sp) && INSIDE(cp_val(*sp))) {
	    return am_true;
	}
    }

    /* 
     * Check all continuation pointers stored in stackdump
     * and clear exception stackdump if there is a pointer
     * to the module.
     */
    if (rp->ftrace != NIL) {
	struct StackTrace *s;
	ASSERT(is_list(rp->ftrace));
	s = (struct StackTrace *) big_val(CDR(list_val(rp->ftrace)));
	if ((s->pc && INSIDE(s->pc)) ||
	    (s->current && INSIDE(s->current))) {
	    rp->freason = EXC_NULL;
	    rp->fvalue = NIL;
	    rp->ftrace = NIL;
	} else {
	    int i;
	    for (i = 0;  i < s->depth;  i++) {
		if (INSIDE(s->trace[i])) {
		    rp->freason = EXC_NULL;
		    rp->fvalue = NIL;
		    rp->ftrace = NIL;
		    break;
		}
	    }
	}
    }

    /*
     * See if there are funs that refer to the old version of the module.
     */

#ifndef HYBRID /* FIND ME! */
 rescan:
    for (funp = MSO(rp).funs; funp; funp = funp->next) {
	Eterm* fun_code;

	fun_code = funp->fe->address;

	if (INSIDE((Eterm *) funp->fe->address)) {
	    if (done_gc) {
		return am_true;
	    } else {
		/*
		 * Try to get rid of this fun by garbage collecting.
		 * Clear both fvalue and ftrace to make sure they
		 * don't hold any funs.
		 */
		rp->freason = EXC_NULL;
		rp->fvalue = NIL;
		rp->ftrace = NIL;
		done_gc = 1;
                FLAGS(rp) |= F_NEED_FULLSWEEP;
		(void) erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
		goto rescan;
	    }
	}
    }
#endif

    /*
     * See if there are constants inside the module referenced by the process.
     */
    done_gc = 0;
    for (;;) {
	ErlMessage* mp;

	if (any_heap_ref_ptrs(&rp->fvalue, &rp->fvalue+1, mod_start, mod_size)) {
	    rp->freason = EXC_NULL;
	    rp->fvalue = NIL;
	    rp->ftrace = NIL;
	}
	if (any_heap_ref_ptrs(rp->stop, rp->hend, mod_start, mod_size)) {
	    goto need_gc;
	}
	if (any_heap_refs(rp->heap, rp->htop, mod_start, mod_size)) {
	    goto need_gc;
	}

	if (any_heap_refs(rp->old_heap, rp->old_htop, mod_start, mod_size)) {
	    goto need_gc;
	}

	if (rp->dictionary != NULL) {
	    Eterm* start = rp->dictionary->data;
	    Eterm* end = start + rp->dictionary->used;

	    if (any_heap_ref_ptrs(start, end, mod_start, mod_size)) {
		goto need_gc;
	    }
	}

	for (mp = rp->msg.first; mp != NULL; mp = mp->next) {
	    if (any_heap_ref_ptrs(mp->m, mp->m+2, mod_start, mod_size)) {
		goto need_gc;
	    }
	}
	break;

    need_gc:
	if (done_gc) {
	    return am_true;
	} else {
	    Eterm* literals;
	    Uint lit_size;

	    /*
	     * Try to get rid of constants by by garbage collecting.
	     * Clear both fvalue and ftrace.
	     */
	    rp->freason = EXC_NULL;
	    rp->fvalue = NIL;
	    rp->ftrace = NIL;
	    done_gc = 1;
	    FLAGS(rp) |= F_NEED_FULLSWEEP;
	    (void) erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
	    literals = (Eterm *) modp->old_code[MI_LITERALS_START];
	    lit_size = (Eterm *) modp->old_code[MI_LITERALS_END] - literals;
	    erts_garbage_collect_literals(rp, literals, lit_size);
	}
    }
    return am_false;
#undef INSIDE
}
Пример #7
0
mlib_status
__mlib_GraphicsFillArc_AB_32(
    mlib_image *buffer,
    mlib_s16 x,
    mlib_s16 y,
    mlib_s32 r,
    mlib_f32 t1,
    mlib_f32 t2,
    mlib_s32 c,
    mlib_s32 a)
{
	mlib_s32 stride = mlib_ImageGetStride(buffer) / sizeof (mlib_s32);
	mlib_s32 width = mlib_ImageGetWidth(buffer) - 1;
	mlib_s32 height = mlib_ImageGetHeight(buffer) - 1;
	mlib_s32 lwidth = width - 1;
	mlib_s32 lheight = height - 1;
	mlib_s32 *data = mlib_ImageGetData(buffer);
	mlib_s32 *line0, *line;
	mlib_s32 cx, cy, del, mask;
	mlib_status rez;

	mlib_s32 stepsignx1, stepsignx2, stepsigny1, stepsigny2;
	mlib_s32 lineindex1 = 0, lineindex2 = 0;
	mlib_s32 ifoverlap = 0;

	mlib_f32 tt1 = t1, tt2 = t2;
	mlib_s32 sn1, cs1, sn2, cs2;
	mlib_s32 sin1, cos1, sin2, cos2, oct1, oct2, flagc, flagd;
	mlib_s32 xx, yy, ux, uy, dx, dy;

	pinfo buf0[BUFSIZE], *buf = 0;
	pinfo_line buf0_line1[RADMAX+1], *buf_line1 = 0;
	pinfo_line buf0_line2[RADMAX+1], *buf_line2 = 0;
	pinfo_line *buf_line;

	mlib_s32 count, scount;
	mlib_s32 start, end;

	mlib_s32 ind0, ind1, ind2, c0, c1, c2, mdel, k;
	mlib_s32 alpha0, alpha1, alpha2;
	mlib_s32 cf0 = c & 0xff, cf1 = (c & 0xff00) >> 8, cf2 =
	    (c & 0xff0000) >> 16;
	mlib_u8 cfalpha = 0xFF;
	mlib_d64 A0, A1;

	a &= 0xff;
	A1 = a / 255.;
	A0 = 1. - A1;

	if (!data)
		return (MLIB_NULLPOINTER);

	if (r < 0)
		return (MLIB_FAILURE);

	CHECK_INTERSECTION;

	if (r == 0) {
		if (INSIDE(x, y)) {
			BLEND32((data + (stride * y + x))[0], c, a);
		}
		return (MLIB_SUCCESS);
	}

	if (mlib_fabs(t1 - t2) >= PIx2) {
		return (__mlib_GraphicsFillCircle_AB_32(buffer, x, y, r, c, a));
	}
	{
		mlib_f32 tt = t1;

		t1 = -t2;
		t2 = -tt;
	}

	if (t1 > t2)
		t2 += PIx2;

	line0 = data + stride * y + x;

	if (r > RADMAX) {
		buf = (pinfo *) __mlib_malloc(sizeof (pinfo) * r);

		if (!buf)
			return (MLIB_FAILURE);

		buf_line1 = (pinfo_line *) __mlib_malloc(sizeof (pinfo_line)
			* (r + 1));

		if (!buf_line1) {
			__mlib_free(buf);
			return (MLIB_FAILURE);
		}
		buf_line2 = (pinfo_line *) __mlib_malloc(sizeof (pinfo_line)
			* (r + 1));
		if (!buf_line2) {
			__mlib_free(buf);
			__mlib_free(buf_line1);
			return (MLIB_FAILURE);
		}
	} else {
		buf = buf0;
		buf_line1 = buf0_line1;
		buf_line2 = buf0_line2;
	}


	k = (0x100000 / r);

	FILL_BUF;

	GET_BORDERS;

	if (t1 == t2) {
		FREE_MEM;
		return (__mlib_GraphicsDrawLine_AB_32(buffer, x, y,
		    x + cs1, y - sn1, c, a));
	}

	FILL_FLAGS;

	FILL_CL_FLAGS;

	SET_STEPSIGN;

	ARC_FILL_LINEBUF(1);
	ARC_FILL_LINEBUF(2);

	start = 0;
	end = count;
	PROC_OCT(y, y - height, x - width, x, 2, cos, 1, 2, stride, -1);
	start = 1;
	end = count;
	PROC_OCT(y, y - height, -x, width - x, 1, cos, 2, 1, stride, 1);
	start = 0;
	end = count;
	PROC_OCT(height - y, -y, x - width, x, 5, cos, 2, 1, -stride, -1);
	start = 1;
	end = count;
	PROC_OCT(height - y, -y, -x, width - x, 6, cos, 1, 2, -stride, 1);

	start = 1;
	end = scount;
	PROC_OCT(x, x - width, y - height, y, 3, sin, 2, 1, 1, -stride);
	start = 0;
	end = scount;
	PROC_OCT(x, x - width, -y, height - y, 4, sin, 1, 2, 1, stride);
	start = 1;
	end = scount;
	PROC_OCT(width - x, -x, y - height, y, 0, sin, 1, 2, -1, -stride);
	start = 0;
	end = scount;
	PROC_OCT(width - x, -x, -y, height - y, 7, sin, 2, 1, -1, stride);

	rez = __mlib_GraphicsFillArc_B_32(buffer, x, y, r - 1, tt1, tt2, c, a);
	if (rez != MLIB_SUCCESS) {
		FREE_MEM;
		return (rez);
	}

	DRAW_LINE_AB(1, 2);
	DRAW_LINE_AB(2, 1);

	FREE_MEM;

	return (MLIB_SUCCESS);
}
Пример #8
0
/**
 * This method checks to see if the given LCD glyph bounds fall within the
 * cached destination texture bounds.  If so, this method can return
 * immediately.  If not, this method will copy a chunk of framebuffer data
 * into the cached destination texture and then update the current cached
 * destination bounds before returning.
 */
static void
OGLTR_UpdateCachedDestination(OGLSDOps *dstOps, GlyphInfo *ginfo,
                              jint gx1, jint gy1, jint gx2, jint gy2,
                              jint glyphIndex, jint totalGlyphs)
{
    jint dx1, dy1, dx2, dy2;
    jint dx1adj, dy1adj;

    if (isCachedDestValid && INSIDE(gx1, gy1, gx2, gy2, cachedDestBounds)) {
        // glyph is already within the cached destination bounds; no need
        // to read back the entire destination region again, but we do
        // need to see if the current glyph overlaps the previous glyph...

        if (INTERSECTS(gx1, gy1, gx2, gy2, previousGlyphBounds)) {
            // the current glyph overlaps the destination region touched
            // by the previous glyph, so now we need to read back the part
            // of the destination corresponding to the previous glyph
            dx1 = previousGlyphBounds.x1;
            dy1 = previousGlyphBounds.y1;
            dx2 = previousGlyphBounds.x2;
            dy2 = previousGlyphBounds.y2;

            // this accounts for lower-left origin of the destination region
            dx1adj = dstOps->xOffset + dx1;
            dy1adj = dstOps->yOffset + dstOps->height - dy2;

            // copy destination into subregion of cached texture tile:
            //   dx1-cachedDestBounds.x1 == +xoffset from left side of texture
            //   cachedDestBounds.y2-dy2 == +yoffset from bottom of texture
            j2d_glActiveTextureARB(GL_TEXTURE1_ARB);
            j2d_glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
                                    dx1 - cachedDestBounds.x1,
                                    cachedDestBounds.y2 - dy2,
                                    dx1adj, dy1adj,
                                    dx2-dx1, dy2-dy1);
        }
    } else {
        jint remainingWidth;

        // destination region is not valid, so we need to read back a
        // chunk of the destination into our cached texture

        // position the upper-left corner of the destination region on the
        // "top" line of glyph list
        // REMIND: this isn't ideal; it would be better if we had some idea
        //         of the bounding box of the whole glyph list (this is
        //         do-able, but would require iterating through the whole
        //         list up front, which may present its own problems)
        dx1 = gx1;
        dy1 = gy1;

        if (ginfo->advanceX > 0) {
            // estimate the width based on our current position in the glyph
            // list and using the x advance of the current glyph (this is just
            // a quick and dirty heuristic; if this is a "thin" glyph image,
            // then we're likely to underestimate, and if it's "thick" then we
            // may end up reading back more than we need to)
            remainingWidth =
                (jint)(ginfo->advanceX * (totalGlyphs - glyphIndex));
            if (remainingWidth > OGLTR_CACHED_DEST_WIDTH) {
                remainingWidth = OGLTR_CACHED_DEST_WIDTH;
            } else if (remainingWidth < ginfo->width) {
                // in some cases, the x-advance may be slightly smaller
                // than the actual width of the glyph; if so, adjust our
                // estimate so that we can accomodate the entire glyph
                remainingWidth = ginfo->width;
            }
        } else {
            // a negative advance is possible when rendering rotated text,
            // in which case it is difficult to estimate an appropriate
            // region for readback, so we will pick a region that
            // encompasses just the current glyph
            remainingWidth = ginfo->width;
        }
        dx2 = dx1 + remainingWidth;

        // estimate the height (this is another sloppy heuristic; we'll
        // make the cached destination region tall enough to encompass most
        // glyphs that are small enough to fit in the glyph cache, and then
        // we add a little something extra to account for descenders
        dy2 = dy1 + OGLTR_CACHE_CELL_HEIGHT + 2;

        // this accounts for lower-left origin of the destination region
        dx1adj = dstOps->xOffset + dx1;
        dy1adj = dstOps->yOffset + dstOps->height - dy2;

        // copy destination into cached texture tile (the lower-left corner
        // of the destination region will be positioned at the lower-left
        // corner (0,0) of the texture)
        j2d_glActiveTextureARB(GL_TEXTURE1_ARB);
        j2d_glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
                                0, 0, dx1adj, dy1adj,
                                dx2-dx1, dy2-dy1);

        // update the cached bounds and mark it valid
        cachedDestBounds.x1 = dx1;
        cachedDestBounds.y1 = dy1;
        cachedDestBounds.x2 = dx2;
        cachedDestBounds.y2 = dy2;
        isCachedDestValid = JNI_TRUE;
    }

    // always update the previous glyph bounds
    previousGlyphBounds.x1 = gx1;
    previousGlyphBounds.y1 = gy1;
    previousGlyphBounds.x2 = gx2;
    previousGlyphBounds.y2 = gy2;
}
DMX_TYPE dmxIdentify(char *name)
{
DMX_TYPE ret=DMX_MPG_UNKNOWN;
uint64_t pos;
uint8_t stream;
FP_TYPE fp=FP_DONT_APPEND;
        uint64_t size;
        uint32_t typeES=0,typePS=0;
        fileParser *parser;
        parser=new fileParser();

        printf("Probing : %s\n",name);
        if(!parser->open(name,&fp))
        {
                goto _fnd;
        }
        // Try to see if it is a TS:
        if(probeTs(parser))
                {
                        delete parser;
                        return DMX_MPG_TS;
                }
        parser->setpos(0);
        while(1)
        {
                parser->getpos(&pos);
                if(pos>MAX_PROBE) goto _nalyze;
                if(!parser->sync(&stream)) goto _nalyze;

#define INSIDE(x,y) (stream>=x && stream<y)
                if(stream==00 || stream==0xb3 || stream==0xb8) 
                {                        
                        typeES++;
                        continue;
                }

                if( INSIDE(0xE0,0xE9)  ) 
                        typePS++;

        }
_nalyze:
                if(typeES>MIN_DETECT)
                {
                        if(typePS>MIN_DETECT)
                        {
                                printf("%s looks like Mpeg PS (%lu/%lu)\n",name,typeES,typePS);
                                ret=DMX_MPG_PS;
                        }
                        else
                        {
                                printf("%s looks like Mpeg ES (%lu/%lu)\n",name,typeES,typePS);
                                ret=DMX_MPG_ES;
                        }
                }
                else
                {
                        // Try TS here
                        printf("Cannot identify %s as mpeg (%lu/%lu)\n",name,typeES,typePS);

                }
     
                           
_fnd:
                delete parser;
                return ret;
}
Пример #10
0
static int
_clipaaline (SDL_Rect *clip, float x1, float _y1, float x2, float y2,
    float *outpts)
{
    int left = clip->x + 1;
    int right = clip->x + clip->w - 2;
    int top = clip->y + 1;
    int bottom = clip->y + clip->h - 2;
    int code1, code2;
    int draw = 0;
    float swaptmp;
    int intswaptmp;
    float m; /*slope*/

    if (!outpts)
    {
        SDL_SetError ("outpts argument NULL");
        return 0;
    }

    while (1)
    {
        code1 = _fencode (x1, _y1, left, top, right, bottom);
        code2 = _fencode (x2, y2, left, top, right, bottom);
        if (ACCEPT (code1, code2))
        {
            draw = 1;
            break;
        }
        else if (REJECT (code1, code2))
            break;
        else
        {
            if (INSIDE (code1))
            {
                swaptmp = x2;
                x2 = x1;
                x1 = swaptmp;
                swaptmp = y2;
                y2 = _y1;
                _y1 = swaptmp;
                intswaptmp = code2;
                code2 = code1;
                code1 = intswaptmp;
            }
            if (x2 != x1)
                m = (y2 - _y1) / (x2 - x1);
            else
                m = 1.0f;
            if (code1 & LEFT_EDGE)
            {
                _y1 += ((float)left - x1) * m;
                x1 = (float)left;
            }
            else if (code1 & RIGHT_EDGE)
            {
                _y1 += ((float)right - x1) * m;
                x1 = (float)right;
            }
            else if (code1 & BOTTOM_EDGE)
            {
                if (x2 != x1)
                    x1 += ((float)bottom - _y1) / m;
                _y1 = (float)bottom;
            }
            else if (code1 & TOP_EDGE)
            {
                if(x2 != x1)
                    x1 += ((float)top - _y1) / m;
                _y1 = (float)top;
            }
        }
    }
    
    if (draw)
    {
        outpts[0] = x1;
        outpts[1] = _y1;
        outpts[2] = x2;
        outpts[3] = y2;
    }
    return draw;
}
Пример #11
0
/* inBoxf:
 * Returns true if p is on or in box bb
 */
static int inBoxf(pointf p, boxf * bb)
{
    return INSIDE(p, *bb);
}
Пример #12
0
void
plP_plfclp(PLINT *x, PLINT *y, PLINT npts,
	   PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax,
	   void (*draw) (short *, short *, PLINT))
{
    PLINT i, xx1, xx2, yy1, yy2;
    int iclp = 0, iout = 2;
    short _xclp[2*PL_MAXPOLY+2], _yclp[2*PL_MAXPOLY+2];
    short *xclp, *yclp;
    int drawable;
    int crossed_xmin1 = 0, crossed_xmax1 = 0;
    int crossed_ymin1 = 0, crossed_ymax1 = 0;
    int crossed_xmin2 = 0, crossed_xmax2 = 0;
    int crossed_ymin2 = 0, crossed_ymax2 = 0;
    int crossed_up    = 0, crossed_down  = 0;
    int crossed_left  = 0, crossed_right = 0;
    int inside_lb ;
    int inside_lu ;
    int inside_rb ;
    int inside_ru ;

/* Must have at least 3 points and draw() specified */
    if (npts < 3 || !draw) return;

    if ( npts < PL_MAXPOLY ) {
        xclp = _xclp;
        yclp = _yclp;
    } else {
        xclp = (short *) malloc( (2*npts+2)*sizeof(short) ) ;
        yclp = (short *) malloc( (2*npts+2)*sizeof(short) ) ;
    }


    inside_lb = pointinpolygon(npts,x,y,xmin,ymin) ;
    inside_lu = pointinpolygon(npts,x,y,xmin,ymax) ;
    inside_rb = pointinpolygon(npts,x,y,xmax,ymin) ;
    inside_ru = pointinpolygon(npts,x,y,xmax,ymax) ;

    for (i = 0; i < npts - 1; i++) {
	xx1 = x[i]; xx2 = x[i+1];
	yy1 = y[i]; yy2 = y[i+1];

	drawable = (INSIDE(xx1, yy1) && INSIDE(xx2, yy2));
	if ( ! drawable)
	    drawable = ! clipline(&xx1, &yy1, &xx2, &yy2,
				  xmin, xmax, ymin, ymax);

	if (drawable) {
	/* Boundary crossing condition -- coming in. */
	    crossed_xmin2 = (xx1 == xmin); crossed_xmax2 = (xx1 == xmax);
	    crossed_ymin2 = (yy1 == ymin); crossed_ymax2 = (yy1 == ymax);

	    crossed_left  = (crossed_left  || crossed_xmin2);
	    crossed_right = (crossed_right || crossed_xmax2);
	    crossed_down  = (crossed_down  || crossed_ymin2);
	    crossed_up    = (crossed_up    || crossed_ymax2);
	    iout = iclp+2;
	/* If the first segment, just add it. */

	    if (iclp == 0) {
		xclp[iclp] = xx1; yclp[iclp] = yy1; iclp++;
		xclp[iclp] = xx2; yclp[iclp] = yy2; iclp++;
	    }

	/* Not first point.  If first point of this segment matches up to the
	   previous point, just add it.  */

	    else if (xx1 == xclp[iclp-1] && yy1 == yclp[iclp-1]) {
		xclp[iclp] = xx2; yclp[iclp] = yy2; iclp++;
	    }

	/* Otherwise, we need to add both points, to connect the points in the
	 * polygon along the clip boundary.  If we encircled a corner, we have
	 * to add that first.
	 */

	    else {
	    /* Treat the case where we encircled two corners:
	       Construct a polygon out of the subset of vertices
	       Note that the direction is important too when adding
	       the extra points */
		xclp[iclp+1] = xx2; yclp[iclp+1] = yy2;
		xclp[iclp+2] = xx1; yclp[iclp+2] = yy1;
		iout = iout - iclp + 1;
	    /* Upper two */
		if ( ((crossed_xmin1 && crossed_xmax2) ||
			     (crossed_xmin2 && crossed_xmax1)) &&
			inside_lu )
		{
		    if ( crossed_xmin1 )
		    {
		        xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
		        xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
		    } else {
		        xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
		        xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
		    }
		}
	    /* Lower two */
		else if ( ((crossed_xmin1 && crossed_xmax2) ||
			          (crossed_xmin2 && crossed_xmax1)) &&
			inside_lb )
		{
		    if ( crossed_xmin1 )
		    {
		        xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
		        xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
		    } else {
		        xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
		        xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
		    }
		}
	    /* Left two */
		else if ( ((crossed_ymin1 && crossed_ymax2) ||
			          (crossed_ymin2 && crossed_ymax1)) &&
			inside_lb )
		{
		    if ( crossed_ymin1 )
		    {
		        xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
		        xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
		    } else {
		        xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
		        xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
		    }
		}
	    /* Right two */
		else if ( ((crossed_ymin1 && crossed_ymax2) ||
			          (crossed_ymin2 && crossed_ymax1)) &&
			inside_rb )
		{
		    if ( crossed_ymin1 )
		    {
		        xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
		        xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
		    } else {
		        xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
		        xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
		    }
		}
	    /* Now the case where we encircled one corner */
	    /* Lower left */
		else if ( (crossed_xmin1 && crossed_ymin2) ||
			  (crossed_ymin1 && crossed_xmin2) )
		{
		    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
		}
	    /* Lower right */
		else if ( (crossed_xmax1 && crossed_ymin2) ||
			  (crossed_ymin1 && crossed_xmax2) )
		{
		    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
		}
	    /* Upper left */
		else if ( (crossed_xmin1 && crossed_ymax2) ||
			  (crossed_ymax1 && crossed_xmin2) )
		{
		    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
		}
	    /* Upper right */
		else if ( (crossed_xmax1 && crossed_ymax2) ||
			  (crossed_ymax1 && crossed_xmax2) )
		{
		    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
		}

	    /* Now add current segment. */
		xclp[iclp] = xx1; yclp[iclp] = yy1; iclp++;
		xclp[iclp] = xx2; yclp[iclp] = yy2; iclp++;
	    }

	/* Boundary crossing condition -- going out. */
	    crossed_xmin1 = (xx2 == xmin); crossed_xmax1 = (xx2 == xmax);
	    crossed_ymin1 = (yy2 == ymin); crossed_ymax1 = (yy2 == ymax);
	}
    }

/* Limit case - all vertices are outside of bounding box.  So just fill entire
   box, *if* the bounding box is completely encircled.
*/

    if (iclp == 0) {
	PLINT xmin1, xmax1, ymin1, ymax1;
	xmin1 = xmax1 = x[0];
	ymin1 = ymax1 = y[0];
	for (i = 1; i < npts; i++) {
	    if (x[i] < xmin1) xmin1 = x[i];
	    if (x[i] > xmax1) xmax1 = x[i];
	    if (y[i] < ymin1) ymin1 = y[i];
	    if (y[i] > ymax1) ymax1 = y[i];
	}
	if (xmin1 <= xmin && xmax1 >= xmax && ymin1 <= ymin && ymax1 >= ymax ) {
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	    (*draw)(xclp, yclp, iclp);

	    if ( xclp != _xclp ) {
	        free( xclp );
	        free( yclp );
	    }


	    return;
	}
    }

/* Now handle cases where fill polygon intersects two sides of the box */

    if (iclp >= 2) {
	int debug=0;
	int dir = circulation(x, y, npts);
	if (debug) {
	    if ( (xclp[0] == xmin && xclp[iclp-1] == xmax) ||
		 (xclp[0] == xmax && xclp[iclp-1] == xmin) ||
		 (yclp[0] == ymin && yclp[iclp-1] == ymax) ||
		 (yclp[0] == ymax && yclp[iclp-1] == ymin) ||
		 (xclp[0] == xmin && yclp[iclp-1] == ymin) ||
		 (yclp[0] == ymin && xclp[iclp-1] == xmin) ||
		 (xclp[0] == xmax && yclp[iclp-1] == ymin) ||
		 (yclp[0] == ymin && xclp[iclp-1] == xmax) ||
		 (xclp[0] == xmax && yclp[iclp-1] == ymax) ||
		 (yclp[0] == ymax && xclp[iclp-1] == xmax) ||
		 (xclp[0] == xmin && yclp[iclp-1] == ymax) ||
		 (yclp[0] == ymax && xclp[iclp-1] == xmin) ) {
		printf("dir=%d, clipped points:\n", dir);
		for (i=0; i < iclp; i++)
		    printf(" x[%d]=%d y[%d]=%d", i, xclp[i], i, yclp[i]);
		printf("\n");
		printf("pre-clipped points:\n");
		for (i=0; i < npts; i++)
		    printf(" x[%d]=%d y[%d]=%d", i, x[i], i, y[i]);
		printf("\n");
	    }
	}

    /* The cases where the fill region is divided 2/2 */
    /* Divided horizontally */
	if (xclp[0] == xmin && xclp[iclp-1] == xmax)
	{
	    if (dir > 0) {
		xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
		xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    }
	    else {
		xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
		xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	    }
	}
	else if (xclp[0] == xmax && xclp[iclp-1] == xmin)
	{
	    if (dir > 0) {
		xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
		xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	    }
	    else {
		xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
		xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	    }
	}

    /* Divided vertically */
	else if (yclp[0] == ymin && yclp[iclp-1] == ymax)
	{
	    if (dir > 0) {
		xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
		xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	    }
	    else {
		xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
		xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	    }
	}
	else if (yclp[0] == ymax && yclp[iclp-1] == ymin)
	{
	    if (dir > 0) {
		xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
		xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	    }
	    else {
		xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
		xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    }
	}

    /* The cases where the fill region is divided 3/1 --
          LL           LR           UR           UL
       +-----+      +-----+      +-----+      +-----+
       |     |      |     |      |    \|      |/    |
       |     |      |     |      |     |      |     |
       |\    |      |    /|      |     |      |     |
       +-----+      +-----+      +-----+      +-----+

       Note when we go the long way around, if the direction is reversed the
       three vertices must be visited in the opposite order.
    */
    /* LL, short way around */
	else if ((xclp[0] == xmin && yclp[iclp-1] == ymin && dir < 0) ||
		 (yclp[0] == ymin && xclp[iclp-1] == xmin && dir > 0) )
	{
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	}
    /* LL, long way around, counterclockwise */
	else if ((xclp[0] == xmin && yclp[iclp-1] == ymin && dir > 0))
	{
	    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	}
    /* LL, long way around, clockwise */
	else if ((yclp[0] == ymin && xclp[iclp-1] == xmin && dir < 0))
	{
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	}
    /* LR, short way around */
	else if ((xclp[0] == xmax && yclp[iclp-1] == ymin && dir > 0) ||
		 (yclp[0] == ymin && xclp[iclp-1] == xmax && dir < 0) )
	{
	    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	}
    /* LR, long way around, counterclockwise */
	else if (yclp[0] == ymin && xclp[iclp-1] == xmax && dir > 0)
	{
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	}
    /* LR, long way around, clockwise */
	else if (xclp[0] == xmax && yclp[iclp-1] == ymin && dir < 0)
	{
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	}
    /* UR, short way around */
	else if ((xclp[0] == xmax && yclp[iclp-1] == ymax && dir < 0) ||
		 (yclp[0] == ymax && xclp[iclp-1] == xmax && dir > 0) )
	{
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	}
    /* UR, long way around, counterclockwise */
	else if (xclp[0] == xmax && yclp[iclp-1] == ymax && dir > 0)
	{
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	}
    /* UR, long way around, clockwise */
	else if (yclp[0] == ymax && xclp[iclp-1] == xmax && dir < 0)
	{
	    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	}
    /* UL, short way around */
	else if ((xclp[0] == xmin && yclp[iclp-1] == ymax && dir > 0) ||
		 (yclp[0] == ymax && xclp[iclp-1] == xmin && dir < 0) )
	{
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	}
    /* UL, long way around, counterclockwise */
	else if (yclp[0] == ymax && xclp[iclp-1] == xmin && dir > 0)
	{
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	}
    /* UL, long way around, clockwise */
	else if (xclp[0] == xmin && yclp[iclp-1] == ymax && dir < 0)
	{
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	}
    }

/* Check for the case that only one side has been crossed
   (AM) Just checking a single point turns out not to be
   enough, apparently the crossed_*1 and crossed_*2 variables
   are not quite what I expected.
*/
    if ( crossed_left+crossed_right+crossed_down+crossed_up == 1 &&
		inside_lb+inside_rb+inside_lu+inside_ru == 4 ) {
	int dir = circulation(x, y, npts);
	PLINT xlim[4], ylim[4];
	int insert;
	int incr;

	xlim[0] = xmin ; ylim[0] = ymin ;
	xlim[1] = xmax ; ylim[1] = ymin ;
	xlim[2] = xmax ; ylim[2] = ymax ;
	xlim[3] = xmin ; ylim[3] = ymax ;
	if ( dir > 0 ) {
	    incr   = 1;
	    insert = 0*crossed_left + 1*crossed_down + 2*crossed_right +
	             3*crossed_up ;
	} else {
	    incr   = -1;
	    insert = 3*crossed_left + 2*crossed_up + 1*crossed_right +
	             0*crossed_down ;
	}
	for ( i=0; i < 4; i ++ ) {
	    xclp[iclp] = xlim[insert] ;
	    yclp[iclp] = ylim[insert] ;
	    iclp   ++ ;
	    insert += incr ;
	    if ( insert > 3 ) insert = 0 ;
	    if ( insert < 0 ) insert = 3 ;
	}
    }

/* Draw the sucker */
    if (iclp >= 3)
	(*draw)(xclp, yclp, iclp);

    if ( xclp != _xclp ) {
        free( xclp );
        free( yclp );
    }
}
Пример #13
0
void
plP_pllclp(PLINT *x, PLINT *y, PLINT npts,
	   PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax,
	   void (*draw) (short *, short *, PLINT))
{
    PLINT xx1, xx2, yy1, yy2;
    PLINT i, iclp = 0;

    short _xclp[PL_MAXPOLY], _yclp[PL_MAXPOLY];
    short *xclp, *yclp;
    int drawable;

    if ( npts < PL_MAXPOLY ) {
        xclp = _xclp;
        yclp = _yclp;
    } else {
        xclp = (short *) malloc( npts*sizeof(short) ) ;
        yclp = (short *) malloc( npts*sizeof(short) ) ;
    }

    for (i = 0; i < npts - 1; i++) {
	xx1 = x[i];
	xx2 = x[i + 1];
	yy1 = y[i];
	yy2 = y[i + 1];

	drawable = (INSIDE(xx1, yy1) && INSIDE(xx2, yy2));
	if ( ! drawable)
	    drawable = ! clipline(&xx1, &yy1, &xx2, &yy2, xmin,
				  xmax, ymin, ymax);

	if (drawable) {

/* First point of polyline. */

	    if (iclp == 0) {
		xclp[iclp] = xx1;
		yclp[iclp] = yy1;
		iclp++;
		xclp[iclp] = xx2;
		yclp[iclp] = yy2;
	    }

/* Not first point.  Check if first point of this segment matches up to
   previous point, and if so, add it to the current polyline buffer. */

	    else if (xx1 == xclp[iclp] && yy1 == yclp[iclp]) {
		iclp++;
		xclp[iclp] = xx2;
		yclp[iclp] = yy2;
	    }

/* Otherwise it's time to start a new polyline */

	    else {
		if (iclp + 1 >= 2)
		    (*draw)(xclp, yclp, iclp + 1);
		iclp = 0;
		xclp[iclp] = xx1;
		yclp[iclp] = yy1;
		iclp++;
		xclp[iclp] = xx2;
		yclp[iclp] = yy2;
	    }
	}
    }

/* Handle remaining polyline */

    if (iclp + 1 >= 2)
	(*draw)(xclp, yclp, iclp + 1);

    plsc->currx = x[npts-1];
    plsc->curry = y[npts-1];

    if ( xclp != _xclp ) {
        free( xclp );
        free( yclp );
    }
}
Пример #14
0
static struct i_bitmap *
i_flood_fill_low(i_img *im,i_img_dim seedx,i_img_dim seedy,
                 i_img_dim *bxminp, i_img_dim *bxmaxp, i_img_dim *byminp, i_img_dim *bymaxp,
		 i_color const *seed, ff_cmpfunc cmpfunc) {
  i_img_dim ltx, rtx;
  i_img_dim tx = 0;

  i_img_dim bxmin = seedx;
  i_img_dim bxmax = seedx;
  i_img_dim bymin = seedy;
  i_img_dim bymax = seedy;

  struct llist *st;
  struct i_bitmap *btm;

  int channels;
  i_img_dim xsize,ysize;
  i_color cval;

  channels = im->channels;
  xsize    = im->xsize;
  ysize    = im->ysize;

  btm = btm_new(xsize, ysize);
  st  = llist_new(100, sizeof(struct stack_element*));

  /* Find the starting span and fill it */
  ltx = i_lspan(im, seedx, seedy, seed, cmpfunc);
  rtx = i_rspan(im, seedx, seedy, seed, cmpfunc);
  for(tx=ltx; tx<=rtx; tx++) SET(tx, seedy);
  bxmin = ltx;
  bxmax = rtx;

  ST_PUSH(ltx, rtx, ltx, rtx, seedy+1,  1);
  ST_PUSH(ltx, rtx, ltx, rtx, seedy-1, -1);

  while(st->count) {
    /* Stack variables */
    i_img_dim lx,rx;
    i_img_dim dadLx,dadRx;
    i_img_dim y;
    int direction;

    i_img_dim x;
    int wasIn=0;

    ST_POP(); /* sets lx, rx, dadLx, dadRx, y, direction */


    if (y<0 || y>ysize-1) continue;
    if (bymin > y) bymin=y; /* in the worst case an extra line */
    if (bymax < y) bymax=y; 


    x = lx+1;
    if ( lx >= 0 && (wasIn = INSIDE(lx, y, seed)) ) {
      SET(lx, y);
      lx--;
      while(lx >= 0 && INSIDE(lx, y, seed)) {
	SET(lx,y);
	lx--;
      }
    }

    if (bxmin > lx) bxmin = lx;
    while(x <= xsize-1) {
      /*  printf("x=%d\n",x); */
      if (wasIn) {
	
	if (INSIDE(x, y, seed)) {
	  /* case 1: was inside, am still inside */
	  SET(x,y);
	} else {
	  /* case 2: was inside, am no longer inside: just found the
	     right edge of a span */
	  ST_STACK(direction, dadLx, dadRx, lx, (x-1), y);

	  if (bxmax < x) bxmax = x;
	  wasIn=0;
	}
      } else {
	if (x > rx) goto EXT;
	if (INSIDE(x, y, seed)) {
	  SET(x, y);
	  /* case 3: Wasn't inside, am now: just found the start of a new run */
	  wasIn = 1;
	    lx = x;
	} else {
	  /* case 4: Wasn't inside, still isn't */
	}
      }
      x++;
    }
  EXT: /* out of loop */
    if (wasIn) {
      /* hit an edge of the frame buffer while inside a run */
      ST_STACK(direction, dadLx, dadRx, lx, (x-1), y);
      if (bxmax < x) bxmax = x;
    }
  }

  llist_destroy(st);

  *bxminp = bxmin;
  *bxmaxp = bxmax;
  *byminp = bymin;
  *bymaxp = bymax;

  return btm;
}
Пример #15
0
static LRESULT CALLBACK
WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
    static int penDown = JAVACALL_FALSE;
    int x, y;
    int i;
    PAINTSTRUCT ps;
    HDC hdc;
    HANDLE  *mutex;
    int key;
    //check if udp or tcp
    int level = SOL_SOCKET;
    int opttarget;
    int optname;
    int optsize = sizeof(optname);

    switch(iMsg) {

#ifdef SKINS_MENU_SUPPORTED
    case WM_COMMAND:

        switch(wParam & 0xFFFF) {
        case EXMENU_ITEM_SHUTDOWN:
            printf("EXMENU_ITEM_SHUTDOWN ...  \n");
            javanotify_shutdown();
            break;

        case EXMENU_ITEM_PAUSE:
            javanotify_pause();
            break;

        case EXMENU_ITEM_RESUME:
            javanotify_resume();
            break;

        default:
            return DefWindowProc (hwnd, iMsg, wParam, lParam);
        } /* end of switch */
        return 0;
#endif

    case WM_CREATE:
        hdc = GetDC(hwnd);
        CHECK_RETURN(SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT)));
        GetTextMetrics(hdc, &fixed_tm);
        CHECK_RETURN(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
        GetTextMetrics(hdc, &tm);
        ReleaseDC(hwnd, hdc);
        return 0;

    case WM_PAINT:
        mutex = (HANDLE*) TlsGetValue(tlsId);
        WaitForSingleObject(*mutex, INFINITE);

        hdc = BeginPaint(hwnd, &ps);

        /*
         * There are 3 bitmap buffers, putpixel screen buffer, the phone
         * bitmap and the actual window buffer. Paint the phone bitmap on the
         * window. LCDUIrefresh has already painted the putpixel buffer on the
         * LCD screen area of the phone bitmap.
         *
         * On a real win32 (or high level window API) device the phone bitmap
         * would not be needed the code below would just paint the putpixel
         * buffer the window.
         */
        DrawBitmap(hdc, hPhoneBitmap, 0, 0, SRCCOPY);

        EndPaint(hwnd, &ps);

        ReleaseMutex(*mutex);
        return 0;

    case WM_CLOSE:
        /*
         * Handle the "X" (close window) button by sending the AMS a shutdown
         * event.
         */
#ifdef SKINS_MENU_SUPPORTED
        destroySkinsMenu();
#endif
        javanotify_shutdown();
        PostQuitMessage(0);
        return 0;

    case WM_SYSKEYDOWN:
    case WM_SYSKEYUP:
        /* The only event of this type that we want MIDP
         * to handle is the F10 key which for some reason is not
         * sent in the WM_KEY messages.
         * if we receive any other key in this message, break.
         */
        if(wParam != VK_F10) {
            break;
        }
        // patch for VK_F10
        if (WM_SYSKEYUP == iMsg) {
            iMsg = WM_KEYUP;
        } else if (WM_SYSKEYDOWN == iMsg) {
            iMsg = WM_KEYDOWN;
        }
    /* fall through */
    case WM_KEYDOWN:
    {
        /* Impl note: to send pause and resume notifications */
        static int isPaused;
        if(VK_F5 == wParam) {
            if(!isPaused) {
                javanotify_pause();
            } else {
                javanotify_resume();
            }
            isPaused =!isPaused;
            break;
        } else if(VK_HOME == wParam) {
            javanotify_switch_to_ams();
            break;
        } else if(VK_F4 == wParam) {
            javanotify_select_foreground_app();
            break;
            /* F3 key used for rotation. */
        } else if(VK_F3 == wParam) {
            javanotify_rotation();
        }
    }
    case WM_KEYUP:
        key = mapKey(wParam, lParam);

        switch(key) {
        case /* MIDP_KEY_INVALID */ 0:
            return 0;

        /*
        case MD_KEY_HOME:
            if (iMsg == WM_KEYDOWN) {
            return 0;
        }

        pMidpEventResult->type = SELECT_FOREGROUND_EVENT;
        pSignalResult->waitingFor = AMS_SIGNAL;
        return 0;
        */
        default:
            break;
        }

        if(iMsg == WM_KEYUP) {
            javanotify_key_event((javacall_key)key, JAVACALL_KEYRELEASED);
        } else if(iMsg == WM_KEYDOWN) {
            if (lParam & 0xf0000000) {
                javanotify_key_event((javacall_key)key, JAVACALL_KEYREPEATED);
            } else {
                javanotify_key_event((javacall_key)key, JAVACALL_KEYPRESSED);
            }
        }

        return 0;

    case WM_TIMER:
        // Stop the timer from repeating the WM_TIMER message.
        KillTimer(hwnd, wParam);

        return 0;

    case WM_MOUSEMOVE:
    case WM_LBUTTONDOWN:
    case WM_LBUTTONUP:
        /* Cast lParam to "short" to preserve sign */
        x = (short)LOWORD(lParam);
        y = (short)HIWORD(lParam);

        /** please uncomment following line if you want to test pen input in win32 emulator.
         **  with ENABLE_PEN_EVENT_NOTIFICATION defined, you should also modify constants.xml
         **  in midp workspace in order to pass related tck cases.
         **/
#define ENABLE_PEN_EVENT_NOTIFICATION 1
#ifdef ENABLE_PEN_EVENT_NOTIFICATION
        midpScreen_bounds.x = x_offset;
        midpScreen_bounds.y = y_offset;
        midpScreen_bounds.width = VRAM.width;
        midpScreen_bounds.height = (inFullScreenMode? VRAM.height: VRAM.height - TOP_BAR_HEIGHT);

        if(iMsg == WM_LBUTTONDOWN && INSIDE(x, y, midpScreen_bounds) ) {
            penAreDragging = JAVACALL_TRUE;
            SetCapture(hwnd);
            if (reverse_orientation) {
                javanotify_pen_event(javacall_lcd_get_screen_width() - y + y_offset, x - x_offset, JAVACALL_PENPRESSED);
            } else {
                javanotify_pen_event(x-x_offset, y-y_offset, JAVACALL_PENPRESSED);
            }
            return 0;
        }
        if(iMsg == WM_LBUTTONUP && (INSIDE(x, y, midpScreen_bounds) ||  penAreDragging == JAVACALL_TRUE)) {
            if(penAreDragging == JAVACALL_TRUE) {
                penAreDragging = JAVACALL_FALSE;
                ReleaseCapture();
            }
            if (reverse_orientation) {
                javanotify_pen_event(javacall_lcd_get_screen_width() - y + y_offset, x - x_offset, JAVACALL_PENRELEASED);
            } else {
                javanotify_pen_event(x-x_offset, y-y_offset, JAVACALL_PENRELEASED);
            }
            return 0;
        }
        if(iMsg == WM_MOUSEMOVE) {
            if(penAreDragging == JAVACALL_TRUE) {
                if (reverse_orientation) {
                    javanotify_pen_event(javacall_lcd_get_screen_width() - y + y_offset, x - x_offset, JAVACALL_PENDRAGGED);
                } else {
                    javanotify_pen_event(x-x_offset, y-y_offset, JAVACALL_PENDRAGGED);
                }
            }
            return 0;
        }
#else
        if(iMsg == WM_MOUSEMOVE) {
            /*
             * Don't process mouse move messages that are not over the LCD
             * screen of the skin.
             */
            return 0;
        }
#endif

        for(i = 0; i < NUMBEROF(Keys); ++i) {
            if(!(INSIDE(x, y, Keys[i].bounds))) {
                continue;
            }

            /* Chameleon processes keys on the way down. */
#ifdef SOUND_SUPPORTED
            if(iMsg == WM_LBUTTONDOWN) {
                MessageBeep(MB_OK);
            }
#endif
            switch(Keys[i].button) {
            case KEY_POWER:
                if(iMsg == WM_LBUTTONUP) {
                    return 0;
                }
                javanotify_shutdown();
                return 0;

            case KEY_END:
                if(iMsg == WM_LBUTTONUP) {
                    return 0;
                }
                /* NEED REVISIT: destroy midlet instead of shutdown? */
                javanotify_shutdown();
                return 0;

            default:
                /* Handle the simulated key events. */
                switch(iMsg) {
                case WM_LBUTTONDOWN:
                    javanotify_key_event((javacall_key)Keys[i].button, JAVACALL_KEYPRESSED);
                    return 0;

                case WM_LBUTTONUP:
                    javanotify_key_event((javacall_key)Keys[i].button, JAVACALL_KEYRELEASED);
                    return 0;

                default:
                    break;
                } /* switch iMsg */
            } /* switch key */
        } /* for */

        return 0;

    case WM_NETWORK:

#ifdef ENABLE_NETWORK_TRACING
        fprintf(stderr, "Got WM_NETWORK(");
        fprintf(stderr, "descriptor = %d, ", (int)wParam);
        fprintf(stderr, "status = %d, ", WSAGETSELECTERROR(lParam));
#endif
        optname = SO_TYPE;
        if(0 != getsockopt((SOCKET)wParam, SOL_SOCKET,  optname,(char*)&opttarget, &optsize)) {
#ifdef ENABLE_NETWORK_TRACING
            fprintf(stderr, "getsocketopt error)\n");
#endif
        }

        if(opttarget == SOCK_STREAM) { // TCP socket

            return handleNetworkStreamEvents(wParam,lParam);

        } else {
            return handleNetworkDatagramEvents(wParam,lParam);
        };

        break;

    case WM_HOST_RESOLVED:
#ifdef ENABLE_TRACE_NETWORKING
        fprintf(stderr, "Got Windows event WM_HOST_RESOLVED \n");
#endif
        javanotify_socket_event(
            JAVACALL_EVENT_NETWORK_GETHOSTBYNAME_COMPLETED,
            (javacall_handle)wParam,
            (WSAGETSELECTERROR(lParam) == 0) ? JAVACALL_OK : JAVACALL_FAIL);
        return 0;

#if 0 /* media */
    case WM_DEBUGGER:
        pSignalResult->waitingFor = VM_DEBUG_SIGNAL;
        return 0;
    case WM_MEDIA:
        pSignalResult->waitingFor = MEDIA_EVENT_SIGNAL;
        pSignalResult->descriptor = (int)wParam;
        pSignalResult->pResult = (void*)lParam;
        return 0;
#endif /* media */
    default:
        break;
    } /* end of external switch */

    return DefWindowProc (hwnd, iMsg, wParam, lParam);

} /* end of WndProc */
Пример #16
0
/**
 * This method checks to see if the given LCD glyph bounds fall within the
 * cached destination texture bounds.  If so, this method can return
 * immediately.  If not, this method will copy a chunk of framebuffer data
 * into the cached destination texture and then update the current cached
 * destination bounds before returning.
 *
 * The agx1, agx2 are "adjusted" glyph bounds, which are only used when checking
 * against the previous glyph bounds.
 */
static HRESULT
D3DTR_UpdateCachedDestination(D3DContext *d3dc, D3DSDOps *dstOps,
                              GlyphInfo *ginfo,
                              jint gx1, jint gy1, jint gx2, jint gy2,
                              jint agx1, jint agx2,
                              jint glyphIndex, jint totalGlyphs)
{
    jint dx1, dy1, dx2, dy2;
    D3DResource *pCachedDestTexRes;
    IDirect3DSurface9 *pCachedDestSurface, *pDst;
    HRESULT res;

    if (isCachedDestValid && INSIDE(gx1, gy1, gx2, gy2, cachedDestBounds)) {
        // glyph is already within the cached destination bounds; no need
        // to read back the entire destination region again, but we do
        // need to see if the current glyph overlaps the previous glyph...

        // only use the "adjusted" glyph bounds when checking against
        // previous glyph's bounds
        gx1 = agx1;
        gx2 = agx2;

        if (INTERSECTS(gx1, gy1, gx2, gy2, previousGlyphBounds)) {
            // the current glyph overlaps the destination region touched
            // by the previous glyph, so now we need to read back the part
            // of the destination corresponding to the previous glyph
            dx1 = previousGlyphBounds.x1;
            dy1 = previousGlyphBounds.y1;
            dx2 = previousGlyphBounds.x2;
            dy2 = previousGlyphBounds.y2;

            // REMIND: make sure we flush any pending primitives that are
            // dependent on the current contents of the cached dest
            d3dc->FlushVertexQueue();

            RETURN_STATUS_IF_NULL(dstOps->pResource, E_FAIL);
            RETURN_STATUS_IF_NULL(pDst = dstOps->pResource->GetSurface(),
                                  E_FAIL);
            res = d3dc->GetResourceManager()->
                GetCachedDestTexture(dstOps->pResource->GetDesc()->Format,
                                     &pCachedDestTexRes);
            RETURN_STATUS_IF_FAILED(res);
            pCachedDestSurface = pCachedDestTexRes->GetSurface();

            // now dxy12 represent the "desired" destination bounds, but the
            // StretchRect() call may fail if these fall outside the actual
            // surface bounds; therefore, we use cxy12 to represent the
            // clamped bounds, and dxy12 are saved for later
            jint cx1 = (dx1 < 0) ? 0 : dx1;
            jint cy1 = (dy1 < 0) ? 0 : dy1;
            jint cx2 = (dx2 > dstOps->width)  ? dstOps->width  : dx2;
            jint cy2 = (dy2 > dstOps->height) ? dstOps->height : dy2;

            if (cx2 > cx1 && cy2 > cy1) {
                // copy destination into subregion of cached texture tile
                //   cx1-cachedDestBounds.x1 == +xoffset from left of texture
                //   cy1-cachedDestBounds.y1 == +yoffset from top of texture
                //   cx2-cachedDestBounds.x1 == +xoffset from left of texture
                //   cy2-cachedDestBounds.y1 == +yoffset from top of texture
                jint cdx1 = cx1-cachedDestBounds.x1;
                jint cdy1 = cy1-cachedDestBounds.y1;
                jint cdx2 = cx2-cachedDestBounds.x1;
                jint cdy2 = cy2-cachedDestBounds.y1;
                RECT srcRect = {  cx1,  cy1,  cx2,  cy2 };
                RECT dstRect = { cdx1, cdy1, cdx2, cdy2 };

                IDirect3DDevice9 *pd3dDevice = d3dc->Get3DDevice();
                res = pd3dDevice->StretchRect(pDst, &srcRect,
                                              pCachedDestSurface, &dstRect,
                                              D3DTEXF_NONE);
            }
        }
    } else {
        // destination region is not valid, so we need to read back a
        // chunk of the destination into our cached texture

        // position the upper-left corner of the destination region on the
        // "top" line of glyph list
        // REMIND: this isn't ideal; it would be better if we had some idea
        //         of the bounding box of the whole glyph list (this is
        //         do-able, but would require iterating through the whole
        //         list up front, which may present its own problems)
        dx1 = gx1;
        dy1 = gy1;

        jint remainingWidth;
        if (ginfo->advanceX > 0) {
            // estimate the width based on our current position in the glyph
            // list and using the x advance of the current glyph (this is just
            // a quick and dirty heuristic; if this is a "thin" glyph image,
            // then we're likely to underestimate, and if it's "thick" then we
            // may end up reading back more than we need to)
            remainingWidth =
                (jint)(ginfo->advanceX * (totalGlyphs - glyphIndex));
            if (remainingWidth > D3DTR_CACHED_DEST_WIDTH) {
                remainingWidth = D3DTR_CACHED_DEST_WIDTH;
            } else if (remainingWidth < ginfo->width) {
                // in some cases, the x-advance may be slightly smaller
                // than the actual width of the glyph; if so, adjust our
                // estimate so that we can accomodate the entire glyph
                remainingWidth = ginfo->width;
            }
        } else {
            // a negative advance is possible when rendering rotated text,
            // in which case it is difficult to estimate an appropriate
            // region for readback, so we will pick a region that
            // encompasses just the current glyph
            remainingWidth = ginfo->width;
        }
        dx2 = dx1 + remainingWidth;

        // estimate the height (this is another sloppy heuristic; we'll
        // make the cached destination region tall enough to encompass most
        // glyphs that are small enough to fit in the glyph cache, and then
        // we add a little something extra to account for descenders
        dy2 = dy1 + D3DTR_CACHE_CELL_HEIGHT + 2;

        // REMIND: make sure we flush any pending primitives that are
        // dependent on the current contents of the cached dest
        d3dc->FlushVertexQueue();

        RETURN_STATUS_IF_NULL(dstOps->pResource, E_FAIL);
        RETURN_STATUS_IF_NULL(pDst = dstOps->pResource->GetSurface(), E_FAIL);
        res = d3dc->GetResourceManager()->
            GetCachedDestTexture(dstOps->pResource->GetDesc()->Format,
                                 &pCachedDestTexRes);
        RETURN_STATUS_IF_FAILED(res);
        pCachedDestSurface = pCachedDestTexRes->GetSurface();

        // now dxy12 represent the "desired" destination bounds, but the
        // StretchRect() call may fail if these fall outside the actual
        // surface bounds; therefore, we use cxy12 to represent the
        // clamped bounds, and dxy12 are saved for later
        jint cx1 = (dx1 < 0) ? 0 : dx1;
        jint cy1 = (dy1 < 0) ? 0 : dy1;
        jint cx2 = (dx2 > dstOps->width)  ? dstOps->width  : dx2;
        jint cy2 = (dy2 > dstOps->height) ? dstOps->height : dy2;

        if (cx2 > cx1 && cy2 > cy1) {
            // copy destination into cached texture tile (the upper-left
            // corner of the destination region will be positioned at the
            // upper-left corner (0,0) of the texture)
            RECT srcRect = { cx1, cy1, cx2, cy2 };
            RECT dstRect = { cx1-dx1, cy1-dy1, cx2-dx1, cy2-dy1 };

            IDirect3DDevice9 *pd3dDevice = d3dc->Get3DDevice();
            res = pd3dDevice->StretchRect(pDst, &srcRect,
                                          pCachedDestSurface, &dstRect,
                                          D3DTEXF_NONE);
        }

        // update the cached bounds and mark it valid
        cachedDestBounds.x1 = dx1;
        cachedDestBounds.y1 = dy1;
        cachedDestBounds.x2 = dx2;
        cachedDestBounds.y2 = dy2;
        isCachedDestValid = JNI_TRUE;
    }

    // always update the previous glyph bounds
    previousGlyphBounds.x1 = gx1;
    previousGlyphBounds.y1 = gy1;
    previousGlyphBounds.x2 = gx2;
    previousGlyphBounds.y2 = gy2;

    return res;
}
Пример #17
0
mlib_status
__mlib_GraphicsDrawArc_AB_32(
    mlib_image *buffer,
    mlib_s16 x,
    mlib_s16 y,
    mlib_s32 r,
    mlib_f32 t1,
    mlib_f32 t2,
    mlib_s32 c,
    mlib_s32 a)
{
	mlib_s32 stride = mlib_ImageGetStride(buffer) / sizeof (mlib_s32);
	mlib_s32 width = mlib_ImageGetWidth(buffer) - 1;
	mlib_s32 height = mlib_ImageGetHeight(buffer) - 1;
	mlib_s32 *data = mlib_ImageGetData(buffer);
	mlib_s32 *line0, *line;
	mlib_s32 cx, cy, del, mask;

	mlib_s32 sin1, cos1, sin2, cos2, oct1, oct2, flagc, flagd;
	pinfo buf0[BUFSIZE], *buf = 0;
	mlib_s32 count, scount;
	mlib_s32 start, end;

	mlib_s32 ind0, ind1, ind2, mdel, k;
	mlib_d64 c0, c1, c2;
	mlib_f32 cf;
	mlib_d64 d_one = ((mlib_d64 *)mlib_v_TabAlias)[0];

	mlib_s32 a1;
	mlib_f32 fa;
	mlib_d64 da, da1, dc;
	mlib_f32 falpha = vis_to_float(0xFF000000);

	a &= 0xff;
	a1 = ~a & 0xff;

	fa = vis_to_float((a << 16) | (a << 8) | a);
	da = vis_to_double((a << 6), (a << 22) | (a << 6));
	da1 = vis_to_double((a1 << 6), (a1 << 22) | (a1 << 6));
	dc = vis_fmul8x16al(vis_to_float(c), vis_to_float(0x4000));
	vis_write_gsr((1 << 3) + 0);

	c |= 0xFF000000;
	cf = vis_to_float(c);
	if (!data)
		return (MLIB_NULLPOINTER);

	if (r < 0)
		return (MLIB_FAILURE);

	CHECK_INTERSECTION;

	if (r == 0) {
		if (INSIDE(x, y))
			BLE32((data + (stride * y + x)), 0);
		return (MLIB_SUCCESS);
	}

	if (mlib_fabs(t1 - t2) >= PIx2)
		return (__mlib_GraphicsDrawCircle_AB_32(buffer, x, y, r, c, a));
	{
		mlib_f32 tt = t1;

		t1 = -t2;
		t2 = -tt;
	}

	if (t1 > t2)
		t2 += PIx2;

	line0 = data + stride * y + x;

	if (r > RADMAX) {
		buf = (pinfo *) __mlib_malloc(sizeof (pinfo) * r);

		if (!buf)
			return (MLIB_FAILURE);
	} else
		buf = buf0;

	k = (0x100000 / r);

	FILL_BUF;

	GET_BORDERS;

	FILL_FLAGS;

	FILL_CL_FLAGS;

	start = 0;
	end = count;
	PROC_OCT(y, y - height, x - width, x, 2, cos, 1, 2, stride, -1);
	start = 1;
	end = count;
	PROC_OCT(y, y - height, -x, width - x, 1, cos, 2, 1, stride, 1);
	start = 0;
	end = count;
	PROC_OCT(height - y, -y, x - width, x, 5, cos, 2, 1, -stride, -1);
	start = 1;
	end = count;
	PROC_OCT(height - y, -y, -x, width - x, 6, cos, 1, 2, -stride, 1);

	start = 1;
	end = scount;
	PROC_OCT(x, x - width, y - height, y, 3, sin, 2, 1, 1, -stride);
	start = 0;
	end = scount;
	PROC_OCT(x, x - width, -y, height - y, 4, sin, 1, 2, 1, stride);
	start = 1;
	end = scount;
	PROC_OCT(width - x, -x, y - height, y, 0, sin, 1, 2, -1, -stride);
	start = 0;
	end = scount;
	PROC_OCT(width - x, -x, -y, height - y, 7, sin, 2, 1, -1, stride);

	if (buf != buf0)
		__mlib_free(buf);

	return (MLIB_SUCCESS);
}
Пример #18
0
void
plP_plfclp(PLINT *x, PLINT *y, PLINT npts,
	   PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax,
	   void (*draw) (short *, short *, PLINT))
{
    PLINT i, x1, x2, y1, y2;
    int iclp = 0, iout = 2;
    short xclp[2*PL_MAXPOLY+2], yclp[2*PL_MAXPOLY+2];
    int drawable;
    int crossed_xmin1 = 0, crossed_xmax1 = 0;
    int crossed_ymin1 = 0, crossed_ymax1 = 0;
    int crossed_xmin2 = 0, crossed_xmax2 = 0;
    int crossed_ymin2 = 0, crossed_ymax2 = 0;

/* Must have at least 3 points and draw() specified */
    if (npts < 3 || !draw) return;

    for (i = 0; i < npts - 1; i++) {
	x1 = x[i]; x2 = x[i+1];
	y1 = y[i]; y2 = y[i+1];

	drawable = (INSIDE(x1, y1) && INSIDE(x2, y2));
	if ( ! drawable)
	    drawable = ! clipline(&x1, &y1, &x2, &y2, xmin, xmax, ymin, ymax);

	if (!drawable) {
	/* Store the edges outside the viewport */
	    xclp[iout] = x2;
	    yclp[iout] = y2;
	    iout ++;
	} else {
	/* Boundary crossing condition -- coming in. */
	    crossed_xmin2 = (x1 == xmin); crossed_xmax2 = (x1 == xmax);
	    crossed_ymin2 = (y1 == ymin); crossed_ymax2 = (y1 == ymax);
	    iout = iclp+2;

	/* If the first segment, just add it. */

	    if (iclp == 0) {
		xclp[iclp] = x1; yclp[iclp] = y1; iclp++;
		xclp[iclp] = x2; yclp[iclp] = y2; iclp++;
	    }

	/* Not first point.  If first point of this segment matches up to the
	   previous point, just add it.  */

	    else if (x1 == xclp[iclp-1] && y1 == yclp[iclp-1]) {
		xclp[iclp] = x2; yclp[iclp] = y2; iclp++;
	    }

	/* Otherwise, we need to add both points, to connect the points in the
	 * polygon along the clip boundary.  If we encircled a corner, we have
	 * to add that first.
	 */

	    else {
	    /* Treat the case where we encircled two corners:
	       Construct a polygon out of the subset of vertices
	       Note that the direction is important too when adding
	       the extra points */
		xclp[iclp+1] = x2; yclp[iclp+1] = y2;
		xclp[iclp+2] = x1; yclp[iclp+2] = y1;
		iout = iout - iclp;
	    /* Upper two */
		if ( ((crossed_xmin1 && crossed_xmax2) ||
			     (crossed_xmin2 && crossed_xmax1)) &&
			pointinpolygon(iout,&xclp[iclp+1],&yclp[iclp+1],xmin,ymax) )
		{
		    if ( crossed_xmin1 )
		    {
		        xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
		        xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
		    } else {
		        xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
		        xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
		    }
		}
	    /* Lower two */
		else if ( ((crossed_xmin1 && crossed_xmax2) ||
			          (crossed_xmin2 && crossed_xmax1)) &&
			pointinpolygon(iout,&xclp[iclp+1],&yclp[iclp+1],xmin,ymin) )
		{
		    if ( crossed_xmin1 )
		    {
		        xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
		        xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
		    } else {
		        xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
		        xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
		    }
		}
	    /* Left two */
		else if ( ((crossed_ymin1 && crossed_ymax2) ||
			          (crossed_ymin2 && crossed_ymax1)) &&
			pointinpolygon(iout,&xclp[iclp+1],&yclp[iclp+1],xmin,ymin) )
		{
		    if ( crossed_ymin1 )
		    {
		        xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
		        xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
		    } else {
		        xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
		        xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
		    }
		}
	    /* Right two */
		else if ( ((crossed_ymin1 && crossed_ymax2) ||
			          (crossed_ymin2 && crossed_ymax1)) &&
			pointinpolygon(iout,&xclp[iclp+1],&yclp[iclp+1],xmax,ymin) )
		{
		    if ( crossed_ymin1 )
		    {
		        xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
		        xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
		    } else {
		        xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
		        xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
		    }
		}
	    /* Now the case where we encircled one corner */
	    /* Lower left */
		else if ( (crossed_xmin1 && crossed_ymin2) ||
			  (crossed_ymin1 && crossed_xmin2) )
		{
		    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
		}
	    /* Lower right */
		else if ( (crossed_xmax1 && crossed_ymin2) ||
			  (crossed_ymin1 && crossed_xmax2) )
		{
		    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
		}
	    /* Upper left */
		else if ( (crossed_xmin1 && crossed_ymax2) ||
			  (crossed_ymax1 && crossed_xmin2) )
		{
		    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
		}
	    /* Upper right */
		else if ( (crossed_xmax1 && crossed_ymax2) ||
			  (crossed_ymax1 && crossed_xmax2) )
		{
		    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
		}

	    /* Now add current segment. */
		xclp[iclp] = x1; yclp[iclp] = y1; iclp++;
		xclp[iclp] = x2; yclp[iclp] = y2; iclp++;
	    }

	/* Boundary crossing condition -- going out. */
	    crossed_xmin1 = (x2 == xmin); crossed_xmax1 = (x2 == xmax);
	    crossed_ymin1 = (y2 == ymin); crossed_ymax1 = (y2 == ymax);
	}
    }

/* Limit case - all vertices are outside of bounding box.  So just fill entire
   box, *if* the bounding box is completely encircled.
*/

    if (iclp == 0) {
	PLINT xmin1, xmax1, ymin1, ymax1;
	xmin1 = xmax1 = x[0];
	ymin1 = ymax1 = y[0];
	for (i = 1; i < npts; i++) {
	    if (x[i] < xmin1) xmin1 = x[i];
	    if (x[i] > xmax1) xmax1 = x[i];
	    if (y[i] < ymin1) ymin1 = y[i];
	    if (y[i] > ymax1) ymax1 = y[i];
	}
	if (xmin1 <= xmin && xmax1 >= xmax && ymin1 <= ymin && ymax1 >= ymax ) {
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	    (*draw)(xclp, yclp, iclp);
	    return;
	}
    }

/* Now handle cases where fill polygon intersects two sides of the box */

    if (iclp >= 2) {
	int debug=0;
	int dir = circulation(x, y, npts);
	if (debug) {
	    if ( (xclp[0] == xmin && xclp[iclp-1] == xmax) ||
		 (xclp[0] == xmax && xclp[iclp-1] == xmin) ||
		 (yclp[0] == ymin && yclp[iclp-1] == ymax) ||
		 (yclp[0] == ymax && yclp[iclp-1] == ymin) ||
		 (xclp[0] == xmin && yclp[iclp-1] == ymin) ||
		 (yclp[0] == ymin && xclp[iclp-1] == xmin) ||
		 (xclp[0] == xmax && yclp[iclp-1] == ymin) ||
		 (yclp[0] == ymin && xclp[iclp-1] == xmax) ||
		 (xclp[0] == xmax && yclp[iclp-1] == ymax) ||
		 (yclp[0] == ymax && xclp[iclp-1] == xmax) ||
		 (xclp[0] == xmin && yclp[iclp-1] == ymax) ||
		 (yclp[0] == ymax && xclp[iclp-1] == xmin) ) {
		printf("dir=%d, clipped points:\n", dir);
		for (i=0; i < iclp; i++)
		    printf(" x[%d]=%d y[%d]=%d", i, xclp[i], i, yclp[i]);
		printf("\n");
		printf("pre-clipped points:\n");
		for (i=0; i < npts; i++)
		    printf(" x[%d]=%d y[%d]=%d", i, x[i], i, y[i]);
		printf("\n");
	    }
	}

    /* The cases where the fill region is divided 2/2 */
    /* Divided horizontally */
	if (xclp[0] == xmin && xclp[iclp-1] == xmax)
	{
	    if (dir > 0) {
		xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
		xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    }
	    else {
		xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
		xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	    }
	}
	else if (xclp[0] == xmax && xclp[iclp-1] == xmin)
	{
	    if (dir > 0) {
		xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
		xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	    }
	    else {
		xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
		xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	    }
	}

    /* Divided vertically */
	else if (yclp[0] == ymin && yclp[iclp-1] == ymax)
	{
	    if (dir > 0) {
		xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
		xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	    }
	    else {
		xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
		xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	    }
	}
	else if (yclp[0] == ymax && yclp[iclp-1] == ymin)
	{
	    if (dir > 0) {
		xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
		xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	    }
	    else {
		xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
		xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    }
	}

    /* The cases where the fill region is divided 3/1 --
          LL           LR           UR           UL
       +-----+      +-----+      +-----+      +-----+
       |     |      |     |      |    \|      |/    |
       |     |      |     |      |     |      |     |
       |\    |      |    /|      |     |      |     |
       +-----+      +-----+      +-----+      +-----+

       Note when we go the long way around, if the direction is reversed the
       three vertices must be visited in the opposite order.
    */
    /* LL, short way around */
	else if ((xclp[0] == xmin && yclp[iclp-1] == ymin && dir < 0) ||
		 (yclp[0] == ymin && xclp[iclp-1] == xmin && dir > 0) )
	{
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	}
    /* LL, long way around, counterclockwise */
	else if ((xclp[0] == xmin && yclp[iclp-1] == ymin && dir > 0))
	{
	    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	}
    /* LL, long way around, clockwise */
	else if ((yclp[0] == ymin && xclp[iclp-1] == xmin && dir < 0))
	{
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	}
    /* LR, short way around */
	else if ((xclp[0] == xmax && yclp[iclp-1] == ymin && dir > 0) ||
		 (yclp[0] == ymin && xclp[iclp-1] == xmax && dir < 0) )
	{
	    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	}
    /* LR, long way around, counterclockwise */
	else if (yclp[0] == ymin && xclp[iclp-1] == xmax && dir > 0)
	{
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	}
    /* LR, long way around, clockwise */
	else if (xclp[0] == xmax && yclp[iclp-1] == ymin && dir < 0)
	{
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	}
    /* UR, short way around */
	else if ((xclp[0] == xmax && yclp[iclp-1] == ymax && dir < 0) ||
		 (yclp[0] == ymax && xclp[iclp-1] == xmax && dir > 0) )
	{
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	}
    /* UR, long way around, counterclockwise */
	else if (xclp[0] == xmax && yclp[iclp-1] == ymax && dir > 0)
	{
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	}
    /* UR, long way around, clockwise */
	else if (yclp[0] == ymax && xclp[iclp-1] == xmax && dir < 0)
	{
	    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	}
    /* UL, short way around */
	else if ((xclp[0] == xmin && yclp[iclp-1] == ymax && dir > 0) ||
		 (yclp[0] == ymax && xclp[iclp-1] == xmin && dir < 0) )
	{
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	}
    /* UL, long way around, counterclockwise */
	else if (yclp[0] == ymax && xclp[iclp-1] == xmin && dir > 0)
	{
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymin; iclp++;
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	}
    /* UL, long way around, clockwise */
	else if (xclp[0] == xmin && yclp[iclp-1] == ymax && dir < 0)
	{
	    xclp[iclp] = xmax; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymax; iclp++;
	    xclp[iclp] = xmin; yclp[iclp] = ymin; iclp++;
	}
    }

/* Draw the sucker */
    if (iclp >= 3)
	(*draw)(xclp, yclp, iclp);
}