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

     1  package draw
     2  
     3  import (
     4  	"log"
     5  )
     6  
     7  var (
     8  	grTmp [4]*Image
     9  	grRed *Image
    10  )
    11  
    12  var sweep = Cursor{
    13  	Point{-7, -7},
    14  	[2 * 16]uint8{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07,
    15  		0xE0, 0x07, 0xE0, 0x07, 0xE3, 0xF7, 0xE3, 0xF7,
    16  		0xE3, 0xE7, 0xE3, 0xF7, 0xE3, 0xFF, 0xE3, 0x7F,
    17  		0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
    18  	[2 * 16]uint8{0x00, 0x00, 0x7F, 0xFE, 0x40, 0x02, 0x40, 0x02,
    19  		0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x41, 0xE2,
    20  		0x41, 0xC2, 0x41, 0xE2, 0x41, 0x72, 0x40, 0x38,
    21  		0x40, 0x1C, 0x40, 0x0E, 0x7F, 0xE6, 0x00, 0x00},
    22  }
    23  
    24  const BorderWidth = 4
    25  
    26  func brects(r Rectangle) [4]Rectangle {
    27  	const W = BorderWidth
    28  	if r.Dx() < 2*W {
    29  		r.Max.X = r.Min.X + 2*W
    30  	}
    31  	if r.Dy() < 2*W {
    32  		r.Max.Y = r.Min.Y + 2*W
    33  	}
    34  	var rp [4]Rectangle
    35  	rp[0] = Rect(r.Min.X, r.Min.Y, r.Max.X, r.Min.Y+W)
    36  	rp[1] = Rect(r.Min.X, r.Max.Y-W, r.Max.X, r.Max.Y)
    37  	rp[2] = Rect(r.Min.X, r.Min.Y+W, r.Min.X+W, r.Max.Y-W)
    38  	rp[3] = Rect(r.Max.X-W, r.Min.Y+W, r.Max.X, r.Max.Y-W)
    39  	return rp
    40  }
    41  
    42  func SweepRect(but int, mc *Mousectl) Rectangle {
    43  	but = 1 << (but - 1)
    44  	mc.Display.SwitchCursor(&sweep)
    45  	for mc.Buttons != 0 {
    46  		mc.Read()
    47  	}
    48  	for mc.Buttons&but == 0 {
    49  		mc.Read()
    50  		if mc.Buttons&(7^but) != 0 {
    51  			for mc.Buttons != 0 {
    52  				mc.Read()
    53  			}
    54  			return ZR
    55  		}
    56  	}
    57  	r := Rectangle{Min: mc.Point, Max: mc.Point}
    58  	var rc Rectangle
    59  	for {
    60  		rc = r.Canon()
    61  		drawgetrect(mc.Display, rc, true)
    62  		mc.Read()
    63  		drawgetrect(mc.Display, rc, false)
    64  		r.Max = mc.Point
    65  		if mc.Buttons != but {
    66  			break
    67  		}
    68  	}
    69  
    70  	mc.Display.SwitchCursor(nil)
    71  	if mc.Buttons&(7^but) != 0 {
    72  		rc = ZR
    73  		for mc.Buttons != 0 {
    74  			mc.Read()
    75  		}
    76  	}
    77  	return rc
    78  }
    79  
    80  func freegrtmp() {
    81  	grTmp[0].Free()
    82  	grTmp[1].Free()
    83  	grTmp[2].Free()
    84  	grTmp[3].Free()
    85  	grRed.Free()
    86  	grTmp = [4]*Image{}
    87  	grRed = nil
    88  }
    89  
    90  func max(a, b int) int {
    91  	if a > b {
    92  		return a
    93  	}
    94  	return b
    95  }
    96  
    97  func drawgetrect(display *Display, rc Rectangle, up bool) {
    98  	screen := display.ScreenImage
    99  	/*
   100  	 * BUG: if for some reason we have two of these going on at once
   101  	 * when we must grow the tmp buffers, we lose data.  Also if tmp
   102  	 * is unallocated and we ask to restore the screen, it would be nice
   103  	 * to complain, but we silently make a mess.
   104  	 */
   105  	if up && grTmp[0] != nil {
   106  		if grTmp[0].R.Dx() < rc.Dx() || grTmp[2].R.Dy() < rc.Dy() {
   107  			freegrtmp()
   108  		}
   109  	}
   110  	if grTmp[0] == nil {
   111  		const W = BorderWidth
   112  		r := Rect(0, 0, max(screen.R.Dx(), rc.Dx()), W)
   113  		grTmp[0], _ = display.AllocImage(r, screen.Pix, false, White)
   114  		grTmp[1], _ = display.AllocImage(r, screen.Pix, false, White)
   115  		r = Rect(0, 0, W, max(screen.R.Dy(), rc.Dy()))
   116  		grTmp[2], _ = display.AllocImage(r, screen.Pix, false, White)
   117  		grTmp[3], _ = display.AllocImage(r, screen.Pix, false, White)
   118  		grRed, _ = display.AllocImage(Rect(0, 0, 1, 1), screen.Pix, true, Red)
   119  		if grTmp[0] == nil || grTmp[1] == nil || grTmp[2] == nil || grTmp[3] == nil || grRed == nil {
   120  			freegrtmp()
   121  			log.Fatalf("getrect: allocimage failed")
   122  		}
   123  	}
   124  	rects := brects(rc)
   125  	if !up {
   126  		for i := 0; i < 4; i++ {
   127  			screen.Draw(rects[i], grTmp[i], nil, ZP)
   128  		}
   129  		return
   130  	}
   131  	for i := 0; i < 4; i++ {
   132  		grTmp[i].Draw(Rect(0, 0, rects[i].Dx(), rects[i].Dy()), screen, nil, rects[i].Min)
   133  		screen.Draw(rects[i], grRed, nil, ZP)
   134  	}
   135  }