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 }