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

     1  package memdraw
     2  
     3  import (
     4  	"9fans.net/go/draw"
     5  )
     6  
     7  func _layerop(fn func(*Image, draw.Rectangle, draw.Rectangle, interface{}, int), i *Image, r draw.Rectangle, clipr draw.Rectangle, etc interface{}, front *Image) {
     8  	RECUR := func(a, b, c, d draw.Point) {
     9  		_layerop(fn, i, draw.Rect(a.X, b.Y, c.X, d.Y), clipr, etc, front.Layer.rear)
    10  	}
    11  
    12  Top:
    13  	if front == i {
    14  		/* no one is in front of this part of window; use the screen */
    15  		fn(i.Layer.Screen.Image, r, clipr, etc, 0)
    16  		return
    17  	}
    18  	fr := front.Layer.Screenr
    19  	if !draw.RectXRect(r, fr) {
    20  		/* r doesn't touch this window; continue on next rearmost */
    21  		/* assert(front && front->layer && front->layer->screen && front->layer->rear); */
    22  		front = front.Layer.rear
    23  		goto Top
    24  	}
    25  	if fr.Max.Y < r.Max.Y {
    26  		RECUR(r.Min, fr.Max, r.Max, r.Max)
    27  		r.Max.Y = fr.Max.Y
    28  	}
    29  	if r.Min.Y < fr.Min.Y {
    30  		RECUR(r.Min, r.Min, r.Max, fr.Min)
    31  		r.Min.Y = fr.Min.Y
    32  	}
    33  	if fr.Max.X < r.Max.X {
    34  		RECUR(fr.Max, r.Min, r.Max, r.Max)
    35  		r.Max.X = fr.Max.X
    36  	}
    37  	if r.Min.X < fr.Min.X {
    38  		RECUR(r.Min, r.Min, fr.Min, r.Max)
    39  		r.Min.X = fr.Min.X
    40  	}
    41  	/* r is covered by front, so put in save area */
    42  	fn(i.Layer.save, r, clipr, etc, 1)
    43  }
    44  
    45  /*
    46   * Assumes incoming rectangle has already been clipped to i's logical r and clipr
    47   */
    48  func _memlayerop(fn func(*Image, draw.Rectangle, draw.Rectangle, interface{}, int), i *Image, screenr draw.Rectangle, clipr draw.Rectangle, etc interface{}) {
    49  	l := i.Layer
    50  	if !draw.RectClip(&screenr, l.Screenr) {
    51  		return
    52  	}
    53  	if l.clear {
    54  		fn(l.Screen.Image, screenr, clipr, etc, 0)
    55  		return
    56  	}
    57  	r := screenr
    58  	scr := l.Screen.Image.Clipr
    59  
    60  	/*
    61  	 * Do the piece on the screen
    62  	 */
    63  	if draw.RectClip(&screenr, scr) {
    64  		_layerop(fn, i, screenr, clipr, etc, l.Screen.Frontmost)
    65  	}
    66  	if draw.RectInRect(r, scr) {
    67  		return
    68  	}
    69  
    70  	/*
    71  	 * Do the piece off the screen
    72  	 */
    73  	if !draw.RectXRect(r, scr) {
    74  		/* completely offscreen; easy */
    75  		fn(l.save, r, clipr, etc, 1)
    76  		return
    77  	}
    78  	if r.Min.Y < scr.Min.Y {
    79  		/* above screen */
    80  		fn(l.save, draw.Rect(r.Min.X, r.Min.Y, r.Max.X, scr.Min.Y), clipr, etc, 1)
    81  		r.Min.Y = scr.Min.Y
    82  	}
    83  	if r.Max.Y > scr.Max.Y {
    84  		/* below screen */
    85  		fn(l.save, draw.Rect(r.Min.X, scr.Max.Y, r.Max.X, r.Max.Y), clipr, etc, 1)
    86  		r.Max.Y = scr.Max.Y
    87  	}
    88  	if r.Min.X < scr.Min.X {
    89  		/* left of screen */
    90  		fn(l.save, draw.Rect(r.Min.X, r.Min.Y, scr.Min.X, r.Max.Y), clipr, etc, 1)
    91  		r.Min.X = scr.Min.X
    92  	}
    93  	if r.Max.X > scr.Max.X {
    94  		/* right of screen */
    95  		fn(l.save, draw.Rect(scr.Max.X, r.Min.Y, r.Max.X, r.Max.Y), clipr, etc, 1)
    96  	}
    97  }