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