Line data Source code
1 : /* Copyright (C) 2000-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #include <stdio.h>
28 : #include <math.h>
29 : #include <time.h>
30 : #include <sys/types.h>
31 : #if !defined(__MINGW32__)
32 : #include <sys/wait.h>
33 : #endif
34 : #include "fontforge-config.h"
35 : #include <unistd.h>
36 :
37 : #include "gpsdrawP.h"
38 : #include "gresource.h"
39 : #include "colorP.h"
40 : #include "fontP.h"
41 : #include "ustring.h"
42 : #include "fileutil.h"
43 :
44 : /* ************************************************************************** */
45 : /* ********************** Noops & Meaningless functions ********************* */
46 : /* ************************************************************************** */
47 :
48 0 : static void PSDrawInit(GDisplay *UNUSED(gdisp)) {
49 : /* delay any real initialization until they actually want to print */
50 : /* no point in reading up on a bunch of fonts which never get used */
51 0 : }
52 :
53 0 : static void PSDrawTerm(GDisplay *UNUSED(gdisp)) {
54 0 : }
55 :
56 0 : static void *PSDrawNativeDisplay(GDisplay *UNUSED(gdisp)) {
57 0 : return( NULL );
58 : }
59 :
60 0 : static void PSDrawSetDefaultIcon(GWindow UNUSED(icon)) {
61 0 : }
62 :
63 0 : static GWindow PSDrawCreateSubWindow(GWindow UNUSED(w), GRect *UNUSED(pos),
64 : int (*eh)(GWindow,GEvent *), void *UNUSED(user_data),
65 : GWindowAttrs *UNUSED(wattrs)) {
66 : (void)eh;
67 0 : fprintf( stderr, "CreateSubWindow not implemented for postscript\n" );
68 0 : return NULL;
69 : }
70 :
71 0 : static GWindow PSDrawCreatePixmap(GDisplay *UNUSED(gdisp), uint16 UNUSED(width),
72 : uint16 UNUSED(height)) {
73 0 : fprintf( stderr, "CreatePixmap not implemented for postscript\n" );
74 0 : return NULL;
75 : }
76 :
77 0 : static GWindow PSDrawCreateBitmap(GDisplay *UNUSED(gdisp), uint16 UNUSED(width),
78 : uint16 UNUSED(height), uint8 *UNUSED(data)) {
79 0 : fprintf( stderr, "CreateBitmap not implemented for postscript\n" );
80 0 : return NULL;
81 : }
82 :
83 0 : static GCursor PSDrawCreateCursor(GWindow UNUSED(src), GWindow UNUSED(mask),
84 : Color UNUSED(fg), Color UNUSED(bg), int16 UNUSED(x), int16 UNUSED(y) ) {
85 0 : fprintf( stderr, "CreateCursor not implemented for postscript\n" );
86 0 : return 0;
87 : }
88 :
89 0 : static void PSSetZoom(GWindow UNUSED(w), GRect *UNUSED(r),
90 : enum gzoom_flags UNUSED(flags) ) {
91 0 : fprintf( stderr, "SetZoom not implemented for postscript\n" );
92 0 : }
93 :
94 0 : static void PSDestroyCursor(GDisplay *UNUSED(gdisp), GCursor UNUSED(ct) ) {
95 0 : fprintf( stderr, "DestroyCursor not implemented for postscript\n" );
96 0 : }
97 :
98 0 : static int PSNativeWindowExists(GDisplay *UNUSED(gdisp), void *UNUSED(native) ) {
99 0 : return( false );
100 : }
101 :
102 0 : static void PSSetWindowBorder(GWindow UNUSED(w), int UNUSED(width),
103 : Color UNUSED(col) ) {
104 0 : fprintf( stderr, "SetWindowBorder not implemented for postscript\n" );
105 0 : }
106 :
107 0 : static void PSSetWindowBackground(GWindow UNUSED(w), Color UNUSED(col) ) {
108 0 : fprintf( stderr, "SetWindowBackground not implemented for postscript\n" );
109 0 : }
110 :
111 0 : static int PSSetDither(GDisplay *UNUSED(gdisp), int UNUSED(dither) ) {
112 0 : fprintf( stderr, "SetDither not implemented for postscript\n" );
113 0 : return( true );
114 : }
115 :
116 0 : static void PSDrawReparentWindow(GWindow UNUSED(child),
117 : GWindow UNUSED(newparent), int UNUSED(x), int UNUSED(y)) {
118 : /* It's a noop */
119 0 : }
120 :
121 0 : static void PSDrawSetVisible(GWindow UNUSED(w), int UNUSED(vis) ) {
122 : /* It's a noop */
123 0 : }
124 :
125 0 : static void PSDrawMove(GWindow UNUSED(w), int32 UNUSED(x), int32 UNUSED(y)) {
126 : /* Not meaningful */
127 0 : }
128 :
129 0 : static void PSDrawResize(GWindow UNUSED(w),
130 : int32 UNUSED(width), int32 UNUSED(height)) {
131 : /* Not meaningful */
132 0 : }
133 :
134 0 : static void PSDrawMoveResize(GWindow UNUSED(w), int32 UNUSED(x), int32 UNUSED(y),
135 : int32 UNUSED(width), int32 UNUSED(height)) {
136 : /* Not meaningful */
137 0 : }
138 :
139 0 : static void PSDrawRaise(GWindow UNUSED(w)) {
140 : /* Not meaningful */
141 0 : }
142 :
143 0 : static void PSDrawRaiseAbove(GWindow UNUSED(w), GWindow UNUSED(below)) {
144 : /* Not meaningful */
145 0 : }
146 :
147 0 : static int PSDrawIsAbove(GWindow UNUSED(w), GWindow UNUSED(below)) {
148 0 : return( -1 ); /* Not meaningful */
149 : }
150 :
151 0 : static void PSDrawLower(GWindow UNUSED(w)) {
152 : /* Not meaningful */
153 0 : }
154 :
155 0 : static void PSDrawSetWindowTitles(GWindow UNUSED(w),
156 : const unichar_t *UNUSED(title), const unichar_t *UNUSED(icontit)) {
157 : /* Not meaningful */
158 0 : }
159 :
160 0 : static void PSDrawSetWindowTitles8(GWindow UNUSED(w),
161 : const char *UNUSED(title), const char *UNUSED(icontit)) {
162 : /* Not meaningful */
163 0 : }
164 :
165 0 : static void PSDrawSetTransientFor(GWindow UNUSED(transient), GWindow UNUSED(owner)) {
166 : /* Not meaningful */
167 0 : }
168 :
169 0 : static void PSDrawGetPointerPosition(GWindow UNUSED(w), GEvent *ret) {
170 : /* Not meaningful */
171 :
172 0 : ret->u.mouse.state = 0;
173 0 : ret->u.mouse.x = 0;
174 0 : ret->u.mouse.y = 0;
175 0 : }
176 :
177 0 : static GWindow PSDrawGetPointerWindow(GWindow UNUSED(w)) {
178 : /* Not meaningful */
179 0 : return( NULL );
180 : }
181 :
182 0 : static void PSDrawSetCursor(GWindow UNUSED(w), GCursor UNUSED(ct)) {
183 : /* Not meaningful */
184 0 : }
185 :
186 0 : static GCursor PSDrawGetCursor(GWindow UNUSED(w)) {
187 : /* Not meaningful */
188 0 : return( ct_default );
189 : }
190 :
191 0 : static GWindow PSDrawGetRedirectWindow(GDisplay *UNUSED(gd)) {
192 : /* Not meaningful */
193 0 : return( NULL );
194 : }
195 :
196 0 : static unichar_t *PSDrawGetWindowTitle(GWindow UNUSED(w)) {
197 0 : return(NULL);
198 : }
199 :
200 0 : static char *PSDrawGetWindowTitle8(GWindow UNUSED(w)) {
201 0 : return(NULL);
202 : }
203 :
204 0 : static void PSDrawTranslateCoordinates(GWindow UNUSED(_from),
205 : GWindow UNUSED(_to), GPoint *UNUSED(pt)) {
206 : /* Only one window active at a time, translation is a noop */
207 0 : }
208 :
209 0 : static void PSDrawScroll(GWindow UNUSED(w), GRect *UNUSED(rect),
210 : int32 UNUSED(hor), int32 UNUSED(vert)) {
211 : /* Not meaningful */
212 0 : }
213 :
214 0 : static void PSDrawBeep(GDisplay *UNUSED(gdisp)) {
215 : /* Not meaningful */
216 0 : }
217 :
218 0 : static void PSDrawFlush(GDisplay *gdisp) {
219 : /* Not meaningful */
220 0 : if ( gdisp->groot!=NULL )
221 0 : fflush(((GPSWindow) (gdisp->groot))->output_file);
222 0 : }
223 :
224 0 : static GIC *PSDrawCreateInputContext(GWindow UNUSED(w),
225 : enum gic_style UNUSED(def_style)) {
226 : /* Not meaningful */
227 0 : return( NULL );
228 : }
229 :
230 0 : static void PSDrawSetGIC(GWindow UNUSED(w), GIC *UNUSED(gic),
231 : int UNUSED(x), int UNUSED(y)) {
232 : /* Not meaningful */
233 0 : }
234 :
235 0 : static void PSDrawPointerUngrab(GDisplay *UNUSED(gdisp)) {
236 : /* Not meaningful */
237 0 : }
238 :
239 0 : static void PSDrawPointerGrab(GWindow UNUSED(w)) {
240 : /* Not meaningful */
241 0 : }
242 :
243 0 : static void PSDrawGrabSelection(GWindow UNUSED(w), enum selnames UNUSED(sel)) {
244 : /* Not meaningful */
245 0 : }
246 :
247 0 : static void PSDrawAddSelectionType(GWindow UNUSED(w), enum selnames UNUSED(sel),
248 : char *UNUSED(type), void *UNUSED(data), int32 UNUSED(len),
249 : int32 UNUSED(unitsize), void *(*gendata)(void *,int32 *len),
250 : void (*freedata)(void *)) {
251 : /* Not meaningful */
252 : (void)gendata;
253 : (void)freedata;
254 0 : }
255 :
256 0 : static void *PSDrawRequestSelection(GWindow UNUSED(w), enum selnames UNUSED(sn),
257 : char *UNUSED(typename), int32 *UNUSED(len)) {
258 : /* Not meaningful */
259 0 : return( NULL );
260 : }
261 :
262 0 : static int PSDrawSelectionHasType(GWindow UNUSED(w), enum selnames UNUSED(sn),
263 : char *UNUSED(typename)) {
264 : /* Not meaningful */
265 0 : return( false );
266 : }
267 :
268 0 : static void PSDrawBindSelection(GDisplay *UNUSED(disp), enum selnames UNUSED(sn),
269 : char *UNUSED(atomname)) {
270 : /* Not meaningful */
271 0 : }
272 :
273 0 : static int PSDrawSelectionHasOwner(GDisplay *UNUSED(disp), enum selnames UNUSED(sn)) {
274 : /* Not meaningful */
275 0 : return( false );
276 : }
277 :
278 0 : static void PSDrawRequestExpose(GWindow UNUSED(gw), GRect *UNUSED(rect),
279 : int UNUSED(doclear)) {
280 : /* Not meaningful */
281 0 : }
282 :
283 0 : static GTimer *PSDrawRequestTimer(GWindow UNUSED(w), int32 UNUSED(time_from_now),
284 : int32 UNUSED(frequency), void *UNUSED(userdata)) {
285 0 : return( NULL );
286 : }
287 :
288 0 : static void PSDrawCancelTimer(GTimer *UNUSED(timer)) {
289 0 : }
290 :
291 0 : static void PSDrawSyncThread(GDisplay *UNUSED(gdisp), void (*func)(void *), void *data) {
292 0 : (func)(data);
293 0 : }
294 :
295 0 : static void PSDrawForceUpdate(GWindow UNUSED(gw)) {
296 0 : }
297 :
298 0 : static void PSDrawSync(GDisplay *UNUSED(gdisp)) {
299 0 : }
300 :
301 0 : static void PSDrawSkipMouseMoveEvents(GWindow UNUSED(gw), GEvent *UNUSED(last)) {
302 0 : }
303 :
304 0 : static void PSDrawProcessPendingEvents(GDisplay *UNUSED(gdisp)) {
305 0 : }
306 :
307 0 : static void PSDrawProcessWindowEvents(GWindow UNUSED(gw)) {
308 0 : }
309 :
310 0 : static void PSDrawEventLoop(GDisplay *UNUSED(gd)) {
311 0 : }
312 :
313 0 : static void PSDrawPostEvent(GEvent *UNUSED(e)) {
314 0 : }
315 :
316 0 : static void PSDrawPostDragEvent(GWindow UNUSED(w), GEvent *UNUSED(mouse),
317 : enum event_type UNUSED(et)) {
318 0 : }
319 :
320 0 : static int PSDrawRequestDeviceEvents(GWindow UNUSED(w), int UNUSED(devcnt),
321 : struct gdeveventmask *UNUSED(de)) {
322 0 : return( 0 );
323 : }
324 :
325 0 : static GImage *_PSDraw_CopyScreenToImage(GWindow UNUSED(w), GRect *UNUSED(rect)) {
326 0 : return( NULL );
327 : }
328 :
329 0 : static void _PSDraw_Pixmap( GWindow UNUSED(_w), GWindow UNUSED(_pixmap),
330 : GRect *UNUSED(src), int32 UNUSED(x), int32 UNUSED(y)) {
331 0 : }
332 :
333 0 : static void _PSDraw_TilePixmap( GWindow UNUSED(_w), GWindow UNUSED(_pixmap),
334 : GRect *UNUSED(src), int32 UNUSED(x), int32 UNUSED(y)) {
335 0 : }
336 :
337 : /* ************************************************************************** */
338 : /* ******************************* Draw Stuff ******************************* */
339 : /* ************************************************************************** */
340 :
341 0 : double _GSPDraw_Distance(GPSWindow ps,int x) {
342 0 : return( 72.0*(double) x/(double)ps->display->res );
343 : }
344 :
345 0 : double _GSPDraw_XPos(GPSWindow ps,int x) {
346 0 : return( 72.0*(double) x/(double)ps->display->res );
347 : }
348 :
349 0 : double _GSPDraw_YPos(GPSWindow ps,int y) {
350 0 : return( -72.0*(double) y/(double)ps->display->res );
351 : }
352 :
353 0 : static void PSUnbufferLine(GPSWindow ps) {
354 0 : if ( ps->buffered_line ) {
355 0 : fprintf( ps->output_file," %g %g lineto\n", _GSPDraw_XPos(ps,ps->line_x), _GSPDraw_YPos(ps,ps->line_y) );
356 0 : ++ps->pnt_cnt;
357 0 : ps->buffered_line = false;
358 : }
359 0 : }
360 :
361 0 : void _GPSDraw_FlushPath(GPSWindow ps) {
362 0 : if ( ps->buffered_line )
363 0 : PSUnbufferLine(ps);
364 0 : if ( ps->pnt_cnt>0 ) {
365 0 : fprintf( ps->output_file,"stroke\n" );
366 0 : ps->pnt_cnt = 0;
367 0 : ps->cur_x = ps->cur_y = -1;
368 : }
369 0 : }
370 :
371 0 : static void PSDrawNewpath(GPSWindow ps) {
372 0 : if ( ps->pnt_cnt!=0 ) {
373 0 : _GPSDraw_FlushPath(ps);
374 0 : fprintf( ps->output_file,"newpath\n" );
375 0 : ps->pnt_cnt = 0;
376 0 : ps->cur_x = ps->cur_y = -1;
377 : }
378 0 : }
379 :
380 0 : static void PSMoveTo(GPSWindow ps, int x, int y) {
381 0 : if ( ps->pnt_cnt>=STROKE_CACHE )
382 0 : _GPSDraw_FlushPath(ps);
383 0 : if ( ps->pnt_cnt==-1 )
384 0 : PSDrawNewpath(ps);
385 0 : if ( ps->cur_x!=x || ps->cur_y!=y ) {
386 0 : if ( ps->buffered_line )
387 0 : PSUnbufferLine(ps);
388 0 : fprintf( ps->output_file," %g %g moveto\n", _GSPDraw_XPos(ps,x), _GSPDraw_YPos(ps,y) );
389 0 : ++ps->pnt_cnt;
390 0 : ps->cur_x = x; ps->cur_y = y;
391 : }
392 0 : }
393 :
394 0 : static void PSLineTo(GPSWindow ps, int x, int y) {
395 0 : if ( ps->pnt_cnt>=STROKE_CACHE )
396 0 : _GPSDraw_FlushPath(ps);
397 0 : if ( ps->pnt_cnt==-1 )
398 0 : PSDrawNewpath(ps);
399 0 : if ( ps->cur_x!=x || ps->cur_y!=y ) {
400 0 : if ( !ps->buffered_line && ps->cur_y==y ) {
401 0 : ps->line_x = x; ps->line_y = y;
402 0 : ps->buffered_line = true;
403 0 : } else if ( ps->buffered_line && ps->cur_y==y ) {
404 0 : ps->line_x = x;
405 : } else {
406 0 : if ( ps->buffered_line )
407 0 : PSUnbufferLine(ps);
408 0 : fprintf( ps->output_file," %g %g lineto\n", _GSPDraw_XPos(ps,x), _GSPDraw_YPos(ps,y) );
409 0 : ++ps->pnt_cnt;
410 : }
411 0 : ps->cur_x = x; ps->cur_y = y;
412 : }
413 0 : }
414 :
415 : /* This is my version of the postscript "arc" function. I've written it because*/
416 : /* I can't use arc for stroking elipses. The obvious thing to do is to scale */
417 : /* x and y differently so that the circle becomes an elipse. Sadly that also */
418 : /* scales the line width so I get a different width at different points on */
419 : /* the elipse. Can't have that. */
420 : /* So here we approximate an elipse by four bezier curves. There is one curve */
421 : /* for each quadrant of the elipse (0->90), (90->180), (180->270), (270-360) */
422 : /* of course if we're just doing bits of the arc (rather than the whole */
423 : /* elipse) we'll not have all of those, nor will they be filled in. The */
424 : /* magic numbers here do indeed produce a good fit to an elipse */
425 0 : static void PSDoArc(GPSWindow ps, double cx, double cy, double radx, double rady,
426 : double sa, double ea ) {
427 : double ss, sc, es, ec;
428 : double lenx, leny;
429 : double sx, sy, ex, ey;
430 : double c1x, c1y, c2x, c2y;
431 :
432 0 : lenx = ((ea-sa)/90.0) * radx * .552;
433 0 : leny = ((ea-sa)/90.0) * rady * .552;
434 0 : sa *= 3.1415926535897932/180; ea *= 3.1415926535897932/180;
435 0 : ss = -sin(sa); sc = cos(sa); es = -sin(ea); ec = cos(ea);
436 0 : sx = cx+sc*radx; sy = cy+ss*rady;
437 0 : PSMoveTo(ps,sx,sy);
438 0 : ex = cx+ec*radx; ey = cy+es*rady;
439 0 : c1x = sx + lenx*ss; c1y = sy - leny*sc;
440 0 : c2x = ex - lenx*es; c2y = ey + leny*ec;
441 0 : fprintf( ps->output_file, " %g %g %g %g %g %g curveto",
442 : _GSPDraw_XPos(ps,c1x), _GSPDraw_YPos(ps,c1y),
443 : _GSPDraw_XPos(ps,c2x), _GSPDraw_YPos(ps,c2y),
444 : _GSPDraw_XPos(ps,ex), _GSPDraw_YPos(ps,ey) );
445 0 : ps->cur_x = ex; ps->cur_y = ey;
446 0 : }
447 :
448 0 : static void PSMyArc(GPSWindow ps, double cx, double cy, double radx, double rady,
449 : double sa, double ta ) {
450 : double ea, temp;
451 :
452 0 : if ( ta<0 ) {
453 0 : sa += ta;
454 0 : ta = -ta;
455 : }
456 0 : if ( ta>360 ) ta = 360;
457 0 : if ( ta==360 ) sa = 0;
458 0 : while ( sa<0 ) sa+= 360;
459 0 : while ( sa>=360 ) sa -= 360;
460 0 : ea = sa+ta;
461 :
462 0 : while ( sa<ea ) {
463 0 : temp = ((int) ((sa+90)/90))*90;
464 0 : PSDoArc(ps,cx,cy,radx,rady,sa,ea<temp?ea:temp);
465 0 : sa = temp;
466 : }
467 0 : }
468 :
469 0 : static void PSDrawElipse(GPSWindow ps, GRect *rct,char *command) {
470 : float cx, cy, radx, rady;
471 : /* This does not make a very good stroked elipse if it isn't a circle */
472 : /* the line width is scaled along with the elipse and so it varies!!! */
473 :
474 0 : _GPSDraw_FlushPath(ps);
475 0 : radx = rct->width/2.0;
476 0 : rady = rct->height/2.0;
477 0 : cx = rct->x + radx;
478 0 : cy = rct->y + rady;
479 0 : PSDrawNewpath(ps);
480 :
481 : /* I can't use arc to draw an elipse. Doing so would mean scaling the */
482 : /* x and y axes differently, which will also scale the stroke width */
483 : /* differently. So I've written my own version that will work for */
484 : /* elipses without scaling. I use arc for circles because it produces */
485 : /* less text in the printing file */
486 0 : if ( radx!=rady )
487 0 : PSMyArc(ps,cx,cy,radx,rady,0,360);
488 : else
489 0 : fprintf( ps->output_file, " %g %g %g 0 360 arc", _GSPDraw_XPos(ps,cx), _GSPDraw_YPos(ps,cy), _GSPDraw_Distance(ps,radx));
490 0 : fprintf( ps->output_file, " closepath %s\n", command );
491 0 : ps->pnt_cnt = 0;
492 0 : ps->cur_x = ps->cur_y = -1;
493 0 : }
494 :
495 0 : static void PSDrawDoPoly(GPSWindow ps, GPoint *pt, int cnt, char *command) {
496 : int i;
497 :
498 0 : if ( pt[cnt-1].x==pt[0].x && pt[cnt-1].y==pt[0].y )
499 0 : --cnt; /* We close paths differently in postscript */
500 0 : _GPSDraw_FlushPath(ps);
501 0 : if ( cnt==4 ) {
502 0 : fprintf( ps->output_file, " %g %g %g %g %g %g %g %g g_quad ",
503 0 : _GSPDraw_XPos(ps,pt[3].x), _GSPDraw_YPos(ps,pt[3].y),
504 0 : _GSPDraw_XPos(ps,pt[2].x), _GSPDraw_YPos(ps,pt[2].y),
505 0 : _GSPDraw_XPos(ps,pt[1].x), _GSPDraw_YPos(ps,pt[1].y),
506 0 : _GSPDraw_XPos(ps,pt[0].x), _GSPDraw_YPos(ps,pt[0].y));
507 : } else {
508 0 : PSMoveTo(ps,pt[0].x,pt[0].y);
509 0 : for ( i=1; i<cnt; ++i )
510 0 : PSLineTo(ps,pt[i].x,pt[i].y);
511 : }
512 0 : fprintf( ps->output_file, "closepath %s %%Polygon\n", command );
513 0 : ps->pnt_cnt = 0;
514 0 : ps->cur_x = ps->cur_y = -1;
515 0 : }
516 :
517 0 : void _GPSDraw_SetClip(GPSWindow ps) {
518 :
519 0 : if ( ps->ggc->clip.x!=ps->cur_clip.x ||
520 0 : ps->ggc->clip.width!=ps->cur_clip.width ||
521 0 : ps->ggc->clip.y!=ps->cur_clip.y ||
522 0 : ps->ggc->clip.height!=ps->cur_clip.height ) {
523 0 : _GPSDraw_FlushPath(ps);
524 0 : if ( ps->ggc->clip.x<ps->cur_clip.x ||
525 0 : ps->ggc->clip.x+ps->ggc->clip.width>ps->cur_clip.x+ps->cur_clip.width ||
526 0 : ps->ggc->clip.y<ps->cur_clip.y ||
527 0 : ps->ggc->clip.y+ps->ggc->clip.height>ps->cur_clip.y+ps->cur_clip.height )
528 0 : fprintf( ps->output_file, "initclip " ); /* we hope never to fall into this case, postscript doesn't like it */
529 0 : fprintf( ps->output_file, " %g %g %g %g %g %g %g %g g_quad clip newpath\n",
530 0 : _GSPDraw_XPos(ps,ps->ggc->clip.x), _GSPDraw_YPos(ps,ps->ggc->clip.y+ps->ggc->clip.height),
531 0 : _GSPDraw_XPos(ps,ps->ggc->clip.x+ps->ggc->clip.width), _GSPDraw_YPos(ps,ps->ggc->clip.y+ps->ggc->clip.height),
532 0 : _GSPDraw_XPos(ps,ps->ggc->clip.x+ps->ggc->clip.width), _GSPDraw_YPos(ps,ps->ggc->clip.y),
533 0 : _GSPDraw_XPos(ps,ps->ggc->clip.x), _GSPDraw_YPos(ps,ps->ggc->clip.y));
534 0 : ps->cur_clip = ps->ggc->clip;
535 : }
536 0 : }
537 :
538 0 : void _GPSDraw_SetColor(GPSWindow ps,Color fg) {
539 0 : if ( ps->display->do_color ) {
540 0 : fprintf( ps->output_file, "%g %g %g setrgbcolor\n", COLOR_RED(fg)/255.0,
541 0 : COLOR_GREEN(fg)/255.0, COLOR_BLUE(fg)/255.0 );
542 : } else {
543 0 : fprintf( ps->output_file, "%g setgray\n", COLOR2GREYR(fg));
544 : }
545 0 : ps->cur_fg = fg;
546 0 : }
547 :
548 0 : static int PSDrawSetcol(GPSWindow ps) {
549 :
550 0 : _GPSDraw_SetClip(ps);
551 0 : if ( ps->ggc->fg!=ps->cur_fg || ps->ggc->ts!=ps->cur_ts ) {
552 0 : _GPSDraw_FlushPath(ps);
553 0 : if ( ps->ggc->ts!=ps->cur_ts ) {
554 0 : if ( ps->ggc->ts ) {
555 0 : fprintf( ps->output_file, "currentcolor DotPattern setpattern\n" );
556 0 : ps->cur_ts = ps->ggc->ts;
557 : } else {
558 0 : fprintf( ps->output_file, "%s setcolorspace\n",
559 0 : ps->display->do_color?"/DeviceRGB":"/DeviceGray" );
560 0 : ps->cur_ts = 0;
561 : }
562 : }
563 0 : _GPSDraw_SetColor(ps,ps->ggc->fg);
564 : }
565 0 : return( true );
566 : }
567 :
568 0 : static int PSDrawSetline(GPSWindow ps) {
569 :
570 0 : PSDrawSetcol(ps);
571 0 : if ( ps->ggc->line_width!=ps->cur_line_width ) {
572 0 : _GPSDraw_FlushPath(ps);
573 0 : fprintf( ps->output_file, "%g setlinewidth\n", _GSPDraw_XPos(ps,ps->ggc->line_width) );
574 0 : ps->cur_line_width = ps->ggc->line_width;
575 : }
576 0 : if ( ps->ggc->dash_len != ps->cur_dash_len || ps->ggc->skip_len != ps->cur_skip_len ||
577 0 : ps->ggc->dash_offset != ps->cur_dash_offset ) {
578 0 : _GPSDraw_FlushPath(ps);
579 0 : if ( ps->ggc->dash_len==0 ) {
580 0 : fprintf( ps->output_file, "[] 0 setdash\n" );
581 : } else {
582 0 : fprintf( ps->output_file, "[%d %d] %d setdash\n",
583 0 : ps->ggc->dash_len, ps->ggc->skip_len,
584 0 : PixelToPoint(ps->ggc->dash_offset,ps->res)%(ps->ggc->dash_len+ps->ggc->skip_len) );
585 : }
586 0 : ps->cur_dash_offset = ps->ggc->dash_offset;
587 0 : ps->cur_dash_len = ps->ggc->dash_len;
588 0 : ps->cur_skip_len = ps->ggc->skip_len;
589 : }
590 0 : return( true );
591 : }
592 :
593 0 : static void PSDrawPushClip(GWindow w,GRect *rct, GRect *old) {
594 0 : GPSWindow ps = (GPSWindow ) w;
595 :
596 0 : _GPSDraw_FlushPath(ps);
597 0 : fprintf( ps->output_file,"gsave\n" );
598 0 : ps->last_dash_len = ps->cur_dash_len;
599 0 : ps->last_skip_len = ps->cur_skip_len;
600 0 : ps->last_dash_offset = ps->cur_dash_offset;
601 0 : ps->last_line_width = ps->cur_line_width;
602 0 : ps->last_ts = ps->cur_ts;
603 0 : ps->last_fg = ps->cur_fg;
604 0 : ps->last_font = ps->cur_font;
605 0 : *old = ps->ggc->clip;
606 0 : ps->ggc->clip = *rct;
607 0 : }
608 :
609 0 : static void PSDrawPopClip(GWindow w,GRect *old) {
610 0 : GPSWindow ps = (GPSWindow ) w;
611 :
612 0 : _GPSDraw_FlushPath(ps);
613 0 : ps->cur_clip = *old;
614 0 : fprintf( ps->output_file,"grestore\n" );
615 0 : ps->cur_dash_len = ps->last_dash_len;
616 0 : ps->cur_skip_len = ps->last_skip_len;
617 0 : ps->cur_line_width = ps->last_line_width;
618 0 : ps->cur_dash_offset = ps->last_dash_offset;
619 0 : ps->cur_ts = ps->last_ts;
620 0 : ps->cur_fg = ps->last_fg;
621 0 : ps->cur_font = ps->last_font;
622 0 : ps->last_dash_len = -1;
623 0 : ps->last_skip_len = -1;
624 0 : ps->last_line_width = -1;
625 0 : ps->last_dash_offset = -1;
626 0 : ps->last_ts = -1;
627 0 : ps->last_fg = -1;
628 0 : ps->last_font = NULL;
629 0 : ps->ggc->clip = *old;
630 0 : }
631 :
632 0 : static void PSDrawDrawLine(GWindow w, int32 x,int32 y,int32 xend,int32 yend,Color col) {
633 0 : GPSWindow ps = (GPSWindow ) w;
634 :
635 0 : ps->ggc->fg = col;
636 0 : PSDrawSetline(ps);
637 0 : PSMoveTo(ps,x,y);
638 0 : PSLineTo(ps,xend,yend);
639 0 : }
640 :
641 0 : static void PSDrawArrow(GPSWindow ps, int32 x, int32 y, int32 xother, int32 yother ) {
642 : GPoint points[3];
643 : double a;
644 : int off1, off2;
645 : double len;
646 0 : int line_width = ps->ggc->line_width;
647 :
648 0 : if ( x==xother && y==yother )
649 0 : return;
650 0 : a = atan2(y-yother,x-xother);
651 0 : len = 72.0*sqrt((double) (x-xother)*(x-xother)+(y-yother)*(y-yother))/ps->res;
652 0 : if ( len>30 ) len = 10+3*line_width/2; else len = (len+line_width)/3;
653 0 : if ( len<2 )
654 0 : return;
655 0 : len *= ps->res/72.0;
656 :
657 0 : points[0].x = x; points[0].y = y;
658 0 : if ( line_width!=0 ) {
659 0 : points[0].x += line_width*1.3*cos(a); points[0].y += line_width*1.3*sin(a);
660 : }
661 0 : off1 = len*sin(a+3.1415926535897932/8)+.5; off2 = len*cos(a+3.1415926535897932/8)+.5;
662 0 : points[1].x = x-off2; points[1].y = y-off1;
663 0 : off1 = len*sin(a-3.1415926535897932/8)+.5; off2 = len*cos(a-3.1415926535897932/8)+.5;
664 0 : points[2].x = x-off2; points[2].y = y-off1;
665 0 : PSDrawDoPoly(ps,points,3,"fill");
666 : }
667 :
668 0 : static void PSDrawDrawArrowLine(GWindow w, int32 x,int32 y,int32 xend,int32 yend,int16 arrows,Color col) {
669 0 : GPSWindow ps = (GPSWindow ) w;
670 :
671 0 : ps->ggc->fg = col;
672 0 : PSDrawSetline(ps);
673 0 : PSMoveTo(ps,x,y);
674 0 : PSLineTo(ps,xend,yend);
675 0 : if ( arrows&1 )
676 0 : PSDrawArrow(ps,x,y,xend,yend);
677 0 : if ( arrows&2 )
678 0 : PSDrawArrow(ps,xend,yend,x,y);
679 0 : }
680 :
681 0 : static void PSDrawDrawRect(GWindow w, GRect *rct,Color col) {
682 0 : GPSWindow ps = (GPSWindow ) w;
683 :
684 0 : ps->ggc->fg = col;
685 0 : PSDrawSetline(ps);
686 0 : fprintf( ps->output_file, " %g %g %g %g %g %g %g %g g_quad stroke\n",
687 0 : _GSPDraw_XPos(ps,rct->x), _GSPDraw_YPos(ps,rct->y+rct->height),
688 0 : _GSPDraw_XPos(ps,rct->x+rct->width), _GSPDraw_YPos(ps,rct->y+rct->height),
689 0 : _GSPDraw_XPos(ps,rct->x+rct->width), _GSPDraw_YPos(ps,rct->y),
690 : _GSPDraw_XPos(ps,rct->x), _GSPDraw_YPos(ps,rct->y));
691 0 : ps->pnt_cnt = 0;
692 0 : }
693 :
694 0 : static void PSDrawFillRect(GWindow w, GRect *rct,Color col) {
695 0 : GPSWindow ps = (GPSWindow ) w;
696 :
697 0 : ps->ggc->fg = col;
698 0 : PSDrawSetcol(ps);
699 0 : _GPSDraw_FlushPath(ps);
700 0 : fprintf( ps->output_file, " %g %g %g %g %g %g %g %g g_quad fill\n",
701 0 : _GSPDraw_XPos(ps,rct->x), _GSPDraw_YPos(ps,rct->y+rct->height),
702 0 : _GSPDraw_XPos(ps,rct->x+rct->width), _GSPDraw_YPos(ps,rct->y+rct->height),
703 0 : _GSPDraw_XPos(ps,rct->x+rct->width), _GSPDraw_YPos(ps,rct->y),
704 : _GSPDraw_XPos(ps,rct->x), _GSPDraw_YPos(ps,rct->y));
705 0 : ps->pnt_cnt = 0;
706 0 : }
707 :
708 0 : static void PSDrawFillRoundRect(GWindow UNUSED(w), GRect *UNUSED(rct),
709 : int UNUSED(radius), Color UNUSED(col)) {
710 0 : fprintf( stderr, "DrawFillRoundRect not implemented for postscript\n" );
711 0 : return;
712 : }
713 :
714 0 : static void PSDrawClear(GWindow w,GRect *rect) {
715 0 : GPSWindow ps = (GPSWindow ) w;
716 0 : if ( rect==NULL )
717 0 : rect = &ps->ggc->clip;
718 0 : PSDrawFillRect(w,rect,COLOR_CREATE(255,255,255));
719 0 : }
720 :
721 0 : static void PSDrawDrawCircle(GWindow w, GRect *rct,Color col) {
722 0 : GPSWindow ps = (GPSWindow ) w;
723 :
724 0 : ps->ggc->fg = col;
725 0 : PSDrawSetline(ps);
726 0 : PSDrawElipse(ps,rct,"stroke");
727 0 : }
728 :
729 0 : static void PSDrawFillCircle(GWindow w, GRect *rct,Color col) {
730 0 : GPSWindow ps = (GPSWindow ) w;
731 :
732 0 : ps->ggc->fg = col;
733 0 : PSDrawSetcol(ps);
734 0 : _GPSDraw_FlushPath(ps);
735 0 : PSDrawElipse(ps,rct,"fill");
736 0 : }
737 :
738 0 : static void PSDrawDrawArc(GWindow w, GRect *rct,int32 sa, int32 ta, Color col) {
739 0 : GPSWindow ps = (GPSWindow ) w;
740 : float cx, cy, radx, rady;
741 :
742 0 : ps->ggc->fg = col;
743 0 : PSDrawSetline(ps);
744 0 : _GPSDraw_FlushPath(ps);
745 :
746 0 : radx = rct->width/2.0;
747 0 : rady = rct->height/2.0;
748 0 : cx = rct->x + radx;
749 0 : cy = rct->y + rady;
750 0 : if ( radx==0 || rady==0 )
751 0 : return;
752 0 : PSDrawNewpath(ps);
753 0 : if ( radx!=rady )
754 0 : PSMyArc(ps,cx,cy,radx,rady,sa/64.0,ta/64.0);
755 : else
756 0 : fprintf( ps->output_file, " %g %g %g %g %g arc", _GSPDraw_XPos(ps,cx), _GSPDraw_YPos(ps,cy), _GSPDraw_Distance(ps,radx),
757 0 : sa/64.0, (sa+ta)/64.0 );
758 0 : fprintf( ps->output_file, " stroke\n" );
759 0 : ps->pnt_cnt = 0;
760 0 : ps->cur_x = ps->cur_y = -1;
761 : }
762 :
763 0 : static void PSDrawDrawPoly(GWindow w, GPoint *pt, int16 cnt,Color col) {
764 0 : GPSWindow ps = (GPSWindow ) w;
765 :
766 0 : ps->ggc->fg = col;
767 0 : PSDrawSetline(ps);
768 0 : PSDrawDoPoly(ps,pt,cnt,"stroke");
769 0 : }
770 :
771 0 : static void PSDrawFillPoly(GWindow w, GPoint *pt, int16 cnt,Color col) {
772 0 : GPSWindow ps = (GPSWindow ) w;
773 :
774 0 : ps->ggc->fg = col;
775 0 : PSDrawSetcol(ps);
776 0 : _GPSDraw_FlushPath(ps);
777 0 : PSDrawDoPoly(ps,pt,cnt,"fill");
778 0 : }
779 :
780 0 : static void PSDrawFontMetrics(GWindow w, FontInstance *fi, int *as, int *ds, int *ld) {
781 0 : GDrawWindowFontMetrics(w, fi, as, ds, ld);
782 0 : }
783 :
784 0 : static enum gcairo_flags PSDrawHasCairo(GWindow UNUSED(w)) {
785 0 : return( gc_buildpath );
786 : }
787 :
788 0 : static void PSDrawPathStartNew(GWindow w) {
789 0 : GPSWindow ps = (GPSWindow ) w;
790 0 : fprintf( ps->output_file," newpath\n" );
791 0 : }
792 :
793 0 : static void PSDrawPathClose(GWindow w) {
794 0 : GPSWindow ps = (GPSWindow ) w;
795 0 : fprintf( ps->output_file," closepath\n" );
796 0 : }
797 :
798 0 : static void PSDrawPathMoveTo(GWindow w,double x, double y) {
799 0 : GPSWindow ps = (GPSWindow ) w;
800 0 : fprintf( ps->output_file," %g %g moveto\n", _GSPDraw_XPos(ps,x), _GSPDraw_YPos(ps,y) );
801 0 : }
802 :
803 0 : static void PSDrawPathLineTo(GWindow w,double x, double y) {
804 0 : GPSWindow ps = (GPSWindow ) w;
805 0 : fprintf( ps->output_file," %g %g lineto\n", _GSPDraw_XPos(ps,x), _GSPDraw_YPos(ps,y) );
806 0 : }
807 :
808 0 : static void PSDrawPathCurveTo(GWindow w,
809 : double cx1, double cy1,
810 : double cx2, double cy2,
811 : double x, double y) {
812 0 : GPSWindow ps = (GPSWindow ) w;
813 0 : fprintf( ps->output_file," %g %g %g %g %g %g curveto\n",
814 : _GSPDraw_XPos(ps,cx1), _GSPDraw_YPos(ps,cy1),
815 : _GSPDraw_XPos(ps,cx2), _GSPDraw_YPos(ps,cy2),
816 : _GSPDraw_XPos(ps,x), _GSPDraw_YPos(ps,y) );
817 0 : }
818 :
819 0 : static void PSDrawPathStroke(GWindow w,Color col) {
820 0 : GPSWindow ps = (GPSWindow ) w;
821 0 : ps->ggc->fg = col;
822 0 : PSDrawSetcol(ps);
823 0 : fprintf( ps->output_file," stroke\n" );
824 0 : }
825 :
826 0 : static void PSDrawPathFill(GWindow w,Color col) {
827 0 : GPSWindow ps = (GPSWindow ) w;
828 0 : ps->ggc->fg = col;
829 0 : PSDrawSetcol(ps);
830 0 : fprintf( ps->output_file," fill\n" );
831 0 : }
832 :
833 0 : static void PSDrawPathFillAndStroke(GWindow w,Color fillcol, Color strokecol) {
834 0 : GPSWindow ps = (GPSWindow ) w;
835 0 : ps->ggc->fg = fillcol;
836 0 : PSDrawSetcol(ps);
837 0 : fprintf( ps->output_file," save fill restore " );
838 0 : ps->ggc->fg = strokecol;
839 0 : PSDrawSetcol(ps);
840 0 : fprintf( ps->output_file," stroke\n" );
841 0 : }
842 :
843 0 : static void PSPageSetup(GPSWindow ps,FILE *out, float thumbscale) {
844 0 : GPSDisplay *gdisp = ps->display;
845 : /* I want to put this somewhere in the document header, but DSC conventions*/
846 : /* don't let me. Frustrating. Or I don't understand how, also frustrating*/
847 :
848 0 : fprintf( out, " %g %g translate\t\t%%Left & Top Margins\n",
849 0 : gdisp->lmargin*72.0, (gdisp->yheight-gdisp->tmargin)*72.0 );
850 0 : fprintf( out, " %g %g %g %g %g %g %g %g g_quad clip newpath\t%%Clip to margins\n",
851 : _GSPDraw_XPos(ps,0), _GSPDraw_YPos(ps,0),
852 0 : _GSPDraw_XPos(ps,0), _GSPDraw_YPos(ps,(gdisp->yheight-gdisp->tmargin-gdisp->bmargin)*gdisp->res),
853 0 : _GSPDraw_XPos(ps,(gdisp->xwidth-gdisp->lmargin-gdisp->rmargin)*gdisp->res), _GSPDraw_YPos(ps,(gdisp->yheight-gdisp->tmargin-gdisp->bmargin)*gdisp->res),
854 0 : _GSPDraw_XPos(ps,(gdisp->xwidth-gdisp->lmargin-gdisp->rmargin)*gdisp->res), _GSPDraw_YPos(ps,0));
855 0 : if ( gdisp->scale*thumbscale!=1 )
856 0 : fprintf( out, " %g %g scale\n", gdisp->scale*thumbscale, gdisp->scale*thumbscale );
857 0 : }
858 :
859 0 : static void PSPageInit(GPSWindow ps) {
860 0 : GPSDisplay *gdisp = (GPSDisplay *) (ps->display);
861 0 : int thumb_per_page = gdisp->linear_thumb_cnt*gdisp->linear_thumb_cnt;
862 0 : int real_page = ( ps->page_cnt%thumb_per_page == 0 );
863 :
864 0 : ++ps->page_cnt;
865 0 : if ( gdisp->eps ) {
866 0 : fprintf( ps->output_file, "\n%%%%Page: 1 1\n" );
867 0 : fprintf( ps->output_file, "%%%%BeginPageSetup\n" );
868 0 : PSPageSetup(ps,ps->output_file,1.0);
869 0 : fprintf( ps->output_file, "%%%%EndPageSetup\n" );
870 0 : } else if ( real_page ) {
871 0 : int page = (ps->page_cnt+thumb_per_page-1)/thumb_per_page;
872 0 : fprintf( ps->output_file, "\n%%%%Page: %d %d\n", page, page );
873 0 : fprintf( ps->output_file, "%%%%BeginPageSetup\n" );
874 0 : fprintf( ps->output_file, "g_startpage\n" );
875 0 : fprintf( ps->output_file, "%%%%EndPageSetup\n" );
876 : } else
877 0 : fprintf( ps->output_file, "\n%% Psuedo Page: \ng_startpage\n" );
878 0 : ps->ggc->clip.y = ps->ggc->clip.x = 0;
879 0 : ps->ggc->clip.height = ps->pos.height; ps->ggc->clip.width = ps->pos.width;
880 0 : ps->cur_clip = ps->ggc->clip;
881 0 : ps->cur_skip_len = ps->cur_dash_len = ps->cur_line_width = ps->cur_dash_offset = ps->cur_ts = 0;
882 0 : ps->cur_font = NULL; ps->cur_fg = 0;
883 0 : }
884 :
885 0 : static void PSPageTerm(GPSWindow ps, int last) {
886 0 : GPSDisplay *gdisp = (GPSDisplay *) (ps->display);
887 0 : int thumb_per_page = gdisp->linear_thumb_cnt*gdisp->linear_thumb_cnt;
888 :
889 0 : _GPSDraw_FlushPath(ps);
890 0 : if ( gdisp->eps )
891 0 : return;
892 0 : if ( last || ps->page_cnt%thumb_per_page==0 ) {
893 0 : fprintf( ps->output_file, "%%%%PageTrailer\n" );
894 0 : if ( last )
895 0 : fprintf( ps->output_file, "g_finalpage\t\t%%End of Page\n" );
896 : else
897 0 : fprintf( ps->output_file, "g_endpage\t\t%%End of Page\n" );
898 0 : fprintf( ps->output_file, "%%%%EndPageTrailer\n" );
899 : } else
900 0 : fprintf( ps->output_file, "g_endpage\t\t%%End of Psuedo Page\n" );
901 : }
902 :
903 0 : static void PSTrailer(GPSWindow ps) {
904 0 : GPSDisplay *gdisp = (GPSDisplay *) (ps->display);
905 0 : int thumb_per_page = gdisp->linear_thumb_cnt*gdisp->linear_thumb_cnt;
906 :
907 0 : fprintf( ps->output_file, "%%%%Trailer\n" );
908 0 : if ( !gdisp->eps )
909 0 : fprintf( ps->output_file, "%%%%Pages: %d\n",
910 0 : (int) (ps->page_cnt+thumb_per_page-1)/thumb_per_page);
911 0 : _GPSDraw_ListNeededFonts(ps);
912 0 : fprintf( ps->output_file, "%%%%EndTrailer\n" );
913 0 : fprintf( ps->output_file, "%%%%EOF\n" );
914 0 : }
915 :
916 0 : static void PSInitJob(GPSWindow ps, unichar_t *title) {
917 0 : GPSDisplay *gdisp = ps->display;
918 : char buf[200];
919 : time_t now;
920 :
921 : /* output magic line to tell lpr this is a postscript file */
922 0 : if ( gdisp->eps ) {
923 0 : fprintf( ps->init_file, "%%!PS-Adobe-3.0 EPSF-3.0\n" );
924 0 : fprintf( ps->init_file, "%%%%Pages: 1\n" );
925 : } else {
926 0 : fprintf( ps->init_file, "%%!PS-Adobe-3.0%s\n", gdisp->eps?" EPSF-3.0":"" );
927 0 : fprintf( ps->init_file, "%%%%Pages: (atend)\n" );
928 : }
929 0 : fprintf( ps->init_file, "%%%%BoundingBox: %g %g %g %g\n",
930 0 : 72.0*gdisp->lmargin, 72.0*gdisp->bmargin,
931 0 : 72.0*(gdisp->xwidth-gdisp->rmargin), 72.0*(gdisp->yheight-gdisp->tmargin));
932 0 : fprintf( ps->init_file, "%%%%Creator: %s\n", GResourceProgramName );
933 0 : time(&now);
934 0 : fprintf( ps->init_file, "%%%%CreationDate: %s", ctime(&now) );
935 0 : if ( title!=NULL )
936 0 : fprintf( ps->init_file, "%%%%Title: %s\n", u2def_strncpy(buf,title,sizeof(buf)) );
937 0 : fprintf( ps->init_file, "%%%%DocumentData: Clean7Bit\n" );
938 0 : fprintf( ps->init_file, "%%%%LanguageLevel: 2\n" );
939 0 : fprintf( ps->init_file, "%%%%Orientation: %s\n", gdisp->landscape?
940 : "Landscape":"Portrait" );
941 0 : fprintf( ps->init_file, "%%%%PageOrder: Ascend\n" );
942 0 : fprintf( ps->init_file, "%%%%DocumentNeededResources: (atend)\n" );
943 0 : fprintf( ps->init_file, "%%%%DocumentSuppliedResources: (atend)\n" );
944 0 : fprintf( ps->init_file, "%%%%EndComments\n\n" );
945 :
946 : /* Need to output a setdevice thing to specify the page size (num copies?) ??? */
947 0 : fprintf( ps->init_file, "%%%%BeginPrologue\n" );
948 :
949 : /* Any predefined functions? */
950 : /* Need one to remap an adobe encoding to some other encoding */
951 0 : fprintf( ps->init_file, "%% <font> <encoding> font_remap <font>\t; from the cookbook\n" );
952 0 : fprintf( ps->init_file, "/reencodedict 5 dict def\n" );
953 0 : fprintf( ps->init_file, "/g_font_remap { reencodedict begin\n" );
954 0 : fprintf( ps->init_file, " /newencoding exch def\n" );
955 0 : fprintf( ps->init_file, " /basefont exch def\n" );
956 0 : fprintf( ps->init_file, " /newfont basefont maxlength dict def\n" );
957 0 : fprintf( ps->init_file, " basefont {\n" );
958 0 : fprintf( ps->init_file, " exch dup dup /FID ne exch /Encoding ne and\n" );
959 0 : fprintf( ps->init_file, "\t{ exch newfont 3 1 roll put }\n" );
960 0 : fprintf( ps->init_file, "\t{ pop pop }\n" );
961 0 : fprintf( ps->init_file, " ifelse\n" );
962 0 : fprintf( ps->init_file, " } forall\n" );
963 0 : fprintf( ps->init_file, " newfont /Encoding newencoding put\n" );
964 0 : fprintf( ps->init_file, " newfont\t%%Leave on stack\n" );
965 0 : fprintf( ps->init_file, " end } def\n" );
966 : /* Simple routine to move somewhere and draw a string */
967 0 : fprintf( ps->init_file, "/g_show { moveto show } bind def\n" );
968 0 : fprintf( ps->init_file, "/g_ashow { moveto ashow } bind def\n" );
969 0 : fprintf( ps->init_file, "/g_quad { moveto lineto lineto lineto closepath } bind def\n" );
970 : /* Routines to start and end pages. simple unless we do thumbnails */
971 0 : if ( gdisp->eps ) {
972 : /* No page procedures at all */
973 0 : } else if ( gdisp->linear_thumb_cnt <= 1 ) {
974 0 : fprintf( ps->init_file, "/g_startpage { save \n" );
975 0 : PSPageSetup(ps,ps->init_file,1.0);
976 0 : fprintf( ps->init_file, "} bind def\n" );
977 0 : fprintf( ps->init_file, "/g_endpage { restore showpage } bind def\n" );
978 0 : fprintf( ps->init_file, "/g_finalpage { g_endpage } bind def\n" );
979 : } else {
980 : float stemp, thumbscale;
981 0 : thumbscale = (gdisp->xwidth-gdisp->lmargin-gdisp->rmargin)/
982 0 : (gdisp->linear_thumb_cnt*gdisp->xwidth-gdisp->lmargin-gdisp->rmargin);
983 0 : stemp = (gdisp->yheight-gdisp->tmargin-gdisp->bmargin)/
984 0 : (gdisp->linear_thumb_cnt*gdisp->yheight-gdisp->tmargin-gdisp->bmargin);
985 0 : if ( stemp<thumbscale ) thumbscale = stemp;
986 0 : thumbscale *= .97; /* rounding errors make the real thing slightly too big */
987 0 : fprintf( ps->init_file, "/g_thumbnum 0 def\n" );
988 0 : fprintf( ps->init_file, "/g_startpage { \n" );
989 0 : fprintf( ps->init_file, " g_thumbnum %d mod 0 eq { save \n",
990 0 : gdisp->linear_thumb_cnt*gdisp->linear_thumb_cnt );
991 0 : PSPageSetup(ps,ps->init_file,thumbscale);
992 0 : fprintf( ps->init_file, " } if\n" );
993 0 : fprintf( ps->init_file, " save\n" );
994 0 : fprintf( ps->init_file, " g_thumbnum %d mod %d mul g_thumbnum %d idiv %d mul translate\n",
995 0 : gdisp->linear_thumb_cnt, (int) ps->pos.width,
996 0 : gdisp->linear_thumb_cnt, (int) -ps->pos.height );
997 0 : fprintf( ps->init_file, " %g %g %g %g %g %g %g %g g_quad clip newpath\n",
998 : _GSPDraw_XPos(ps,0), _GSPDraw_YPos(ps,0),
999 : _GSPDraw_XPos(ps,0), _GSPDraw_YPos(ps,ps->pos.height),
1000 : _GSPDraw_XPos(ps,ps->pos.width), _GSPDraw_YPos(ps,ps->pos.height),
1001 : _GSPDraw_XPos(ps,ps->pos.width), _GSPDraw_YPos(ps,0));
1002 0 : fprintf(ps->init_file, "} bind def\n" );
1003 0 : fprintf( ps->init_file, "/g_endpage { restore /g_thumbnum g_thumbnum 1 add def\n g_thumbnum %d eq { restore /g_thumbnum 0 def showpage } if\n } bind def\n",
1004 0 : gdisp->linear_thumb_cnt*gdisp->linear_thumb_cnt );
1005 0 : fprintf( ps->init_file, "/g_finalpage { restore restore showpage } bind def\n" );
1006 : }
1007 0 : _GPSDraw_InitPatterns(ps);
1008 0 : _GPSDraw_InitFonts(gdisp->fontstate);
1009 :
1010 0 : fprintf( ps->init_file, "%% Font Initialization (download needed fonts, remap locals)\n" );
1011 0 : fprintf( ps->init_file, "/MyFontDict 100 dict def\n" );
1012 :
1013 0 : fprintf( ps->output_file, "\n%%%%EndProlog\n\n" );
1014 0 : fprintf( ps->output_file, "\n%%%%BeginSetup\n" );
1015 0 : if ( !gdisp->eps )
1016 0 : fprintf( ps->output_file, "<< /PageSize [%g %g] >> setpagedevice\n\n",
1017 0 : 72.0*gdisp->xwidth, 72.0*gdisp->yheight );
1018 : /* Could set NumCopies in the InputAttributes sub-dictionary but I think */
1019 : /* that is best done on the lpr command line */
1020 0 : fprintf( ps->output_file, "%%%%EndSetup\n\n" );
1021 0 : ps->cur_clip.x = ps->cur_clip.y = 0;
1022 0 : ps->cur_clip.width = ps->pos.width;
1023 0 : ps->cur_clip.height = ps->pos.height;
1024 0 : ps->ggc->clip = ps->cur_clip;
1025 0 : PSPageInit(ps);
1026 0 : }
1027 :
1028 0 : static int PSQueueFile(GPSWindow ps) {
1029 : #if !defined(__MINGW32__)
1030 0 : GPSDisplay *gdisp = ps->display;
1031 0 : int pid = fork();
1032 :
1033 0 : rewind( ps->init_file );
1034 0 : if ( pid==0 ) {
1035 : /* In child */
1036 0 : int in = fileno(stdin);
1037 : char *prog;
1038 : char *argv[30];
1039 0 : int argc=0;
1040 : char pbuf[200], cbuf[40];
1041 : char buffer[1025];
1042 : char *parg, *carg, *spt, *pt;
1043 :
1044 0 : close(in);
1045 0 : dup2(fileno(ps->init_file),in);
1046 0 : close(fileno(ps->init_file));
1047 :
1048 0 : if ( gdisp->use_lpr ) {
1049 0 : prog = "lpr";
1050 0 : parg = "P";
1051 0 : carg = "#";
1052 : } else {
1053 0 : prog = "lp";
1054 0 : parg = "d";
1055 0 : carg = "n";
1056 : }
1057 0 : argv[argc++] = prog;
1058 0 : if ( !gdisp->use_lpr )
1059 0 : argv[argc++] = "-s";
1060 0 : if ( gdisp->printer_name!=NULL ) {
1061 0 : sprintf(pbuf, "-%s%s ", parg, gdisp->printer_name );
1062 0 : argv[argc++] = pbuf;
1063 : }
1064 0 : if ( gdisp->num_copies!=0 ) {
1065 0 : sprintf(cbuf, "-%s%d ", carg, gdisp->num_copies );
1066 0 : argv[argc++] = pbuf;
1067 : }
1068 0 : if ( gdisp->lpr_args!=NULL ) {
1069 0 : strncpy(buffer, gdisp->lpr_args,sizeof(buffer)-1 );
1070 0 : for ( spt = buffer; *spt==' '; ++spt );
1071 0 : while ( (pt = strchr(spt,' '))!=NULL ) {
1072 0 : argv[argc++] = spt;
1073 0 : *pt = '\0';
1074 0 : for ( spt=pt+1; *spt==' '; ++spt );
1075 : }
1076 0 : if ( *spt!='\0' )
1077 0 : argv[argc++] = spt;
1078 : }
1079 0 : argv[argc] = NULL;
1080 0 : if ( execvp(prog,argv)==-1 )
1081 0 : _exit(1);
1082 0 : } else if ( pid==-1 )
1083 0 : return( false );
1084 : else {
1085 : /* in parent */
1086 : int status;
1087 0 : if ( waitpid(pid,&status,0)==-1 )
1088 0 : return( false );
1089 0 : if ( WIFEXITED(status))
1090 0 : return( true );
1091 : }
1092 : #endif
1093 0 : return( false );
1094 : }
1095 :
1096 0 : static int PSFinishJob(GPSWindow ps,int cancel) {
1097 0 : GPSDisplay *gdisp = ps->display;
1098 0 : int error = ferror(ps->output_file);
1099 :
1100 0 : if ( ps->output_file!=ps->init_file ) {
1101 0 : rewind(ps->output_file);
1102 0 : _GPSDraw_CopyFile(ps->init_file,ps->output_file);
1103 0 : fclose(ps->output_file);
1104 : }
1105 0 : error |= ferror(ps->init_file);
1106 0 : if ( error || cancel ) {
1107 0 : if ( !cancel )
1108 0 : GDrawError("An error occurred while saving the print job to disk.\nNot printed." );
1109 0 : if ( gdisp->filename!=NULL )
1110 0 : GFileUnlink(gdisp->filename);
1111 0 : fclose(ps->init_file);
1112 0 : return(false);
1113 : }
1114 0 : if ( !gdisp->print_to_file ) {
1115 0 : if ( !PSQueueFile(ps)) {
1116 0 : GDrawError("Could not queue print job" );
1117 0 : fclose(ps->init_file);
1118 0 : return( false );
1119 : }
1120 : }
1121 0 : fclose(ps->init_file);
1122 0 : return( true );
1123 : }
1124 :
1125 0 : static void PSDestroyContext(GPSDisplay *gd) {
1126 0 : free(gd->groot->ggc);
1127 0 : free(gd->groot);
1128 0 : gd->groot = NULL;
1129 0 : }
1130 :
1131 0 : static GGC *_GPSDraw_NewGGC(GPSDisplay *ps) {
1132 0 : GGC *ggc = calloc(1,sizeof(GGC));
1133 0 : ggc->clip.width = ggc->clip.height = 0x7fff;
1134 0 : ggc->fg = 0;
1135 0 : ggc->bg = 0xffffff;
1136 0 : ggc->line_width = ps->scale_screen_by;
1137 0 : return( ggc );
1138 : }
1139 :
1140 0 : static GWindow GPSPrinterStartJob(GDisplay *gd,void *user_data,GPrinterAttrs *attrs) {
1141 0 : GPSDisplay *gdisp = (GPSDisplay *) gd;
1142 0 : double factor = 1;
1143 : char *oldpn, *oldea, *oldfn;
1144 : FILE *output, *init;
1145 : GPSWindow groot;
1146 :
1147 0 : if ( gd->groot!=NULL ) {
1148 0 : GDrawError("Please wait for current print job to complete before starting a new one" );
1149 0 : return( NULL );
1150 : }
1151 :
1152 0 : if ( attrs!=NULL ) {
1153 0 : if ( attrs->units==pu_mm )
1154 0 : factor = 25.4;
1155 0 : else if ( attrs->units == pu_points )
1156 0 : factor = 72;
1157 :
1158 0 : if ( attrs->mask&pam_pagesize ) {
1159 0 : gdisp->xwidth = attrs->width/factor;
1160 0 : gdisp->yheight = attrs->height/factor;
1161 : }
1162 0 : if ( attrs->mask&pam_margins ) {
1163 0 : gdisp->lmargin = attrs->lmargin/factor;
1164 0 : gdisp->rmargin = attrs->rmargin/factor;
1165 0 : gdisp->tmargin = attrs->tmargin/factor;
1166 0 : gdisp->bmargin = attrs->bmargin/factor;
1167 : }
1168 0 : if ( attrs->mask&pam_scale )
1169 0 : gdisp->scale = attrs->scale;
1170 0 : if ( gdisp->scale<=0 ) gdisp->scale = 1.0;
1171 0 : gdisp->last_units = attrs->units;
1172 0 : if ( attrs->mask&pam_res )
1173 0 : gdisp->res = attrs->res;
1174 0 : gdisp->scale_screen_by = gdisp->res/screen_display->res;
1175 0 : if ( gdisp->scale_screen_by==0 ) gdisp->scale_screen_by =1;
1176 0 : if ( attrs->mask&pam_copies )
1177 0 : gdisp->num_copies = attrs->num_copies;
1178 : else
1179 0 : gdisp->num_copies = 1;
1180 0 : if ( attrs->mask&pam_thumbnails )
1181 0 : gdisp->linear_thumb_cnt = attrs->thumbnails;
1182 : else
1183 0 : gdisp->linear_thumb_cnt = 1;
1184 0 : if ( gdisp->linear_thumb_cnt<=0 )
1185 0 : gdisp->linear_thumb_cnt = 1;
1186 0 : if ( attrs->mask&pam_transparent )
1187 0 : gdisp->do_transparent = attrs->do_transparent;
1188 0 : if ( attrs->mask&pam_color )
1189 0 : gdisp->do_color = attrs->do_color;
1190 0 : if ( attrs->mask&pam_lpr )
1191 0 : gdisp->use_lpr = attrs->use_lpr;
1192 0 : if ( attrs->mask&pam_queue )
1193 0 : gdisp->print_to_file = attrs->donot_queue;
1194 0 : if ( attrs->mask&pam_eps )
1195 0 : gdisp->eps = attrs->eps;
1196 : else
1197 0 : gdisp->eps = false;
1198 0 : if ( gdisp->eps ) {
1199 0 : gdisp->print_to_file = true;
1200 0 : gdisp->linear_thumb_cnt = 1;
1201 0 : gdisp->scale_screen_by =1;
1202 : }
1203 0 : if ( attrs->mask&pam_landscape )
1204 0 : gdisp->landscape = attrs->landscape;
1205 :
1206 0 : oldpn = gdisp->printer_name; oldea = gdisp->lpr_args; oldfn = gdisp->filename;
1207 0 : if ( gdisp->print_to_file && (attrs->mask&pam_filename) )
1208 0 : gdisp->filename = copy(attrs->file_name);
1209 : else
1210 0 : gdisp->filename = NULL;
1211 0 : if ( attrs->mask&pam_printername )
1212 0 : gdisp->printer_name = copy(attrs->printer_name);
1213 : else
1214 0 : oldpn = NULL;
1215 0 : if ( attrs->mask&pam_args )
1216 0 : gdisp->lpr_args = copy(attrs->extra_lpr_args);
1217 : else
1218 0 : oldea = NULL;
1219 0 : free(oldfn); free(oldpn); free(oldea);
1220 : }
1221 0 : if ( gdisp->filename==NULL ) {
1222 0 : init = tmpfile();
1223 0 : if ( init==NULL ) {
1224 0 : GDrawError("Can't open printer temporary file" );
1225 0 : return( NULL );
1226 : }
1227 0 : } else if (( init = fopen(gdisp->filename,"wb"))==NULL ) {
1228 0 : GDrawError("Can't open %s: %s", gdisp->print_to_file?"user file":"printer spooling file",
1229 : gdisp->filename);
1230 0 : return( NULL );
1231 : }
1232 0 : output = tmpfile();
1233 0 : if ( output==NULL )
1234 0 : output = init;
1235 :
1236 0 : gdisp->fontstate->res = gdisp->res;
1237 :
1238 0 : gdisp->groot = calloc(1,sizeof(struct gpswindow));
1239 0 : groot = (GPSWindow)(gdisp->groot);
1240 0 : groot->ggc = _GPSDraw_NewGGC(gdisp);
1241 0 : groot->display = gdisp;
1242 0 : groot->pos.width = (gdisp->xwidth-gdisp->lmargin-gdisp->rmargin)*gdisp->res/gdisp->scale;
1243 0 : groot->pos.height = (gdisp->yheight-gdisp->tmargin-gdisp->bmargin)*gdisp->res/gdisp->scale;
1244 0 : groot->user_data = user_data;
1245 0 : groot->output_file = output;
1246 0 : groot->init_file = init;
1247 0 : groot->cur_x = groot->cur_y = -1;
1248 0 : groot->cur_fg = COLOR_UNKNOWN;
1249 0 : groot->pnt_cnt = -1;
1250 0 : groot->res = gdisp->res;
1251 0 : groot->cur_dash_len = groot->cur_skip_len = -1;
1252 0 : groot->cur_line_width = -1;
1253 0 : groot->cur_dash_offset = -1;
1254 0 : groot->cur_ts = -1;
1255 0 : groot->last_dash_len = groot->last_skip_len = -1;
1256 0 : groot->last_line_width = -1;
1257 0 : groot->last_dash_offset = -1;
1258 0 : groot->last_ts = -1;
1259 0 : groot->last_fg = COLOR_UNKNOWN;
1260 0 : groot->is_toplevel = true;
1261 0 : groot->is_visible = true;
1262 :
1263 0 : PSInitJob(groot,(attrs->mask&pam_title)?attrs->title:NULL);
1264 0 : return( (GWindow) groot);
1265 : }
1266 :
1267 0 : static void GPSPrinterNextPage(GWindow w) {
1268 0 : GPSWindow ps = (GPSWindow) w;
1269 0 : if (ps->display->eps )
1270 0 : GDrawIError("Attempt to start a new page within an encapsulated postscript document");
1271 : else {
1272 0 : PSPageTerm(ps,false);
1273 0 : PSPageInit(ps);
1274 : }
1275 0 : }
1276 :
1277 0 : static int GPSPrinterEndJob(GWindow w,int cancel) {
1278 0 : GPSWindow ps = (GPSWindow) w;
1279 0 : GPSDisplay *gdisp = ps->display;
1280 : int ret;
1281 :
1282 0 : PSPageTerm(ps,true);
1283 0 : PSTrailer(ps);
1284 0 : ret = PSFinishJob(ps,cancel);
1285 0 : _GPSDraw_ResetFonts(gdisp->fontstate);
1286 0 : PSDestroyContext(gdisp);
1287 0 : free(gdisp->filename); gdisp->filename=NULL;
1288 0 : return( ret );
1289 : }
1290 :
1291 0 : static GWindow PSDrawCreateTopWindow(GDisplay *gdisp, GRect *UNUSED(pos),
1292 : int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs) {
1293 : (void)eh;
1294 0 : return( GPSPrinterStartJob(gdisp, wattrs==NULL ? NULL : user_data, NULL));
1295 : }
1296 :
1297 0 : static void PSDrawDestroyWindow(GWindow w) {
1298 0 : GPSPrinterEndJob(w,true);
1299 0 : }
1300 :
1301 : static struct displayfuncs psfuncs = {
1302 : PSDrawInit,
1303 : PSDrawTerm,
1304 : PSDrawNativeDisplay,
1305 :
1306 : PSDrawSetDefaultIcon,
1307 :
1308 : PSDrawCreateTopWindow,
1309 : PSDrawCreateSubWindow,
1310 : PSDrawCreatePixmap,
1311 : PSDrawCreateBitmap,
1312 : PSDrawCreateCursor,
1313 : PSDrawDestroyWindow,
1314 : PSDestroyCursor,
1315 : PSNativeWindowExists,
1316 : PSSetZoom,
1317 : PSSetWindowBorder,
1318 : PSSetWindowBackground,
1319 : PSSetDither,
1320 :
1321 : PSDrawReparentWindow,
1322 : PSDrawSetVisible,
1323 : PSDrawMove,
1324 : PSDrawMove,
1325 : PSDrawResize,
1326 : PSDrawMoveResize,
1327 : PSDrawRaise,
1328 : PSDrawRaiseAbove,
1329 : PSDrawIsAbove,
1330 : PSDrawLower,
1331 : PSDrawSetWindowTitles,
1332 : PSDrawSetWindowTitles8,
1333 : PSDrawGetWindowTitle,
1334 : PSDrawGetWindowTitle8,
1335 : PSDrawSetTransientFor,
1336 : PSDrawGetPointerPosition,
1337 : PSDrawGetPointerWindow,
1338 : PSDrawSetCursor,
1339 : PSDrawGetCursor,
1340 : PSDrawGetRedirectWindow,
1341 : PSDrawTranslateCoordinates,
1342 :
1343 : PSDrawBeep,
1344 : PSDrawFlush,
1345 :
1346 : PSDrawPushClip,
1347 : PSDrawPopClip,
1348 :
1349 : PSDrawClear,
1350 : PSDrawDrawLine,
1351 : PSDrawDrawArrowLine,
1352 : PSDrawDrawRect,
1353 : PSDrawFillRect,
1354 : PSDrawFillRoundRect,
1355 : PSDrawDrawCircle,
1356 : PSDrawFillCircle,
1357 : PSDrawDrawArc,
1358 : PSDrawDrawPoly,
1359 : PSDrawFillPoly,
1360 : PSDrawScroll,
1361 :
1362 : _GPSDraw_Image,
1363 : _GPSDraw_TileImage,
1364 : _GPSDraw_Image,
1365 : _GPSDraw_ImageMagnified,
1366 : _PSDraw_CopyScreenToImage,
1367 : _PSDraw_Pixmap,
1368 : _PSDraw_TilePixmap,
1369 :
1370 : PSDrawCreateInputContext,
1371 : PSDrawSetGIC,
1372 :
1373 : PSDrawGrabSelection,
1374 : PSDrawAddSelectionType,
1375 : PSDrawRequestSelection,
1376 : PSDrawSelectionHasType,
1377 : PSDrawBindSelection,
1378 : PSDrawSelectionHasOwner,
1379 :
1380 : PSDrawPointerUngrab,
1381 : PSDrawPointerGrab,
1382 : PSDrawRequestExpose,
1383 : PSDrawForceUpdate,
1384 : PSDrawSync,
1385 : PSDrawSkipMouseMoveEvents,
1386 : PSDrawProcessPendingEvents,
1387 : PSDrawProcessWindowEvents,
1388 : PSDrawProcessPendingEvents, /* Same as for OneEvent */
1389 : PSDrawEventLoop,
1390 : PSDrawPostEvent,
1391 : PSDrawPostDragEvent,
1392 : PSDrawRequestDeviceEvents,
1393 :
1394 : PSDrawRequestTimer,
1395 : PSDrawCancelTimer,
1396 :
1397 : PSDrawSyncThread,
1398 :
1399 : GPSPrinterStartJob,
1400 : GPSPrinterNextPage,
1401 : GPSPrinterEndJob,
1402 :
1403 : PSDrawFontMetrics,
1404 :
1405 : PSDrawHasCairo,
1406 :
1407 : PSDrawPathStartNew,
1408 : PSDrawPathClose,
1409 : PSDrawPathMoveTo,
1410 : PSDrawPathLineTo,
1411 : PSDrawPathCurveTo,
1412 : PSDrawPathStroke,
1413 : PSDrawPathFill,
1414 : PSDrawPathFillAndStroke,
1415 :
1416 : NULL, /* Pango layout */
1417 : NULL,
1418 : NULL,
1419 : NULL,
1420 : NULL,
1421 : NULL,
1422 : NULL,
1423 : NULL,
1424 : NULL,
1425 : NULL
1426 : };
1427 :
1428 0 : void _GPSDraw_DestroyDisplay(GDisplay *gdisp) {
1429 0 : if (gdisp->fontstate != NULL) { free(gdisp->fontstate); gdisp->fontstate = NULL; }
1430 0 : free(gdisp);
1431 0 : return;
1432 : }
1433 :
1434 0 : GDisplay *_GPSDraw_CreateDisplay() {
1435 : GPSDisplay *gdisp;
1436 :
1437 0 : gdisp = calloc(1,sizeof(GPSDisplay));
1438 0 : if ( gdisp==NULL ) {
1439 0 : return( NULL );
1440 : }
1441 :
1442 0 : gdisp->funcs = &psfuncs;
1443 0 : gdisp->res = 600;
1444 0 : if ( screen_display!=NULL )
1445 0 : gdisp->scale_screen_by = gdisp->res/screen_display->res;
1446 0 : if ( gdisp->scale_screen_by==0 ) gdisp->scale_screen_by =1;
1447 :
1448 0 : gdisp->scale = 1.;
1449 0 : gdisp->xwidth = 8.5;
1450 0 : gdisp->yheight = 11;
1451 0 : gdisp->lmargin = gdisp->rmargin = gdisp->tmargin = gdisp->bmargin = 1;
1452 0 : gdisp->use_lpr = true;
1453 0 : gdisp->do_transparent = true;
1454 0 : gdisp->num_copies = 1;
1455 0 : gdisp->linear_thumb_cnt = 1;
1456 0 : gdisp->fontstate = calloc(1,sizeof(FState));
1457 0 : gdisp->fontstate->res = gdisp->res;
1458 :
1459 0 : gdisp->def_background = COLOR_CREATE(0xff,0xff,0xff);
1460 0 : gdisp->def_background = COLOR_CREATE(0x00,0x00,0x00);
1461 :
1462 0 : (gdisp->funcs->init)((GDisplay *) gdisp);
1463 0 : return( (GDisplay *) gdisp);
1464 : }
|