9fans.net/go@v0.0.5/draw/memdraw/ldraw.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 _Draw struct {
    14  	deltas   draw.Point
    15  	deltam   draw.Point
    16  	dstlayer *Layer
    17  	src      *Image
    18  	mask     *Image
    19  	op       draw.Op
    20  }
    21  
    22  func ldrawop(dst *Image, screenr draw.Rectangle, clipr draw.Rectangle, etc interface{}, insave int) {
    23  	d := etc.(*_Draw)
    24  	if insave != 0 && d.dstlayer.save == nil {
    25  		return
    26  	}
    27  
    28  	p0 := screenr.Min.Add(d.deltas)
    29  	p1 := screenr.Min.Add(d.deltam)
    30  	var r draw.Rectangle
    31  
    32  	if insave != 0 {
    33  		r = screenr.Sub(d.dstlayer.Delta)
    34  		clipr = clipr.Sub(d.dstlayer.Delta)
    35  	} else {
    36  		r = screenr
    37  	}
    38  
    39  	/* now in logical coordinates */
    40  
    41  	/* clipr may have narrowed what we should draw on, so clip if necessary */
    42  	if !draw.RectInRect(r, clipr) {
    43  		oclipr := dst.Clipr
    44  		dst.Clipr = clipr
    45  		var mr draw.Rectangle
    46  		var srcr draw.Rectangle
    47  		ok := drawclip(dst, &r, d.src, &p0, d.mask, &p1, &srcr, &mr)
    48  		dst.Clipr = oclipr
    49  		if ok == 0 {
    50  			return
    51  		}
    52  	}
    53  	Draw(dst, r, d.src, p0, d.mask, p1, d.op)
    54  }
    55  
    56  func Draw(dst *Image, r draw.Rectangle, src *Image, p0 draw.Point, mask *Image, p1 draw.Point, op draw.Op) {
    57  	if drawdebug != 0 {
    58  		iprint("memdraw %p %v %p %v %p %v\n", dst, r, src, p0, mask, p1)
    59  	}
    60  
    61  	if mask == nil {
    62  		mask = Opaque
    63  	}
    64  
    65  	if mask.Layer != nil {
    66  		if drawdebug != 0 {
    67  			iprint("mask->layer != nil\n")
    68  		}
    69  		return /* too hard, at least for now */
    70  	}
    71  
    72  Top:
    73  	if dst.Layer == nil && src.Layer == nil {
    74  		dst.Draw(r, src, p0, mask, p1, op)
    75  		return
    76  	}
    77  	var srcr draw.Rectangle
    78  	var mr draw.Rectangle
    79  
    80  	if drawclip(dst, &r, src, &p0, mask, &p1, &srcr, &mr) == 0 {
    81  		if drawdebug != 0 {
    82  			iprint("drawclip dstcr %v srccr %v maskcr %v\n", dst.Clipr, src.Clipr, mask.Clipr)
    83  		}
    84  		return
    85  	}
    86  
    87  	/*
    88  	 * Convert to screen coordinates.
    89  	 */
    90  	dl := dst.Layer
    91  	if dl != nil {
    92  		r.Min.X += dl.Delta.X
    93  		r.Min.Y += dl.Delta.Y
    94  		r.Max.X += dl.Delta.X
    95  		r.Max.Y += dl.Delta.Y
    96  	}
    97  Clearlayer:
    98  	if dl != nil && dl.clear {
    99  		if src == dst {
   100  			p0.X += dl.Delta.X
   101  			p0.Y += dl.Delta.Y
   102  			src = dl.Screen.Image
   103  		}
   104  		dst = dl.Screen.Image
   105  		goto Top
   106  	}
   107  
   108  	sl := src.Layer
   109  	if sl != nil {
   110  		p0.X += sl.Delta.X
   111  		p0.Y += sl.Delta.Y
   112  		srcr.Min.X += sl.Delta.X
   113  		srcr.Min.Y += sl.Delta.Y
   114  		srcr.Max.X += sl.Delta.X
   115  		srcr.Max.Y += sl.Delta.Y
   116  	}
   117  
   118  	/*
   119  	 * Now everything is in screen coordinates.
   120  	 * mask is an image.  dst and src are images or obscured layers.
   121  	 */
   122  
   123  	/*
   124  	 * if dst and src are the same layer, just draw in save area and expose.
   125  	 */
   126  	if dl != nil && dst == src {
   127  		if dl.save == nil {
   128  			return /* refresh function makes this case unworkable */
   129  		}
   130  		if draw.RectXRect(r, srcr) {
   131  			tr := r
   132  			if srcr.Min.X < tr.Min.X {
   133  				p1.X += tr.Min.X - srcr.Min.X
   134  				tr.Min.X = srcr.Min.X
   135  			}
   136  			if srcr.Min.Y < tr.Min.Y {
   137  				p1.Y += tr.Min.X - srcr.Min.X
   138  				tr.Min.Y = srcr.Min.Y
   139  			}
   140  			if srcr.Max.X > tr.Max.X {
   141  				tr.Max.X = srcr.Max.X
   142  			}
   143  			if srcr.Max.Y > tr.Max.Y {
   144  				tr.Max.Y = srcr.Max.Y
   145  			}
   146  			memlhide(dst, tr)
   147  		} else {
   148  			memlhide(dst, r)
   149  			memlhide(dst, srcr)
   150  		}
   151  		Draw(dl.save, r.Sub(dl.Delta), dl.save, srcr.Min.Sub(src.Layer.Delta), mask, p1, op)
   152  		memlexpose(dst, r)
   153  		return
   154  	}
   155  
   156  	if sl != nil {
   157  		if sl.clear {
   158  			src = sl.Screen.Image
   159  			if dl != nil {
   160  				r.Min.X -= dl.Delta.X
   161  				r.Min.Y -= dl.Delta.Y
   162  				r.Max.X -= dl.Delta.X
   163  				r.Max.Y -= dl.Delta.Y
   164  			}
   165  			goto Top
   166  		}
   167  		/* relatively rare case; use save area */
   168  		if sl.save == nil {
   169  			return /* refresh function makes this case unworkable */
   170  		}
   171  		memlhide(src, srcr)
   172  		/* convert back to logical coordinates */
   173  		p0.X -= sl.Delta.X
   174  		p0.Y -= sl.Delta.Y
   175  		srcr.Min.X -= sl.Delta.X
   176  		srcr.Min.Y -= sl.Delta.Y
   177  		srcr.Max.X -= sl.Delta.X
   178  		srcr.Max.Y -= sl.Delta.Y
   179  		src = src.Layer.save
   180  	}
   181  
   182  	/*
   183  	 * src is now an image.  dst may be an image or a clear layer
   184  	 */
   185  	if dst.Layer == nil {
   186  		goto Top
   187  	}
   188  	if dst.Layer.clear {
   189  		goto Clearlayer
   190  	}
   191  	var d _Draw
   192  
   193  	/*
   194  	 * dst is an obscured layer
   195  	 */
   196  	d.deltas = p0.Sub(r.Min)
   197  	d.deltam = p1.Sub(r.Min)
   198  	d.dstlayer = dl
   199  	d.src = src
   200  	d.op = op
   201  	d.mask = mask
   202  	_memlayerop(ldrawop, dst, r, r, &d)
   203  }