diff --git a/areaplan.md b/areaplan.md index e760d3f..3651f0b 100644 --- a/areaplan.md +++ b/areaplan.md @@ -61,12 +61,83 @@ func repaint(s *sysData) HRESULT { if hdc == 0 { // failure panic(fmt.Errorf("error beginning Area repaint: %v", err)) } + + cliprect := image.Rect(int(xrect.Left), int(xrect.Top), int(xrect.Right), int(xrect.Bottom)) + imgret := make(chan *image.NRGBA) + defer close(imgret) + s.paint <- PaintRequest{ + Rect: cliprect, + Out: imgret, + } + i := <-imgret // TODO DRAW + EndPaint(s.hwnd, &ps) return 0 } ``` +We can use GDI+ (gdiplus.dll) and its flat API for drawing... +```c +GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, PixelFormat format, BYTE* scan0, GpBitmap** bitmap); +GpStatus WINGDIPAPI GdipCreateFromHDC(HDC hdc, GpGraphics **graphics) +GpStatus WINGDIPAPI GdipDrawImageI(GpGraphics *graphics, GpImage *image, INT x, INT y) +GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics) +GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image) +``` +(`GpBitmap` extends `GpImage`.) The only problem is the pixel format: the most appropriate one is `PixelFormat32bppARGB`, which is not premultiplied, but the components are in the wrong order... (there is no RGBA pixel format in any bit width) (TODO `GdipDisposeImage` seems wrong since it bypasses `~Bitmap()` and goes right for `~Image()` but I don't see an explicit `~Bitmap`...) + +Disregarding the RGBA issue, the draw code would be +```go + var bitmap, graphics uintptr + + status := GdipCreateBitmapFromScan0( + i.Rect.Dx(), + i.Rect.Dy(), + i.Stride, + PixelFormat32bppARGB, + (*byte)(unsafe.Pointer(&i.Pix[0])), + &bitmap) + if status != 0 { // failure + panic(fmt.Errorf("error creating GDI+ bitmap to blit (GDI+ error code %d)", status)) + } + status = GdipCreateFromHDC(hdc, &graphics) + if status != 0 { // failure + panic(fmt.Errorf("error creating GDI+ graphics context to blit to (GDI+ error code %d)", status)) + } + status = GdipDrawImageI(graphics, bitmap, cliprect.Min.X, cliprect.Min.Y) + if status != 0 { // failure + panic(fmt.Errorf("error blitting GDI+ bitmap (GDI+ error code %d)", status)) + } + status = GdipDeleteGraphics(graphics) + if status != 0 { // failure + panic(fmt.Errorf("error freeing GDI+ graphics context to blit to (GDI+ error code %d)", status)) + } + status = GdipDisposeImage(bitmap) + if status != 0 { // failure + panic(fmt.Errorf("error freeing GDI+ bitmap to blit (GDI+ error code %d)", status)) + } +``` + +We must also initialize and shut down GDI+ in uitask: +```go + var gdiplustoken uintptr + + // init + startupinfo := &GdiplusStartupInput{ + GdiplusVersion: 1, + } + status := GdiplusStartup(&token, startupinfo, nil) + if status != 0 { // failure + return fmt.Errorf("error initializing GDI+ (GDI+ error code %d)", status) + } + + // shutdown + GdiplusShutdown(gdiplustoken) +``` + +TODO is there a function to turn a `GpStatus` into a string? + TODO note http://msdn.microsoft.com/en-us/library/windows/desktop/bb775501%28v=vs.85%29.aspx#win_class for information on handling some key presses, tab switch, etc. (need to do this for the ones below too) TODO figure out scrolling @@ -165,7 +236,7 @@ func our_drawRect(self C.id, rect C.struct_xrect) { bitmapFormat:NSAlphaNonpremultipliedBitmapFormat // this is where the flag for placing alpha first would go if alpha came first; the default is alpha last, which is how we're doing things bytesPerRow:i.Stride bitsPerPixel:32] - [bitmap drawAtPoint:NSMakePoint(cliprect.x, cliprect.y)] + [bitmap drawAtPoint:NSMakePoint(cliprect.Min.X, cliprect.Min.Y)] [bitmap release] } ``` diff --git a/todo.md b/todo.md index fff0510..ca9e9e3 100644 --- a/todo.md +++ b/todo.md @@ -77,6 +77,7 @@ important things: - do this for type signatures in exported functions: (err error) or just error? - do this for the names of GTK+ helper functions (gtkXXX or gXXX) - on windows 7, progress bars seem to animate from 0 -> pos when you turn off marquee mode and set pos; see if that's documented or if I'm doing something wrong +- clean up windows struct field names (holdover from when the intent was to make a wrapper lib first and then use it rather than using the windows API directly) far off: - localization