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