Pass a PHYSDEV to EnumDeviceFont and release the GDI lock in
[wine] / dlls / wineps / graphics.c
1 /*
2  *      PostScript driver graphics functions
3  *
4  *      Copyright 1998  Huw D M Davies
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <string.h>
24 #include <math.h>
25 #if defined(HAVE_FLOAT_H)
26  #include <float.h>
27 #endif
28 #if !defined(PI)
29  #define PI M_PI
30 #endif
31 #include "psdrv.h"
32 #include "wine/debug.h"
33 #include "winspool.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
36
37
38 /***********************************************************************
39  *           PSDRV_LineTo
40  */
41 BOOL PSDRV_LineTo(PSDRV_PDEVICE *physDev, INT x, INT y)
42 {
43     DC *dc = physDev->dc;
44
45     TRACE("%d %d\n", x, y);
46
47     PSDRV_SetPen(physDev);
48     PSDRV_WriteMoveTo(physDev, INTERNAL_XWPTODP(dc, dc->CursPosX, dc->CursPosY),
49                       INTERNAL_YWPTODP(dc, dc->CursPosX, dc->CursPosY));
50     PSDRV_WriteLineTo(physDev, INTERNAL_XWPTODP(dc, x, y),
51                       INTERNAL_YWPTODP(dc, x, y));
52     PSDRV_DrawLine(physDev);
53
54     return TRUE;
55 }
56
57
58 /***********************************************************************
59  *           PSDRV_Rectangle
60  */
61 BOOL PSDRV_Rectangle( PSDRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom )
62 {
63     INT width;
64     INT height;
65     DC *dc = physDev->dc;
66
67     TRACE("%d %d - %d %d\n", left, top, right, bottom);
68     width = INTERNAL_XWSTODS(dc, right - left);
69     height = INTERNAL_YWSTODS(dc, bottom - top);
70     PSDRV_WriteRectangle(physDev, INTERNAL_XWPTODP(dc, left, top),
71                          INTERNAL_YWPTODP(dc, left, top), width, height);
72     PSDRV_Brush(physDev,0);
73     PSDRV_SetPen(physDev);
74     PSDRV_DrawLine(physDev);
75     return TRUE;
76 }
77
78
79 /***********************************************************************
80  *           PSDRV_RoundRect
81  */
82 BOOL PSDRV_RoundRect( PSDRV_PDEVICE *physDev, INT left, INT top, INT right,
83                       INT bottom, INT ell_width, INT ell_height )
84 {
85     DC *dc = physDev->dc;
86
87     left = XLPTODP( dc, left );
88     right = XLPTODP( dc, right );
89     top = YLPTODP( dc, top );
90     bottom = YLPTODP( dc, bottom );
91     ell_width = XLSTODS( dc, ell_width );
92     ell_height = YLSTODS( dc, ell_height );
93
94     if( left > right ) { INT tmp = left; left = right; right = tmp; }
95     if( top > bottom ) { INT tmp = top; top = bottom; bottom = tmp; }
96
97     if(ell_width > right - left) ell_width = right - left;
98     if(ell_height > bottom - top) ell_height = bottom - top;
99
100     PSDRV_WriteMoveTo( physDev, left, top + ell_height/2 );
101     PSDRV_WriteArc( physDev, left + ell_width/2, top + ell_height/2, ell_width,
102                     ell_height, 90.0, 180.0);
103     PSDRV_WriteLineTo( physDev, right - ell_width/2, top );
104     PSDRV_WriteArc( physDev, right - ell_width/2, top + ell_height/2, ell_width,
105                     ell_height, 0.0, 90.0);
106     PSDRV_WriteLineTo( physDev, right, bottom - ell_height/2 );
107     PSDRV_WriteArc( physDev, right - ell_width/2, bottom - ell_height/2, ell_width,
108                     ell_height, -90.0, 0.0);
109     PSDRV_WriteLineTo( physDev, right - ell_width/2, bottom);
110     PSDRV_WriteArc( physDev, left + ell_width/2, bottom - ell_height/2, ell_width,
111                     ell_height, 180.0, -90.0);
112     PSDRV_WriteClosePath( physDev );
113
114     PSDRV_Brush(physDev,0);
115     PSDRV_SetPen(physDev);
116     PSDRV_DrawLine(physDev);
117     return TRUE;
118 }
119
120 /***********************************************************************
121  *           PSDRV_DrawArc
122  *
123  * Does the work of Arc, Chord and Pie. lines is 0, 1 or 2 respectively.
124  */
125 static BOOL PSDRV_DrawArc( PSDRV_PDEVICE *physDev, INT left, INT top,
126                            INT right, INT bottom, INT xstart, INT ystart,
127                            INT xend, INT yend, int lines )
128 {
129     DC *dc = physDev->dc;
130     INT x, y, h, w;
131     double start_angle, end_angle, ratio;
132
133     x = XLPTODP(dc, (left + right)/2);
134     y = YLPTODP(dc, (top + bottom)/2);
135
136     w = XLSTODS(dc, (right - left));
137     h = YLSTODS(dc, (bottom - top));
138
139     if(w < 0) w = -w;
140     if(h < 0) h = -h;
141     ratio = ((double)w)/h;
142
143     /* angle is the angle after the rectangle is transformed to a square and is
144        measured anticlockwise from the +ve x-axis */
145
146     start_angle = atan2((double)(y - ystart) * ratio, (double)(xstart - x));
147     end_angle = atan2((double)(y - yend) * ratio, (double)(xend - x));
148
149     start_angle *= 180.0 / PI;
150     end_angle *= 180.0 / PI;
151
152     if(lines == 2) /* pie */
153         PSDRV_WriteMoveTo(physDev, x, y);
154     else
155         PSDRV_WriteNewPath( physDev );
156
157     PSDRV_WriteArc(physDev, x, y, w, h, start_angle, end_angle);
158     if(lines == 1 || lines == 2) { /* chord or pie */
159         PSDRV_WriteClosePath(physDev);
160         PSDRV_Brush(physDev,0);
161     }
162     PSDRV_SetPen(physDev);
163     PSDRV_DrawLine(physDev);
164     return TRUE;
165 }
166
167
168 /***********************************************************************
169  *           PSDRV_Arc
170  */
171 BOOL PSDRV_Arc( PSDRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom,
172                 INT xstart, INT ystart, INT xend, INT yend )
173 {
174     return PSDRV_DrawArc( physDev, left, top, right, bottom, xstart, ystart, xend, yend, 0 );
175 }
176
177 /***********************************************************************
178  *           PSDRV_Chord
179  */
180 BOOL PSDRV_Chord( PSDRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom,
181                   INT xstart, INT ystart, INT xend, INT yend )
182 {
183     return PSDRV_DrawArc( physDev, left, top, right, bottom, xstart, ystart, xend, yend, 1 );
184 }
185
186
187 /***********************************************************************
188  *           PSDRV_Pie
189  */
190 BOOL PSDRV_Pie( PSDRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom,
191                 INT xstart, INT ystart, INT xend, INT yend )
192 {
193     return PSDRV_DrawArc( physDev, left, top, right, bottom, xstart, ystart, xend, yend, 2 );
194 }
195
196
197 /***********************************************************************
198  *           PSDRV_Ellipse
199  */
200 BOOL PSDRV_Ellipse( PSDRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom)
201 {
202     INT x, y, w, h;
203     DC *dc = physDev->dc;
204
205     TRACE("%d %d - %d %d\n", left, top, right, bottom);
206
207     x = XLPTODP(dc, (left + right)/2);
208     y = YLPTODP(dc, (top + bottom)/2);
209
210     w = XLSTODS(dc, (right - left));
211     h = YLSTODS(dc, (bottom - top));
212
213     PSDRV_WriteNewPath(physDev);
214     PSDRV_WriteArc(physDev, x, y, w, h, 0.0, 360.0);
215     PSDRV_WriteClosePath(physDev);
216     PSDRV_Brush(physDev,0);
217     PSDRV_SetPen(physDev);
218     PSDRV_DrawLine(physDev);
219     return TRUE;
220 }
221
222
223 /***********************************************************************
224  *           PSDRV_PolyPolyline
225  */
226 BOOL PSDRV_PolyPolyline( PSDRV_PDEVICE *physDev, const POINT* pts, const DWORD* counts,
227                            DWORD polylines )
228 {
229     DWORD polyline, line;
230     const POINT* pt;
231     DC *dc = physDev->dc;
232
233     TRACE("\n");
234
235     pt = pts;
236     for(polyline = 0; polyline < polylines; polyline++) {
237         PSDRV_WriteMoveTo(physDev, INTERNAL_XWPTODP(dc, pt->x, pt->y), INTERNAL_YWPTODP(dc, pt->x, pt->y));
238         pt++;
239         for(line = 1; line < counts[polyline]; line++) {
240             PSDRV_WriteLineTo(physDev, INTERNAL_XWPTODP(dc, pt->x, pt->y), INTERNAL_YWPTODP(dc, pt->x, pt->y));
241             pt++;
242         }
243     }
244     PSDRV_SetPen(physDev);
245     PSDRV_DrawLine(physDev);
246     return TRUE;
247 }   
248
249
250 /***********************************************************************
251  *           PSDRV_Polyline
252  */
253 BOOL PSDRV_Polyline( PSDRV_PDEVICE *physDev, const POINT* pt, INT count )
254 {
255     return PSDRV_PolyPolyline( physDev, pt, (LPDWORD) &count, 1 );
256 }
257
258
259 /***********************************************************************
260  *           PSDRV_PolyPolygon
261  */
262 BOOL PSDRV_PolyPolygon( PSDRV_PDEVICE *physDev, const POINT* pts, const INT* counts,
263                           UINT polygons )
264 {
265     DWORD polygon, line;
266     const POINT* pt;
267     DC *dc = physDev->dc;
268
269     TRACE("\n");
270
271     pt = pts;
272     for(polygon = 0; polygon < polygons; polygon++) {
273         PSDRV_WriteMoveTo(physDev, INTERNAL_XWPTODP(dc, pt->x, pt->y), INTERNAL_YWPTODP(dc, pt->x, pt->y));
274         pt++;
275         for(line = 1; line < counts[polygon]; line++) {
276             PSDRV_WriteLineTo(physDev, INTERNAL_XWPTODP(dc, pt->x, pt->y), INTERNAL_YWPTODP(dc, pt->x, pt->y));
277             pt++;
278         }
279         PSDRV_WriteClosePath(physDev);
280     }
281
282     if(GetPolyFillMode( physDev->hdc ) == ALTERNATE)
283         PSDRV_Brush(physDev, 1);
284     else /* WINDING */
285         PSDRV_Brush(physDev, 0);
286     PSDRV_SetPen(physDev);
287     PSDRV_DrawLine(physDev);
288     return TRUE;
289 }
290
291
292 /***********************************************************************
293  *           PSDRV_Polygon
294  */
295 BOOL PSDRV_Polygon( PSDRV_PDEVICE *physDev, const POINT* pt, INT count )
296 {
297      return PSDRV_PolyPolygon( physDev, pt, &count, 1 );
298 }
299
300
301 /***********************************************************************
302  *           PSDRV_SetPixel
303  */
304 COLORREF PSDRV_SetPixel( PSDRV_PDEVICE *physDev, INT x, INT y, COLORREF color )
305 {
306     PSCOLOR pscolor;
307     DC *dc = physDev->dc;
308
309     x = INTERNAL_XWPTODP(dc, x, y);
310     y = INTERNAL_YWPTODP(dc, x, y);
311
312     PSDRV_WriteRectangle( physDev, x, y, 0, 0 );
313     PSDRV_CreateColor( physDev, &pscolor, color );
314     PSDRV_WriteSetColor( physDev, &pscolor );
315     PSDRV_WriteFill( physDev );
316     return color;
317 }
318
319
320 /***********************************************************************
321  *           PSDRV_DrawLine
322  */
323 VOID PSDRV_DrawLine( PSDRV_PDEVICE *physDev )
324 {
325     if (physDev->pen.style == PS_NULL)
326         PSDRV_WriteNewPath(physDev);
327     else
328         PSDRV_WriteStroke(physDev);
329 }