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 }