wininet: Support the Cache-Control max-age directive for setting url cache entry...
[wine/testsucceed.git] / dlls / gdi32 / mfdrv / objects.c
blobc4b160280ba301b28eb3ff1cc2a5f676ad853ed9
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 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
218 BOOL r;
220 if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1;
222 switch(logbrush.lbStyle)
224 case BS_SOLID:
225 case BS_NULL:
226 case BS_HATCHED:
228 LOGBRUSH16 lb16;
230 lb16.lbStyle = logbrush.lbStyle;
231 lb16.lbColor = logbrush.lbColor;
232 lb16.lbHatch = logbrush.lbHatch;
233 size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2;
234 mr = HeapAlloc( GetProcessHeap(), 0, size );
235 mr->rdSize = size / 2;
236 mr->rdFunction = META_CREATEBRUSHINDIRECT;
237 memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16));
238 break;
240 case BS_PATTERN:
242 BITMAP bm;
243 BITMAPINFO *info;
244 DWORD bmSize;
245 COLORREF cref;
247 GetObjectA((HANDLE)logbrush.lbHatch, sizeof(bm), &bm);
248 if(bm.bmBitsPixel != 1 || bm.bmPlanes != 1) {
249 FIXME("Trying to store a colour pattern brush\n");
250 goto done;
253 bmSize = DIB_GetDIBImageBytes(bm.bmWidth, bm.bmHeight, DIB_PAL_COLORS);
255 size = sizeof(METARECORD) + sizeof(WORD) + sizeof(BITMAPINFO) +
256 sizeof(RGBQUAD) + bmSize;
258 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
259 if(!mr) goto done;
260 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
261 mr->rdSize = size / 2;
262 mr->rdParm[0] = BS_PATTERN;
263 mr->rdParm[1] = DIB_RGB_COLORS;
264 info = (BITMAPINFO *)(mr->rdParm + 2);
266 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
267 info->bmiHeader.biWidth = bm.bmWidth;
268 info->bmiHeader.biHeight = bm.bmHeight;
269 info->bmiHeader.biPlanes = 1;
270 info->bmiHeader.biBitCount = 1;
271 info->bmiHeader.biSizeImage = bmSize;
273 GetBitmapBits((HANDLE)logbrush.lbHatch,
274 bm.bmHeight * BITMAP_GetWidthBytes (bm.bmWidth, bm.bmBitsPixel),
275 (LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD));
277 /* Change the padding to be DIB compatible if needed */
278 if(bm.bmWidth & 31)
279 MFDRV_PadTo32((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD),
280 bm.bmWidth, bm.bmHeight);
281 /* BMP and DIB have opposite row order conventions */
282 MFDRV_Reverse((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD),
283 bm.bmWidth, bm.bmHeight);
285 cref = GetTextColor(physDev->hdc);
286 info->bmiColors[0].rgbRed = GetRValue(cref);
287 info->bmiColors[0].rgbGreen = GetGValue(cref);
288 info->bmiColors[0].rgbBlue = GetBValue(cref);
289 info->bmiColors[0].rgbReserved = 0;
290 cref = GetBkColor(physDev->hdc);
291 info->bmiColors[1].rgbRed = GetRValue(cref);
292 info->bmiColors[1].rgbGreen = GetGValue(cref);
293 info->bmiColors[1].rgbBlue = GetBValue(cref);
294 info->bmiColors[1].rgbReserved = 0;
295 break;
298 case BS_DIBPATTERN:
300 BITMAPINFO *info;
301 DWORD bmSize, biSize;
303 info = GlobalLock( (HGLOBAL)logbrush.lbHatch );
304 if (info->bmiHeader.biCompression)
305 bmSize = info->bmiHeader.biSizeImage;
306 else
307 bmSize = DIB_GetDIBImageBytes(info->bmiHeader.biWidth,
308 info->bmiHeader.biHeight,
309 info->bmiHeader.biBitCount);
310 biSize = bitmap_info_size(info, LOWORD(logbrush.lbColor));
311 size = sizeof(METARECORD) + biSize + bmSize + 2;
312 mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
313 if (!mr)
315 GlobalUnlock( (HGLOBAL)logbrush.lbHatch );
316 goto done;
318 mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
319 mr->rdSize = size / 2;
320 *(mr->rdParm) = logbrush.lbStyle;
321 *(mr->rdParm + 1) = LOWORD(logbrush.lbColor);
322 memcpy(mr->rdParm + 2, info, biSize + bmSize);
323 GlobalUnlock( (HGLOBAL)logbrush.lbHatch );
324 break;
326 default:
327 FIXME("Unkonwn brush style %x\n", logbrush.lbStyle);
328 return 0;
330 r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
331 HeapFree(GetProcessHeap(), 0, mr);
332 if( !r )
333 return -1;
334 done:
335 return MFDRV_AddHandle( dev, hBrush );
339 /***********************************************************************
340 * MFDRV_SelectBrush
342 HBRUSH CDECL MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush )
344 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
345 INT16 index;
347 index = MFDRV_FindObject(dev, hbrush);
348 if( index < 0 )
350 index = MFDRV_CreateBrushIndirect( dev, hbrush );
351 if( index < 0 )
352 return 0;
353 GDI_hdc_using_object(hbrush, physDev->hdc);
355 return MFDRV_SelectObject( dev, index ) ? hbrush : HGDI_ERROR;
358 /******************************************************************
359 * MFDRV_CreateFontIndirect
362 static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, LOGFONTW *logfont)
364 char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
365 METARECORD *mr = (METARECORD *)&buffer;
366 LOGFONT16 *font16;
367 INT written;
369 mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
370 mr->rdFunction = META_CREATEFONTINDIRECT;
371 font16 = (LOGFONT16 *)&mr->rdParm;
373 font16->lfHeight = logfont->lfHeight;
374 font16->lfWidth = logfont->lfWidth;
375 font16->lfEscapement = logfont->lfEscapement;
376 font16->lfOrientation = logfont->lfOrientation;
377 font16->lfWeight = logfont->lfWeight;
378 font16->lfItalic = logfont->lfItalic;
379 font16->lfUnderline = logfont->lfUnderline;
380 font16->lfStrikeOut = logfont->lfStrikeOut;
381 font16->lfCharSet = logfont->lfCharSet;
382 font16->lfOutPrecision = logfont->lfOutPrecision;
383 font16->lfClipPrecision = logfont->lfClipPrecision;
384 font16->lfQuality = logfont->lfQuality;
385 font16->lfPitchAndFamily = logfont->lfPitchAndFamily;
386 written = WideCharToMultiByte( CP_ACP, 0, logfont->lfFaceName, -1, font16->lfFaceName, LF_FACESIZE - 1, NULL, NULL );
387 /* Zero pad the facename buffer, so that we don't write uninitialized data to disk */
388 memset(font16->lfFaceName + written, 0, LF_FACESIZE - written);
390 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
391 return 0;
392 return MFDRV_AddHandle( dev, hFont );
396 /***********************************************************************
397 * MFDRV_SelectFont
399 HFONT CDECL MFDRV_SelectFont( PHYSDEV dev, HFONT hfont, HANDLE gdiFont )
401 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
402 LOGFONTW font;
403 INT16 index;
405 index = MFDRV_FindObject(dev, hfont);
406 if( index < 0 )
408 if (!GetObjectW( hfont, sizeof(font), &font ))
409 return HGDI_ERROR;
410 index = MFDRV_CreateFontIndirect(dev, hfont, &font);
411 if( index < 0 )
412 return HGDI_ERROR;
413 GDI_hdc_using_object(hfont, physDev->hdc);
415 return MFDRV_SelectObject( dev, index ) ? hfont : HGDI_ERROR;
418 /******************************************************************
419 * MFDRV_CreatePenIndirect
421 static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen)
423 char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
424 METARECORD *mr = (METARECORD *)&buffer;
426 mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
427 mr->rdFunction = META_CREATEPENINDIRECT;
428 memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
429 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
430 return 0;
431 return MFDRV_AddHandle( dev, hPen );
435 /***********************************************************************
436 * MFDRV_SelectPen
438 HPEN CDECL MFDRV_SelectPen( PHYSDEV dev, HPEN hpen )
440 METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
441 LOGPEN16 logpen;
442 INT16 index;
444 index = MFDRV_FindObject(dev, hpen);
445 if( index < 0 )
447 /* must be an extended pen */
448 INT size = GetObjectW( hpen, 0, NULL );
450 if (!size) return 0;
452 if (size == sizeof(LOGPEN))
454 LOGPEN pen;
456 GetObjectW( hpen, sizeof(pen), &pen );
457 logpen.lopnStyle = pen.lopnStyle;
458 logpen.lopnWidth.x = pen.lopnWidth.x;
459 logpen.lopnWidth.y = pen.lopnWidth.y;
460 logpen.lopnColor = pen.lopnColor;
462 else /* must be an extended pen */
464 EXTLOGPEN *elp = HeapAlloc( GetProcessHeap(), 0, size );
466 GetObjectW( hpen, size, elp );
467 /* FIXME: add support for user style pens */
468 logpen.lopnStyle = elp->elpPenStyle;
469 logpen.lopnWidth.x = elp->elpWidth;
470 logpen.lopnWidth.y = 0;
471 logpen.lopnColor = elp->elpColor;
473 HeapFree( GetProcessHeap(), 0, elp );
476 index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
477 if( index < 0 )
478 return 0;
479 GDI_hdc_using_object(hpen, physDev->hdc);
481 return MFDRV_SelectObject( dev, index ) ? hpen : HGDI_ERROR;
485 /******************************************************************
486 * MFDRV_CreatePalette
488 static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
490 int index;
491 BOOL ret;
492 METARECORD *mr;
494 mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) );
495 mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD);
496 mr->rdFunction = META_CREATEPALETTE;
497 memcpy(&(mr->rdParm), logPalette, sizeofPalette);
498 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD))))
500 HeapFree(GetProcessHeap(), 0, mr);
501 return FALSE;
504 mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
505 mr->rdFunction = META_SELECTPALETTE;
507 if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
508 else
510 *(mr->rdParm) = index;
511 ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
513 HeapFree(GetProcessHeap(), 0, mr);
514 return ret;
518 /***********************************************************************
519 * MFDRV_SelectPalette
521 HPALETTE CDECL MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
523 #define PALVERSION 0x0300
525 PLOGPALETTE logPalette;
526 WORD wNumEntries = 0;
527 BOOL creationSucceed;
528 int sizeofPalette;
530 GetObjectA(hPalette, sizeof(WORD), &wNumEntries);
532 if (wNumEntries == 0) return 0;
534 sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
535 logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
537 if (logPalette == NULL) return 0;
539 logPalette->palVersion = PALVERSION;
540 logPalette->palNumEntries = wNumEntries;
542 GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
544 creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
546 HeapFree( GetProcessHeap(), 0, logPalette );
548 if (creationSucceed)
549 return hPalette;
551 return 0;
554 /***********************************************************************
555 * MFDRV_RealizePalette
557 UINT CDECL MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
559 char buffer[sizeof(METARECORD) - sizeof(WORD)];
560 METARECORD *mr = (METARECORD *)&buffer;
562 mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
563 mr->rdFunction = META_REALIZEPALETTE;
565 if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
567 /* The return value is suppose to be the number of entries
568 in the logical palette mapped to the system palette or 0
569 if the function failed. Since it's not trivial here to
570 get that kind of information and since it's of little
571 use in the case of metafiles, we'll always return 1. */
572 return 1;