25
25
*/
26
26
27
27
#include "customlinecap-private.h"
28
+ #include "graphics-path-private.h"
29
+ #include "graphics-private.h"
30
+ #include "graphics-cairo-private.h"
28
31
29
32
static GpStatus gdip_custom_linecap_setup (GpGraphics * graphics , GpCustomLineCap * cap );
30
33
static GpStatus gdip_custom_linecap_clone_cap (GpCustomLineCap * cap , GpCustomLineCap * * clonedCap );
31
34
static GpStatus gdip_custom_linecap_destroy (GpCustomLineCap * cap );
35
+ static GpStatus gdip_custom_linecap_draw (GpGraphics * graphics , GpPen * pen , GpCustomLineCap * cap , float x , float y , float otherend_x , float otherend_y );
32
36
33
37
/*
34
38
* we have a single copy of vtable for
@@ -38,7 +42,8 @@ static GpStatus gdip_custom_linecap_destroy (GpCustomLineCap *cap);
38
42
static CapClass vtable = { CustomLineCapTypeDefault ,
39
43
gdip_custom_linecap_setup ,
40
44
gdip_custom_linecap_clone_cap ,
41
- gdip_custom_linecap_destroy };
45
+ gdip_custom_linecap_destroy ,
46
+ gdip_custom_linecap_draw };
42
47
43
48
void
44
49
gdip_custom_linecap_init (GpCustomLineCap * cap , CapClass * vt )
@@ -51,6 +56,8 @@ gdip_custom_linecap_init (GpCustomLineCap *cap, CapClass *vt)
51
56
cap -> base_inset = 0.0 ;
52
57
/* LAMESPEC: Default value is documented as 1.0, but actually it is 0.0 */
53
58
cap -> width_scale = 0.0 ;
59
+ cap -> fill_path = NULL ;
60
+ cap -> stroke_path = NULL ;
54
61
}
55
62
56
63
static GpCustomLineCap *
@@ -68,6 +75,7 @@ GpStatus
68
75
gdip_custom_linecap_clone_cap (GpCustomLineCap * cap , GpCustomLineCap * * clonedCap )
69
76
{
70
77
GpCustomLineCap * newcap ;
78
+ GpPath * fillpath = NULL , * strokepath = NULL ;
71
79
72
80
if (!cap || !clonedCap )
73
81
return InvalidParameter ;
@@ -84,6 +92,27 @@ gdip_custom_linecap_clone_cap (GpCustomLineCap *cap, GpCustomLineCap **clonedCap
84
92
newcap -> base_inset = cap -> base_inset ;
85
93
newcap -> width_scale = cap -> width_scale ;
86
94
95
+ if (cap -> fill_path ) {
96
+ if (GdipClonePath (cap -> fill_path , & fillpath ) != Ok ) {
97
+ if (fillpath != NULL )
98
+ GdipFree (fillpath );
99
+ GdipFree (newcap );
100
+ return OutOfMemory ;
101
+ }
102
+ }
103
+ newcap -> fill_path = fillpath ;
104
+
105
+ if (cap -> stroke_path ) {
106
+ if (GdipClonePath (cap -> stroke_path , & strokepath ) != Ok ) {
107
+ if (strokepath != NULL )
108
+ GdipFree (strokepath );
109
+ GdipFree (fillpath );
110
+ GdipFree (newcap );
111
+ return OutOfMemory ;
112
+ }
113
+ }
114
+ newcap -> stroke_path = strokepath ;
115
+
87
116
* clonedCap = newcap ;
88
117
89
118
return Ok ;
@@ -95,6 +124,14 @@ gdip_custom_linecap_destroy (GpCustomLineCap *cap)
95
124
if (!cap )
96
125
return InvalidParameter ;
97
126
127
+ if (cap -> fill_path ) {
128
+ GdipDeletePath (cap -> fill_path );
129
+ cap -> fill_path = NULL ;
130
+ }
131
+ if (cap -> stroke_path ) {
132
+ GdipDeletePath (cap -> stroke_path );
133
+ cap -> stroke_path = NULL ;
134
+ }
98
135
GdipFree (cap );
99
136
100
137
return Ok ;
@@ -110,6 +147,105 @@ gdip_custom_linecap_setup (GpGraphics *graphics, GpCustomLineCap *customCap)
110
147
return NotImplemented ;
111
148
}
112
149
150
+ double
151
+ gdip_custom_linecap_angle (float x , float y , float otherend_x , float otherend_y )
152
+ {
153
+ float slope ;
154
+ double angle ;
155
+
156
+ if (y < otherend_y ) {
157
+ slope = (otherend_y - y ) / (otherend_x - x );
158
+ if (x < otherend_x ) {
159
+ angle = PI /2 ;
160
+ } else {
161
+ angle = PI /-2 ;
162
+ }
163
+ } else {
164
+ slope = (otherend_x - x ) / (y - otherend_y );
165
+ angle = 0 ;
166
+ }
167
+ angle += atan (slope );
168
+
169
+ return angle ;
170
+ }
171
+
172
+ GpStatus
173
+ gdip_custom_linecap_draw (GpGraphics * graphics , GpPen * pen , GpCustomLineCap * customCap , float x , float y , float otherend_x , float otherend_y )
174
+ {
175
+ double angle ;
176
+ int points ;
177
+ int i , idx = 0 ;
178
+ float penwidth ;
179
+
180
+ if (!graphics || !pen || !customCap )
181
+ return InvalidParameter ;
182
+
183
+ penwidth = pen -> width ;
184
+ angle = gdip_custom_linecap_angle (x , y , otherend_x , otherend_y );
185
+
186
+ cairo_save (graphics -> ct );
187
+
188
+ /* FIXME: handle base_inset (including set/get!) */
189
+ cairo_translate (graphics -> ct , x , y );
190
+ cairo_rotate (graphics -> ct , angle );
191
+
192
+ if (customCap -> stroke_path ) {
193
+ GpPath * path = customCap -> stroke_path ;
194
+ points = path -> count ;
195
+
196
+ for (i = 0 ; i < points ; i ++ ) {
197
+ /* Adapted from gdip_plot_path() */
198
+ GpPointF point = g_array_index (path -> points , GpPointF , i );
199
+ BYTE type = g_array_index (path -> types , BYTE , i );
200
+ GpPointF pts [3 ];
201
+
202
+ /* mask the bits so that we get only the type value not the other flags */
203
+ switch (type & PathPointTypePathTypeMask ) {
204
+ case PathPointTypeStart :
205
+ gdip_cairo_move_to (graphics , point .X * penwidth , point .Y * penwidth , TRUE, TRUE);
206
+ break ;
207
+
208
+ case PathPointTypeLine :
209
+ gdip_cairo_line_to (graphics , point .X * penwidth , point .Y * penwidth , TRUE, TRUE);
210
+ break ;
211
+
212
+ case PathPointTypeBezier :
213
+ /* make sure we only add at most 3 points to pts */
214
+ if (idx < 3 ) {
215
+ pts [idx ] = point ;
216
+ idx ++ ;
217
+ }
218
+
219
+ /* once we've added 3 pts, we can draw the curve */
220
+ if (idx == 3 ) {
221
+ gdip_cairo_curve_to (graphics , pts [0 ].X * penwidth , pts [0 ].Y * penwidth , pts [1 ].X * penwidth , pts [1 ].Y * penwidth , pts [2 ].X * penwidth , pts [2 ].Y * penwidth , TRUE, TRUE);
222
+ idx = 0 ;
223
+ }
224
+ break ;
225
+
226
+ default :
227
+ g_warning ("Unknown PathPointType %d" , type );
228
+ return NotImplemented ;
229
+ }
230
+
231
+ /* close the subpath */
232
+ if (type & PathPointTypeCloseSubpath ) {
233
+ cairo_close_path (graphics -> ct );
234
+ }
235
+ }
236
+
237
+ gdip_pen_setup (graphics , pen );
238
+ cairo_stroke (graphics -> ct );
239
+ cairo_set_matrix (graphics -> ct , graphics -> copy_of_ctm );
240
+ }
241
+
242
+ /* FIXME: handle fill_path */
243
+
244
+ cairo_restore (graphics -> ct );
245
+
246
+ return gdip_get_status (cairo_status (graphics -> ct ));
247
+ }
248
+
113
249
/* this setup function gets called from pen */
114
250
115
251
GpStatus
@@ -121,13 +257,25 @@ gdip_linecap_setup (GpGraphics *graphics, GpCustomLineCap *customCap)
121
257
return customCap -> vtable -> setup (graphics , customCap );
122
258
}
123
259
260
+ /* this draw function gets called from pen */
261
+
262
+ GpStatus
263
+ gdip_linecap_draw (GpGraphics * graphics , GpPen * pen , GpCustomLineCap * customCap , float x , float y , float otherend_x , float otherend_y )
264
+ {
265
+ if (!graphics || !pen || !customCap )
266
+ return InvalidParameter ;
267
+
268
+ return customCap -> vtable -> draw (graphics , pen , customCap , x , y , otherend_x , otherend_y );
269
+ }
270
+
124
271
/* CustomLineCap functions */
125
272
126
273
// coverity[+alloc : arg-*4]
127
274
GpStatus
128
275
GdipCreateCustomLineCap (GpPath * fillPath , GpPath * strokePath , GpLineCap baseCap , float baseInset , GpCustomLineCap * * customCap )
129
276
{
130
277
GpCustomLineCap * cap ;
278
+ GpPath * fillpath_clone = NULL , * strokepath_clone = NULL ;
131
279
132
280
if ((!fillPath && !strokePath ) || !customCap )
133
281
return InvalidParameter ;
@@ -136,8 +284,27 @@ GdipCreateCustomLineCap (GpPath *fillPath, GpPath *strokePath, GpLineCap baseCap
136
284
if (!cap )
137
285
return OutOfMemory ;
138
286
139
- cap -> fill_path = fillPath ;
140
- cap -> stroke_path = strokePath ;
287
+ if (fillPath ) {
288
+ if (GdipClonePath (fillPath , & fillpath_clone ) != Ok ) {
289
+ if (fillpath_clone != NULL )
290
+ GdipFree (fillpath_clone );
291
+ GdipFree (cap );
292
+ return OutOfMemory ;
293
+ }
294
+ }
295
+ cap -> fill_path = fillpath_clone ;
296
+
297
+ if (strokePath ) {
298
+ if (GdipClonePath (strokePath , & strokepath_clone ) != Ok ) {
299
+ if (strokepath_clone != NULL )
300
+ GdipFree (strokepath_clone );
301
+ GdipFree (fillpath_clone );
302
+ GdipFree (cap );
303
+ return OutOfMemory ;
304
+ }
305
+ }
306
+ cap -> stroke_path = strokepath_clone ;
307
+
141
308
cap -> base_cap = baseCap ;
142
309
cap -> base_inset = baseInset ;
143
310
0 commit comments