gdi32: Pass the dest visible rectangle to the PatBlt driver entry point.
[wine/testsucceed.git] / dlls / gdi32 / mfdrv / objects.c
blobeea468944734e41d9520bcd154e6b8eb1a4cb4eb
1 /*
2 * GDI objects
4 * Copyright 1993 Alexandre Julliard
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.
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.
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
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "wine/wingdi16.h"
30 #include "mfdrv/metafiledrv.h"
31 #include "gdi_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
36 /******************************************************************
37 * MFDRV_AddHandle
39 UINT MFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj )
41 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
42 UINT16 index;
44 for(index = 0; index < physDev->handles_size; index++)
45 if(physDev->handles[index] == 0) break;
46 if(index == physDev->handles_size) {
47 physDev->handles_size += HANDLE_LIST_INC;
48 physDev->handles = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
49 physDev->handles,
50 physDev->handles_size * sizeof(physDev->handles[0]));
52 physDev->handles[index] = obj;
54 physDev->cur_handles++;
55 if(physDev->cur_handles > physDev->mh->mtNoObjects)
56 physDev->mh->mtNoObjects++;
58 return index ; /* index 0 is not reserved for metafiles */
61 /******************************************************************
62 * MFDRV_RemoveHandle
64 BOOL MFDRV_RemoveHandle( PHYSDEV dev, UINT index )
66 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
67 BOOL ret = FALSE;
69 if (index < physDev->handles_size && physDev->handles[index])
71 physDev->handles[index] = 0;
72 physDev->cur_handles--;
73 ret = TRUE;
75 return ret;
78 /******************************************************************
79 * MFDRV_FindObject
81 static INT16 MFDRV_FindObject( PHYSDEV dev, HGDIOBJ obj )
83 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
84 INT16 index;
86 for(index = 0; index < physDev->handles_size; index++)
87 if(physDev->handles[index] == obj) break;
89 if(index == physDev->handles_size) return -1;
91 return index ;
95 /******************************************************************
96 * MFDRV_DeleteObject
98 BOOL CDECL MFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj )
100 METARECORD mr;
101 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
102 INT16 index;
103 BOOL ret = TRUE;
105 index = MFDRV_FindObject(dev, obj);
106 if( index < 0 )
107 return 0;
109 mr.rdSize = sizeof mr / 2;
110 mr.rdFunction = META_DELETEOBJECT;
111 mr.rdParm[0] = index;
113 if(!MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 ))
114 ret = FALSE;
116 physDev->handles[index] = 0;
117 physDev->cur_handles--;
118 return ret;
122 /***********************************************************************
123 * MFDRV_SelectObject
125 static BOOL MFDRV_SelectObject( PHYSDEV dev, INT16 index)
127 METARECORD mr;
129 mr.rdSize = sizeof mr / 2;
130 mr.rdFunction = META_SELECTOBJECT;
131 mr.rdParm[0] = index;
133 return MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 );
137 /***********************************************************************
138 * MFDRV_SelectBitmap
140 HBITMAP CDECL MFDRV_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap )
142 return 0;
145 /***********************************************************************
146 * Internal helper for MFDRV_CreateBrushIndirect():
147 * Change the padding of a bitmap from 16 (BMP) to 32 (DIB) bits.
149 static inline void MFDRV_PadTo32(LPBYTE lpRows, int height, int width)
151 int bytes16 = 2 * ((width + 15) / 16);
152 int bytes32 = 4 * ((width + 31) / 32);
153 LPBYTE lpSrc, lpDst;
154 int i;
156 if (!height)
157 return;
159 height = abs(height) - 1;
160 lpSrc = lpRows + height * bytes16;
161 lpDst = lpRows + height * bytes32;
163 /* Note that we work backwards so we can re-pad in place */
164 while (height >= 0)
166 for (i = bytes32; i > bytes16; i--)
167 lpDst[i - 1] = 0; /* Zero the padding bytes */
168 for (; i > 0; i--)
169 lpDst[i - 1] = lpSrc[i - 1]; /* Move image bytes into alignment */
170 lpSrc -= bytes16;
171 lpDst -= bytes32;
172 height--;
176 /***********************************************************************
177 * Internal helper for MFDRV_CreateBrushIndirect():
178 * Reverse order of bitmap rows in going from BMP to DIB.
180 static inline void MFDRV_Reverse(LPBYTE lpRows, int height, int width)
182 int bytes = 4 * ((width + 31) / 32);
183 LPBYTE lpSrc, lpDst;
184 BYTE temp;
185 int i;
187 if (!height)
188 return;
190 lpSrc = lpRows;
191 lpDst = lpRows + (height-1) * bytes;
192 height = height/2;
194 while (height > 0)
196 for (i = 0; i < bytes; i++)
198 temp = lpDst[i];
199 lpDst[i] = lpSrc[i];
200 lpSrc[i] = temp;
202 lpSrc += bytes;
203 lpDst -= bytes;
204 height--;
208 /******************************************************************
209 * MFDRV_CreateBrushIndirect
212 INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush )
214 DWORD size;
215 METARECORD *mr;
216 LOGBRUSH logbrush;
217 BOOL r;
219 if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1;
221 switch(logbrush.lbStyle)
223 case BS_SOLID:
224 case BS_NULL:
225 case BS_HATCHED:
227 LOGBRUSH16 lb16;
229 lb16.lbStyle = logbrush.lbStyle;
230 lb16.lbColor = logbrush.lbColor;
231 lb16.lbHatch = logbrush.lbHatch;
232 size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2;
233 mr = HeapAlloc( GetProcessHeap(), 0, size );
234 mr->rdSize = size / 2;
235 mr->rdFunction = META_CREATEBRUSHINDIRECT;
236 memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16));
237 break;
239 case BS_PATTERN:
241 BITMAP bm;
242 BITMAPINFO *info;
243 DWORD bmSize;
244 COLORREF cref;
246 GetObjectA((HANDLE)logbrush.lbHatch, sizeof(bm), &bm);
247 if(bm.bmBitsPixel != 1 || bm.bmPlanes != 1) {
248 FIXME("Trying to store a colour pattern brush\n");
249 goto done;
252 bmSize = DIB_GetDIBImageBytes(bm.bmWidth, bm.bmHeight, DIB_PAL_COLORS);
254 size = sizeof(METARECORD) + sizeof(WORD) + sizeof(BITMAPINFO) +
255 sizeof(RGBQUAD) + bmSize;
257 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
258 if(!mr) goto done;
259 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
260 mr->rdSize = size / 2;
261 mr->rdParm[0] = BS_PATTERN;
262 mr->rdParm[1] = DIB_RGB_COLORS;
263 info = (BITMAPINFO *)(mr->rdParm + 2);
265 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
266 info->bmiHeader.biWidth = bm.bmWidth;
267 info->bmiHeader.biHeight = bm.bmHeight;
268 info->bmiHeader.biPlanes = 1;
269 info->bmiHeader.biBitCount = 1;
270 info->bmiHeader.biSizeImage = bmSize;
272 GetBitmapBits((HANDLE)logbrush.lbHatch,
273 bm.bmHeight * BITMAP_GetWidthBytes (bm.bmWidth, bm.bmBitsPixel),
274 (LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD));
276 /* Change the padding to be DIB compatible if needed */
277 if(bm.bmWidth & 31)
278 MFDRV_PadTo32((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD),
279 bm.bmWidth, bm.bmHeight);
280 /* BMP and DIB have opposite row order conventions */
281 MFDRV_Reverse((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD),
282 bm.bmWidth, bm.bmHeight);
284 cref = GetTextColor( dev->hdc );
285 info->bmiColors[0].rgbRed = GetRValue(cref);
286 info->bmiColors[0].rgbGreen = GetGValue(cref);
287 info->bmiColors[0].rgbBlue = GetBValue(cref);
288 info->bmiColors[0].rgbReserved = 0;
289 cref = GetBkColor( dev->hdc );
290 info->bmiColors[1].rgbRed = GetRValue(cref);
291 info->bmiColors[1].rgbGreen = GetGValue(cref);
292 info->bmiColors[1].rgbBlue = GetBValue(cref);
293 info->bmiColors[1].rgbReserved = 0;
294 break;
297 case BS_DIBPATTERN:
299 BITMAPINFO *info;
300 DWORD bmSize, biSize;
302 info = GlobalLock( (HGLOBAL)logbrush.lbHatch );
303 if (info->bmiHeader.biCompression)
304 bmSize = info->bmiHeader.biSizeImage;
305 else
306 bmSize = DIB_GetDIBImageBytes(info->bmiHeader.biWidth,
307 info->bmiHeader.biHeight,
308 info->bmiHeader.biBitCount);
309 biSize = bitmap_info_size(info, LOWORD(logbrush.lbColor));
310 size = sizeof(METARECORD) + biSize + bmSize + 2;
311 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
312 if (!mr)
314 GlobalUnlock( (HGLOBAL)logbrush.lbHatch );
315 goto done;
317 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
318 mr->rdSize = size / 2;
319 *(mr->rdParm) = logbrush.lbStyle;
320 *(mr->rdParm + 1) = LOWORD(logbrush.lbColor);
321 memcpy(mr->rdParm + 2, info, biSize + bmSize);
322 GlobalUnlock( (HGLOBAL)logbrush.lbHatch );
323 break;
325 default:
326 FIXME("Unkonwn brush style %x\n", logbrush.lbStyle);
327 return 0;
329 r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
330 HeapFree(GetProcessHeap(), 0, mr);
331 if( !r )
332 return -1;
333 done:
334 return MFDRV_AddHandle( dev, hBrush );
338 /***********************************************************************
339 * MFDRV_SelectBrush
341 HBRUSH CDECL MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush )
343 INT16 index;
345 index = MFDRV_FindObject(dev, hbrush);
346 if( index < 0 )
348 index = MFDRV_CreateBrushIndirect( dev, hbrush );
349 if( index < 0 )
350 return 0;
351 GDI_hdc_using_object(hbrush, dev->hdc);
353 return MFDRV_SelectObject( dev, index ) ? hbrush : HGDI_ERROR;
356 /******************************************************************
357 * MFDRV_CreateFontIndirect
360 static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, LOGFONTW *logfont)
362 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
363 METARECORD *mr = (METARECORD *)&buffer;
364 LOGFONT16 *font16;
365 INT written;
367 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
368 mr->rdFunction = META_CREATEFONTINDIRECT;
369 font16 = (LOGFONT16 *)&mr->rdParm;
371 font16->lfHeight = logfont->lfHeight;
372 font16->lfWidth = logfont->lfWidth;
373 font16->lfEscapement = logfont->lfEscapement;
374 font16->lfOrientation = logfont->lfOrientation;
375 font16->lfWeight = logfont->lfWeight;
376 font16->lfItalic = logfont->lfItalic;
377 font16->lfUnderline = logfont->lfUnderline;
378 font16->lfStrikeOut = logfont->lfStrikeOut;
379 font16->lfCharSet = logfont->lfCharSet;
380 font16->lfOutPrecision = logfont->lfOutPrecision;
381 font16->lfClipPrecision = logfont->lfClipPrecision;
382 font16->lfQuality = logfont->lfQuality;
383 font16->lfPitchAndFamily = logfont->lfPitchAndFamily;
384 written = WideCharToMultiByte( CP_ACP, 0, logfont->lfFaceName, -1, font16->lfFaceName, LF_FACESIZE - 1, NULL, NULL );
385 /* Zero pad the facename buffer, so that we don't write uninitialized data to disk */
386 memset(font16->lfFaceName + written, 0, LF_FACESIZE - written);
388 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
389 return 0;
390 return MFDRV_AddHandle( dev, hFont );
394 /***********************************************************************
395 * MFDRV_SelectFont
397 HFONT CDECL MFDRV_SelectFont( PHYSDEV dev, HFONT hfont, HANDLE gdiFont )
399 LOGFONTW font;
400 INT16 index;
402 index = MFDRV_FindObject(dev, hfont);
403 if( index < 0 )
405 if (!GetObjectW( hfont, sizeof(font), &font ))
406 return HGDI_ERROR;
407 index = MFDRV_CreateFontIndirect(dev, hfont, &font);
408 if( index < 0 )
409 return HGDI_ERROR;
410 GDI_hdc_using_object(hfont, dev->hdc);
412 return MFDRV_SelectObject( dev, index ) ? hfont : HGDI_ERROR;
415 /******************************************************************
416 * MFDRV_CreatePenIndirect
418 static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen)
420 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
421 METARECORD *mr = (METARECORD *)&buffer;
423 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
424 mr->rdFunction = META_CREATEPENINDIRECT;
425 memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
426 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
427 return 0;
428 return MFDRV_AddHandle( dev, hPen );
432 /***********************************************************************
433 * MFDRV_SelectPen
435 HPEN CDECL MFDRV_SelectPen( PHYSDEV dev, HPEN hpen )
437 LOGPEN16 logpen;
438 INT16 index;
440 index = MFDRV_FindObject(dev, hpen);
441 if( index < 0 )
443 /* must be an extended pen */
444 INT size = GetObjectW( hpen, 0, NULL );
446 if (!size) return 0;
448 if (size == sizeof(LOGPEN))
450 LOGPEN pen;
452 GetObjectW( hpen, sizeof(pen), &pen );
453 logpen.lopnStyle = pen.lopnStyle;
454 logpen.lopnWidth.x = pen.lopnWidth.x;
455 logpen.lopnWidth.y = pen.lopnWidth.y;
456 logpen.lopnColor = pen.lopnColor;
458 else /* must be an extended pen */
460 EXTLOGPEN *elp = HeapAlloc( GetProcessHeap(), 0, size );
462 GetObjectW( hpen, size, elp );
463 /* FIXME: add support for user style pens */
464 logpen.lopnStyle = elp->elpPenStyle;
465 logpen.lopnWidth.x = elp->elpWidth;
466 logpen.lopnWidth.y = 0;
467 logpen.lopnColor = elp->elpColor;
469 HeapFree( GetProcessHeap(), 0, elp );
472 index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
473 if( index < 0 )
474 return 0;
475 GDI_hdc_using_object(hpen, dev->hdc);
477 return MFDRV_SelectObject( dev, index ) ? hpen : HGDI_ERROR;
481 /******************************************************************
482 * MFDRV_CreatePalette
484 static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
486 int index;
487 BOOL ret;
488 METARECORD *mr;
490 mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) );
491 mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD);
492 mr->rdFunction = META_CREATEPALETTE;
493 memcpy(&(mr->rdParm), logPalette, sizeofPalette);
494 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD))))
496 HeapFree(GetProcessHeap(), 0, mr);
497 return FALSE;
500 mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
501 mr->rdFunction = META_SELECTPALETTE;
503 if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
504 else
506 *(mr->rdParm) = index;
507 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
509 HeapFree(GetProcessHeap(), 0, mr);
510 return ret;
514 /***********************************************************************
515 * MFDRV_SelectPalette
517 HPALETTE CDECL MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
519 #define PALVERSION 0x0300
521 PLOGPALETTE logPalette;
522 WORD wNumEntries = 0;
523 BOOL creationSucceed;
524 int sizeofPalette;
526 GetObjectA(hPalette, sizeof(WORD), &wNumEntries);
528 if (wNumEntries == 0) return 0;
530 sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
531 logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
533 if (logPalette == NULL) return 0;
535 logPalette->palVersion = PALVERSION;
536 logPalette->palNumEntries = wNumEntries;
538 GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
540 creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
542 HeapFree( GetProcessHeap(), 0, logPalette );
544 if (creationSucceed)
545 return hPalette;
547 return 0;
550 /***********************************************************************
551 * MFDRV_RealizePalette
553 UINT CDECL MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
555 char buffer[sizeof(METARECORD) - sizeof(WORD)];
556 METARECORD *mr = (METARECORD *)&buffer;
558 mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
559 mr->rdFunction = META_REALIZEPALETTE;
561 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
563 /* The return value is suppose to be the number of entries
564 in the logical palette mapped to the system palette or 0
565 if the function failed. Since it's not trivial here to
566 get that kind of information and since it's of little
567 use in the case of metafiles, we'll always return 1. */
568 return 1;