1 /* Copyright (C) 2001-2019 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied,
8    modified or distributed except as expressly authorized under the terms
9    of the license contained in the file LICENSE in this distribution.
10 
11    Refer to licensing information at http://www.artifex.com or contact
12    Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13    CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 
17 /* Graphics-state-aware fill and stroke procedures */
18 #include "gx.h"
19 #include "gzstate.h"
20 #include "gxdevice.h"
21 #include "gxhttile.h"
22 #include "gxpaint.h"
23 #include "gxpath.h"
24 #include "gxfont.h"
25 
caching_an_outline_font(const gs_gstate * pgs)26 static bool caching_an_outline_font(const gs_gstate * pgs)
27 {
28     return pgs->in_cachedevice > 1 &&
29             pgs->font != NULL &&
30             pgs->font->FontType != ft_user_defined &&
31             pgs->font->FontType != ft_PDF_user_defined &&
32             pgs->font->FontType != ft_PCL_user_defined &&
33             pgs->font->FontType != ft_GL2_stick_user_defined &&
34             pgs->font->FontType != ft_CID_user_defined;
35 }
36 
37 /* Fill a path. */
38 int
gx_fill_path(gx_path * ppath,gx_device_color * pdevc,gs_gstate * pgs,int rule,fixed adjust_x,fixed adjust_y)39 gx_fill_path(gx_path * ppath, gx_device_color * pdevc, gs_gstate * pgs,
40              int rule, fixed adjust_x, fixed adjust_y)
41 {
42     gx_device *dev = gs_currentdevice_inline(pgs);
43     gx_clip_path *pcpath;
44     int code = gx_effective_clip_path(pgs, &pcpath);
45     gx_fill_params params;
46 
47     if (code < 0)
48         return code;
49     params.rule = rule;
50     params.adjust.x = adjust_x;
51     params.adjust.y = adjust_y;
52     params.flatness = (caching_an_outline_font(pgs) ? 0.0 : pgs->flatness);
53     return (*dev_proc(dev, fill_path))
54         (dev, (const gs_gstate *)pgs, ppath, &params, pdevc, pcpath);
55 }
56 
57 /* Stroke a path for drawing or saving. */
58 int
gx_stroke_fill(gx_path * ppath,gs_gstate * pgs)59 gx_stroke_fill(gx_path * ppath, gs_gstate * pgs)
60 {
61     gx_device *dev = gs_currentdevice_inline(pgs);
62     gx_clip_path *pcpath;
63     int code = gx_effective_clip_path(pgs, &pcpath);
64     gx_stroke_params params;
65 
66     if (code < 0)
67         return code;
68     params.flatness = (caching_an_outline_font(pgs) ? 0.0 : pgs->flatness);
69     params.traditional = false;
70     return (*dev_proc(dev, stroke_path))
71         (dev, (const gs_gstate *)pgs, ppath, &params,
72          gs_currentdevicecolor_inline(pgs), pcpath);
73 }
74 
75 int
gx_fill_stroke_path(gs_gstate * pgs,int rule)76 gx_fill_stroke_path(gs_gstate * pgs, int rule)
77 {
78     gx_device *dev = gs_currentdevice_inline(pgs);
79     gx_clip_path *pcpath;
80     int code = gx_effective_clip_path(pgs, &pcpath);
81     gx_stroke_params stroke_params;
82     gx_fill_params fill_params;
83 
84     if (code < 0)
85         return code;
86     fill_params.rule = rule;
87     fill_params.adjust.x = pgs->fill_adjust.x;
88     fill_params.adjust.y = pgs->fill_adjust.y;
89     fill_params.flatness = (caching_an_outline_font(pgs) ? 0.0 : pgs->flatness);
90     stroke_params.flatness = (caching_an_outline_font(pgs) ? 0.0 : pgs->flatness);
91     stroke_params.traditional = false;
92     return (*dev_proc(dev, fill_stroke_path))
93         (dev, (const gs_gstate *)pgs, pgs->path,
94          &fill_params, gs_currentdevicecolor_inline(pgs),
95          &stroke_params, gs_altdevicecolor_inline(pgs),
96          pcpath);
97 }
98 
99 int
gx_stroke_add(gx_path * ppath,gx_path * to_path,const gs_gstate * pgs,bool traditional)100 gx_stroke_add(gx_path * ppath, gx_path * to_path,
101               const gs_gstate * pgs, bool traditional)
102 {
103     gx_stroke_params params;
104 
105     params.flatness = (caching_an_outline_font(pgs) ? 0.0 : pgs->flatness);
106     params.traditional = traditional;
107     return gx_stroke_path_only(ppath, to_path, pgs->device,
108                                (const gs_gstate *)pgs,
109                                &params, NULL, NULL);
110 }
111 
112 int
gx_gstate_stroke_add(gx_path * ppath,gx_path * to_path,gx_device * dev,const gs_gstate * pgs)113 gx_gstate_stroke_add(gx_path *ppath, gx_path *to_path,
114                      gx_device *dev, const gs_gstate *pgs)
115 {
116     gx_stroke_params params;
117 
118     params.flatness = pgs->flatness;
119     params.traditional = false;
120     return gx_stroke_path_only(ppath, to_path, dev, pgs,
121                                &params, NULL, NULL);
122 }
123