user32: Support more user preference system parameters.
[wine] / dlls / wineps.drv / pen.c
1 /*
2  *      PostScript pen handling
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "psdrv.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
30
31 static const DWORD PEN_dash[]       = { 50, 30 };                 /* -----   -----   -----  */
32 static const DWORD PEN_dot[]        = { 20 };                     /* --  --  --  --  --  -- */
33 static const DWORD PEN_dashdot[]    = { 40, 30, 20, 30 };         /* ----   --   ----   --  */
34 static const DWORD PEN_dashdotdot[] = { 40, 20, 20, 20, 20, 20 }; /* ----  --  --  ----  */
35 static const DWORD PEN_alternate[]  = { 1 };
36
37 /***********************************************************************
38  *           SelectPen   (WINEPS.@)
39  */
40 HPEN PSDRV_SelectPen( PHYSDEV dev, HPEN hpen, const struct brush_pattern *pattern )
41 {
42     PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
43     LOGPEN logpen;
44     EXTLOGPEN *elp = NULL;
45
46     if (!GetObjectW( hpen, sizeof(logpen), &logpen ))
47     {
48         /* must be an extended pen */
49         INT size = GetObjectW( hpen, 0, NULL );
50
51         if (!size) return 0;
52
53         elp = HeapAlloc( GetProcessHeap(), 0, size );
54
55         GetObjectW( hpen, size, elp );
56         /* FIXME: add support for user style pens */
57         logpen.lopnStyle = elp->elpPenStyle;
58         logpen.lopnWidth.x = elp->elpWidth;
59         logpen.lopnWidth.y = 0;
60         logpen.lopnColor = elp->elpColor;
61     }
62
63     TRACE("hpen = %p colour = %08x\n", hpen, logpen.lopnColor);
64
65     physDev->pen.width = logpen.lopnWidth.x;
66     if ((logpen.lopnStyle & PS_GEOMETRIC) || (physDev->pen.width > 1))
67     {
68         physDev->pen.width = PSDRV_XWStoDS( dev, physDev->pen.width );
69         if(physDev->pen.width < 0) physDev->pen.width = -physDev->pen.width;
70     }
71     if (hpen == GetStockObject( DC_PEN ))
72         logpen.lopnColor = GetDCPenColor( dev->hdc );
73
74     switch (logpen.lopnStyle & PS_JOIN_MASK)
75     {
76     default:
77     case PS_JOIN_ROUND: physDev->pen.join = 1; break;
78     case PS_JOIN_BEVEL: physDev->pen.join = 2; break;
79     case PS_JOIN_MITER: physDev->pen.join = 0; break;
80     }
81
82     switch (logpen.lopnStyle & PS_ENDCAP_MASK)
83     {
84     default:
85     case PS_ENDCAP_ROUND:  physDev->pen.endcap = 1; break;
86     case PS_ENDCAP_SQUARE: physDev->pen.endcap = 2; break;
87     case PS_ENDCAP_FLAT:   physDev->pen.endcap = 0; break;
88     }
89
90     PSDRV_CreateColor(dev, &physDev->pen.color, logpen.lopnColor);
91     physDev->pen.style = logpen.lopnStyle & PS_STYLE_MASK;
92
93     switch(physDev->pen.style) {
94     case PS_DASH:
95         memcpy( physDev->pen.dash, PEN_dash, sizeof(PEN_dash) );
96         physDev->pen.dash_len = sizeof(PEN_dash) / sizeof(DWORD);
97         break;
98
99     case PS_DOT:
100         memcpy( physDev->pen.dash, PEN_dot, sizeof(PEN_dot) );
101         physDev->pen.dash_len = sizeof(PEN_dot) / sizeof(DWORD);
102         break;
103
104     case PS_DASHDOT:
105         memcpy( physDev->pen.dash, PEN_dashdot, sizeof(PEN_dashdot) );
106         physDev->pen.dash_len = sizeof(PEN_dashdot) / sizeof(DWORD);
107         break;
108
109     case PS_DASHDOTDOT:
110         memcpy( physDev->pen.dash, PEN_dashdotdot, sizeof(PEN_dashdotdot) );
111         physDev->pen.dash_len = sizeof(PEN_dashdotdot) / sizeof(DWORD);
112         break;
113
114     case PS_ALTERNATE:
115         memcpy( physDev->pen.dash, PEN_alternate, sizeof(PEN_alternate) );
116         physDev->pen.dash_len = sizeof(PEN_alternate) / sizeof(DWORD);
117         break;
118
119     case PS_USERSTYLE:
120         physDev->pen.dash_len = min( elp->elpNumEntries, MAX_DASHLEN );
121         memcpy( physDev->pen.dash, elp->elpStyleEntry, physDev->pen.dash_len * sizeof(DWORD) );
122         break;
123
124     default:
125         physDev->pen.dash_len = 0;
126     }
127
128     if ((physDev->pen.width > 1) && physDev->pen.dash_len &&
129         physDev->pen.style != PS_USERSTYLE && physDev->pen.style != PS_ALTERNATE)
130     {
131         physDev->pen.style = PS_SOLID;
132         physDev->pen.dash_len = 0;
133     }
134
135     HeapFree( GetProcessHeap(), 0, elp );
136     physDev->pen.set = FALSE;
137     return hpen;
138 }
139
140
141 /***********************************************************************
142  *           SetDCPenColor (WINEPS.@)
143  */
144 COLORREF PSDRV_SetDCPenColor( PHYSDEV dev, COLORREF color )
145 {
146     PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
147
148     if (GetCurrentObject( dev->hdc, OBJ_PEN ) == GetStockObject( DC_PEN ))
149         PSDRV_CreateColor( dev, &physDev->pen.color, color );
150     return color;
151 }
152
153
154 /**********************************************************************
155  *
156  *      PSDRV_SetPen
157  *
158  */
159 BOOL PSDRV_SetPen( PHYSDEV dev )
160 {
161     PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
162
163     if (physDev->pen.style != PS_NULL) {
164         PSDRV_WriteSetColor(dev, &physDev->pen.color);
165
166         if(!physDev->pen.set) {
167             PSDRV_WriteSetPen(dev);
168             physDev->pen.set = TRUE;
169         }
170     }
171
172     return TRUE;
173 }