9fans.net/go@v0.0.5/draw/memdraw/lline.go (about)

     1  // #include <u.h>
     2  // #include <libc.h>
     3  // #include <draw.h>
     4  // #include <memdraw.h>
     5  // #include <memlayer.h>
     6  
     7  package memdraw
     8  
     9  import (
    10  	"9fans.net/go/draw"
    11  )
    12  
    13  type lline struct {
    14  	p0       draw.Point
    15  	p1       draw.Point
    16  	delta    draw.Point
    17  	end0     draw.End
    18  	end1     draw.End
    19  	radius   int
    20  	sp       draw.Point
    21  	dstlayer *Layer
    22  	src      *Image
    23  	op       draw.Op
    24  }
    25  
    26  func _memline(dst *Image, p0 draw.Point, p1 draw.Point, end0, end1 draw.End, radius int, src *Image, sp draw.Point, clipr draw.Rectangle, op draw.Op) {
    27  	if radius < 0 {
    28  		return
    29  	}
    30  	if src.Layer != nil { /* can't draw line with layered source */
    31  		return
    32  	}
    33  	srcclipped := 0
    34  
    35  Top:
    36  	dl := dst.Layer
    37  	if dl == nil {
    38  		_memimageline(dst, p0, p1, end0, end1, radius, src, sp, clipr, op)
    39  		return
    40  	}
    41  	if srcclipped == 0 {
    42  		d := sp.Sub(p0)
    43  		if !draw.RectClip(&clipr, src.Clipr.Sub(d)) {
    44  			return
    45  		}
    46  		if src.Flags&Frepl == 0 && !draw.RectClip(&clipr, src.R.Sub(d)) {
    47  			return
    48  		}
    49  		srcclipped = 1
    50  	}
    51  
    52  	/* dst is known to be a layer */
    53  	p0.X += dl.Delta.X
    54  	p0.Y += dl.Delta.Y
    55  	p1.X += dl.Delta.X
    56  	p1.Y += dl.Delta.Y
    57  	clipr.Min.X += dl.Delta.X
    58  	clipr.Min.Y += dl.Delta.Y
    59  	clipr.Max.X += dl.Delta.X
    60  	clipr.Max.Y += dl.Delta.Y
    61  	if dl.clear {
    62  		dst = dst.Layer.Screen.Image
    63  		goto Top
    64  	}
    65  
    66  	/* XXX */
    67  	/* this is not the correct set of tests */
    68  	/*	if(log2[dst->depth] != log2[src->depth] || log2[dst->depth]!=3) */
    69  	/*		return; */
    70  
    71  	/* can't use sutherland-cohen clipping because lines are wide */
    72  	r := LineBBox(p0, p1, end0, end1, radius)
    73  	/*
    74  	 * r is now a bounding box for the line;
    75  	 * use it as a clipping rectangle for subdivision
    76  	 */
    77  	if !draw.RectClip(&r, clipr) {
    78  		return
    79  	}
    80  	var ll lline
    81  	ll.p0 = p0
    82  	ll.p1 = p1
    83  	ll.end0 = end0
    84  	ll.end1 = end1
    85  	ll.sp = sp
    86  	ll.dstlayer = dst.Layer
    87  	ll.src = src
    88  	ll.radius = radius
    89  	ll.delta = dl.Delta
    90  	ll.op = op
    91  	_memlayerop(llineop, dst, r, r, &ll)
    92  }
    93  
    94  func llineop(dst *Image, screenr draw.Rectangle, clipr draw.Rectangle, etc interface{}, insave int) {
    95  	ll := etc.(*lline)
    96  	if insave != 0 && ll.dstlayer.save == nil {
    97  		return
    98  	}
    99  	if !draw.RectClip(&clipr, screenr) {
   100  		return
   101  	}
   102  	var p0 draw.Point
   103  	var p1 draw.Point
   104  	if insave != 0 {
   105  		p0 = ll.p0.Sub(ll.delta)
   106  		p1 = ll.p1.Sub(ll.delta)
   107  		clipr = clipr.Sub(ll.delta)
   108  	} else {
   109  		p0 = ll.p0
   110  		p1 = ll.p1
   111  	}
   112  	_memline(dst, p0, p1, ll.end0, ll.end1, ll.radius, ll.src, ll.sp, clipr, ll.op)
   113  }
   114  
   115  func Line(dst *Image, p0 draw.Point, p1 draw.Point, end0, end1 draw.End, radius int, src *Image, sp draw.Point, op draw.Op) {
   116  	_memline(dst, p0, p1, end0, end1, radius, src, sp, dst.Clipr, op)
   117  }