xref: /plan9-contrib/sys/src/cmd/gs/src/gxshade4.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /* Copyright (C) 1998, 1999 Aladdin Enterprises.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: gxshade4.c,v 1.30 2005/04/19 12:22:08 igor Exp $ */
187dd7cddfSDavid du Colombier /* Rendering for Gouraud triangle shadings */
193ff48bf5SDavid du Colombier #include "math_.h"
207dd7cddfSDavid du Colombier #include "memory_.h"
217dd7cddfSDavid du Colombier #include "gx.h"
227dd7cddfSDavid du Colombier #include "gserrors.h"
237dd7cddfSDavid du Colombier #include "gsmatrix.h"		/* for gscoord.h */
247dd7cddfSDavid du Colombier #include "gscoord.h"
25*593dc095SDavid du Colombier #include "gsptype2.h"
267dd7cddfSDavid du Colombier #include "gxcspace.h"
277dd7cddfSDavid du Colombier #include "gxdcolor.h"
287dd7cddfSDavid du Colombier #include "gxdevcli.h"
297dd7cddfSDavid du Colombier #include "gxistate.h"
307dd7cddfSDavid du Colombier #include "gxpath.h"
317dd7cddfSDavid du Colombier #include "gxshade.h"
327dd7cddfSDavid du Colombier #include "gxshade4.h"
33*593dc095SDavid du Colombier #include "vdtrace.h"
347dd7cddfSDavid du Colombier 
35*593dc095SDavid du Colombier #define VD_TRACE_TRIANGLE_PATCH 1
367dd7cddfSDavid du Colombier 
377dd7cddfSDavid du Colombier /* Initialize the fill state for triangle shading. */
38*593dc095SDavid du Colombier 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)397dd7cddfSDavid du Colombier mesh_init_fill_state(mesh_fill_state_t * pfs, const gs_shading_mesh_t * psh,
40*593dc095SDavid du Colombier 		     const gs_fixed_rect * rect_clip, gx_device * dev,
417dd7cddfSDavid du Colombier 		     gs_imager_state * pis)
427dd7cddfSDavid du Colombier {
437dd7cddfSDavid du Colombier     shade_init_fill_state((shading_fill_state_t *) pfs,
447dd7cddfSDavid du Colombier 			  (const gs_shading_t *)psh, dev, pis);
457dd7cddfSDavid du Colombier     pfs->pshm = psh;
46*593dc095SDavid du Colombier     pfs->rect = *rect_clip;
477dd7cddfSDavid du Colombier     return 0;
487dd7cddfSDavid du Colombier }
497dd7cddfSDavid du Colombier 
507dd7cddfSDavid du Colombier /* ---------------- Gouraud triangle shadings ---------------- */
517dd7cddfSDavid du Colombier 
527dd7cddfSDavid du Colombier private int
Gt_next_vertex(const gs_shading_mesh_t * psh,shade_coord_stream_t * cs,shading_vertex_t * vertex)537dd7cddfSDavid du Colombier Gt_next_vertex(const gs_shading_mesh_t * psh, shade_coord_stream_t * cs,
54*593dc095SDavid du Colombier 	       shading_vertex_t * vertex)
557dd7cddfSDavid du Colombier {
567dd7cddfSDavid du Colombier     int code = shade_next_vertex(cs, vertex);
577dd7cddfSDavid du Colombier 
587dd7cddfSDavid du Colombier     if (code >= 0 && psh->params.Function) {
59*593dc095SDavid du Colombier 	vertex->c.t[0] = vertex->c.cc.paint.values[0];
60*593dc095SDavid du Colombier 	vertex->c.t[1] = 0;
617dd7cddfSDavid du Colombier 	/* Decode the color with the function. */
62*593dc095SDavid du Colombier 	code = gs_function_evaluate(psh->params.Function, vertex->c.t,
63*593dc095SDavid du Colombier 				    vertex->c.cc.paint.values);
647dd7cddfSDavid du Colombier     }
657dd7cddfSDavid du Colombier     return code;
667dd7cddfSDavid du Colombier }
677dd7cddfSDavid du Colombier 
687dd7cddfSDavid du Colombier 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*593dc095SDavid du Colombier Gt_fill_triangle(mesh_fill_state_t * pfs, const shading_vertex_t * va,
70*593dc095SDavid du Colombier 		 const shading_vertex_t * vb, const shading_vertex_t * vc)
717dd7cddfSDavid du Colombier {
72*593dc095SDavid du Colombier     patch_fill_state_t pfs1;
73*593dc095SDavid du Colombier     int code = 0;
74*593dc095SDavid du Colombier 
75*593dc095SDavid du Colombier     memcpy(&pfs1, (shading_fill_state_t *)pfs, sizeof(shading_fill_state_t));
76*593dc095SDavid du Colombier     pfs1.Function = pfs->pshm->params.Function;
77*593dc095SDavid du Colombier     pfs1.rect = pfs->rect;
78*593dc095SDavid du Colombier     code = init_patch_fill_state(&pfs1);
79*593dc095SDavid du Colombier     if (code < 0)
80*593dc095SDavid du Colombier 	return code;
81*593dc095SDavid du Colombier     if (INTERPATCH_PADDING) {
82*593dc095SDavid du Colombier 	code = mesh_padding(&pfs1, &va->p, &vb->p, &va->c, &vb->c);
83*593dc095SDavid du Colombier 	if (code >= 0)
84*593dc095SDavid du Colombier 	    code = mesh_padding(&pfs1, &vb->p, &vc->p, &vb->c, &vc->c);
85*593dc095SDavid du Colombier 	if (code >= 0)
86*593dc095SDavid du Colombier 	    code = mesh_padding(&pfs1, &vc->p, &va->p, &vc->c, &va->c);
87*593dc095SDavid du Colombier     }
88*593dc095SDavid du Colombier     if (code >= 0)
89*593dc095SDavid du Colombier 	code = mesh_triangle(&pfs1, va, vb, vc);
90*593dc095SDavid du Colombier     term_patch_fill_state(&pfs1);
91*593dc095SDavid du Colombier     return code;
927dd7cddfSDavid du Colombier }
937dd7cddfSDavid du Colombier 
947dd7cddfSDavid du Colombier 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)957dd7cddfSDavid du Colombier gs_shading_FfGt_fill_rectangle(const gs_shading_t * psh0, const gs_rect * rect,
96*593dc095SDavid du Colombier 			       const gs_fixed_rect * rect_clip,
977dd7cddfSDavid du Colombier 			       gx_device * dev, gs_imager_state * pis)
987dd7cddfSDavid du Colombier {
997dd7cddfSDavid du Colombier     const gs_shading_FfGt_t * const psh = (const gs_shading_FfGt_t *)psh0;
1007dd7cddfSDavid du Colombier     mesh_fill_state_t state;
1017dd7cddfSDavid du Colombier     shade_coord_stream_t cs;
1027dd7cddfSDavid du Colombier     int num_bits = psh->params.BitsPerFlag;
1037dd7cddfSDavid du Colombier     int flag;
104*593dc095SDavid du Colombier     shading_vertex_t va, vb, vc;
105*593dc095SDavid du Colombier     int code;
1067dd7cddfSDavid du Colombier 
107*593dc095SDavid du Colombier     if (VD_TRACE_TRIANGLE_PATCH && vd_allowed('s')) {
108*593dc095SDavid du Colombier 	vd_get_dc('s');
109*593dc095SDavid du Colombier 	vd_set_shift(0, 0);
110*593dc095SDavid du Colombier 	vd_set_scale(0.01);
111*593dc095SDavid du Colombier 	vd_set_origin(0, 0);
112*593dc095SDavid du Colombier     }
113*593dc095SDavid du Colombier     code = mesh_init_fill_state(&state, (const gs_shading_mesh_t *)psh, rect_clip,
1147dd7cddfSDavid du Colombier 			 dev, pis);
115*593dc095SDavid du Colombier     if (code < 0)
116*593dc095SDavid du Colombier 	return code;
1177dd7cddfSDavid du Colombier     shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params,
1187dd7cddfSDavid du Colombier 		    pis);
1197dd7cddfSDavid du Colombier     while ((flag = shade_next_flag(&cs, num_bits)) >= 0) {
1207dd7cddfSDavid du Colombier 	switch (flag) {
1217dd7cddfSDavid du Colombier 	    default:
1227dd7cddfSDavid du Colombier 		return_error(gs_error_rangecheck);
1237dd7cddfSDavid du Colombier 	    case 0:
1247dd7cddfSDavid du Colombier 		if ((code = Gt_next_vertex(state.pshm, &cs, &va)) < 0 ||
1257dd7cddfSDavid du Colombier 		    (code = shade_next_flag(&cs, num_bits)) < 0 ||
1267dd7cddfSDavid du Colombier 		    (code = Gt_next_vertex(state.pshm, &cs, &vb)) < 0 ||
1277dd7cddfSDavid du Colombier 		    (code = shade_next_flag(&cs, num_bits)) < 0
1287dd7cddfSDavid du Colombier 		    )
1297dd7cddfSDavid du Colombier 		    return code;
1307dd7cddfSDavid du Colombier 		goto v2;
1317dd7cddfSDavid du Colombier 	    case 1:
1327dd7cddfSDavid du Colombier 		va = vb;
1337dd7cddfSDavid du Colombier 	    case 2:
1347dd7cddfSDavid du Colombier 		vb = vc;
135*593dc095SDavid du Colombier v2:		if ((code = Gt_next_vertex(state.pshm, &cs, &vc)) < 0)
136*593dc095SDavid du Colombier 		    return code;
137*593dc095SDavid du Colombier 		if ((code = Gt_fill_triangle(&state, &va, &vb, &vc)) < 0)
1387dd7cddfSDavid du Colombier 		    return code;
1397dd7cddfSDavid du Colombier 	}
1407dd7cddfSDavid du Colombier     }
141*593dc095SDavid du Colombier     if (VD_TRACE_TRIANGLE_PATCH && vd_allowed('s'))
142*593dc095SDavid du Colombier 	vd_release_dc;
143*593dc095SDavid du Colombier     if (!cs.is_eod(&cs))
144*593dc095SDavid du Colombier 	return_error(gs_error_rangecheck);
1457dd7cddfSDavid du Colombier     return 0;
1467dd7cddfSDavid du Colombier }
1477dd7cddfSDavid du Colombier 
1487dd7cddfSDavid du Colombier 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)1497dd7cddfSDavid du Colombier gs_shading_LfGt_fill_rectangle(const gs_shading_t * psh0, const gs_rect * rect,
150*593dc095SDavid du Colombier 			       const gs_fixed_rect * rect_clip,
1517dd7cddfSDavid du Colombier 			       gx_device * dev, gs_imager_state * pis)
1527dd7cddfSDavid du Colombier {
1537dd7cddfSDavid du Colombier     const gs_shading_LfGt_t * const psh = (const gs_shading_LfGt_t *)psh0;
1547dd7cddfSDavid du Colombier     mesh_fill_state_t state;
1557dd7cddfSDavid du Colombier     shade_coord_stream_t cs;
156*593dc095SDavid du Colombier     shading_vertex_t *vertex;
157*593dc095SDavid du Colombier     shading_vertex_t next;
1587dd7cddfSDavid du Colombier     int per_row = psh->params.VerticesPerRow;
159*593dc095SDavid du Colombier     int i, code;
1607dd7cddfSDavid du Colombier 
161*593dc095SDavid du Colombier     if (VD_TRACE_TRIANGLE_PATCH && vd_allowed('s')) {
162*593dc095SDavid du Colombier 	vd_get_dc('s');
163*593dc095SDavid du Colombier 	vd_set_shift(0, 0);
164*593dc095SDavid du Colombier 	vd_set_scale(0.01);
165*593dc095SDavid du Colombier 	vd_set_origin(0, 0);
166*593dc095SDavid du Colombier     }
167*593dc095SDavid du Colombier     code = mesh_init_fill_state(&state, (const gs_shading_mesh_t *)psh, rect_clip,
1687dd7cddfSDavid du Colombier 			 dev, pis);
169*593dc095SDavid du Colombier     if (code < 0)
170*593dc095SDavid du Colombier 	return code;
1717dd7cddfSDavid du Colombier     shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params,
1727dd7cddfSDavid du Colombier 		    pis);
173*593dc095SDavid du Colombier     vertex = (shading_vertex_t *)
1747dd7cddfSDavid du Colombier 	gs_alloc_byte_array(pis->memory, per_row, sizeof(*vertex),
1757dd7cddfSDavid du Colombier 			    "gs_shading_LfGt_render");
1767dd7cddfSDavid du Colombier     if (vertex == 0)
1777dd7cddfSDavid du Colombier 	return_error(gs_error_VMerror);
1787dd7cddfSDavid du Colombier     for (i = 0; i < per_row; ++i)
1797dd7cddfSDavid du Colombier 	if ((code = Gt_next_vertex(state.pshm, &cs, &vertex[i])) < 0)
1807dd7cddfSDavid du Colombier 	    goto out;
1817dd7cddfSDavid du Colombier     while (!seofp(cs.s)) {
1827dd7cddfSDavid du Colombier 	code = Gt_next_vertex(state.pshm, &cs, &next);
1837dd7cddfSDavid du Colombier 	if (code < 0)
1847dd7cddfSDavid du Colombier 	    goto out;
1857dd7cddfSDavid du Colombier 	for (i = 1; i < per_row; ++i) {
1867dd7cddfSDavid du Colombier 	    code = Gt_fill_triangle(&state, &vertex[i - 1], &vertex[i], &next);
1877dd7cddfSDavid du Colombier 	    if (code < 0)
1887dd7cddfSDavid du Colombier 		goto out;
1897dd7cddfSDavid du Colombier 	    vertex[i - 1] = next;
1907dd7cddfSDavid du Colombier 	    code = Gt_next_vertex(state.pshm, &cs, &next);
1917dd7cddfSDavid du Colombier 	    if (code < 0)
1927dd7cddfSDavid du Colombier 		goto out;
1937dd7cddfSDavid du Colombier 	    code = Gt_fill_triangle(&state, &vertex[i], &vertex[i - 1], &next);
1947dd7cddfSDavid du Colombier 	    if (code < 0)
1957dd7cddfSDavid du Colombier 		goto out;
1967dd7cddfSDavid du Colombier 	}
1977dd7cddfSDavid du Colombier 	vertex[per_row - 1] = next;
1987dd7cddfSDavid du Colombier     }
1997dd7cddfSDavid du Colombier out:
200*593dc095SDavid du Colombier     if (VD_TRACE_TRIANGLE_PATCH && vd_allowed('s'))
201*593dc095SDavid du Colombier 	vd_release_dc;
2027dd7cddfSDavid du Colombier     gs_free_object(pis->memory, vertex, "gs_shading_LfGt_render");
2037dd7cddfSDavid du Colombier     return code;
2047dd7cddfSDavid du Colombier }
205