1 /* Copyright (C) 1998, 1999 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gxshade4.c,v 1.30 2005/04/19 12:22:08 igor Exp $ */
18 /* Rendering for Gouraud triangle shadings */
19 #include "math_.h"
20 #include "memory_.h"
21 #include "gx.h"
22 #include "gserrors.h"
23 #include "gsmatrix.h" /* for gscoord.h */
24 #include "gscoord.h"
25 #include "gsptype2.h"
26 #include "gxcspace.h"
27 #include "gxdcolor.h"
28 #include "gxdevcli.h"
29 #include "gxistate.h"
30 #include "gxpath.h"
31 #include "gxshade.h"
32 #include "gxshade4.h"
33 #include "vdtrace.h"
34
35 #define VD_TRACE_TRIANGLE_PATCH 1
36
37 /* Initialize the fill state for triangle shading. */
38 int
mesh_init_fill_state(mesh_fill_state_t * pfs,const gs_shading_mesh_t * psh,const gs_fixed_rect * rect_clip,gx_device * dev,gs_imager_state * pis)39 mesh_init_fill_state(mesh_fill_state_t * pfs, const gs_shading_mesh_t * psh,
40 const gs_fixed_rect * rect_clip, gx_device * dev,
41 gs_imager_state * pis)
42 {
43 shade_init_fill_state((shading_fill_state_t *) pfs,
44 (const gs_shading_t *)psh, dev, pis);
45 pfs->pshm = psh;
46 pfs->rect = *rect_clip;
47 return 0;
48 }
49
50 /* ---------------- Gouraud triangle shadings ---------------- */
51
52 private int
Gt_next_vertex(const gs_shading_mesh_t * psh,shade_coord_stream_t * cs,shading_vertex_t * vertex)53 Gt_next_vertex(const gs_shading_mesh_t * psh, shade_coord_stream_t * cs,
54 shading_vertex_t * vertex)
55 {
56 int code = shade_next_vertex(cs, vertex);
57
58 if (code >= 0 && psh->params.Function) {
59 vertex->c.t[0] = vertex->c.cc.paint.values[0];
60 vertex->c.t[1] = 0;
61 /* Decode the color with the function. */
62 code = gs_function_evaluate(psh->params.Function, vertex->c.t,
63 vertex->c.cc.paint.values);
64 }
65 return code;
66 }
67
68 inline private int
Gt_fill_triangle(mesh_fill_state_t * pfs,const shading_vertex_t * va,const shading_vertex_t * vb,const shading_vertex_t * vc)69 Gt_fill_triangle(mesh_fill_state_t * pfs, const shading_vertex_t * va,
70 const shading_vertex_t * vb, const shading_vertex_t * vc)
71 {
72 patch_fill_state_t pfs1;
73 int code = 0;
74
75 memcpy(&pfs1, (shading_fill_state_t *)pfs, sizeof(shading_fill_state_t));
76 pfs1.Function = pfs->pshm->params.Function;
77 pfs1.rect = pfs->rect;
78 code = init_patch_fill_state(&pfs1);
79 if (code < 0)
80 return code;
81 if (INTERPATCH_PADDING) {
82 code = mesh_padding(&pfs1, &va->p, &vb->p, &va->c, &vb->c);
83 if (code >= 0)
84 code = mesh_padding(&pfs1, &vb->p, &vc->p, &vb->c, &vc->c);
85 if (code >= 0)
86 code = mesh_padding(&pfs1, &vc->p, &va->p, &vc->c, &va->c);
87 }
88 if (code >= 0)
89 code = mesh_triangle(&pfs1, va, vb, vc);
90 term_patch_fill_state(&pfs1);
91 return code;
92 }
93
94 int
gs_shading_FfGt_fill_rectangle(const gs_shading_t * psh0,const gs_rect * rect,const gs_fixed_rect * rect_clip,gx_device * dev,gs_imager_state * pis)95 gs_shading_FfGt_fill_rectangle(const gs_shading_t * psh0, const gs_rect * rect,
96 const gs_fixed_rect * rect_clip,
97 gx_device * dev, gs_imager_state * pis)
98 {
99 const gs_shading_FfGt_t * const psh = (const gs_shading_FfGt_t *)psh0;
100 mesh_fill_state_t state;
101 shade_coord_stream_t cs;
102 int num_bits = psh->params.BitsPerFlag;
103 int flag;
104 shading_vertex_t va, vb, vc;
105 int code;
106
107 if (VD_TRACE_TRIANGLE_PATCH && vd_allowed('s')) {
108 vd_get_dc('s');
109 vd_set_shift(0, 0);
110 vd_set_scale(0.01);
111 vd_set_origin(0, 0);
112 }
113 code = mesh_init_fill_state(&state, (const gs_shading_mesh_t *)psh, rect_clip,
114 dev, pis);
115 if (code < 0)
116 return code;
117 shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params,
118 pis);
119 while ((flag = shade_next_flag(&cs, num_bits)) >= 0) {
120 switch (flag) {
121 default:
122 return_error(gs_error_rangecheck);
123 case 0:
124 if ((code = Gt_next_vertex(state.pshm, &cs, &va)) < 0 ||
125 (code = shade_next_flag(&cs, num_bits)) < 0 ||
126 (code = Gt_next_vertex(state.pshm, &cs, &vb)) < 0 ||
127 (code = shade_next_flag(&cs, num_bits)) < 0
128 )
129 return code;
130 goto v2;
131 case 1:
132 va = vb;
133 case 2:
134 vb = vc;
135 v2: if ((code = Gt_next_vertex(state.pshm, &cs, &vc)) < 0)
136 return code;
137 if ((code = Gt_fill_triangle(&state, &va, &vb, &vc)) < 0)
138 return code;
139 }
140 }
141 if (VD_TRACE_TRIANGLE_PATCH && vd_allowed('s'))
142 vd_release_dc;
143 if (!cs.is_eod(&cs))
144 return_error(gs_error_rangecheck);
145 return 0;
146 }
147
148 int
gs_shading_LfGt_fill_rectangle(const gs_shading_t * psh0,const gs_rect * rect,const gs_fixed_rect * rect_clip,gx_device * dev,gs_imager_state * pis)149 gs_shading_LfGt_fill_rectangle(const gs_shading_t * psh0, const gs_rect * rect,
150 const gs_fixed_rect * rect_clip,
151 gx_device * dev, gs_imager_state * pis)
152 {
153 const gs_shading_LfGt_t * const psh = (const gs_shading_LfGt_t *)psh0;
154 mesh_fill_state_t state;
155 shade_coord_stream_t cs;
156 shading_vertex_t *vertex;
157 shading_vertex_t next;
158 int per_row = psh->params.VerticesPerRow;
159 int i, code;
160
161 if (VD_TRACE_TRIANGLE_PATCH && vd_allowed('s')) {
162 vd_get_dc('s');
163 vd_set_shift(0, 0);
164 vd_set_scale(0.01);
165 vd_set_origin(0, 0);
166 }
167 code = mesh_init_fill_state(&state, (const gs_shading_mesh_t *)psh, rect_clip,
168 dev, pis);
169 if (code < 0)
170 return code;
171 shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params,
172 pis);
173 vertex = (shading_vertex_t *)
174 gs_alloc_byte_array(pis->memory, per_row, sizeof(*vertex),
175 "gs_shading_LfGt_render");
176 if (vertex == 0)
177 return_error(gs_error_VMerror);
178 for (i = 0; i < per_row; ++i)
179 if ((code = Gt_next_vertex(state.pshm, &cs, &vertex[i])) < 0)
180 goto out;
181 while (!seofp(cs.s)) {
182 code = Gt_next_vertex(state.pshm, &cs, &next);
183 if (code < 0)
184 goto out;
185 for (i = 1; i < per_row; ++i) {
186 code = Gt_fill_triangle(&state, &vertex[i - 1], &vertex[i], &next);
187 if (code < 0)
188 goto out;
189 vertex[i - 1] = next;
190 code = Gt_next_vertex(state.pshm, &cs, &next);
191 if (code < 0)
192 goto out;
193 code = Gt_fill_triangle(&state, &vertex[i], &vertex[i - 1], &next);
194 if (code < 0)
195 goto out;
196 }
197 vertex[per_row - 1] = next;
198 }
199 out:
200 if (VD_TRACE_TRIANGLE_PATCH && vd_allowed('s'))
201 vd_release_dc;
202 gs_free_object(pis->memory, vertex, "gs_shading_LfGt_render");
203 return code;
204 }
205