|
1 From: Robert O'Callahan <robert@ocallahan.org> |
|
2 Bug 768348. Avoid ExtCreatePen failures by avoiding rounding widths and dash lengths down to zero. r=jrmuizel |
|
3 |
|
4 diff --git a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c |
|
5 --- a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c |
|
6 +++ b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c |
|
7 @@ -1251,22 +1251,24 @@ static cairo_int_status_t |
|
8 { |
|
9 cairo_win32_surface_t *surface = abstract_surface; |
|
10 cairo_int_status_t status; |
|
11 HPEN pen; |
|
12 LOGBRUSH brush; |
|
13 COLORREF color; |
|
14 XFORM xform; |
|
15 DWORD pen_style; |
|
16 + DWORD pen_width; |
|
17 DWORD *dash_array; |
|
18 HGDIOBJ obj; |
|
19 unsigned int i; |
|
20 cairo_solid_pattern_t clear; |
|
21 cairo_matrix_t mat; |
|
22 double scale; |
|
23 + double scaled_width; |
|
24 |
|
25 status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); |
|
26 if (status) |
|
27 return status; |
|
28 |
|
29 if (op == CAIRO_OPERATOR_CLEAR) { |
|
30 _cairo_win32_printing_surface_init_clear_color (surface, &clear); |
|
31 source = (cairo_pattern_t*) &clear; |
|
32 @@ -1288,17 +1290,21 @@ static cairo_int_status_t |
|
33 _cairo_matrix_factor_out_scale (&mat, &scale); |
|
34 |
|
35 pen_style = PS_GEOMETRIC; |
|
36 dash_array = NULL; |
|
37 if (style->num_dashes) { |
|
38 pen_style |= PS_USERSTYLE; |
|
39 dash_array = calloc (sizeof (DWORD), style->num_dashes); |
|
40 for (i = 0; i < style->num_dashes; i++) { |
|
41 - dash_array[i] = (DWORD) (scale * style->dash[i]); |
|
42 + DWORD dashes = (DWORD) (scale * style->dash[i]); |
|
43 + /* zero dash-lengths cause ExtCreatePen to fail. Make the dashes |
|
44 + * longer if necessary. |
|
45 + */ |
|
46 + dash_array[i] = MAX(1, dashes); |
|
47 } |
|
48 } else { |
|
49 pen_style |= PS_SOLID; |
|
50 } |
|
51 |
|
52 SetMiterLimit (surface->dc, (FLOAT) (style->miter_limit), NULL); |
|
53 if (source->type == CAIRO_PATTERN_TYPE_SOLID) { |
|
54 cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source; |
|
55 @@ -1310,18 +1316,29 @@ static cairo_int_status_t |
|
56 /* Color not used as the pen will only be used by WidenPath() */ |
|
57 color = RGB (0,0,0); |
|
58 } |
|
59 brush.lbStyle = BS_SOLID; |
|
60 brush.lbColor = color; |
|
61 brush.lbHatch = 0; |
|
62 pen_style |= _cairo_win32_line_cap (style->line_cap); |
|
63 pen_style |= _cairo_win32_line_join (style->line_join); |
|
64 + scaled_width = scale * style->line_width; |
|
65 + if (scaled_width == 0.0) |
|
66 + return status; |
|
67 + pen_width = (DWORD)scaled_width; |
|
68 + if (pen_width == 0) { |
|
69 + /* ExtCreatePen will fail if passed zero width. We have to choose |
|
70 + * between drawing something too wide, or drawing nothing at all. |
|
71 + * Let's draw something. |
|
72 + */ |
|
73 + pen_width = 1; |
|
74 + } |
|
75 pen = ExtCreatePen(pen_style, |
|
76 - scale * style->line_width, |
|
77 + pen_width, |
|
78 &brush, |
|
79 style->num_dashes, |
|
80 dash_array); |
|
81 if (pen == NULL) |
|
82 return _cairo_win32_print_gdi_error ("_win32_surface_stroke:ExtCreatePen"); |
|
83 obj = SelectObject (surface->dc, pen); |
|
84 if (obj == NULL) |
|
85 return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectObject"); |