1 /* Copyright (C) 2001-2006 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, modified
8    or distributed except as expressly authorized under the terms of that
9    license.  Refer to licensing information at http://www.artifex.com/
10    or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11    San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 
14 /* $Id: vdtrace.c 8489 2008-01-17 13:47:11Z leonardo $ */
15 /* Visual tracer service */
16 
17 #include "math_.h"
18 #include "gxfixed.h"
19 #include "vdtrace.h"
20 
21 /* Global data for all instances : */
22 vd_trace_interface * vd_trace0 = NULL, * vd_trace1 = NULL;
23 char vd_flags[128] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
24                      "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
25                      "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
26                      "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
27 
28 static double px, py;
29 
30 #define NullRET if(vd_trace1 == NULL) return
31 
scale_x(vd_trace_interface * I,double x)32 static inline double scale_x(vd_trace_interface *I, double x)
33 { return (x - I->orig_x) * I->scale_x + I->shift_x;
34 }
35 
scale_y(vd_trace_interface * I,double y)36 static inline double scale_y(vd_trace_interface *I, double y)
37 { return (y - I->orig_y) * I->scale_y + I->shift_y;
38 }
39 
40 #define SX(x) scale_x(vd_trace1, x)
41 #define SY(y) scale_y(vd_trace1, y)
42 
bezier_point(double p0,double p1,double p2,double p3,double t)43 static inline double bezier_point(double p0, double p1, double p2, double p3, double t)
44 {   double s = 1-t;
45     return p0*s*s*s + 3*p1*s*s*t + 3*p2*s*t*t + p3*t*t*t;
46 }
47 
vd_flatten(double p0x,double p0y,double p1x,double p1y,double p2x,double p2y,double p3x,double p3y)48 static void vd_flatten(double p0x, double p0y, double p1x, double p1y, double p2x, double p2y, double p3x, double p3y)
49 {
50 #ifdef DEBUG
51     double flat = 0.5;
52     double d2x0 = (p0x - 2 * p1x + p2x), d2y0 = (p0y - 2 * p1y + p2y);
53     double d2x1 = (p1x - 2 * p2x + p3x), d2y1 = (p1y - 2 * p2y + p3y);
54     double d2norm0 = hypot(d2x0, d2y0);
55     double d2norm1 = hypot(d2x1, d2y1);
56     double D = max(d2norm0, d2norm1); /* This is half of maximum norm of 2nd derivative of the curve by parameter t. */
57     int NN = (int)ceil(sqrt(D * 3 / 4 / flat)); /* Number of output segments. */
58     int i;
59     int N = max(NN, 1); /* safety (if the curve degenerates to line) */
60     double e = 0.5 / N;
61 
62     for (i = 0; i < N; i++) {
63 	double t = (double)i / N + e;
64 	double px = bezier_point(p0x, p1x, p2x, p3x, t);
65 	double py = bezier_point(p0y, p1y, p2y, p3y, t);
66 
67 	vd_lineto(px, py);
68     }
69     vd_lineto(p3x, p3y);
70 #endif
71 }
72 
vd_impl_moveto(double x,double y)73 void vd_impl_moveto(double x, double y)
74 {   NullRET;
75     px = SX(x), py = SY(y);
76     vd_trace1->moveto(vd_trace1, px, py);
77 }
78 
vd_impl_lineto(double x,double y)79 void vd_impl_lineto(double x, double y)
80 {   NullRET;
81     px = SX(x), py = SY(y);
82     vd_trace1->lineto(vd_trace1, px, py);
83 }
84 
vd_impl_lineto_multi(const struct gs_fixed_point_s * p,int n)85 void vd_impl_lineto_multi(const struct gs_fixed_point_s *p, int n)
86 {   int i;
87     NullRET;
88     for (i = 0; i < n; i++) {
89         px = SX(p[i].x), py = SY(p[i].y);
90         vd_trace1->lineto(vd_trace1, px, py);
91     }
92 }
93 
vd_impl_curveto(double x1,double y1,double x2,double y2,double x3,double y3)94 void vd_impl_curveto(double x1, double y1, double x2, double y2, double x3, double y3)
95 {   double p1x, p1y, p2x, p2y, p3x, p3y;
96 
97     NullRET;
98     p1x = SX(x1), p1y = SY(y1);
99     p2x = SX(x2), p2y = SY(y2);
100     p3x = SX(x3), p3y = SY(y3);
101     if (vd_trace1->curveto != NULL)
102         vd_trace1->curveto(vd_trace1, p1x, p1y, p2x, p2y, p3x, p3y);
103     else
104         vd_flatten(px, py, p1x, p1y, p2x, p2y, p3x, p3y);
105     px = p3x, py = p3y;
106 }
107 
vd_impl_bar(double x0,double y0,double x1,double y1,int w,unsigned long c)108 void vd_impl_bar(double x0, double y0, double x1, double y1, int w, unsigned long c)
109 {   NullRET;
110     vd_trace1->setcolor(vd_trace1, c);
111     vd_trace1->setlinewidth(vd_trace1, w);
112     vd_trace1->beg_path(vd_trace1);
113     vd_trace1->moveto(vd_trace1, SX(x0), SY(y0));
114     vd_trace1->lineto(vd_trace1, SX(x1), SY(y1));
115     vd_trace1->end_path(vd_trace1);
116     vd_trace1->stroke(vd_trace1);
117 }
118 
vd_impl_square(double x,double y,int w,unsigned int c)119 void vd_impl_square(double x, double y, int w, unsigned int c)
120 {   NullRET;
121     vd_trace1->setcolor(vd_trace1, c);
122     vd_trace1->setlinewidth(vd_trace1, 1);
123     vd_trace1->beg_path(vd_trace1);
124     vd_trace1->moveto(vd_trace1, SX(x) - w, SY(y) - w);
125     vd_trace1->lineto(vd_trace1, SX(x) + w, SY(y) - w);
126     vd_trace1->lineto(vd_trace1, SX(x) + w, SY(y) + w);
127     vd_trace1->lineto(vd_trace1, SX(x) - w, SY(y) + w);
128     vd_trace1->lineto(vd_trace1, SX(x) - w, SY(y) - w);
129     vd_trace1->end_path(vd_trace1);
130     vd_trace1->stroke(vd_trace1);
131 }
132 
vd_impl_rect(double x0,double y0,double x1,double y1,int w,unsigned int c)133 void vd_impl_rect(double x0, double y0, double x1, double y1, int w, unsigned int c)
134 {   NullRET;
135     vd_trace1->setcolor(vd_trace1, c);
136     vd_trace1->setlinewidth(vd_trace1, w);
137     vd_trace1->beg_path(vd_trace1);
138     vd_trace1->moveto(vd_trace1, SX(x0), SY(y0));
139     vd_trace1->lineto(vd_trace1, SX(x0), SY(y1));
140     vd_trace1->lineto(vd_trace1, SX(x1), SY(y1));
141     vd_trace1->lineto(vd_trace1, SX(x1), SY(y0));
142     vd_trace1->lineto(vd_trace1, SX(x0), SY(y0));
143     vd_trace1->end_path(vd_trace1);
144     vd_trace1->stroke(vd_trace1);
145 }
146 
vd_impl_quad(double x0,double y0,double x1,double y1,double x2,double y2,double x3,double y3,int w,unsigned int c)147 void vd_impl_quad(double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3, int w, unsigned int c)
148 {   NullRET;
149     vd_trace1->setcolor(vd_trace1, c);
150     vd_trace1->setlinewidth(vd_trace1, w);
151     vd_trace1->beg_path(vd_trace1);
152     vd_trace1->moveto(vd_trace1, SX(x0), SY(y0));
153     vd_trace1->lineto(vd_trace1, SX(x1), SY(y1));
154     vd_trace1->lineto(vd_trace1, SX(x2), SY(y2));
155     vd_trace1->lineto(vd_trace1, SX(x3), SY(y3));
156     vd_trace1->lineto(vd_trace1, SX(x0), SY(y0));
157     vd_trace1->end_path(vd_trace1);
158     vd_trace1->stroke(vd_trace1);
159 }
160 
vd_impl_curve(double x0,double y0,double x1,double y1,double x2,double y2,double x3,double y3,int w,unsigned long c)161 void vd_impl_curve(double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3, int w, unsigned long c)
162 {   NullRET;
163     vd_trace1->setcolor(vd_trace1, c);
164     vd_trace1->setlinewidth(vd_trace1, w);
165     vd_trace1->beg_path(vd_trace1);
166     vd_trace1->moveto(vd_trace1, SX(x0), SY(y0));
167     vd_impl_curveto(x1, y1, x2, y2, x3, y3);
168     vd_trace1->end_path(vd_trace1);
169     vd_trace1->stroke(vd_trace1);
170 }
171 
vd_impl_circle(double x,double y,int r,unsigned long c)172 void vd_impl_circle(double x, double y, int r, unsigned long c)
173 {   NullRET;
174     vd_trace1->setcolor(vd_trace1, c);
175     vd_trace1->setlinewidth(vd_trace1, 1);
176     vd_trace1->circle(vd_trace1, SX(x), SY(y), r);
177 }
178 
vd_impl_round(double x,double y,int r,unsigned long c)179 void vd_impl_round(double x, double y, int r, unsigned long c)
180 {   NullRET;
181     vd_trace1->setcolor(vd_trace1, c);
182     vd_trace1->setlinewidth(vd_trace1, 1);
183     vd_trace1->round(vd_trace1, SX(x), SY(y), r);
184 }
185 
vd_impl_pixel(double x,double y,unsigned long c)186 void vd_impl_pixel(double x, double y, unsigned long c)
187 {   NullRET;
188     vd_trace1->pixel(vd_trace1, SX(x), SY(y), c);
189 }
190 
vd_impl_text(double x,double y,char * s,unsigned long c)191 void vd_impl_text(double x, double y, char *s, unsigned long c)
192 {   NullRET;
193     vd_trace1->setcolor(vd_trace1, c);
194     vd_trace1->text(vd_trace1, SX(x), SY(y), s);
195 }
196 
vd_setflag(char f,char v)197 void vd_setflag(char f, char v)
198 {   vd_flags[f & 127] = v;
199 }
200