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