mshtml/tests: Make sure return values are used (LLVM/Clang).
[wine] / dlls / gdi32 / mfdrv / objects.c
1 /*
2  * GDI objects
3  *
4  * Copyright 1993 Alexandre Julliard
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 <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdarg.h>
25
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"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
35
36 /******************************************************************
37  *         MFDRV_AddHandle
38  */
39 UINT MFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj )
40 {
41     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
42     UINT16 index;
43
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]));
51     }
52     physDev->handles[index] = obj;
53
54     physDev->cur_handles++; 
55     if(physDev->cur_handles > physDev->mh->mtNoObjects)
56         physDev->mh->mtNoObjects++;
57
58     return index ; /* index 0 is not reserved for metafiles */
59 }
60
61 /******************************************************************
62  *         MFDRV_RemoveHandle
63  */
64 BOOL MFDRV_RemoveHandle( PHYSDEV dev, UINT index )
65 {
66     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
67     BOOL ret = FALSE;
68
69     if (index < physDev->handles_size && physDev->handles[index])
70     {
71         physDev->handles[index] = 0;
72         physDev->cur_handles--;
73         ret = TRUE;
74     }
75     return ret;
76 }
77
78 /******************************************************************
79  *         MFDRV_FindObject
80  */
81 static INT16 MFDRV_FindObject( PHYSDEV dev, HGDIOBJ obj )
82 {
83     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
84     INT16 index;
85
86     for(index = 0; index < physDev->handles_size; index++)
87         if(physDev->handles[index] == obj) break;
88
89     if(index == physDev->handles_size) return -1;
90
91     return index ;
92 }
93
94
95 /******************************************************************
96  *         MFDRV_DeleteObject
97  */
98 BOOL CDECL MFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj )
99 {
100     METARECORD mr;
101     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
102     INT16 index;
103     BOOL ret = TRUE;
104
105     index = MFDRV_FindObject(dev, obj);
106     if( index < 0 )
107         return 0;
108
109     mr.rdSize = sizeof mr / 2;
110     mr.rdFunction = META_DELETEOBJECT;
111     mr.rdParm[0] = index;
112
113     if(!MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 ))
114         ret = FALSE;
115
116     physDev->handles[index] = 0;
117     physDev->cur_handles--;
118     return ret;
119 }
120
121
122 /***********************************************************************
123  *           MFDRV_SelectObject
124  */
125 static BOOL MFDRV_SelectObject( PHYSDEV dev, INT16 index)
126 {
127     METARECORD mr;
128
129     mr.rdSize = sizeof mr / 2;
130     mr.rdFunction = META_SELECTOBJECT;
131     mr.rdParm[0] = index;
132
133     return MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 );
134 }
135
136
137 /***********************************************************************
138  *           MFDRV_SelectBitmap
139  */
140 HBITMAP CDECL MFDRV_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap )
141 {
142     return 0;
143 }
144
145 /***********************************************************************
146  * Internal helper for MFDRV_CreateBrushIndirect():
147  * Change the padding of a bitmap from 16 (BMP) to 32 (DIB) bits.
148  */
149 static inline void MFDRV_PadTo32(LPBYTE lpRows, int height, int width)
150 {
151     int bytes16 = 2 * ((width + 15) / 16);
152     int bytes32 = 4 * ((width + 31) / 32);
153     LPBYTE lpSrc, lpDst;
154     int i;
155
156     if (!height)
157         return;
158
159     height = abs(height) - 1;
160     lpSrc = lpRows + height * bytes16;
161     lpDst = lpRows + height * bytes32;
162
163     /* Note that we work backwards so we can re-pad in place */
164     while (height >= 0)
165     {
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--;
173     }
174 }
175
176 /***********************************************************************
177  * Internal helper for MFDRV_CreateBrushIndirect():
178  * Reverse order of bitmap rows in going from BMP to DIB.
179  */
180 static inline void MFDRV_Reverse(LPBYTE lpRows, int height, int width)
181 {
182     int bytes = 4 * ((width + 31) / 32);
183     LPBYTE lpSrc, lpDst;
184     BYTE temp;
185     int i;
186
187     if (!height)
188         return;
189
190     lpSrc = lpRows;
191     lpDst = lpRows + (height-1) * bytes;
192     height = height/2;
193
194     while (height > 0)
195     {
196         for (i = 0; i < bytes; i++)
197         {
198             temp = lpDst[i];
199             lpDst[i] = lpSrc[i];
200             lpSrc[i] = temp;
201         }
202         lpSrc += bytes;
203         lpDst -= bytes;
204         height--;
205     }
206 }
207
208 /******************************************************************
209  *         MFDRV_CreateBrushIndirect
210  */
211
212 INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush )
213 {
214     DWORD size;
215     METARECORD *mr;
216     LOGBRUSH logbrush;
217     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
218     BOOL r;
219
220     if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1;
221
222     switch(logbrush.lbStyle)
223     {
224     case BS_SOLID:
225     case BS_NULL:
226     case BS_HATCHED:
227         {
228             LOGBRUSH16 lb16;
229
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;
239         }
240     case BS_PATTERN:
241         {
242             BITMAP bm;
243             BITMAPINFO *info;
244             DWORD bmSize;
245             COLORREF cref;
246
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;
251             }
252
253             bmSize = DIB_GetDIBImageBytes(bm.bmWidth, bm.bmHeight, DIB_PAL_COLORS);
254
255             size = sizeof(METARECORD) + sizeof(WORD) + sizeof(BITMAPINFO) +
256               sizeof(RGBQUAD) + bmSize;
257
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);
265
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;
272
273             GetBitmapBits((HANDLE)logbrush.lbHatch,
274                       bm.bmHeight * BITMAP_GetWidthBytes (bm.bmWidth, bm.bmBitsPixel),
275                       (LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD));
276
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);
284
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;
296         }
297
298     case BS_DIBPATTERN:
299         {
300               BITMAPINFO *info;
301               DWORD bmSize, biSize;
302
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)
314               {
315                   GlobalUnlock( (HGLOBAL)logbrush.lbHatch );
316                   goto done;
317               }
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;
325         }
326         default:
327             FIXME("Unkonwn brush style %x\n", logbrush.lbStyle);
328             return 0;
329     }
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 );
336 }
337
338
339 /***********************************************************************
340  *           MFDRV_SelectBrush
341  */
342 HBRUSH CDECL MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush )
343 {
344     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
345     INT16 index;
346
347     index = MFDRV_FindObject(dev, hbrush);
348     if( index < 0 )
349     {
350         index = MFDRV_CreateBrushIndirect( dev, hbrush );
351         if( index < 0 )
352             return 0;
353         GDI_hdc_using_object(hbrush, physDev->hdc);
354     }
355     return MFDRV_SelectObject( dev, index ) ? hbrush : HGDI_ERROR;
356 }
357
358 /******************************************************************
359  *         MFDRV_CreateFontIndirect
360  */
361
362 static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, LOGFONTW *logfont)
363 {
364     char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
365     METARECORD *mr = (METARECORD *)&buffer;
366     LOGFONT16 *font16;
367     INT written;
368
369     mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
370     mr->rdFunction = META_CREATEFONTINDIRECT;
371     font16 = (LOGFONT16 *)&mr->rdParm;
372
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);
389
390     if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
391         return 0;
392     return MFDRV_AddHandle( dev, hFont );
393 }
394
395
396 /***********************************************************************
397  *           MFDRV_SelectFont
398  */
399 HFONT CDECL MFDRV_SelectFont( PHYSDEV dev, HFONT hfont, HANDLE gdiFont )
400 {
401     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
402     LOGFONTW font;
403     INT16 index;
404
405     index = MFDRV_FindObject(dev, hfont);
406     if( index < 0 )
407     {
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);
414     }
415     return MFDRV_SelectObject( dev, index ) ? hfont : HGDI_ERROR;
416 }
417
418 /******************************************************************
419  *         MFDRV_CreatePenIndirect
420  */
421 static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen)
422 {
423     char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
424     METARECORD *mr = (METARECORD *)&buffer;
425
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 );
432 }
433
434
435 /***********************************************************************
436  *           MFDRV_SelectPen
437  */
438 HPEN CDECL MFDRV_SelectPen( PHYSDEV dev, HPEN hpen )
439 {
440     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
441     LOGPEN16 logpen;
442     INT16 index;
443
444     index = MFDRV_FindObject(dev, hpen);
445     if( index < 0 )
446     {
447         /* must be an extended pen */
448         INT size = GetObjectW( hpen, 0, NULL );
449
450         if (!size) return 0;
451
452         if (size == sizeof(LOGPEN))
453         {
454             LOGPEN pen;
455
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;
461         }
462         else  /* must be an extended pen */
463         {
464             EXTLOGPEN *elp = HeapAlloc( GetProcessHeap(), 0, size );
465
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;
472
473             HeapFree( GetProcessHeap(), 0, elp );
474         }
475
476         index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
477         if( index < 0 )
478             return 0;
479         GDI_hdc_using_object(hpen, physDev->hdc);
480     }
481     return MFDRV_SelectObject( dev, index ) ? hpen : HGDI_ERROR;
482 }
483
484
485 /******************************************************************
486  *         MFDRV_CreatePalette
487  */
488 static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
489 {
490     int index;
491     BOOL ret;
492     METARECORD *mr;
493
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))))
499     {
500         HeapFree(GetProcessHeap(), 0, mr);
501         return FALSE;
502     }
503
504     mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
505     mr->rdFunction = META_SELECTPALETTE;
506
507     if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
508     else
509     {
510         *(mr->rdParm) = index;
511         ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
512     }
513     HeapFree(GetProcessHeap(), 0, mr);
514     return ret;
515 }
516
517
518 /***********************************************************************
519  *           MFDRV_SelectPalette
520  */
521 HPALETTE CDECL MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
522 {
523 #define PALVERSION 0x0300
524
525     PLOGPALETTE logPalette;
526     WORD        wNumEntries = 0;
527     BOOL        creationSucceed;
528     int         sizeofPalette;
529
530     GetObjectA(hPalette, sizeof(WORD), &wNumEntries);
531
532     if (wNumEntries == 0) return 0;
533
534     sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
535     logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
536
537     if (logPalette == NULL) return 0;
538
539     logPalette->palVersion = PALVERSION;
540     logPalette->palNumEntries = wNumEntries;
541
542     GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
543
544     creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
545
546     HeapFree( GetProcessHeap(), 0, logPalette );
547
548     if (creationSucceed)
549         return hPalette;
550
551     return 0;
552 }
553
554 /***********************************************************************
555  *           MFDRV_RealizePalette
556  */
557 UINT CDECL MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
558 {
559     char buffer[sizeof(METARECORD) - sizeof(WORD)];
560     METARECORD *mr = (METARECORD *)&buffer;
561
562     mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
563     mr->rdFunction = META_REALIZEPALETTE;
564
565     if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
566
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;
573 }