From 35ae7c8f5939c0ba77b4023a14596706852f5acd Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Thu, 9 Feb 2017 01:42:34 +0300 Subject: [PATCH] uxtheme: Partial implementation of BeginBufferedPaint(). Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/uxtheme/buffer.c | 88 +++++++++++++++++++++++++++++++------ dlls/uxtheme/tests/system.c | 40 +++++++++++++---- 2 files changed, 107 insertions(+), 21 deletions(-) diff --git a/dlls/uxtheme/buffer.c b/dlls/uxtheme/buffer.c index 8583f1a7042..972df685f7f 100644 --- a/dlls/uxtheme/buffer.c +++ b/dlls/uxtheme/buffer.c @@ -2,6 +2,7 @@ * uxtheme Double-buffered Drawing API * * Copyright (C) 2008 Reece H. Dunn + * Copyright 2017 Nikolay Sivov for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -34,6 +35,20 @@ WINE_DEFAULT_DEBUG_CHANNEL(uxtheme); +struct paintbuffer +{ + HDC targetdc; + HDC memorydc; + RECT rect; + void *bits; +}; + +static void free_paintbuffer(struct paintbuffer *buffer) +{ + DeleteDC(buffer->memorydc); + HeapFree(GetProcessHeap(), 0, buffer); +} + /*********************************************************************** * BufferedPaintInit (UXTHEME.@) */ @@ -55,24 +70,71 @@ HRESULT WINAPI BufferedPaintUnInit(VOID) /*********************************************************************** * BeginBufferedPaint (UXTHEME.@) */ -HPAINTBUFFER WINAPI BeginBufferedPaint(HDC hdcTarget, - const RECT * prcTarget, - BP_BUFFERFORMAT dwFormat, - BP_PAINTPARAMS *pPaintParams, - HDC *phdc) +HPAINTBUFFER WINAPI BeginBufferedPaint(HDC targetdc, const RECT *rect, + BP_BUFFERFORMAT format, BP_PAINTPARAMS *params, HDC *retdc) { - static int i; + char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])]; + BITMAPINFO *bmi = (BITMAPINFO *)bmibuf; + struct paintbuffer *buffer; + HBITMAP hbm; - TRACE("Stub (%p %p %d %p %p)\n", hdcTarget, prcTarget, dwFormat, - pPaintParams, phdc); + TRACE("(%p %s %d %p %p)\n", targetdc, wine_dbgstr_rect(rect), format, + params, retdc); - if (!i++) - FIXME("Stub (%p %p %d %p %p)\n", hdcTarget, prcTarget, dwFormat, - pPaintParams, phdc); - return NULL; + if (retdc) + *retdc = NULL; + + if (!targetdc || IsRectEmpty(rect)) + return NULL; + + if (params) + FIXME("painting parameters are ignored\n"); + + buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(*buffer)); + buffer->targetdc = targetdc; + buffer->rect = *rect; + buffer->memorydc = CreateCompatibleDC(targetdc); + + switch (format) + { + case BPBF_COMPATIBLEBITMAP: + hbm = CreateCompatibleBitmap(buffer->memorydc, rect->right - rect->left, rect->bottom - rect->top); + buffer->bits = NULL; + break; + case BPBF_DIB: + case BPBF_TOPDOWNDIB: + case BPBF_TOPDOWNMONODIB: + /* create DIB section */ + memset(bmi, 0, sizeof(bmibuf)); + bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader); + bmi->bmiHeader.biHeight = format == BPBF_DIB ? rect->bottom - rect->top : + -(rect->bottom - rect->top); + bmi->bmiHeader.biWidth = rect->right - rect->left; + bmi->bmiHeader.biBitCount = format == BPBF_TOPDOWNMONODIB ? 1 : 32; + bmi->bmiHeader.biPlanes = 1; + bmi->bmiHeader.biCompression = BI_RGB; + hbm = CreateDIBSection(buffer->memorydc, bmi, DIB_RGB_COLORS, &buffer->bits, NULL, 0); + break; + default: + WARN("Unknown buffer format %d\n", format); + free_paintbuffer(buffer); + return NULL; + } + + if (!hbm) + { + WARN("Failed to create buffer bitmap\n"); + free_paintbuffer(buffer); + return NULL; + } + + DeleteObject(SelectObject(buffer->memorydc, hbm)); + + *retdc = buffer->memorydc; + + return (HPAINTBUFFER)buffer; } - /*********************************************************************** * EndBufferedPaint (UXTHEME.@) */ diff --git a/dlls/uxtheme/tests/system.c b/dlls/uxtheme/tests/system.c index d7ba43c6d64..66f696b62ef 100644 --- a/dlls/uxtheme/tests/system.c +++ b/dlls/uxtheme/tests/system.c @@ -552,31 +552,55 @@ static void test_buffered_paint(void) ¶ms, NULL); ok(buffer == NULL, "Unexpected buffer %p\n", buffer); + src = (void *)0xdeadbeef; buffer = pBeginBufferedPaint(target, NULL, BPBF_COMPATIBLEBITMAP, ¶ms, &src); ok(buffer == NULL, "Unexpected buffer %p\n", buffer); + ok(src == NULL, "Unexpected buffered dc %p\n", src); /* target rect is mandatory */ - rect.left = rect.top = 0; - rect.right = rect.bottom = 0; + SetRectEmpty(&rect); + src = (void *)0xdeadbeef; buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP, ¶ms, &src); ok(buffer == NULL, "Unexpected buffer %p\n", buffer); + ok(src == NULL, "Unexpected buffered dc %p\n", src); - rect.left = rect.top = 0; - rect.right = rect.bottom = 5; + /* inverted rectangle */ + SetRect(&rect, 10, 0, 5, 5); + src = (void *)0xdeadbeef; + buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP, + ¶ms, &src); + ok(buffer == NULL, "Unexpected buffer %p\n", buffer); + ok(src == NULL, "Unexpected buffered dc %p\n", src); + + SetRect(&rect, 0, 10, 5, 0); + src = (void *)0xdeadbeef; + buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP, + ¶ms, &src); + ok(buffer == NULL, "Unexpected buffer %p\n", buffer); + ok(src == NULL, "Unexpected buffered dc %p\n", src); + + /* valid rectangle, no target dc */ + SetRect(&rect, 0, 0, 5, 5); + src = (void *)0xdeadbeef; + buffer = pBeginBufferedPaint(NULL, &rect, BPBF_COMPATIBLEBITMAP, + ¶ms, &src); + ok(buffer == NULL, "Unexpected buffer %p\n", buffer); + ok(src == NULL, "Unexpected buffered dc %p\n", src); + + SetRect(&rect, 0, 0, 5, 5); + src = NULL; buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP, ¶ms, &src); -todo_wine ok(buffer != NULL, "Unexpected buffer %p\n", buffer); + ok(src != NULL, "Expected buffered dc\n"); hr = pEndBufferedPaint(buffer, FALSE); ok(hr == S_OK, "Unexpected return code %#x\n", hr); - rect.left = rect.top = 0; - rect.right = rect.bottom = 5; + SetRect(&rect, 0, 0, 5, 5); buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP, ¶ms, &src); -todo_wine ok(buffer != NULL, "Unexpected buffer %p\n", buffer); /* clearing */