github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/exp/shiny/driver/windriver/windraw.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build windows 6 7 package windriver 8 9 import ( 10 "syscall" 11 "unsafe" 12 13 "golang.org/x/exp/shiny/driver/internal/win32" 14 ) 15 16 func mkbitmap(dx, dy int32) (syscall.Handle, *byte, error) { 17 bi := _BITMAPINFO{ 18 Header: _BITMAPINFOHEADER{ 19 Size: uint32(unsafe.Sizeof(_BITMAPINFOHEADER{})), 20 Width: dx, 21 Height: -dy, // negative height to force top-down drawing 22 Planes: 1, 23 BitCount: 32, 24 Compression: _BI_RGB, 25 SizeImage: uint32(dx * dy * 4), 26 }, 27 } 28 29 var ppvBits *byte 30 bitmap, err := _CreateDIBSection(0, &bi, _DIB_RGB_COLORS, &ppvBits, 0, 0) 31 if err != nil { 32 return 0, nil, err 33 } 34 return bitmap, ppvBits, nil 35 } 36 37 func blend(dc win32.HDC, bitmap syscall.Handle, dr *_RECT, sdx int32, sdy int32) (err error) { 38 compatibleDC, err := _CreateCompatibleDC(dc) 39 if err != nil { 40 return err 41 } 42 defer func() { 43 err2 := _DeleteDC(compatibleDC) 44 if err == nil { 45 err = err2 46 } 47 }() 48 prevBitmap, err := _SelectObject(compatibleDC, bitmap) 49 if err != nil { 50 return err 51 } 52 53 blendfunc := _BLENDFUNCTION{ 54 BlendOp: _AC_SRC_OVER, 55 BlendFlags: 0, 56 SourceConstantAlpha: 255, // only use per-pixel alphas 57 AlphaFormat: _AC_SRC_ALPHA, // premultiplied 58 } 59 err = _AlphaBlend(dc, dr.Left, dr.Top, 60 dr.Right-dr.Left, dr.Bottom-dr.Top, 61 compatibleDC, 0, 0, sdx, sdy, 62 blendfunc.ToUintptr()) 63 if err != nil { 64 return err 65 } 66 67 _, err = _SelectObject(compatibleDC, prevBitmap) 68 return err 69 } 70 71 func blit(dc win32.HDC, dp _POINT, bitmap syscall.Handle, sr *_RECT) (err error) { 72 compatibleDC, err := _CreateCompatibleDC(dc) 73 if err != nil { 74 return err 75 } 76 defer func() { 77 err2 := _DeleteDC(compatibleDC) 78 if err == nil { 79 err = err2 80 } 81 }() 82 prevBitmap, err := _SelectObject(compatibleDC, bitmap) 83 if err != nil { 84 return err 85 } 86 87 dx, dy := sr.Right-sr.Left, sr.Bottom-sr.Top 88 _, err = _BitBlt(dc, dp.X, dp.Y, dx, dy, compatibleDC, sr.Left, sr.Top, _SRCCOPY) 89 if err != nil { 90 return err 91 } 92 _, err = _SelectObject(compatibleDC, prevBitmap) 93 return err 94 } 95 96 func fillSrc(hwnd win32.HWND, uMsg uint32, wParam, lParam uintptr) { 97 dc, err := win32.GetDC(hwnd) 98 if err != nil { 99 panic(err) // TODO handle error? 100 } 101 defer win32.ReleaseDC(hwnd, dc) 102 r := (*_RECT)(unsafe.Pointer(lParam)) 103 color := _COLORREF(wParam) 104 105 // COLORREF is 0x00BBGGRR; color is 0xAARRGGBB 106 color = _RGB(byte((color >> 16)), byte((color >> 8)), byte(color)) 107 brush, err := _CreateSolidBrush(color) 108 if err != nil { 109 panic(err) // TODO handle error 110 } 111 defer _DeleteObject(brush) 112 err = _FillRect(dc, r, brush) 113 if err != nil { 114 panic(err) // TODO handle error 115 } 116 } 117 118 func fillOver(hwnd win32.HWND, uMsg uint32, wParam, lParam uintptr) { 119 dc, err := win32.GetDC(hwnd) 120 if err != nil { 121 panic(err) // TODO handle error 122 } 123 defer win32.ReleaseDC(hwnd, dc) 124 r := (*_RECT)(unsafe.Pointer(lParam)) 125 color := _COLORREF(wParam) 126 127 // AlphaBlend will stretch the input image (using StretchBlt's 128 // COLORONCOLOR mode) to fill the output rectangle. Testing 129 // this shows that the result appears to be the same as if we had 130 // used a MxN bitmap instead. 131 bitmap, bitvalues, err := mkbitmap(1, 1) 132 if err != nil { 133 panic(err) // TODO handle error 134 } 135 defer _DeleteObject(bitmap) // TODO handle error? 136 *(*_COLORREF)(unsafe.Pointer(bitvalues)) = color 137 if err = blend(dc, bitmap, r, 1, 1); err != nil { 138 panic(err) // TODO handle error 139 } 140 } 141 142 var ( 143 msgFillSrc = win32.AddWindowMsg(fillSrc) 144 msgFillOver = win32.AddWindowMsg(fillOver) 145 msgUpload = win32.AddWindowMsg(handleUpload) 146 ) 147 148 // TODO(andlabs): Draw