xref: /plan9/sys/src/cmd/gs/src/dwtrace.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: dwtrace.c,v 1.6 2004/02/14 08:44:30 igor Exp $ */
18 /* Graphical trace server for Windows */
19 
20 /*  This module use Win32-specific API.
21     For 16-bit Windows many of functions compile to stubs.
22 */
23 
24 /*  fixme : Restoring image on WM_PAINT is NOT implemented yet.
25 */
26 
27 #define STRICT
28 #include <windows.h>
29 #include <math.h>
30 #include "dwimg.h"
31 
WindowsColor(unsigned long c)32 static COLORREF WindowsColor(unsigned long c)
33 {   /*  This body uses a Windows specific macro RGB, which is being
34         redefined in GS include files. Please include them after
35         this definition.
36     */
37     return RGB(c >> 16, (c >> 8) & 255, c & 255);
38 }
39 
40 #include "gscdefs.h"
41 #include "stdpre.h"
42 #include "gsdll.h"
43 #include "vdtrace.h"
44 #include "dwtrace.h"
45 
46 struct vd_trace_host_s {
47     bool inited;
48     IMAGE * tw;
49     HDC hdc;
50     int count_GetDC;
51     int window_height;
52     int line_width;
53     COLORREF color;
54     HPEN pen, pen0;
55     HBRUSH brush, brush0;
56     double bx, by;
57 };
58 
59 static struct vd_trace_host_s host = {false, NULL, NULL};
60 vd_trace_interface visual_tracer = { &host, 1, 1, 0, 0, 0, 0 };
61 static const char *vdtrace_ini = "gs_vdtrace.ini";
62 
get_window()63 private void get_window()
64 {   if (!host.inited) {
65         host.tw = image_new(NULL, NULL);	/* create and add to list */
66         if (host.tw) {
67             image_open(host.tw);
68             UpdateWindow(host.tw->hwnd);
69         }
70 	host.hdc = NULL;
71 	host.count_GetDC = 0;
72 	host.window_height = 100;
73 	host.line_width = 1;
74 	host.color = 0;
75 	host.inited = true;
76     }
77 }
78 
ScaleX(struct vd_trace_host_s * h,double x)79 private inline int ScaleX(struct vd_trace_host_s *h, double x)
80 {   return (int)(x + 0.5);
81 }
82 
ScaleY(struct vd_trace_host_s * h,double y)83 private inline int ScaleY(struct vd_trace_host_s *h, double y)
84 {   return h->window_height - (int)(y + 0.5);
85 }
86 
87 #define SX(x) ScaleX(I->host,x)
88 #define SY(y) ScaleY(I->host,y)
89 
delete_pen_brush(vd_trace_interface * I)90 private inline void delete_pen_brush(vd_trace_interface *I)
91 {   SelectObject(I->host->hdc, I->host->pen0);
92     SelectObject(I->host->hdc, I->host->brush0);
93     if(I->host->pen != NULL)
94 	DeleteObject(I->host->pen);
95     I->host->pen = NULL;
96     if(I->host->brush != NULL)
97 	DeleteObject(I->host->brush);
98     I->host->brush = NULL;
99 }
100 
new_pen_brush(vd_trace_interface * I)101 private inline void new_pen_brush(vd_trace_interface *I)
102 {   delete_pen_brush(I);
103     I->host->pen = CreatePen(PS_SOLID, I->host->line_width, WindowsColor(I->host->color));
104     I->host->brush = CreateSolidBrush(WindowsColor(I->host->color));
105     SelectObject(I->host->hdc, I->host->pen);
106     SelectObject(I->host->hdc, I->host->brush);
107 }
108 
dw_gt_get_size_x(vd_trace_interface * I)109 private double dw_gt_get_size_x(vd_trace_interface *I)
110 {   RECT r;
111     get_window();
112     if (host.tw == NULL)
113         return(100);
114     GetClientRect(I->host->tw->hwnd,&r);
115     return r.right - r.left;
116 }
117 
dw_gt_get_size_y(vd_trace_interface * I)118 private double dw_gt_get_size_y(vd_trace_interface *I)
119 {   RECT r;
120     get_window();
121     if (host.tw == NULL)
122         return(100);
123     GetClientRect(I->host->tw->hwnd,&r);
124     return r.bottom - r.top;
125 }
126 
dw_gt_get_dc(vd_trace_interface * I,vd_trace_interface ** I1)127 private void dw_gt_get_dc(vd_trace_interface *I, vd_trace_interface **I1)
128 {   get_window();
129     if (host.tw == NULL)
130         return;
131     if (I->host->hdc == NULL) {
132 	RECT r;
133 	I->host->hdc = GetDC(I->host->tw->hwnd);
134 	SetMapMode(I->host->hdc,MM_TEXT);
135 	GetClientRect(I->host->tw->hwnd, &r);
136 	I->host->window_height = r.bottom;
137 	SetBkMode(I->host->hdc,TRANSPARENT);
138 	I->host->pen0 = (HPEN)SelectObject(I->host->hdc, GetStockObject(BLACK_PEN));
139 	I->host->brush0 = (HBRUSH)SelectObject(I->host->hdc, GetStockObject(BLACK_BRUSH));
140 	I->host->color = 0;
141 	I->host->count_GetDC = 1;
142         *I1 = I;
143     } else
144 	++I->host->count_GetDC;
145 }
146 
dw_gt_release_dc(vd_trace_interface * I,vd_trace_interface ** I1)147 private void dw_gt_release_dc(vd_trace_interface *I, vd_trace_interface **I1)
148 {   get_window();
149     if (host.tw == NULL)
150         return;
151     --I->host->count_GetDC;
152     if(I->host->count_GetDC == 0) {
153 	ReleaseDC(I->host->tw->hwnd, I->host->hdc);
154 	I->host->hdc = NULL;
155 	delete_pen_brush(I);
156         *I1 = NULL;
157     } else if(I->host->count_GetDC < 0) {
158         /* safety : */
159 	I->host->count_GetDC = 0;
160         *I1 = NULL;
161     }
162 }
163 
dw_gt_erase(vd_trace_interface * I,unsigned long rgbcolor)164 private void dw_gt_erase(vd_trace_interface *I, unsigned long rgbcolor)
165 {   HWND hwnd;
166     RECT r;
167     HBRUSH hbr;
168     get_window();
169     if (host.tw == NULL)
170         return;
171     hwnd = I->host->tw->hwnd;
172     GetClientRect(hwnd, &r);
173     hbr = CreateSolidBrush(rgbcolor);
174     FillRect(I->host->hdc, &r, hbr);
175     DeleteObject(hbr);
176 }
177 
dw_gt_beg_path(vd_trace_interface * I)178 private void dw_gt_beg_path(vd_trace_interface *I)
179 {   get_window();
180     if (host.tw == NULL)
181         return;
182     BeginPath(I->host->hdc);
183 }
184 
dw_gt_end_path(vd_trace_interface * I)185 private void dw_gt_end_path(vd_trace_interface *I)
186 {   get_window();
187     if (host.tw == NULL)
188         return;
189     EndPath(I->host->hdc);
190 }
191 
dw_gt_moveto(vd_trace_interface * I,double x,double y)192 private void dw_gt_moveto(vd_trace_interface *I, double x, double y)
193 {   POINT p;
194     get_window();
195     if (host.tw == NULL)
196         return;
197 #ifdef __WIN32__
198     MoveToEx(I->host->hdc, SX(x), SY(y), &p);
199 #else
200     MoveTo(I->host->hdc, SX(x), SY(y));
201 #endif
202     I->host->bx = x; I->host->by = y;
203 }
204 
dw_gt_lineto(vd_trace_interface * I,double x,double y)205 private void dw_gt_lineto(vd_trace_interface *I, double x, double y)
206 {   get_window();
207     if (host.tw == NULL)
208         return;
209     LineTo(I->host->hdc, SX(x), SY(y));
210 }
211 
dw_gt_curveto(vd_trace_interface * I,double x0,double y0,double x1,double y1,double x2,double y2)212 private void dw_gt_curveto(vd_trace_interface *I, double x0, double y0, double x1, double y1, double x2, double y2)
213 {   POINT p[3];
214     get_window();
215     if (host.tw == NULL)
216         return;
217     p[0].x = SX(x0), p[0].y = SY(y0);
218     p[1].x = SX(x1), p[1].y = SY(y1);
219     p[2].x = SX(x2), p[2].y = SY(y2);
220     PolyBezierTo(I->host->hdc, p, 3);
221 }
222 
dw_gt_closepath(vd_trace_interface * I)223 private void dw_gt_closepath(vd_trace_interface *I)
224 {   get_window();
225     if (host.tw == NULL)
226         return;
227     LineTo(I->host->hdc, SX(I->host->bx), SY(I->host->by));
228     CloseFigure(I->host->hdc);
229 }
230 
dw_gt_circle(vd_trace_interface * I,double x,double y,int r)231 private void dw_gt_circle(vd_trace_interface *I, double x, double y, int r)
232 {   HBRUSH h;
233     get_window();
234     if (host.tw == NULL)
235         return;
236     h = (HBRUSH)SelectObject(I->host->hdc, GetStockObject(NULL_BRUSH));
237     Ellipse(I->host->hdc, SX(x)-r, SY(y)-r, SX(x)+r, SY(y)+r);
238     SelectObject(I->host->hdc, h);
239 }
240 
dw_gt_round(vd_trace_interface * I,double x,double y,int r)241 private void dw_gt_round(vd_trace_interface *I, double x, double y, int r)
242 {   HPEN h;
243     get_window();
244     if (host.tw == NULL)
245         return;
246     h = (HPEN)SelectObject(I->host->hdc, GetStockObject(NULL_PEN));
247     Ellipse(I->host->hdc, SX(x)-r, SY(y)-r, SX(x)+r, SY(y)+r);
248     SelectObject(I->host->hdc, h);
249 }
250 
dw_gt_fill(vd_trace_interface * I)251 private void dw_gt_fill(vd_trace_interface *I)
252 {   get_window();
253     if (host.tw == NULL)
254         return;
255     FillPath(I->host->hdc);
256 }
257 
dw_gt_stroke(vd_trace_interface * I)258 private void dw_gt_stroke(vd_trace_interface *I)
259 {   get_window();
260     if (host.tw == NULL)
261         return;
262     StrokePath(I->host->hdc);
263 }
264 
dw_gt_setcolor(vd_trace_interface * I,unsigned long rgbcolor)265 private void dw_gt_setcolor(vd_trace_interface *I, unsigned long rgbcolor)
266 {   get_window();
267     if (host.tw == NULL)
268         return;
269     if (I->host->color != rgbcolor) {
270 	I->host->color = rgbcolor;
271 	new_pen_brush(I);
272 	SetTextColor(I->host->hdc, rgbcolor);
273     }
274 }
275 
dw_gt_setlinewidth(vd_trace_interface * I,unsigned int width)276 private void dw_gt_setlinewidth(vd_trace_interface *I, unsigned int width)
277 {   get_window();
278     if (host.tw == NULL)
279         return;
280     if (I->host->line_width != width) {
281 	I->host->line_width = width;
282 	new_pen_brush(I);
283     }
284 }
285 
dw_gt_text(vd_trace_interface * I,double x,double y,char * ASCIIZ)286 private void dw_gt_text(vd_trace_interface *I, double x, double y, char *ASCIIZ)
287 {   get_window();
288     if (host.tw == NULL)
289         return;
290     TextOut(I->host->hdc, SX(x), SY(y), ASCIIZ, strlen(ASCIIZ));
291 }
292 
dw_gt_wait(vd_trace_interface * I)293 private void dw_gt_wait(vd_trace_interface *I)
294 {   get_window();
295     if (host.tw == NULL)
296         return;
297     /* fixme : not implemented yet. */
298 }
299 
dw_gt_set_scale(vd_trace_interface * I)300 private void dw_gt_set_scale(vd_trace_interface *I)
301 {   get_window();
302     if (host.tw == NULL)
303         return;
304     I->scale_x *= GetPrivateProfileInt("VDTRACE", "ScaleX", 1000, vdtrace_ini) / 1000.0;
305     I->scale_y *= GetPrivateProfileInt("VDTRACE", "ScaleY", 1000, vdtrace_ini) / 1000.0;
306 }
307 
dw_gt_set_shift(vd_trace_interface * I)308 private void dw_gt_set_shift(vd_trace_interface *I)
309 {   get_window();
310     if (host.tw == NULL)
311         return;
312     I->shift_x += (int)GetPrivateProfileInt("VDTRACE", "ShiftX", 0, vdtrace_ini);
313     I->shift_y += (int)GetPrivateProfileInt("VDTRACE", "ShiftY", 0, vdtrace_ini);
314 }
315 
dw_gt_set_origin(vd_trace_interface * I)316 private void dw_gt_set_origin(vd_trace_interface *I)
317 {   get_window();
318     if (host.tw == NULL)
319         return;
320     I->orig_x += (int)GetPrivateProfileInt("VDTRACE", "OrigX", 0, vdtrace_ini);
321     I->orig_y += (int)GetPrivateProfileInt("VDTRACE", "OrigY", 0, vdtrace_ini);
322 }
323 
324 #ifdef __WIN32__
325 #    define SET_CALLBACK(I,a) I.a = dw_gt_##a
326 #else
327 #    define SET_CALLBACK(I,a) I.a = 0
328 #endif
329 
visual_tracer_init(void)330 void visual_tracer_init(void)
331 {   SET_CALLBACK(visual_tracer, get_dc);
332     SET_CALLBACK(visual_tracer, release_dc);
333     SET_CALLBACK(visual_tracer, erase);
334     SET_CALLBACK(visual_tracer, get_size_x);
335     SET_CALLBACK(visual_tracer, get_size_y);
336     SET_CALLBACK(visual_tracer, erase);
337     SET_CALLBACK(visual_tracer, beg_path);
338     SET_CALLBACK(visual_tracer, end_path);
339     SET_CALLBACK(visual_tracer, moveto);
340     SET_CALLBACK(visual_tracer, lineto);
341     SET_CALLBACK(visual_tracer, curveto); /* optional */
342     SET_CALLBACK(visual_tracer, closepath);
343     SET_CALLBACK(visual_tracer, circle);
344     SET_CALLBACK(visual_tracer, round);
345     SET_CALLBACK(visual_tracer, fill);
346     SET_CALLBACK(visual_tracer, stroke);
347     SET_CALLBACK(visual_tracer, setcolor);
348     SET_CALLBACK(visual_tracer, setlinewidth);
349     SET_CALLBACK(visual_tracer, text);
350     SET_CALLBACK(visual_tracer, wait);
351     SET_CALLBACK(visual_tracer, set_scale);
352     SET_CALLBACK(visual_tracer, set_shift);
353     SET_CALLBACK(visual_tracer, set_origin);
354 }
355 
visual_tracer_close(void)356 void visual_tracer_close(void)
357 {   if (host.tw != NULL) {
358         image_delete(host.tw);
359         image_close(host.tw);
360     }
361 }
362 
363 
364 
365 
366 
367