Fixed error handling in DGA_IDirectDraw2Impl_GetCaps().
[wine] / graphics / metafiledrv / objects.c
1 /*
2  * GDI objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  */
6
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include "bitmap.h"
10 #include "brush.h"
11 #include "font.h"
12 #include "metafiledrv.h"
13 #include "pen.h"
14 #include "debugtools.h"
15 #include "heap.h"
16
17 DECLARE_DEBUG_CHANNEL(gdi)
18 DECLARE_DEBUG_CHANNEL(metafile)
19
20 /***********************************************************************
21  *           MFDRV_BITMAP_SelectObject
22  */
23 static HBITMAP16 MFDRV_BITMAP_SelectObject( DC * dc, HBITMAP16 hbitmap,
24                                             BITMAPOBJ * bmp )
25 {
26     return 0;
27 }
28
29
30 /******************************************************************
31  *         MFDRV_CreateBrushIndirect
32  */
33
34 INT16 MFDRV_CreateBrushIndirect(DC *dc, HBRUSH hBrush )
35 {
36     INT16 index;
37     DWORD size;
38     METARECORD *mr;
39     BRUSHOBJ *brushObj = (BRUSHOBJ *)GDI_GetObjPtr( hBrush, BRUSH_MAGIC );
40     if(!brushObj) return -1;
41     
42     switch(brushObj->logbrush.lbStyle) {
43     case BS_SOLID:
44     case BS_NULL:
45     case BS_HATCHED:
46         {
47             LOGBRUSH16 lb16;
48
49             lb16.lbStyle = brushObj->logbrush.lbStyle;
50             lb16.lbColor = brushObj->logbrush.lbColor;
51             lb16.lbHatch = brushObj->logbrush.lbHatch;
52             size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2;
53             mr = HeapAlloc( SystemHeap, 0, size );
54             mr->rdSize = size / 2;
55             mr->rdFunction = META_CREATEBRUSHINDIRECT;
56             memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH));
57             break;
58         }
59     case BS_PATTERN:
60         {
61             BITMAP bm;
62             BYTE *bits;
63             BITMAPINFO *info;
64             DWORD bmSize;
65
66             GetObjectA(brushObj->logbrush.lbHatch, sizeof(bm), &bm);
67             if(bm.bmBitsPixel != 1 || bm.bmPlanes != 1) {
68                 FIXME_(metafile)("Trying to store a colour pattern brush\n");
69                 return FALSE;
70             }
71
72             bmSize = DIB_GetDIBImageBytes(bm.bmWidth, bm.bmHeight, 1);
73
74             size = sizeof(METARECORD) + sizeof(WORD) + sizeof(BITMAPINFO) + 
75               sizeof(RGBQUAD) + bmSize;
76
77             mr = HeapAlloc(SystemHeap, HEAP_ZERO_MEMORY, size);
78             if(!mr) return FALSE;
79             mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
80             mr->rdSize = size / 2;
81             mr->rdParm[0] = BS_PATTERN;
82             mr->rdParm[1] = DIB_RGB_COLORS;
83             info = (BITMAPINFO *)(mr->rdParm + 2);
84
85             info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
86             info->bmiHeader.biWidth = bm.bmWidth;
87             info->bmiHeader.biHeight = bm.bmHeight;
88             info->bmiHeader.biPlanes = 1;
89             info->bmiHeader.biBitCount = 1;
90             bits = ((BYTE *)info) + sizeof(BITMAPINFO) + sizeof(RGBQUAD);
91
92             GetDIBits(dc->hSelf, brushObj->logbrush.lbHatch, 0, bm.bmHeight,
93                       bits, info, DIB_RGB_COLORS);
94             *(DWORD *)info->bmiColors = 0;
95             *(DWORD *)(info->bmiColors + 1) = 0xffffff;
96             break;
97         }
98
99     case BS_DIBPATTERN:
100         {
101               BITMAPINFO *info;
102               DWORD bmSize, biSize;
103
104               info = GlobalLock16((HGLOBAL16)brushObj->logbrush.lbHatch);
105               if (info->bmiHeader.biCompression)
106                   bmSize = info->bmiHeader.biSizeImage;
107               else
108                   bmSize = DIB_GetDIBImageBytes(info->bmiHeader.biWidth,
109                                                 info->bmiHeader.biHeight,
110                                                 info->bmiHeader.biBitCount);
111               biSize = DIB_BitmapInfoSize(info,
112                                           LOWORD(brushObj->logbrush.lbColor)); 
113               size = sizeof(METARECORD) + biSize + bmSize + 2;
114               mr = HeapAlloc(SystemHeap, HEAP_ZERO_MEMORY, size);
115               if(!mr) return FALSE;
116               mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
117               mr->rdSize = size / 2;
118               *(mr->rdParm) = brushObj->logbrush.lbStyle;
119               *(mr->rdParm + 1) = LOWORD(brushObj->logbrush.lbColor);
120               memcpy(mr->rdParm + 2, info, biSize + bmSize);
121               break;
122         }
123         default:
124             FIXME_(metafile)("Unkonwn brush style %x\n", 
125                   brushObj->logbrush.lbStyle);
126             return -1;
127     }
128     index = MFDRV_AddHandleDC( dc );
129     if(!MFDRV_WriteRecord( dc, mr, mr->rdSize * 2))
130         index = -1;
131     HeapFree(SystemHeap, 0, mr);
132     GDI_HEAP_UNLOCK( hBrush );
133     return index;
134 }
135
136
137 /***********************************************************************
138  *           MFDRV_BRUSH_SelectObject
139  */
140 static HBRUSH MFDRV_BRUSH_SelectObject( DC *dc, HBRUSH hbrush,
141                                         BRUSHOBJ * brush )
142 {
143     INT16 index;
144     METARECORD mr;
145
146     index = MFDRV_CreateBrushIndirect( dc, hbrush );
147     if(index == -1) return 0;
148
149     mr.rdSize = sizeof(mr) / 2;
150     mr.rdFunction = META_SELECTOBJECT;
151     mr.rdParm[0] = index;
152     return MFDRV_WriteRecord( dc, &mr, mr.rdSize * 2);
153 }
154
155 /******************************************************************
156  *         MFDRV_CreateFontIndirect
157  */
158
159 static BOOL MFDRV_CreateFontIndirect(DC *dc, HFONT16 hFont, LOGFONT16 *logfont)
160 {
161     int index;
162     char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
163     METARECORD *mr = (METARECORD *)&buffer;
164
165     mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
166     mr->rdFunction = META_CREATEFONTINDIRECT;
167     memcpy(&(mr->rdParm), logfont, sizeof(LOGFONT16));
168     if (!(MFDRV_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
169
170     mr->rdSize = sizeof(METARECORD) / 2;
171     mr->rdFunction = META_SELECTOBJECT;
172
173     if ((index = MFDRV_AddHandleDC( dc )) == -1) return FALSE;
174     *(mr->rdParm) = index;
175     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
176 }
177
178
179 /***********************************************************************
180  *           MFDRV_FONT_SelectObject
181  */
182 static HFONT16 MFDRV_FONT_SelectObject( DC * dc, HFONT16 hfont,
183                                         FONTOBJ * font )
184 {
185     HFONT16 prevHandle = dc->w.hFont;
186     if (MFDRV_CreateFontIndirect(dc, hfont, &(font->logfont)))
187         return prevHandle;
188     return 0;
189 }
190
191 /******************************************************************
192  *         MFDRV_CreatePenIndirect
193  */
194 static BOOL MFDRV_CreatePenIndirect(DC *dc, HPEN16 hPen, LOGPEN16 *logpen)
195 {
196     int index;
197     char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
198     METARECORD *mr = (METARECORD *)&buffer;
199
200     mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
201     mr->rdFunction = META_CREATEPENINDIRECT;
202     memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
203     if (!(MFDRV_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
204
205     mr->rdSize = sizeof(METARECORD) / 2;
206     mr->rdFunction = META_SELECTOBJECT;
207
208     if ((index = MFDRV_AddHandleDC( dc )) == -1) return FALSE;
209     *(mr->rdParm) = index;
210     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
211 }
212
213
214 /***********************************************************************
215  *           MFDRV_PEN_SelectObject
216  */
217 static HPEN MFDRV_PEN_SelectObject( DC * dc, HPEN hpen, PENOBJ * pen )
218 {
219     LOGPEN16 logpen;
220     HPEN prevHandle = dc->w.hPen;
221
222     logpen.lopnStyle = pen->logpen.lopnStyle;
223     logpen.lopnWidth.x = pen->logpen.lopnWidth.x;
224     logpen.lopnWidth.y = pen->logpen.lopnWidth.y;
225     logpen.lopnColor = pen->logpen.lopnColor;
226
227     if (MFDRV_CreatePenIndirect( dc, hpen, &logpen )) return prevHandle;
228
229     return 0;
230 }
231
232
233 /***********************************************************************
234  *           MFDRV_SelectObject
235  */
236 HGDIOBJ MFDRV_SelectObject( DC *dc, HGDIOBJ handle )
237 {
238     GDIOBJHDR * ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
239     HGDIOBJ ret = 0;
240
241     if (!ptr) return 0;
242     TRACE_(gdi)("hdc=%04x %04x\n", dc->hSelf, handle );
243     
244     switch(ptr->wMagic)
245     {
246       case PEN_MAGIC:
247           ret = MFDRV_PEN_SelectObject( dc, handle, (PENOBJ *)ptr );
248           break;
249       case BRUSH_MAGIC:
250           ret = MFDRV_BRUSH_SelectObject( dc, handle, (BRUSHOBJ *)ptr );
251           break;
252       case BITMAP_MAGIC:
253           ret = MFDRV_BITMAP_SelectObject( dc, handle, (BITMAPOBJ *)ptr );
254           break;
255       case FONT_MAGIC:
256           ret = MFDRV_FONT_SelectObject( dc, handle, (FONTOBJ *)ptr );    
257           break;
258       case REGION_MAGIC:
259           ret = (HGDIOBJ16)SelectClipRgn16( dc->hSelf, handle );
260           break;
261     }
262     GDI_HEAP_UNLOCK( handle );
263     return ret;
264 }
265
266