Release 20050930.
[wine/gsoc-2012-control.git] / dlls / gdi / mfdrv / objects.c
blob1cda8feb0b21703d7b8f41ce47a32b23dc41c647
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 "wownt32.h"
30 #include "mfdrv/metafiledrv.h"
31 #include "gdi.h"
32 #include "gdi_private.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
37 /******************************************************************
38 * MFDRV_AddHandle
40 UINT MFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj )
42 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
43 UINT16 index;
45 for(index = 0; index < physDev->handles_size; index++)
46 if(physDev->handles[index] == 0) break;
47 if(index == physDev->handles_size) {
48 physDev->handles_size += HANDLE_LIST_INC;
49 physDev->handles = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
50 physDev->handles,
51 physDev->handles_size * sizeof(physDev->handles[0]));
53 physDev->handles[index] = obj;
55 physDev->cur_handles++;
56 if(physDev->cur_handles > physDev->mh->mtNoObjects)
57 physDev->mh->mtNoObjects++;
59 return index ; /* index 0 is not reserved for metafiles */
62 /******************************************************************
63 * MFDRV_FindObject
65 static INT16 MFDRV_FindObject( PHYSDEV dev, HGDIOBJ obj )
67 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
68 INT16 index;
70 for(index = 0; index < physDev->handles_size; index++)
71 if(physDev->handles[index] == obj) break;
73 if(index == physDev->handles_size) return -1;
75 return index ;
79 /******************************************************************
80 * MFDRV_DeleteObject
82 BOOL MFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj )
84 METARECORD mr;
85 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
86 INT16 index;
87 BOOL ret = TRUE;
89 index = MFDRV_FindObject(dev, obj);
90 if( index < 0 )
91 return 0;
93 mr.rdSize = sizeof mr / 2;
94 mr.rdFunction = META_DELETEOBJECT;
95 mr.rdParm[0] = index;
97 if(!MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 ))
98 ret = FALSE;
100 physDev->handles[index] = 0;
101 physDev->cur_handles--;
102 return ret;
106 /***********************************************************************
107 * MFDRV_SelectObject
109 static BOOL MFDRV_SelectObject( PHYSDEV dev, INT16 index)
111 METARECORD mr;
113 mr.rdSize = sizeof mr / 2;
114 mr.rdFunction = META_SELECTOBJECT;
115 mr.rdParm[0] = index;
117 return MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 );
121 /***********************************************************************
122 * MFDRV_SelectBitmap
124 HBITMAP MFDRV_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap )
126 return 0;
129 /***********************************************************************
130 * Internal helper for MFDRV_CreateBrushIndirect():
131 * Change the padding of a bitmap from 16 (BMP) to 32 (DIB) bits.
133 static inline void MFDRV_PadTo32(LPBYTE lpRows, int height, int width)
135 int bytes16 = 2 * ((width + 15) / 16);
136 int bytes32 = 4 * ((width + 31) / 32);
137 LPBYTE lpSrc, lpDst;
138 int i;
140 if (!height)
141 return;
143 height = abs(height) - 1;
144 lpSrc = lpRows + height * bytes16;
145 lpDst = lpRows + height * bytes32;
147 /* Note that we work backwards so we can re-pad in place */
148 while (height >= 0)
150 for (i = bytes32; i > bytes16; i--)
151 lpDst[i - 1] = 0; /* Zero the padding bytes */
152 for (; i > 0; i--)
153 lpDst[i - 1] = lpSrc[i - 1]; /* Move image bytes into alignment */
154 lpSrc -= bytes16;
155 lpDst -= bytes32;
156 height--;
160 /***********************************************************************
161 * Internal helper for MFDRV_CreateBrushIndirect():
162 * Reverse order of bitmap rows in going from BMP to DIB.
164 static inline void MFDRV_Reverse(LPBYTE lpRows, int height, int width)
166 int bytes = 4 * ((width + 31) / 32);
167 LPBYTE lpSrc, lpDst;
168 BYTE temp;
169 int i;
171 if (!height)
172 return;
174 lpSrc = lpRows;
175 lpDst = lpRows + (height-1) * bytes;
176 height = height/2;
178 while (height > 0)
180 for (i = 0; i < bytes; i++)
182 temp = lpDst[i];
183 lpDst[i] = lpSrc[i];
184 lpSrc[i] = temp;
186 lpSrc += bytes;
187 lpDst -= bytes;
188 height--;
192 /******************************************************************
193 * MFDRV_CreateBrushIndirect
196 INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush )
198 DWORD size;
199 METARECORD *mr;
200 LOGBRUSH logbrush;
201 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
202 BOOL r;
204 if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1;
206 switch(logbrush.lbStyle)
208 case BS_SOLID:
209 case BS_NULL:
210 case BS_HATCHED:
212 LOGBRUSH16 lb16;
214 lb16.lbStyle = logbrush.lbStyle;
215 lb16.lbColor = logbrush.lbColor;
216 lb16.lbHatch = logbrush.lbHatch;
217 size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2;
218 mr = HeapAlloc( GetProcessHeap(), 0, size );
219 mr->rdSize = size / 2;
220 mr->rdFunction = META_CREATEBRUSHINDIRECT;
221 memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16));
222 break;
224 case BS_PATTERN:
226 BITMAP bm;
227 BITMAPINFO *info;
228 DWORD bmSize;
229 COLORREF cref;
231 GetObjectA((HANDLE)logbrush.lbHatch, sizeof(bm), &bm);
232 if(bm.bmBitsPixel != 1 || bm.bmPlanes != 1) {
233 FIXME("Trying to store a colour pattern brush\n");
234 goto done;
237 bmSize = DIB_GetDIBImageBytes(bm.bmWidth, bm.bmHeight, DIB_PAL_COLORS);
239 size = sizeof(METARECORD) + sizeof(WORD) + sizeof(BITMAPINFO) +
240 sizeof(RGBQUAD) + bmSize;
242 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
243 if(!mr) goto done;
244 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
245 mr->rdSize = size / 2;
246 mr->rdParm[0] = BS_PATTERN;
247 mr->rdParm[1] = DIB_RGB_COLORS;
248 info = (BITMAPINFO *)(mr->rdParm + 2);
250 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
251 info->bmiHeader.biWidth = bm.bmWidth;
252 info->bmiHeader.biHeight = bm.bmHeight;
253 info->bmiHeader.biPlanes = 1;
254 info->bmiHeader.biBitCount = 1;
255 info->bmiHeader.biSizeImage = bmSize;
257 GetBitmapBits((HANDLE)logbrush.lbHatch,
258 bm.bmHeight * BITMAP_GetWidthBytes (bm.bmWidth, bm.bmBitsPixel),
259 (LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD));
261 /* Change the padding to be DIB compatible if needed */
262 if(bm.bmWidth & 31)
263 MFDRV_PadTo32((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD),
264 bm.bmWidth, bm.bmHeight);
265 /* BMP and DIB have opposite row order conventions */
266 MFDRV_Reverse((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD),
267 bm.bmWidth, bm.bmHeight);
269 cref = GetTextColor(physDev->hdc);
270 info->bmiColors[0].rgbRed = GetRValue(cref);
271 info->bmiColors[0].rgbGreen = GetGValue(cref);
272 info->bmiColors[0].rgbBlue = GetBValue(cref);
273 info->bmiColors[0].rgbReserved = 0;
274 cref = GetBkColor(physDev->hdc);
275 info->bmiColors[1].rgbRed = GetRValue(cref);
276 info->bmiColors[1].rgbGreen = GetGValue(cref);
277 info->bmiColors[1].rgbBlue = GetBValue(cref);
278 info->bmiColors[1].rgbReserved = 0;
279 break;
282 case BS_DIBPATTERN:
284 BITMAPINFO *info;
285 DWORD bmSize, biSize;
287 info = GlobalLock16((HGLOBAL16)logbrush.lbHatch);
288 if (info->bmiHeader.biCompression)
289 bmSize = info->bmiHeader.biSizeImage;
290 else
291 bmSize = DIB_GetDIBImageBytes(info->bmiHeader.biWidth,
292 info->bmiHeader.biHeight,
293 info->bmiHeader.biBitCount);
294 biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush.lbColor));
295 size = sizeof(METARECORD) + biSize + bmSize + 2;
296 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
297 if(!mr) goto done;
298 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
299 mr->rdSize = size / 2;
300 *(mr->rdParm) = logbrush.lbStyle;
301 *(mr->rdParm + 1) = LOWORD(logbrush.lbColor);
302 memcpy(mr->rdParm + 2, info, biSize + bmSize);
303 break;
305 default:
306 FIXME("Unkonwn brush style %x\n", logbrush.lbStyle);
307 return 0;
309 r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
310 HeapFree(GetProcessHeap(), 0, mr);
311 if( !r )
312 return -1;
313 done:
314 return MFDRV_AddHandle( dev, hBrush );
318 /***********************************************************************
319 * MFDRV_SelectBrush
321 HBRUSH MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush )
323 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
324 INT16 index;
326 index = MFDRV_FindObject(dev, hbrush);
327 if( index < 0 )
329 index = MFDRV_CreateBrushIndirect( dev, hbrush );
330 if( index < 0 )
331 return 0;
332 GDI_hdc_using_object(hbrush, physDev->hdc);
334 return MFDRV_SelectObject( dev, index ) ? hbrush : HGDI_ERROR;
337 /******************************************************************
338 * MFDRV_CreateFontIndirect
341 static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, LOGFONT16 *logfont)
343 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
344 METARECORD *mr = (METARECORD *)&buffer;
346 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
347 mr->rdFunction = META_CREATEFONTINDIRECT;
348 memcpy(&(mr->rdParm), logfont, sizeof(LOGFONT16));
349 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
350 return 0;
351 return MFDRV_AddHandle( dev, hFont );
355 /***********************************************************************
356 * MFDRV_SelectFont
358 HFONT MFDRV_SelectFont( PHYSDEV dev, HFONT hfont, HANDLE gdiFont )
360 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
361 LOGFONT16 lf16;
362 INT16 index;
364 index = MFDRV_FindObject(dev, hfont);
365 if( index < 0 )
367 if (!GetObject16( HFONT_16(hfont), sizeof(lf16), &lf16 ))
368 return HGDI_ERROR;
369 index = MFDRV_CreateFontIndirect(dev, hfont, &lf16);
370 if( index < 0 )
371 return HGDI_ERROR;
372 GDI_hdc_using_object(hfont, physDev->hdc);
374 return MFDRV_SelectObject( dev, index ) ? hfont : HGDI_ERROR;
377 /******************************************************************
378 * MFDRV_CreatePenIndirect
380 static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen)
382 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
383 METARECORD *mr = (METARECORD *)&buffer;
385 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
386 mr->rdFunction = META_CREATEPENINDIRECT;
387 memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
388 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
389 return 0;
390 return MFDRV_AddHandle( dev, hPen );
394 /***********************************************************************
395 * MFDRV_SelectPen
397 HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen )
399 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
400 LOGPEN16 logpen;
401 INT16 index;
403 index = MFDRV_FindObject(dev, hpen);
404 if( index < 0 )
406 if (!GetObject16( HPEN_16(hpen), sizeof(logpen), &logpen ))
407 return 0;
408 index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
409 if( index < 0 )
410 return 0;
411 GDI_hdc_using_object(hpen, physDev->hdc);
413 return MFDRV_SelectObject( dev, index ) ? hpen : HGDI_ERROR;
417 /******************************************************************
418 * MFDRV_CreatePalette
420 static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
422 int index;
423 BOOL ret;
424 METARECORD *mr;
426 mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) );
427 mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD);
428 mr->rdFunction = META_CREATEPALETTE;
429 memcpy(&(mr->rdParm), logPalette, sizeofPalette);
430 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD))))
432 HeapFree(GetProcessHeap(), 0, mr);
433 return FALSE;
436 mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
437 mr->rdFunction = META_SELECTPALETTE;
439 if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
440 else
442 *(mr->rdParm) = index;
443 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
445 HeapFree(GetProcessHeap(), 0, mr);
446 return ret;
450 /***********************************************************************
451 * MFDRV_SelectPalette
453 HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
455 #define PALVERSION 0x0300
457 PLOGPALETTE logPalette;
458 WORD wNumEntries = 0;
459 BOOL creationSucceed;
460 int sizeofPalette;
462 GetObjectA(hPalette, sizeof(WORD), (LPSTR) &wNumEntries);
464 if (wNumEntries == 0) return 0;
466 sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
467 logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
469 if (logPalette == NULL) return 0;
471 logPalette->palVersion = PALVERSION;
472 logPalette->palNumEntries = wNumEntries;
474 GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
476 creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
478 HeapFree( GetProcessHeap(), 0, logPalette );
480 if (creationSucceed)
481 return hPalette;
483 return 0;
486 /***********************************************************************
487 * MFDRV_RealizePalette
489 UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
491 char buffer[sizeof(METARECORD) - sizeof(WORD)];
492 METARECORD *mr = (METARECORD *)&buffer;
494 mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
495 mr->rdFunction = META_REALIZEPALETTE;
497 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
499 /* The return value is suppose to be the number of entries
500 in the logical palette mapped to the system palette or 0
501 if the function failed. Since it's not trivial here to
502 get that kind of information and since it's of little
503 use in the case of metafiles, we'll always return 1. */
504 return 1;