Update the address of the Free Software Foundation.
[wine.git] / dlls / gdi / mfdrv / objects.c
blob98e3f323048e97b64c326506350e576ec2422118
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 "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 ))
408 /* must be an extended pen */
409 EXTLOGPEN *elp;
410 INT size = GetObjectW( hpen, 0, NULL );
412 if (!size) return 0;
414 elp = HeapAlloc( GetProcessHeap(), 0, size );
416 GetObjectW( hpen, size, elp );
417 /* FIXME: add support for user style pens */
418 logpen.lopnStyle = elp->elpPenStyle;
419 logpen.lopnWidth.x = elp->elpWidth;
420 logpen.lopnWidth.y = 0;
421 logpen.lopnColor = elp->elpColor;
423 HeapFree( GetProcessHeap(), 0, elp );
426 index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
427 if( index < 0 )
428 return 0;
429 GDI_hdc_using_object(hpen, physDev->hdc);
431 return MFDRV_SelectObject( dev, index ) ? hpen : HGDI_ERROR;
435 /******************************************************************
436 * MFDRV_CreatePalette
438 static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
440 int index;
441 BOOL ret;
442 METARECORD *mr;
444 mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) );
445 mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD);
446 mr->rdFunction = META_CREATEPALETTE;
447 memcpy(&(mr->rdParm), logPalette, sizeofPalette);
448 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD))))
450 HeapFree(GetProcessHeap(), 0, mr);
451 return FALSE;
454 mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
455 mr->rdFunction = META_SELECTPALETTE;
457 if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
458 else
460 *(mr->rdParm) = index;
461 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
463 HeapFree(GetProcessHeap(), 0, mr);
464 return ret;
468 /***********************************************************************
469 * MFDRV_SelectPalette
471 HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
473 #define PALVERSION 0x0300
475 PLOGPALETTE logPalette;
476 WORD wNumEntries = 0;
477 BOOL creationSucceed;
478 int sizeofPalette;
480 GetObjectA(hPalette, sizeof(WORD), (LPSTR) &wNumEntries);
482 if (wNumEntries == 0) return 0;
484 sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
485 logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
487 if (logPalette == NULL) return 0;
489 logPalette->palVersion = PALVERSION;
490 logPalette->palNumEntries = wNumEntries;
492 GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
494 creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
496 HeapFree( GetProcessHeap(), 0, logPalette );
498 if (creationSucceed)
499 return hPalette;
501 return 0;
504 /***********************************************************************
505 * MFDRV_RealizePalette
507 UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
509 char buffer[sizeof(METARECORD) - sizeof(WORD)];
510 METARECORD *mr = (METARECORD *)&buffer;
512 mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
513 mr->rdFunction = META_REALIZEPALETTE;
515 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
517 /* The return value is suppose to be the number of entries
518 in the logical palette mapped to the system palette or 0
519 if the function failed. Since it's not trivial here to
520 get that kind of information and since it's of little
521 use in the case of metafiles, we'll always return 1. */
522 return 1;