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