1 /* Copyright (C) 1999 artofcode LLC.  All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify it
4   under the terms of the GNU General Public License as published by the
5   Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License along
14   with this program; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 
17 */
18 
19 /*$Id: gsptype2.c,v 1.5.2.1.2.1 2003/01/17 00:49:03 giles Exp $ */
20 /* PatternType 2 implementation */
21 #include "gx.h"
22 #include "gscspace.h"
23 #include "gsshade.h"
24 #include "gsmatrix.h"           /* for gspcolor.h */
25 #include "gsstate.h"            /* for set/currentfilladjust */
26 #include "gxcolor2.h"
27 #include "gxdcolor.h"
28 #include "gsptype2.h"
29 #include "gxpcolor.h"
30 #include "gxstate.h"            /* for gs_state_memory */
31 #include "gzpath.h"
32 
33 /* GC descriptors */
34 private_st_pattern2_template();
35 private_st_pattern2_instance();
36 
37 /* GC procedures */
ENUM_PTRS_BEGIN(pattern2_instance_enum_ptrs)38 private ENUM_PTRS_BEGIN(pattern2_instance_enum_ptrs) {
39     if (index < st_pattern2_template_max_ptrs) {
40         gs_ptr_type_t ptype =
41             ENUM_SUPER_ELT(gs_pattern2_instance_t, st_pattern2_template,
42                            template, 0);
43 
44         if (ptype)
45             return ptype;
46         return ENUM_OBJ(NULL);  /* don't stop early */
47     }
48     ENUM_PREFIX(st_pattern_instance, st_pattern2_template_max_ptrs);
49 }
50 ENUM_PTRS_END
RELOC_PTRS_BEGIN(pattern2_instance_reloc_ptrs)51 private RELOC_PTRS_BEGIN(pattern2_instance_reloc_ptrs) {
52     RELOC_PREFIX(st_pattern_instance);
53     RELOC_SUPER(gs_pattern2_instance_t, st_pattern2_template, template);
54 } RELOC_PTRS_END
55 
56 /* Define a PatternType 2 pattern. */
57 private pattern_proc_uses_base_space(gs_pattern2_uses_base_space);
58 private pattern_proc_make_pattern(gs_pattern2_make_pattern);
59 private pattern_proc_get_pattern(gs_pattern2_get_pattern);
60 private pattern_proc_remap_color(gs_pattern2_remap_color);
61 private const gs_pattern_type_t gs_pattern2_type = {
62     2, {
63         gs_pattern2_uses_base_space, gs_pattern2_make_pattern,
64         gs_pattern2_get_pattern, gs_pattern2_remap_color
65     }
66 };
67 
68 /* Initialize a PatternType 2 pattern. */
69 void
gs_pattern2_init(gs_pattern2_template_t * ppat)70 gs_pattern2_init(gs_pattern2_template_t * ppat)
71 {
72     gs_pattern_common_init((gs_pattern_template_t *)ppat, &gs_pattern2_type);
73 }
74 
75 /* Test whether a PatternType 2 pattern uses a base space. */
76 private bool
gs_pattern2_uses_base_space(const gs_pattern_template_t * ptemp)77 gs_pattern2_uses_base_space(const gs_pattern_template_t *ptemp)
78 {
79     return false;
80 }
81 
82 /* Make an instance of a PatternType 2 pattern. */
83 private int
gs_pattern2_make_pattern(gs_client_color * pcc,const gs_pattern_template_t * pcp,const gs_matrix * pmat,gs_state * pgs,gs_memory_t * mem)84 gs_pattern2_make_pattern(gs_client_color * pcc,
85                          const gs_pattern_template_t * pcp,
86                          const gs_matrix * pmat, gs_state * pgs,
87                          gs_memory_t * mem)
88 {
89     const gs_pattern2_template_t *ptemp =
90         (const gs_pattern2_template_t *)pcp;
91     int code = gs_make_pattern_common(pcc, pcp, pmat, pgs, mem,
92                                       &st_pattern2_instance);
93     gs_pattern2_instance_t *pinst;
94 
95     if (code < 0)
96         return code;
97     pinst = (gs_pattern2_instance_t *)pcc->pattern;
98     pinst->template = *ptemp;
99     return 0;
100 }
101 
102 /* Get the template of a PatternType 2 pattern instance. */
103 private const gs_pattern_template_t *
gs_pattern2_get_pattern(const gs_pattern_instance_t * pinst)104 gs_pattern2_get_pattern(const gs_pattern_instance_t *pinst)
105 {
106     return (const gs_pattern_template_t *)
107         &((const gs_pattern2_instance_t *)pinst)->template;
108 }
109 
110 /* ---------------- Rendering ---------------- */
111 
112 /* GC descriptor */
113 gs_private_st_ptrs_add0(st_dc_pattern2, gx_device_color, "dc_pattern2",
114                         dc_pattern2_enum_ptrs, dc_pattern2_reloc_ptrs,
115                         st_client_color, ccolor);
116 
117 private dev_color_proc_load(gx_dc_pattern2_load);
118 private dev_color_proc_fill_rectangle(gx_dc_pattern2_fill_rectangle);
119 private dev_color_proc_equal(gx_dc_pattern2_equal);
120 /*
121  * Define the PatternType 2 Pattern device color type.  This is public only
122  * for testing when writing PDF or PostScript.
123  */
124 const gx_device_color_type_t gx_dc_pattern2 = {
125     &st_dc_pattern2,
126     gx_dc_pattern2_load, gx_dc_pattern2_fill_rectangle,
127     gx_dc_default_fill_masked, gx_dc_pattern2_equal
128 };
129 
130 /* Check device color for Pattern Type 2. */
131 bool
gx_dc_is_pattern2_color(const gx_device_color * pdevc)132 gx_dc_is_pattern2_color(const gx_device_color *pdevc)
133 {
134     return pdevc->type == &gx_dc_pattern2;
135 }
136 
137 /* Load a PatternType 2 color into the cache.  (No effect.) */
138 private int
gx_dc_pattern2_load(gx_device_color * pdevc,const gs_imager_state * ignore_pis,gx_device * ignore_dev,gs_color_select_t ignore_select)139 gx_dc_pattern2_load(gx_device_color *pdevc, const gs_imager_state *ignore_pis,
140                     gx_device *ignore_dev, gs_color_select_t ignore_select)
141 {
142     return 0;
143 }
144 
145 /* Remap a PatternType 2 color. */
146 private int
gs_pattern2_remap_color(const gs_client_color * pc,const gs_color_space * pcs,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)147 gs_pattern2_remap_color(const gs_client_color * pc, const gs_color_space * pcs,
148                         gx_device_color * pdc, const gs_imager_state * pis,
149                         gx_device * dev, gs_color_select_t select)
150 {
151     /* We don't do any actual color mapping now. */
152     pdc->type = &gx_dc_pattern2;
153     pdc->ccolor = *pc;
154     return 0;
155 }
156 
157 /* Fill path or rect, with adjustment, and with a PatternType 2 color. */
158 int
gx_dc_pattern2_fill_path_adjusted(const gx_device_color * pdevc,gx_path * ppath,gs_fixed_rect * rect,gx_device * dev)159 gx_dc_pattern2_fill_path_adjusted(const gx_device_color * pdevc,
160                               gx_path * ppath, gs_fixed_rect * rect,
161                               gx_device * dev)
162 {
163     gs_pattern2_instance_t *pinst =
164         (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
165     gs_state *pgs = pinst->saved;
166     gs_point save_adjust;
167     int code;
168 
169     /* We don't want any adjustment of the box. */
170     gs_currentfilladjust(pgs, &save_adjust);
171 
172     /*
173      * We should set the fill adjustment to zero here, so that we don't
174      * get multiply-written pixels as a result of filling abutting
175      * triangles.  However, numerical inaccuracies in the shading
176      * algorithms can cause pixel dropouts, and a non-zero adjustment
177      * is by far the easiest way to work around them as a stopgap.
178      * NOTE: This makes shadings not interact properly with
179      * non-idempotent RasterOps (not a problem in practice, since
180      * PostScript doesn't have RasterOps and PCL doesn't have shadings).
181      */
182     gs_setfilladjust(pgs, 0.5, 0.5);
183     /****** DOESN'T HANDLE RASTER OP ******/
184     code = gs_shading_fill_path(pinst->template.Shading, ppath, rect, dev,
185                                 (gs_imager_state *)pgs, true);
186     gs_setfilladjust(pgs, save_adjust.x, save_adjust.y);
187     return code;
188 }
189 
190 /* Fill a rectangle with a PatternType 2 color. */
191 private int
gx_dc_pattern2_fill_rectangle(const gx_device_color * pdevc,int x,int y,int w,int h,gx_device * dev,gs_logical_operation_t lop,const gx_rop_source_t * source)192 gx_dc_pattern2_fill_rectangle(const gx_device_color * pdevc, int x, int y,
193                               int w, int h, gx_device * dev,
194                               gs_logical_operation_t lop,
195                               const gx_rop_source_t * source)
196 {
197     gs_fixed_rect rect;
198     rect.p.x = int2fixed(x);
199     rect.p.y = int2fixed(y);
200     rect.q.x = int2fixed(x + w);
201     rect.q.y = int2fixed(y + h);
202     return gx_dc_pattern2_fill_path_adjusted(pdevc, NULL, &rect,  dev);
203 }
204 
205 /* Compare two PatternType 2 colors for equality. */
206 private bool
gx_dc_pattern2_equal(const gx_device_color * pdevc1,const gx_device_color * pdevc2)207 gx_dc_pattern2_equal(const gx_device_color * pdevc1,
208                      const gx_device_color * pdevc2)
209 {
210     return pdevc2->type == pdevc1->type &&
211         pdevc1->ccolor.pattern == pdevc2->ccolor.pattern;
212 }
213