void
twin_path_draw (twin_path_t *path, twin_fixed_t x, twin_fixed_t y)
{
    _twin_path_sdraw (path, 
		      _twin_matrix_x (&path->state.matrix, x, y),
		      _twin_matrix_y (&path->state.matrix, x, y));
}
void
twin_path_rdraw (twin_path_t *path, twin_fixed_t dx, twin_fixed_t dy)
{
    twin_spoint_t   here = _twin_path_current_spoint (path);
    _twin_path_sdraw (path, 
		      here.x +
		      _twin_matrix_dx (&path->state.matrix, dx, dy),
		      here.y + 
		      _twin_matrix_dy (&path->state.matrix, dx, dy));
}
void 
_twin_path_smove (twin_path_t *path, twin_sfixed_t x, twin_sfixed_t y)
{
    switch (_twin_current_subpath_len (path)) {
    default:
	_twin_path_sfinish (path);
    case 0:
	_twin_path_sdraw (path, x, y);
	break;
    case 1:
	path->points[path->npoints-1].x = x;
	path->points[path->npoints-1].y = y;
	break;
    }
}
void
twin_path_close (twin_path_t *path)
{
    twin_spoint_t   f;
    
    switch (_twin_current_subpath_len(path)) {
    case 0:
    case 1:
	break;
    default:
	f = _twin_path_subpath_first_spoint (path);
	_twin_path_sdraw (path, f.x, f.y);
	break;
    }
}
void
twin_path_append (twin_path_t *dst, twin_path_t *src)
{
    int	    p;
    int	    s = 0;

    for (p = 0; p < src->npoints; p++)
    {
	if (s < src->nsublen && p == src->sublen[s])
	{
	    _twin_path_sfinish (dst);
	    s++;
	}
	_twin_path_sdraw (dst, src->points[p].x, src->points[p].y);
    }
}
示例#6
0
文件: twin_hull.c 项目: Joouis/EVGUI
/*
 * Convert the hull structure back to a simple path
 */
static twin_path_t *
_twin_hull_to_path (twin_hull_t *hull, int num_hull)
{
    twin_path_t	*path = twin_path_create ();
    int		i;

    DBGMSG (("convex hull\n"));
    for (i = 0; i < num_hull; i++) 
    {
	DBGMSG (("\t%d: %9.4f, %9.4f %c\n",
		 i, S(hull[i].point.x), S(hull[i].point.y), 
		 hull[i].discard ? '*' : ' '));
	if (hull[i].discard)
	    continue;
	_twin_path_sdraw (path, hull[i].point.x, hull[i].point.y);
    }

    return path;
}
/*
 * Convolve one subpath with a convex pen.  The result is
 * a closed path.
 */
static void
_twin_subpath_convolve (twin_path_t	*path,
			twin_path_t	*stroke,
			twin_path_t	*pen)
{
    twin_spoint_t   *sp   = stroke->points;
    twin_spoint_t   *pp   = pen->points;
    int		    ns    = stroke->npoints;
    int		    np    = pen->npoints;
    twin_spoint_t   *sp0  = &sp[0];
    twin_spoint_t   *sp1  = &sp[1];
    int		    start = _twin_path_leftpoint (pen, sp0, sp1);
    twin_spoint_t   *spn1 = &sp[ns-1];
    twin_spoint_t   *spn2 = &sp[ns-2];
    int		    ret   = _twin_path_leftpoint (pen, spn1, spn2);
    int		    p;
    int		    s;
    int		    starget;
    int		    ptarget;
    int		    inc;
    int		    first;

    DBGOUT ("convolve stroke:\n");
    for (s = 0; s < ns; s++)
	DBGOUT ("\ts%02d: %9.4f, %9.4f\n", s, F(sp[s].x), F(sp[s].y));
    DBGOUT ("convolve pen:\n");
    for (p = 0; p < np; p++)
	DBGOUT ("\tp%02d: %9.4f, %9.4f\n", p, F(pp[p].x), F(pp[p].y));
    
    s = 0;
    p = start;
    DBGOUT ("start:  ");
    DBGOUT ("s%02d (%9.4f, %9.4f), p%02d (%9.4f, %9.4f): %9.4f, %9.4f\n",
	    s, F(sp[s].x), F(sp[s].y),
	    p, F(pp[p].x), F(pp[p].y),
	    F(sp[s].x + pp[p].x), F(sp[s].y + pp[p].y));
    _twin_path_smove (path, sp[s].x + pp[p].x, sp[s].y + pp[p].y);
    first = path->npoints - 1;
    
    /* step along the path first */
    inc = 1;
    starget = ns-1;
    ptarget = ret;
    for (;;)
    {
	/*
	 * Convolve the edges
	 */
	do
	{
	    int	sn = s + inc;
	    int	pn = (p == np - 1) ? 0 : p + 1;
	    int	pm = (p == 0) ? np - 1 : p - 1;
    
	    /*
	     * step along pen (forwards or backwards) or stroke as appropriate
	     */
	     
	    DBGOUT ("\tangles: stroke %9.4f +pen %9.4f -pen %9.4f\n",
		    _angle (&sp[s], &sp[sn]),
		    _angle (&pp[p], &pp[pn]),
		    _angle (&pp[pm], &pp[p]));
	    if (_around_order (&sp[s],&sp[sn],&pp[p],&pp[pn]) > 0)
	    {
		DBGOUT ("+pen:   ");
		p = pn;
	    }
	    else if (_around_order (&sp[s],&sp[sn],&pp[pm],&pp[p]) < 0)
	    {
		DBGOUT ("-pen:   ");
		p = pm;
	    }
	    else
	    {
		DBGOUT ("stroke: ");
		s = sn;
	    }
	    DBGOUT ("s%02d (%9.4f, %9.4f), p%02d (%9.4f, %9.4f): %9.4f, %9.4f\n",
		    s, F(sp[s].x), F(sp[s].y),
		    p, F(pp[p].x), F(pp[p].y),
		    F(sp[s].x + pp[p].x), F(sp[s].y + pp[p].y));
	    _twin_path_sdraw (path, sp[s].x + pp[p].x, sp[s].y + pp[p].y);
	} while (s != starget);
	
	/*
	 * Finish this edge
	 */
	
	/* draw a cap */
	switch (path->state.cap_style) {
	    int		pm;
	case TwinCapProjecting:
	    /*
	     * This draws a rough projecting cap using the
	     * pen.
	     *
	     * First, project the line forward one pen radius
	     * by finding the pen location halfway between the
	     * two normals.
	     *
	     * Then, just add that to the normals themselves to
	     * find the corners of the projecting cap.  
	     * 
	     * The result may have significant error, so overwrite
	     * the existing corners with the new coordinates to
	     * avoid a kink.
	     */
	    if (p <= ptarget)
		pm = (ptarget + p) >> 1;
	    else
	    {
		pm = (ptarget + np + p) >> 1;
		if (pm >= np) pm -= np;
	    }
	    
	    /* replace last point with corner of cap */
	    path->npoints--;
	    _twin_path_sdraw (path,
			      sp[s].x + pp[pm].x + pp[p].x,
			      sp[s].y + pp[pm].y + pp[p].y);
	    p = ptarget;
	    if (inc == 1)
	    {
		/* start next line at cap corner */
		_twin_path_sdraw (path,
				  sp[s].x + pp[pm].x + pp[p].x,
				  sp[s].y + pp[pm].y + pp[p].y);
	    }
	    else
	    {
		/* overwrite initial point */
		path->points[first].x = sp[s].x + pp[pm].x + pp[p].x;
		path->points[first].y = sp[s].y + pp[pm].y + pp[p].y;
	    }
	    break;
	case TwinCapButt:
	    p = ptarget-1;
	    /* fall through … */
	case TwinCapRound:
	    while (p != ptarget)
	    {
		if (++p == np) p = 0;
		DBGOUT("cap:    ");
		DBGOUT ("s%02d (%9.4f, %9.4f), p%02d (%9.4f, %9.4f): %9.4f, %9.4f\n",
			s, F(sp[s].x), F(sp[s].y),
			p, F(pp[p].x), F(pp[p].y),
			F(sp[s].x + pp[p].x), F(sp[s].y + pp[p].y));
		_twin_path_sdraw (path, sp[s].x + pp[p].x, sp[s].y + pp[p].y);
	    }
	    break;
	}
	
	if (inc == -1)
	    break;
	
	/* reach the end of the path?  Go back the other way now */
	inc = -1;
	ptarget = start;
	starget = 0;
    }