1 /* 2 * Unit test suite for brushes 3 * 4 * Copyright 2004 Kevin Koltzau 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdarg.h> 22 23 #include "windef.h" 24 #include "winbase.h" 25 #include "wingdi.h" 26 #include "winuser.h" 27 28 #include "wine/test.h" 29 30 typedef struct _STOCK_BRUSH { 31 COLORREF color; 32 int stockobj; 33 const char *name; 34 } STOCK_BRUSH; 35 36 static void test_solidbrush(void) 37 { 38 static const STOCK_BRUSH stock[] = { 39 {RGB(255,255,255), WHITE_BRUSH, "white"}, 40 {RGB(192,192,192), LTGRAY_BRUSH, "ltgray"}, 41 {RGB(128,128,128), GRAY_BRUSH, "gray"}, 42 {RGB(0,0,0), BLACK_BRUSH, "black"}, 43 {RGB(0,0,255), -1, "blue"} 44 }; 45 HBRUSH solidBrush; 46 HBRUSH stockBrush; 47 LOGBRUSH br; 48 size_t i; 49 INT ret; 50 51 for(i=0; i<sizeof(stock)/sizeof(stock[0]); i++) { 52 solidBrush = CreateSolidBrush(stock[i].color); 53 54 if(stock[i].stockobj != -1) { 55 stockBrush = GetStockObject(stock[i].stockobj); 56 ok(stockBrush!=solidBrush || 57 broken(stockBrush==solidBrush), /* win9x does return stock object */ 58 "Stock %s brush equals solid %s brush\n", stock[i].name, stock[i].name); 59 } 60 else 61 stockBrush = NULL; 62 memset(&br, 0, sizeof(br)); 63 ret = GetObjectW(solidBrush, sizeof(br), &br); 64 ok( ret !=0, "GetObject on solid %s brush failed, error=%d\n", stock[i].name, GetLastError()); 65 ok(br.lbStyle==BS_SOLID, "%s brush has wrong style, got %d expected %d\n", stock[i].name, br.lbStyle, BS_SOLID); 66 ok(br.lbColor==stock[i].color, "%s brush has wrong color, got 0x%08x expected 0x%08x\n", stock[i].name, br.lbColor, stock[i].color); 67 68 if(stockBrush) { 69 /* Sanity check, make sure the colors being compared do in fact have a stock brush */ 70 ret = GetObjectW(stockBrush, sizeof(br), &br); 71 ok( ret !=0, "GetObject on stock %s brush failed, error=%d\n", stock[i].name, GetLastError()); 72 ok(br.lbColor==stock[i].color, "stock %s brush unexpected color, got 0x%08x expected 0x%08x\n", stock[i].name, br.lbColor, stock[i].color); 73 } 74 75 DeleteObject(solidBrush); 76 ret = GetObjectW(solidBrush, sizeof(br), &br); 77 ok(ret==0 || 78 broken(ret!=0), /* win9x */ 79 "GetObject succeeded on a deleted %s brush\n", stock[i].name); 80 } 81 } 82 83 static void test_hatch_brush(void) 84 { 85 int i, size; 86 HBRUSH brush; 87 LOGBRUSH lb; 88 89 for (i = 0; i < 20; i++) 90 { 91 SetLastError( 0xdeadbeef ); 92 brush = CreateHatchBrush( i, RGB(12,34,56) ); 93 if (i < HS_API_MAX) 94 { 95 ok( brush != 0, "%u: CreateHatchBrush failed err %u\n", i, GetLastError() ); 96 size = GetObjectW( brush, sizeof(lb), &lb ); 97 ok( size == sizeof(lb), "wrong size %u\n", size ); 98 ok( lb.lbColor == RGB(12,34,56), "wrong color %08x\n", lb.lbColor ); 99 if (i <= HS_DIAGCROSS) 100 { 101 ok( lb.lbStyle == BS_HATCHED, "wrong style %u\n", lb.lbStyle ); 102 ok( lb.lbHatch == i, "wrong hatch %lu/%u\n", lb.lbHatch, i ); 103 } 104 else 105 { 106 ok( lb.lbStyle == BS_SOLID, "wrong style %u\n", lb.lbStyle ); 107 ok( lb.lbHatch == 0, "wrong hatch %lu\n", lb.lbHatch ); 108 } 109 DeleteObject( brush ); 110 } 111 else 112 { 113 ok( !brush, "%u: CreateHatchBrush succeeded\n", i ); 114 ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() ); 115 } 116 } 117 } 118 119 static void test_pattern_brush(void) 120 { 121 char buffer[sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD) + 32 * 32 / 8]; 122 BITMAPINFO *info = (BITMAPINFO *)buffer; 123 HBRUSH brush; 124 HBITMAP bitmap; 125 LOGBRUSH br; 126 INT ret; 127 void *bits; 128 DIBSECTION dib; 129 HGLOBAL mem; 130 131 bitmap = CreateBitmap( 20, 20, 1, 1, NULL ); 132 ok( bitmap != NULL, "CreateBitmap failed\n" ); 133 brush = CreatePatternBrush( bitmap ); 134 ok( brush != NULL, "CreatePatternBrush failed\n" ); 135 memset( &br, 0x55, sizeof(br) ); 136 ret = GetObjectW( brush, sizeof(br), &br ); 137 ok( ret == sizeof(br), "wrong size %u\n", ret ); 138 ok( br.lbStyle == BS_PATTERN, "wrong style %u\n", br.lbStyle ); 139 ok( br.lbColor == 0, "wrong color %u\n", br.lbColor ); 140 ok( (HBITMAP)br.lbHatch == bitmap, "wrong handle %p/%p\n", (HBITMAP)br.lbHatch, bitmap ); 141 DeleteObject( brush ); 142 143 br.lbStyle = BS_PATTERN8X8; 144 br.lbColor = 0x12345; 145 br.lbHatch = (ULONG_PTR)bitmap; 146 brush = CreateBrushIndirect( &br ); 147 ok( brush != NULL, "CreatePatternBrush failed\n" ); 148 memset( &br, 0x55, sizeof(br) ); 149 ret = GetObjectW( brush, sizeof(br), &br ); 150 ok( ret == sizeof(br), "wrong size %u\n", ret ); 151 ok( br.lbStyle == BS_PATTERN, "wrong style %u\n", br.lbStyle ); 152 ok( br.lbColor == 0, "wrong color %u\n", br.lbColor ); 153 ok( (HBITMAP)br.lbHatch == bitmap, "wrong handle %p/%p\n", (HBITMAP)br.lbHatch, bitmap ); 154 ret = GetObjectW( bitmap, sizeof(dib), &dib ); 155 ok( ret == sizeof(dib.dsBm), "wrong size %u\n", ret ); 156 DeleteObject( bitmap ); 157 ret = GetObjectW( bitmap, sizeof(dib), &dib ); 158 ok( ret == 0, "wrong size %u\n", ret ); 159 DeleteObject( brush ); 160 161 memset( info, 0, sizeof(buffer) ); 162 info->bmiHeader.biSize = sizeof(info->bmiHeader); 163 info->bmiHeader.biHeight = 32; 164 info->bmiHeader.biWidth = 32; 165 info->bmiHeader.biBitCount = 1; 166 info->bmiHeader.biPlanes = 1; 167 info->bmiHeader.biCompression = BI_RGB; 168 bitmap = CreateDIBSection( 0, info, DIB_RGB_COLORS, (void**)&bits, NULL, 0 ); 169 ok( bitmap != NULL, "CreateDIBSection failed\n" ); 170 171 /* MSDN says a DIB section is not allowed, but it works fine */ 172 brush = CreatePatternBrush( bitmap ); 173 ok( brush != NULL, "CreatePatternBrush failed\n" ); 174 memset( &br, 0x55, sizeof(br) ); 175 ret = GetObjectW( brush, sizeof(br), &br ); 176 ok( ret == sizeof(br), "wrong size %u\n", ret ); 177 ok( br.lbStyle == BS_PATTERN, "wrong style %u\n", br.lbStyle ); 178 ok( br.lbColor == 0, "wrong color %u\n", br.lbColor ); 179 ok( (HBITMAP)br.lbHatch == bitmap, "wrong handle %p/%p\n", (HBITMAP)br.lbHatch, bitmap ); 180 ret = GetObjectW( bitmap, sizeof(dib), &dib ); 181 ok( ret == sizeof(dib), "wrong size %u\n", ret ); 182 DeleteObject( brush ); 183 DeleteObject( bitmap ); 184 185 brush = CreateDIBPatternBrushPt( info, DIB_RGB_COLORS ); 186 ok( brush != NULL, "CreatePatternBrush failed\n" ); 187 memset( &br, 0x55, sizeof(br) ); 188 ret = GetObjectW( brush, sizeof(br), &br ); 189 ok( ret == sizeof(br), "wrong size %u\n", ret ); 190 ok( br.lbStyle == BS_DIBPATTERN, "wrong style %u\n", br.lbStyle ); 191 ok( br.lbColor == 0, "wrong color %u\n", br.lbColor ); 192 ok( (BITMAPINFO *)br.lbHatch == info || broken(!br.lbHatch), /* nt4 */ 193 "wrong handle %p/%p\n", (BITMAPINFO *)br.lbHatch, info ); 194 DeleteObject( brush ); 195 196 br.lbStyle = BS_DIBPATTERNPT; 197 br.lbColor = DIB_PAL_COLORS; 198 br.lbHatch = (ULONG_PTR)info; 199 brush = CreateBrushIndirect( &br ); 200 ok( brush != NULL, "CreatePatternBrush failed\n" ); 201 memset( &br, 0x55, sizeof(br) ); 202 ret = GetObjectW( brush, sizeof(br), &br ); 203 ok( ret == sizeof(br), "wrong size %u\n", ret ); 204 ok( br.lbStyle == BS_DIBPATTERN, "wrong style %u\n", br.lbStyle ); 205 ok( br.lbColor == 0, "wrong color %u\n", br.lbColor ); 206 ok( (BITMAPINFO *)br.lbHatch == info || broken(!br.lbHatch), /* nt4 */ 207 "wrong handle %p/%p\n", (BITMAPINFO *)br.lbHatch, info ); 208 209 mem = GlobalAlloc( GMEM_MOVEABLE, sizeof(buffer) ); 210 memcpy( GlobalLock( mem ), buffer, sizeof(buffer) ); 211 212 br.lbStyle = BS_DIBPATTERN; 213 br.lbColor = DIB_PAL_COLORS; 214 br.lbHatch = (ULONG_PTR)mem; 215 brush = CreateBrushIndirect( &br ); 216 ok( brush != NULL, "CreatePatternBrush failed\n" ); 217 memset( &br, 0x55, sizeof(br) ); 218 ret = GetObjectW( brush, sizeof(br), &br ); 219 ok( ret == sizeof(br), "wrong size %u\n", ret ); 220 ok( br.lbStyle == BS_DIBPATTERN, "wrong style %u\n", br.lbStyle ); 221 ok( br.lbColor == 0, "wrong color %u\n", br.lbColor ); 222 ok( (HGLOBAL)br.lbHatch != mem, "wrong handle %p/%p\n", (HGLOBAL)br.lbHatch, mem ); 223 bits = GlobalLock( mem ); 224 ok( (HGLOBAL)br.lbHatch == bits || broken(!br.lbHatch), /* nt4 */ 225 "wrong handle %p/%p\n", (HGLOBAL)br.lbHatch, bits ); 226 ret = GlobalFlags( mem ); 227 ok( ret == 2, "wrong flags %x\n", ret ); 228 DeleteObject( brush ); 229 ret = GlobalFlags( mem ); 230 ok( ret == 2, "wrong flags %x\n", ret ); 231 232 brush = CreateDIBPatternBrushPt( info, DIB_PAL_COLORS ); 233 ok( brush != 0, "CreateDIBPatternBrushPt failed\n" ); 234 DeleteObject( brush ); 235 brush = CreateDIBPatternBrushPt( info, DIB_PAL_COLORS + 1 ); 236 ok( brush != 0, "CreateDIBPatternBrushPt failed\n" ); 237 DeleteObject( brush ); 238 brush = CreateDIBPatternBrushPt( info, DIB_PAL_COLORS + 2 ); 239 ok( !brush, "CreateDIBPatternBrushPt succeeded\n" ); 240 brush = CreateDIBPatternBrushPt( info, DIB_PAL_COLORS + 3 ); 241 ok( !brush, "CreateDIBPatternBrushPt succeeded\n" ); 242 243 info->bmiHeader.biBitCount = 8; 244 info->bmiHeader.biCompression = BI_RLE8; 245 brush = CreateDIBPatternBrushPt( info, DIB_RGB_COLORS ); 246 ok( !brush, "CreateDIBPatternBrushPt succeeded\n" ); 247 248 info->bmiHeader.biBitCount = 4; 249 info->bmiHeader.biCompression = BI_RLE4; 250 brush = CreateDIBPatternBrushPt( info, DIB_RGB_COLORS ); 251 ok( !brush, "CreateDIBPatternBrushPt succeeded\n" ); 252 253 br.lbStyle = BS_DIBPATTERN8X8; 254 br.lbColor = DIB_RGB_COLORS; 255 br.lbHatch = (ULONG_PTR)mem; 256 brush = CreateBrushIndirect( &br ); 257 ok( !brush, "CreatePatternBrush succeeded\n" ); 258 259 br.lbStyle = BS_MONOPATTERN; 260 br.lbColor = DIB_RGB_COLORS; 261 br.lbHatch = (ULONG_PTR)mem; 262 brush = CreateBrushIndirect( &br ); 263 ok( !brush, "CreatePatternBrush succeeded\n" ); 264 265 br.lbStyle = BS_INDEXED; 266 br.lbColor = DIB_RGB_COLORS; 267 br.lbHatch = (ULONG_PTR)mem; 268 brush = CreateBrushIndirect( &br ); 269 ok( !brush, "CreatePatternBrush succeeded\n" ); 270 271 GlobalFree( mem ); 272 } 273 274 static void test_palette_brush(void) 275 { 276 char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD) + 16 * 16]; 277 BITMAPINFO *info = (BITMAPINFO *)buffer; 278 WORD *indices = (WORD *)info->bmiColors; 279 char pal_buffer[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)]; 280 LOGPALETTE *pal = (LOGPALETTE *)pal_buffer; 281 HDC hdc = CreateCompatibleDC( 0 ); 282 DWORD *dib_bits; 283 HBITMAP dib; 284 HBRUSH brush; 285 int i; 286 HPALETTE palette, palette2; 287 288 memset( info, 0, sizeof(*info) ); 289 info->bmiHeader.biSize = sizeof(info->bmiHeader); 290 info->bmiHeader.biWidth = 16; 291 info->bmiHeader.biHeight = 16; 292 info->bmiHeader.biPlanes = 1; 293 info->bmiHeader.biBitCount = 32; 294 info->bmiHeader.biCompression = BI_RGB; 295 dib = CreateDIBSection( NULL, info, DIB_RGB_COLORS, (void**)&dib_bits, NULL, 0 ); 296 ok( dib != NULL, "CreateDIBSection failed\n" ); 297 298 info->bmiHeader.biBitCount = 8; 299 for (i = 0; i < 256; i++) indices[i] = 255 - i; 300 for (i = 0; i < 256; i++) ((BYTE *)(indices + 256))[i] = i; 301 brush = CreateDIBPatternBrushPt( info, DIB_PAL_COLORS ); 302 ok( brush != NULL, "CreateDIBPatternBrushPt failed\n" ); 303 304 pal->palVersion = 0x300; 305 pal->palNumEntries = 256; 306 for (i = 0; i < 256; i++) 307 { 308 pal->palPalEntry[i].peRed = i * 2; 309 pal->palPalEntry[i].peGreen = i * 2; 310 pal->palPalEntry[i].peBlue = i * 2; 311 pal->palPalEntry[i].peFlags = 0; 312 } 313 palette = CreatePalette( pal ); 314 315 ok( SelectObject( hdc, dib ) != NULL, "SelectObject failed\n" ); 316 ok( SelectPalette( hdc, palette, 0 ) != NULL, "SelectPalette failed\n" ); 317 ok( SelectObject( hdc, brush ) != NULL, "SelectObject failed\n" ); 318 memset( dib_bits, 0xaa, 16 * 16 * 4 ); 319 PatBlt( hdc, 0, 0, 16, 16, PATCOPY ); 320 for (i = 0; i < 256; i++) 321 { 322 DWORD expect = (pal->palPalEntry[255 - i].peRed << 16 | 323 pal->palPalEntry[255 - i].peGreen << 8 | 324 pal->palPalEntry[255 - i].peBlue); 325 ok( dib_bits[i] == expect, "wrong bits %x/%x at %u,%u\n", dib_bits[i], expect, i % 16, i / 16 ); 326 } 327 328 for (i = 0; i < 256; i++) pal->palPalEntry[i].peRed = i * 3; 329 palette2 = CreatePalette( pal ); 330 ok( SelectPalette( hdc, palette2, 0 ) != NULL, "SelectPalette failed\n" ); 331 memset( dib_bits, 0xaa, 16 * 16 * 4 ); 332 PatBlt( hdc, 0, 0, 16, 16, PATCOPY ); 333 for (i = 0; i < 256; i++) 334 { 335 DWORD expect = (pal->palPalEntry[255 - i].peRed << 16 | 336 pal->palPalEntry[255 - i].peGreen << 8 | 337 pal->palPalEntry[255 - i].peBlue); 338 ok( dib_bits[i] == expect, "wrong bits %x/%x at %u,%u\n", dib_bits[i], expect, i % 16, i / 16 ); 339 } 340 DeleteDC( hdc ); 341 DeleteObject( dib ); 342 DeleteObject( brush ); 343 DeleteObject( palette ); 344 DeleteObject( palette2 ); 345 } 346 347 static void test_brush_org( void ) 348 { 349 HDC hdc = GetDC( 0 ); 350 POINT old, pt; 351 352 SetBrushOrgEx( hdc, 0, 0, &old ); 353 354 SetBrushOrgEx( hdc, 1, 1, &pt ); 355 ok( pt.x == 0 && pt.y == 0, "got %d,%d\n", pt.x, pt.y ); 356 SetBrushOrgEx( hdc, 0x10000, -1, &pt ); 357 ok( pt.x == 1 && pt.y == 1, "got %d,%d\n", pt.x, pt.y ); 358 SetBrushOrgEx( hdc, old.x, old.y, &pt ); 359 ok( pt.x == 0x10000 && pt.y == -1, "got %d,%d\n", pt.x, pt.y ); 360 361 ReleaseDC( 0, hdc ); 362 } 363 364 START_TEST(brush) 365 { 366 test_solidbrush(); 367 test_hatch_brush(); 368 test_pattern_brush(); 369 test_palette_brush(); 370 test_brush_org(); 371 } 372