2 |
- |
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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 |
}
|