1 #   include	"drawMetaConfig.h"
2 
3 #   include	<stddef.h>
4 
5 #   include	"drawMetafileImpl.h"
6 #   include	"drawMetafilePs.h"
7 #   include	"drawWinMetaImpl.h"
8 #   include	<psFontMetrics.h>
9 #   include	<utilMatchFont.h>
10 #   include	<psPrint.h>
11 #   include	<psPrintShape.h>
12 #   include	<psShading.h>
13 #   include	<bmWmfIo.h>
14 #   include	<bmEmfIo.h>
15 #   include	<bmBitmapPrinter.h>
16 #   include	"drawMacPictImpl.h"
17 
18 #   include	<math.h>
19 
20 #   include	<appDebugon.h>
21 
22 # if 0
23 #    define	WMFDEB(x)	(x)
24 # else
25 #    define	WMFDEB(x)	/*nothing*/
26 # endif
27 
28 # if 0
29 #    define	WMFLOG(x)	(x)
30 # else
31 #    define	WMFLOG(x)	/*nothing*/
32 # endif
33 
34 /************************************************************************/
35 /*									*/
36 /*  Play a windows metafile to PostScript.				*/
37 /*									*/
38 /************************************************************************/
39 
appMetaSetColorPs(PrintingState * ps,DeviceContext * dc,const RGB8Color * rgb8)40 static void appMetaSetColorPs(		PrintingState *		ps,
41 					DeviceContext *		dc,
42 					const RGB8Color *	rgb8 )
43     {
44     if  ( dc->dcColorSet.rgb8Red == rgb8->rgb8Red	&&
45 	  dc->dcColorSet.rgb8Green == rgb8->rgb8Green	&&
46 	  dc->dcColorSet.rgb8Blue == rgb8->rgb8Blue	)
47 	{ return;	}
48 
49     psSetRgb8Color( ps, rgb8 );
50 
51     dc->dcColorSet= *rgb8;
52 
53     return;
54     }
55 
appMetafileRectPathPs(PrintingState * ps,const DocumentRectangle * dr)56 static void appMetafileRectPathPs(	PrintingState *			ps,
57 					const DocumentRectangle *	dr )
58     {
59     int		dx= dr->drX1- dr->drX0;
60     int		dy= dr->drY1- dr->drY0;
61 
62     sioOutPrintf( ps->psSos, "%d %d bp ",  dr->drX0,  dr->drY0 );
63     sioOutPrintf( ps->psSos, "%d %d rl ",  dx,   0 );
64     sioOutPrintf( ps->psSos, "%d %d rl ",   0,  dy );
65     sioOutPrintf( ps->psSos, "%d %d rl ", -dx,   0 );
66 
67     sioOutPrintf( ps->psSos, "closepath\n" );
68 
69     return;
70     }
71 
appMetaSetFontPs(PrintingState * ps,DeviceContext * dc,TextAttribute ta,int fontSizeTwips)72 static void appMetaSetFontPs(		PrintingState *		ps,
73 					DeviceContext *		dc,
74 					TextAttribute		ta,
75 					int			fontSizeTwips )
76     {
77     ta.taFontSizeHalfPoints= fontSizeTwips/ 10;
78 
79     if  ( docEqualTextAttributes( &ta, &(dc->dcTextAttributeSet) ) )
80 	{ return;	}
81 
82     dc->dcTextAttributeSet= ta;
83     psSetFont( ps, dc->dcAfi, &(dc->dcTextAttributeSet) );
84     }
85 
appMetaIssueDotsPs(SimpleOutputStream * sos,const unsigned char * dots,int dotCount)86 static void appMetaIssueDotsPs(		SimpleOutputStream *	sos,
87 					const unsigned char *	dots,
88 					int			dotCount )
89     {
90     const char *	before= "";
91 
92     sioOutPrintf( sos, "[" );
93     while( dotCount-- > 0 )
94 	{ sioOutPrintf( sos, "%s%d", before, *(dots++) ); before= " ";	}
95     sioOutPrintf( sos, "] 0 setdash\n" );
96 
97     return;
98     }
99 
appMetaSetPenPs(DeviceContext * dc,void * through,const LogicalPen * lp)100 static void appMetaSetPenPs(		DeviceContext *		dc,
101 					void *			through,
102 					const LogicalPen *	lp )
103     {
104     PrintingState *		ps= (PrintingState *)through;
105     SimpleOutputStream *	sos= ps->psSos;
106     int				widthTwips;
107 
108     unsigned char		dots[6];
109     int				dotCount;
110 
111     if  ( dc->dcPenSet.lpStyle == lp->lpStyle		&&
112 	  dc->dcPenSet.lpWidth == lp->lpWidth		)
113 	{ return;	}
114 
115     widthTwips= appMetaGetPenWidth( dc, lp );
116     dotCount= appMetaGetPenDots( dc, dots, lp );
117 
118     if  ( widthTwips > 0 )
119 	{
120 	sioOutPrintf( sos, "%d setlinewidth ", widthTwips );
121 	appMetaIssueDotsPs( sos, dots, dotCount );
122 	}
123 
124     dc->dcPenSet= *lp;
125 
126     return;
127     }
128 
129 /************************************************************************/
130 
131 typedef struct PushedGraphics
132     {
133     RGB8Color		pgColor;
134     } PushedGraphics;
135 
appWinMetaPushGraphics(PushedGraphics * pg,const DeviceContext * dc,PrintingState * ps)136 static void appWinMetaPushGraphics(	PushedGraphics *	pg,
137 					const DeviceContext *	dc,
138 					PrintingState *		ps )
139     {
140     sioOutPrintf( ps->psSos, "gsave " );
141     pg->pgColor= dc->dcColorSet;
142     }
143 
appWinMetaPushGraphicsForDraw(PushedGraphics * pg,DeviceContext * dc,PrintingState * ps,int fillInsides,int drawBorders)144 static void appWinMetaPushGraphicsForDraw(
145 					PushedGraphics *	pg,
146 					DeviceContext *		dc,
147 					PrintingState *		ps,
148 					int			fillInsides,
149 					int			drawBorders )
150     {
151     if  ( fillInsides )
152 	{
153 	if  ( ! dc->dcFillPattern )
154 	    {
155 	    appMetaSetColorPs( ps, dc, &(dc->dcBrush.lbColor) );
156 	    goto ready;
157 	    }
158 	}
159 
160     if  ( drawBorders )
161 	{
162 	appMetaSetColorPs( ps, dc, &(dc->dcPen.lpColor) );
163 	goto ready;
164 	}
165 
166   ready:
167     appWinMetaPushGraphics( pg, dc, ps );
168     return;
169     }
170 
appWinMetaPopGraphics(const PushedGraphics * pg,DeviceContext * dc,PrintingState * ps)171 static void appWinMetaPopGraphics(	const PushedGraphics *	pg,
172 					DeviceContext *		dc,
173 					PrintingState *		ps )
174     {
175     sioOutPrintf( ps->psSos, "grestore\n" );
176     dc->dcColorSet= pg->pgColor;
177     }
178 
179 /************************************************************************/
180 /*									*/
181 /*  Insert a bitmap image in the PostScript output for a metafile.	*/
182 /*									*/
183 /************************************************************************/
184 
appDrawMetaBitmapImagePs(DeviceContext * dc,void * through,const RasterImage * abi,const DocumentRectangle * drSrc,const DocumentRectangle * drDest)185 static int appDrawMetaBitmapImagePs(
186 				DeviceContext *			dc,
187 				void *				through,
188 				const RasterImage *		abi,
189 				const DocumentRectangle *	drSrc,
190 				const DocumentRectangle *	drDest )
191     {
192     PrintingState *		ps= (PrintingState *)through;
193     SimpleOutputStream *	sos= ps->psSos;
194     const BitmapDescription *	bd= &(abi->riDescription);
195     const int			onWhite= 1;
196 
197     int				twipsWide= drDest->drX1- drDest->drX0+ 1;
198     int				twipsHigh= drDest->drY1- drDest->drY0+ 1;
199 
200     sioOutPrintf( sos, "gsave 1 setgray\n" );
201     sioOutPrintf( sos, "%d %d %d %d rectfill\n", drDest->drX0, drDest->drY0,
202 							twipsWide, twipsHigh );
203     sioOutPrintf( sos, "grestore\n" );
204 
205     if  ( bmPsPrintBitmapImage( sos, 1,
206 			    twipsWide, -twipsHigh,
207 			    drDest->drX0, ( drDest->drY0+ twipsHigh ),
208 			    drSrc, onWhite,
209 			    ps->psUsePostScriptFilters,
210 			    ps->psUsePostScriptIndexedImages,
211 			    bd, abi->riBytes ) )
212 	{ LDEB(1); return -1;	}
213 
214     return 0;
215     }
216 
appCleanObjectPs(DeviceContext * dc,void * through,MetaFileObject * mfo)217 static int appCleanObjectPs(		DeviceContext *		dc,
218 					void *			through,
219 					MetaFileObject *	mfo )
220     { return 0;	}
221 
appWinMeta_FillPathPs(PrintingState * ps,DeviceContext * dc)222 static int appWinMeta_FillPathPs(	PrintingState *		ps,
223 					DeviceContext *		dc )
224     {
225     SimpleOutputStream *	sos= ps->psSos;
226 
227     if  ( dc->dcFillPattern )
228 	{
229 	sioOutPrintf( sos, "fill-pattern\n" );
230 	return 0;
231 	}
232 
233     appMetaSetColorPs( ps, dc, &(dc->dcBrush.lbColor) );
234 
235     if  ( dc->dcFillHatched )
236 	{
237 	double	det;
238 
239 	det= geoAffineTransformDeterminant2D( &(dc->dcTransform.dctLogicalToOutput) );
240 	switch( dc->dcBrush.lbHatch )
241 	    {
242 	    case HS_HORIZONTAL:
243 		sioOutPrintf( sos, "%s\n", PsShadingNames[PSshdHORIZ] );
244 		break;
245 	    case HS_VERTICAL:
246 		sioOutPrintf( sos, "%s\n", PsShadingNames[PSshdVERT] );
247 		break;
248 	    case HS_FDIAGONAL:
249 		if  ( det >= 0 )
250 		    { sioOutPrintf( sos, "%s\n", PsShadingNames[PSshdBDIAG] ); }
251 		else{ sioOutPrintf( sos, "%s\n", PsShadingNames[PSshdFDIAG] ); }
252 		break;
253 	    case HS_BDIAGONAL:
254 		if  ( det >= 0 )
255 		    { sioOutPrintf( sos, "%s\n", PsShadingNames[PSshdFDIAG] );	}
256 		else{ sioOutPrintf( sos, "%s\n", PsShadingNames[PSshdBDIAG] );	}
257 		break;
258 	    case HS_CROSS:
259 		sioOutPrintf( sos, "%s\n", PsShadingNames[PSshdCROSS] );
260 		break;
261 	    case HS_DIAGCROSS:
262 		sioOutPrintf( sos, "%s\n", PsShadingNames[PSshdDCROSS] );
263 		break;
264 	    default:
265 		LDEB(dc->dcBrush.lbHatch);
266 		sioOutPrintf( sos, "%% HATCH %d !!!!!!!!!!!\n",
267 						    dc->dcBrush.lbHatch );
268 	    }
269 	}
270     else{
271 	if  ( dc->dcPolyFillMode == WINDING )
272 	    { sioOutPrintf( sos, "eofill\n" );	}
273 	else{ sioOutPrintf( sos, "fill\n" );	}
274 	}
275 
276     return 0;
277     }
278 
appMetafilePolygonPathPs(PrintingState * ps,const Point2DI * points,int count,const char * command,const char * psOperator,int closePath)279 static int appMetafilePolygonPathPs(	PrintingState *		ps,
280 					const Point2DI *	points,
281 					int			count,
282 					const char *		command,
283 					const char *		psOperator,
284 					int			closePath )
285     {
286     SimpleOutputStream *	sos= ps->psSos;
287 
288     int				done;
289     int				x0;
290     int				y0;
291 
292 
293     x0= 0; y0= 0;
294 
295     for ( done= 0; done < count; done++ )
296 	{
297 	int	sep;
298 
299 	if  ( done % 8 == 7 )
300 	    { sep= '\n';	}
301 	else{ sep= ' ';		}
302 
303 	sioOutPrintf( sos, "%d %d %s%c",
304 			    points[done].x- x0,
305 			    points[done].y- y0,
306 			    command, sep );
307 
308 	command= "rl"; x0= points[done].x; y0= points[done].y;
309 	}
310 
311     if  ( closePath )
312 	{
313 	int	sep;
314 
315 	if  ( done % 8 == 7 )
316 	    { sep= '\n';	}
317 	else{ sep= ' ';		}
318 
319 	sioOutPrintf( sos, "%d %d %s%c",
320 			    points[0].x- x0,
321 			    points[0].y- y0,
322 			    command, sep );
323 	}
324 
325     if  ( psOperator )
326 	{ sioOutPrintf( sos, "%s", psOperator );	}
327 
328     return 0;
329     }
330 
appMeta_PolyPolygonPs(DeviceContext * dc,void * through,int polyCount,const int * pointCounts,const Point2DI * points,int fillInsides,int drawBorders,int closePath)331 static int appMeta_PolyPolygonPs( DeviceContext *		dc,
332 				void *			through,
333 				int			polyCount,
334 				const int *		pointCounts,
335 				const Point2DI *	points,
336 				int			fillInsides,
337 				int			drawBorders,
338 				int			closePath )
339     {
340     PrintingState *		ps= (PrintingState *)through;
341     int				poly;
342 
343     const char *		sep;
344 
345     if  ( polyCount == 1 )
346 	{ sep= " ";	}
347     else{ sep= "\n";	}
348 
349     if  ( fillInsides )
350 	{
351 	const char *	command= "bp";
352 	int		done= 0;
353 
354 	for ( poly= 0; poly < polyCount; poly++ )
355 	    {
356 	    appMetafilePolygonPathPs( ps, points+ done, pointCounts[poly],
357 						    command, sep, closePath );
358 	    command= "mt";
359 	    done += pointCounts[poly];
360 	    }
361 
362 	appWinMeta_FillPathPs( ps, dc );
363 	}
364 
365     if  ( drawBorders )
366 	{
367 	const char *	command= "bp";
368 	int		done= 0;
369 
370 	appMetaSetColorPs( ps, dc, &(dc->dcPen.lpColor) );
371 	appMetaSetPenPs( dc, through, &(dc->dcPen) );
372 
373 	for ( poly= 0; poly < polyCount; poly++ )
374 	    {
375 	    appMetafilePolygonPathPs( ps, points+ done, pointCounts[poly],
376 						    command, sep, closePath );
377 	    command= "mt";
378 	    done += pointCounts[poly];
379 	    }
380 
381 	if  ( polyCount == 1 && closePath )
382 	    { sioOutPrintf( ps->psSos, "cp stroke\n" );	}
383 	else{ sioOutPrintf( ps->psSos, "stroke\n" );	}
384 	}
385 
386     return 0;
387     }
388 
appMeta_PolyBezierPs(DeviceContext * dc,void * through,int count,const Point2DI * points,int startPath,int fillInsides,int drawBorders,int closePath)389 static int appMeta_PolyBezierPs( DeviceContext *	dc,
390 				void *			through,
391 				int			count,
392 				const Point2DI *	points,
393 				int			startPath,
394 				int			fillInsides,
395 				int			drawBorders,
396 				int			closePath )
397     {
398 return 0;
399     }
400 
appMetaDrawStringPs(DeviceContext * dc,void * through,int x0,int y0,const MemoryBuffer * text)401 static int appMetaDrawStringPs(		DeviceContext *		dc,
402 					void *			through,
403 					int			x0,
404 					int			y0,
405 					const MemoryBuffer *	text )
406     {
407     PrintingState *	ps= (PrintingState *)through;
408     const AfmFontInfo *	afi= dc->dcAfi;
409     LogicalFont *	lf= &(dc->dcFont);
410 
411     int			wide;
412     DocumentRectangle	drText;
413     const int		withKerning= 0;
414     const int		vswap= 1;
415     int			fontSizeTwips;
416 
417     const char *	s= utilMemoryBufferGetString( text );
418     int			len= text->mbSize;
419 
420     PushedGraphics	pg;
421 
422     if  ( ! afi )
423 	{ XDEB(afi); return -1;	}
424 
425     fontSizeTwips= appWinMetaOutputSize( dc, lf->lfHeight );
426 
427     wide= psCalculateStringExtents( &drText, s, len,
428 				    fontSizeTwips, withKerning, vswap, afi );
429     drText.drX0 += x0;
430     drText.drX1 += x0;
431     drText.drY0 += y0;
432     drText.drY1 += y0;
433 
434     switch( dc->dcTextAlignment & 0x01 )
435 	{
436 	case TA_NOUPDATECP:
437 	    break;
438 
439 	case TA_UPDATECP:
440 	    x0= DC_xViewport( dc->dcX, dc->dcY, dc );
441 	    y0= DC_yViewport( dc->dcX, dc->dcY, dc );
442 	    break;
443 
444 	default:
445 	    XDEB(dc->dcTextAlignment & 0x01 );
446 	    break;
447 	}
448 
449     switch( dc->dcTextAlignment & 0x06 )
450 	{
451 	int		xshift;
452 
453 	case TA_LEFT:
454 	    break;
455 
456 	case TA_RIGHT:
457 	    xshift= -wide;
458 	    x0 += xshift;
459 	    drText.drX0 += xshift;
460 	    drText.drX1 += xshift;
461 	    break;
462 
463 	case TA_CENTER:
464 	    xshift= -wide/ 2;
465 	    x0 += xshift;
466 	    drText.drX0 += xshift;
467 	    drText.drX1 += xshift;
468 	    break;
469 
470 	default:
471 	    XDEB(dc->dcTextAlignment & 0x06);
472 	    break;
473 	}
474 
475     switch( dc->dcTextAlignment & 0x18 )
476 	{
477 	int			yshift;
478 	DocumentRectangle	drFontBBox;
479 	DocumentRectangle	drFontAscDesc;
480 
481 	case TA_TOP:
482 	    psFontBBox( &drFontBBox, &drFontAscDesc, fontSizeTwips,
483 								vswap, afi );
484 	    yshift= -drFontAscDesc.drY0;
485 	    y0 += yshift;
486 	    drText.drY0 += yshift;
487 	    drText.drY1 += yshift;
488 	    break;
489 
490 	case TA_BOTTOM:
491 	    psFontBBox( &drFontBBox, &drFontAscDesc, fontSizeTwips,
492 								vswap, afi );
493 	    yshift= -drFontAscDesc.drY1;
494 	    y0 += yshift;
495 	    drText.drY0 += yshift;
496 	    drText.drY1 += yshift;
497 	    break;
498 
499 	case TA_BASELINE:
500 	    break;
501 
502 	default:
503 	    WMFDEB(appDebug(" 0x%x", dc->dcTextAlignment & 0x18 ));
504 	    break;
505 	}
506 
507     if  ( dc->dcBkMode == OPAQUE )
508 	{
509 	appMetaSetColorPs( ps, dc, &(dc->dcBkColor) );
510 
511 	psFillRectangle( ps, drText.drX0, drText.drY0,
512 				    drText.drX1- drText.drX0+ 1,
513 				    drText.drY1- drText.drY0+ 1 );
514 	}
515 
516     appMetaSetFontPs( ps, dc, dc->dcFont.lfTextAttribute, fontSizeTwips );
517     appMetaSetColorPs( ps, dc, &(dc->dcTextColor) );
518 
519     if  ( dc->dcFont.lfOrientation != 0 )
520 	{
521 	appWinMetaPushGraphics( &pg, dc, ps );
522 	sioOutPrintf( ps->psSos, "%d %d translate %g rotate\n",
523 				x0, y0, -0.1* dc->dcFont.lfOrientation );
524 
525 	x0= y0= 0;
526 	}
527 
528     psMoveShowString( ps, (unsigned char *)s, len, x0, y0 );
529 
530     if  ( dc->dcFont.lfTextAttribute.taTextIsUnderlined )
531 	{
532 	int		h;
533 	int		pos;
534 
535 	psUnderlineGeometry( &pos, &h, y0, fontSizeTwips, afi );
536 
537 	psFillRectangle( ps, x0, y0, wide, h );
538 	}
539 
540     if  ( dc->dcFont.lfOrientation != 0 )
541 	{
542 	appWinMetaPopGraphics( &pg, dc, ps );
543 	}
544 
545     return 0;
546     }
547 
appMetaPatBltPs(DeviceContext * dc,void * through,long rop,const DocumentRectangle * drOutput)548 static int appMetaPatBltPs(	DeviceContext *			dc,
549 				void *				through,
550 				long				rop,
551 				const DocumentRectangle *	drOutput )
552     {
553     PrintingState *	ps= (PrintingState *)through;
554 
555     if  ( dc->dcFillInsides )
556 	{
557 	appMetafileRectPathPs( ps, drOutput );
558 	appWinMeta_FillPathPs( ps, dc );
559 	}
560 
561     return 0;
562     }
563 
appMetaGetArcPs(DeviceContext * dc,int * pW,int * pH,int * pXm,int * pYm,int * pXs,int * pYs,double * pas,double * pae,const DocumentRectangle * dr,int xs,int ys,int xe,int ye)564 static void appMetaGetArcPs(	DeviceContext *			dc,
565 				int *				pW,
566 				int *				pH,
567 				int *				pXm,
568 				int *				pYm,
569 				int *				pXs,
570 				int *				pYs,
571 				double *			pas,
572 				double *			pae,
573 				const DocumentRectangle *	dr,
574 				int				xs,
575 				int				ys,
576 				int				xe,
577 				int				ye )
578 
579     {
580     int			ym;
581     int			xm;
582     int			h;
583     int			w;
584 
585     double		as;
586     double		ae;
587 
588     DocumentRectangle	drFixed;
589 
590     ym= ( dr->drY1+ dr->drY0 )/2;
591     xm= ( dr->drX1+ dr->drX0 )/2;
592     drFixed= *dr;
593 
594     if  ( dr->drX1 < dr->drX0 )
595 	{
596 	xs= 2* xm- xs;
597 	xe= 2* xm- xe;
598 	drFixed.drX0= dr->drX1;
599 	drFixed.drX1= dr->drX0;
600 	}
601     if  ( dr->drY1 < dr->drY0 )
602 	{
603 	ys= 2* ym- ys;
604 	ye= 2* ym- ye;
605 	drFixed.drY0= dr->drY1;
606 	drFixed.drY1= dr->drY0;
607 	}
608 
609     h= drFixed.drY1- drFixed.drY0;
610     w= drFixed.drX1- drFixed.drX0;
611 
612     as= -atan2(	(double) w* ( ys- ym ), (double) h* ( xs- xm ) );
613     ae= -atan2(	(double) w* ( ye- ym ), (double) h* ( xe- xm ) );
614 
615     xs= (int)( ( ( drFixed.drX1- drFixed.drX0 )/ 2 )* cos( as )+ xm );
616     ys= (int)( ( ( drFixed.drY1- drFixed.drY0 )/ 2 )* sin( as ) );
617 
618     as= ( 180* as )/ M_PI;
619     ae= ( 180* ae )/ M_PI;
620 
621     *pW= w;
622     *pH= h;
623     *pXm= xm;
624     *pYm= ym;
625 
626     *pYs= ys;
627     *pXs= xs;
628     *pas= as;
629     *pae= ae;
630 *pas= -as;
631 *pae= 360- ae;
632 
633     return;
634     }
635 
appMetaDrawArcPs(DeviceContext * dc,void * through,const DocumentRectangle * dr,int xs,int ys,int xe,int ye,int fillInside,int drawBorder)636 static int appMetaDrawArcPs(	DeviceContext *			dc,
637 				void *				through,
638 				const DocumentRectangle *	dr,
639 				int				xs,
640 				int				ys,
641 				int				xe,
642 				int				ye,
643 				int				fillInside,
644 				int				drawBorder )
645     {
646     PrintingState *	ps= (PrintingState *)through;
647     double		as;
648     double		ae;
649     int			xm;
650     int			ym;
651     int			w;
652     int			h;
653 
654     appMetaGetArcPs( dc, &w, &h, &xm, &ym, &xs, &ys, &as, &ae,
655 							dr, xs, ys, xe, ye );
656 
657     if  ( drawBorder )
658 	{
659 	appMetaSetColorPs( ps, dc, &(dc->dcPen.lpColor) );
660 	appMetaSetPenPs( dc, through, &(dc->dcPen) );
661 
662 	sioOutPrintf( ps->psSos, "gsave [1 0 0 %g 0 %d] concat\n",
663 						    (double)h/(double)w, ym );
664 
665 	sioOutPrintf( ps->psSos, "%d %d bp ", xs, ys );
666 
667 	sioOutPrintf( ps->psSos, "%d 0 %d %f %f arc stroke\n",
668 							    xm, w/2, as, ae );
669 
670 	sioOutPrintf( ps->psSos, "grestore\n" );
671 	}
672 
673     return 0;
674     }
675 
appMetaDrawPiePs(DeviceContext * dc,void * through,const DocumentRectangle * dr,int xs,int ys,int xe,int ye,int fillInside,int drawBorder)676 static int appMetaDrawPiePs(	DeviceContext *			dc,
677 				void *				through,
678 				const DocumentRectangle *	dr,
679 				int				xs,
680 				int				ys,
681 				int				xe,
682 				int				ye,
683 				int				fillInside,
684 				int				drawBorder )
685     {
686     PrintingState *	ps= (PrintingState *)through;
687     double		as;
688     double		ae;
689     int			xm;
690     int			ym;
691     int			w;
692     int			h;
693 
694     PushedGraphics	pg;
695 
696     appMetaGetArcPs( dc, &w, &h, &xm, &ym, &xs, &ys, &as, &ae,
697 							dr, xs, ys, xe, ye );
698     appWinMetaPushGraphicsForDraw( &pg, dc, ps, fillInside, drawBorder );
699     sioOutPrintf( ps->psSos, "[1 0 0 %g 0 %d] concat\n",
700 						    (double)h/(double)w, ym );
701 
702     if  ( fillInside )
703 	{
704 	sioOutPrintf( ps->psSos, "%d %d bp ", xs, ys );
705 
706 	sioOutPrintf( ps->psSos, "%d 0 %d %f %f arc\n", xm, w/2, as, ae );
707 	sioOutPrintf( ps->psSos, "%d  0 lineto ", xm );
708 	sioOutPrintf( ps->psSos, "%d %d lineto closepath\n", xs, ys );
709 
710 	appWinMeta_FillPathPs( ps, dc );
711 	}
712 
713     if  ( drawBorder )
714 	{
715 	appMetaSetColorPs( ps, dc, &(dc->dcPen.lpColor) );
716 	appMetaSetPenPs( dc, through, &(dc->dcPen) );
717 
718 	sioOutPrintf( ps->psSos, "%d %d bp ", xs, ys );
719 
720 	sioOutPrintf( ps->psSos, "%d 0 %d %f %f arc ", xm, w/2, as, ae );
721 	sioOutPrintf( ps->psSos, "%d  0 lineto ", xm );
722 	sioOutPrintf( ps->psSos, "%d %d lineto stroke\n", xs, ys );
723 	}
724 
725     appWinMetaPopGraphics( &pg, dc, ps );
726 
727     return 0;
728     }
729 
appMetaDrawChordPs(DeviceContext * dc,void * through,const DocumentRectangle * dr,int xs,int ys,int xe,int ye,int fillInside,int drawBorder)730 static int appMetaDrawChordPs(	DeviceContext *			dc,
731 				void *				through,
732 				const DocumentRectangle *	dr,
733 				int				xs,
734 				int				ys,
735 				int				xe,
736 				int				ye,
737 				int				fillInside,
738 				int				drawBorder )
739     {
740     PrintingState *	ps= (PrintingState *)through;
741     double		as;
742     double		ae;
743     int			xm;
744     int			ym;
745     int			w;
746     int			h;
747 
748     PushedGraphics	pg;
749 
750     appMetaGetArcPs( dc, &w, &h, &xm, &ym, &xs, &ys, &as, &ae,
751 							dr, xs, ys, xe, ye );
752 
753     appWinMetaPushGraphicsForDraw( &pg, dc, ps, fillInside, drawBorder );
754     sioOutPrintf( ps->psSos, "[1 0 0 %g 0 %d] concat\n",
755 						    (double)h/(double)w, ym );
756 
757     if  ( drawBorder )
758 	{
759 	appMetaSetColorPs( ps, dc, &(dc->dcPen.lpColor) );
760 	appMetaSetPenPs( dc, through, &(dc->dcPen) );
761 
762 	sioOutPrintf( ps->psSos, "%d %d bp ", xs, ys );
763 
764 	sioOutPrintf( ps->psSos, "%d 0 %d %f %f arc %d %d lineto stroke\n",
765 						    xm, w/2, as, ae, xs, ys );
766 	}
767 
768     appWinMetaPopGraphics( &pg, dc, ps );
769 
770     return 0;
771     }
772 
appMetaDrawEllipsePs(DeviceContext * dc,void * through,const DocumentRectangle * dr,int fillInside,int drawBorder)773 static int appMetaDrawEllipsePs(DeviceContext *			dc,
774 				void *				through,
775 				const DocumentRectangle *	dr,
776 				int				fillInside,
777 				int				drawBorder )
778     {
779     PrintingState *	ps= (PrintingState *)through;
780     int			w= dr->drX1- dr->drX0;
781     int			h= dr->drY1- dr->drY0;
782     int			xm= ( dr->drX0+ dr->drX1 )/ 2;
783     int			ym= ( dr->drY0+ dr->drY1 )/ 2;
784 
785     PushedGraphics	pg;
786 
787     appWinMetaPushGraphicsForDraw( &pg, dc, ps, fillInside, drawBorder );
788     sioOutPrintf( ps->psSos, "[1 0 0 %g 0 %d] concat\n",
789 						(double)h/(double)w, ym );
790 
791     if  ( fillInside )
792 	{
793 	sioOutPrintf( ps->psSos, "%d 0 bp ", dr->drX1 );
794 	sioOutPrintf( ps->psSos, "%d 0 %d 0 360 arc closepath\n", xm, w/2 );
795 
796 	appWinMeta_FillPathPs( ps, dc );
797 	}
798 
799     if  ( drawBorder )
800 	{
801 	appMetaSetColorPs( ps, dc, &(dc->dcPen.lpColor) );
802 	appMetaSetPenPs( dc, through, &(dc->dcPen) );
803 
804 	sioOutPrintf( ps->psSos, "%d 0 bp ", dr->drX1 );
805 	sioOutPrintf( ps->psSos, "%d 0 %d 0 360 arc stroke\n", xm, w/2 );
806 	}
807 
808     appWinMetaPopGraphics( &pg, dc, ps );
809 
810     return 0;
811     }
812 
appMetaDrawRoundedRectanglePs(DeviceContext * dc,void * through,const DocumentRectangle * dr,int wide,int high,int fillInside,int drawBorder)813 static int appMetaDrawRoundedRectanglePs(
814 				DeviceContext *			dc,
815 				void *				through,
816 				const DocumentRectangle *	dr,
817 				int				wide,
818 				int				high,
819 				int				fillInside,
820 				int				drawBorder )
821     {
822     PrintingState *		ps= (PrintingState *)through;
823     SimpleOutputStream *	sos= ps->psSos;
824 
825     DocumentRectangle		drHere;
826     PushedGraphics		pg;
827     int				r;
828 
829     geoNormalizeRectangle( &drHere, dr );
830 
831     if  ( high < 0 )
832 	{ high= -high;	}
833     if  ( wide < 0 )
834 	{ wide= -wide;	}
835 
836     r= sqrt( wide*wide+ high*high )/ 2;
837 
838     appWinMetaPushGraphicsForDraw( &pg, dc, ps, fillInside, drawBorder );
839 
840     if  ( fillInside )
841 	{
842 	psDrawRoundRectPath( sos, &drHere, r, "closepath\n" );
843 
844 	appWinMeta_FillPathPs( ps, dc );
845 	}
846 
847     if  ( drawBorder )
848 	{
849 	appMetaSetColorPs( ps, dc, &(dc->dcPen.lpColor) );
850 	appMetaSetPenPs( dc, through, &(dc->dcPen) );
851 
852 	psDrawRoundRectPath( sos, &drHere, r, "stroke\n" );
853 	}
854 
855     appWinMetaPopGraphics( &pg, dc, ps );
856 
857     return 0;
858     }
859 
appMetaIgnoreColorPs(DeviceContext * dc,void * through,int r,int g,int b)860 static int appMetaIgnoreColorPs(	DeviceContext *		dc,
861 					void *			through,
862 					int			r,
863 					int			g,
864 					int			b )
865     { return 0;	}
866 
appMetaSetPolyFillModePs(DeviceContext * dc,void * through,int mode)867 static int appMetaSetPolyFillModePs(	DeviceContext *		dc,
868 					void *			through,
869 					int			mode )
870     { return 0;	}
871 
872 /************************************************************************/
873 /*									*/
874 /*  Start a pattern fill.						*/
875 /*									*/
876 /************************************************************************/
877 
appMetaSelectPatternBrushObjectPs(DeviceContext * dc,void * through,PatternBrush * pb)878 static int appMetaSelectPatternBrushObjectPs(	DeviceContext *		dc,
879 						void *			through,
880 						PatternBrush *		pb )
881     {
882     PrintingState *		ps= (PrintingState *)through;
883     const RasterImage *	abi= pb->pbAbi;
884 
885     SimpleOutputStream *	sos= ps->psSos;
886 
887     int				bytesPerRow;
888 
889     const int			useFilters= 0;
890     const int			indexedImages= 0;
891     BitmapPrinter		bp;
892     const int			onWhite= 1;
893 
894     bytesPerRow= bmPsRowStringSize( &(abi->riDescription),
895 						abi->riDescription.bdPixelsWide,
896 						indexedImages );
897     if  ( bytesPerRow < 1 )
898 	{ LDEB(bytesPerRow); return -1;	}
899 
900     sioOutPrintf( sos, "currentfile %d string readhexstring\n",
901 				    abi->riDescription.bdPixelsHigh* bytesPerRow );
902 
903     bmPsOpenBitmapPrinter( &bp, sos, &(abi->riDescription),
904 						useFilters, indexedImages );
905 
906     {
907     DocumentRectangle	drSel;
908 
909     drSel.drX0= 0;
910     drSel.drY0= 0;
911     drSel.drX1= abi->riDescription.bdPixelsWide- 1;
912     drSel.drY1= abi->riDescription.bdPixelsHigh- 1;
913     if  ( bmPsWriteBitmapData( &bp, &drSel,
914 				    &(abi->riDescription), abi->riBytes ) )
915 	{ LDEB(1); return -1;	}
916     }
917 
918     bmCloseBitmapPrinter( &bp );
919 
920     sioOutPrintf( sos, "%%\n" );
921     sioOutPrintf( sos, "pop /fill-data exch store\n" );
922 
923     sioOutPrintf( sos, "/fill-wide %d store\n", abi->riDescription.bdPixelsWide );
924     sioOutPrintf( sos, "/fill-high %d store\n", abi->riDescription.bdPixelsHigh );
925 
926     sioOutPrintf( sos, "/fill-cell " );
927     sioOutPrintf( sos, "{ " );
928     sioOutPrintf( sos, "gsave " );
929     sioOutPrintf( sos, "%d %d scale\n" ,
930 			    abi->riDescription.bdPixelsWide,
931 			    abi->riDescription.bdPixelsHigh );
932 
933     sioOutPrintf( sos, "1 setgray 0 0 1 1 rectfill\n" );
934 
935     bmPsWriteImageInstructions( sos,
936 			    &(abi->riDescription), onWhite,
937 			    abi->riDescription.bdPixelsWide,
938 			    abi->riDescription.bdPixelsHigh,
939 			    "{ /fill-data load } bind",
940 			    indexedImages );
941 
942     sioOutPrintf( sos, "grestore " );
943     sioOutPrintf( sos, "} bind def\n" );
944 
945     dc->dcFillHatched= 0;
946     dc->dcFillPattern= 1;
947     dc->dcFillInsides= 1;
948 
949     return 0;
950     }
951 
appMetaStartPs(DeviceContext * dc,int objectCount,const MetafilePlayer * player,const DocumentRectangle * drLogical,int mapMode)952 static int appMetaStartPs(	DeviceContext *			dc,
953 				int				objectCount,
954 				const MetafilePlayer *		player,
955 				const DocumentRectangle *	drLogical,
956 				int				mapMode )
957     {
958     if  ( appMetaInitDeviceContext( dc, player, objectCount,
959 				    drLogical, mapMode,
960 				    player->mpTwipsWide, player->mpTwipsHigh,
961 				    player->mpTwipsWide, player->mpTwipsHigh ) )
962 	{ LDEB(objectCount); return -1;	}
963 
964     dc->dcCleanObject= appCleanObjectPs;
965     dc->dcDrawRasterImage= appDrawMetaBitmapImagePs;
966     dc->dcSelectPenObject= appMetaSelectPenObjectImpl;
967     dc->dcSelectBrushObject= appMetaSelectBrushObjectImpl;
968     dc->dcSelectFontObject= appMetaSelectFontObjectImpl;
969     dc->dcSelectPatternBrushObject= appMetaSelectPatternBrushObjectPs;
970     dc->dcDrawPolyPolygon= appMeta_PolyPolygonPs;
971     dc->dcDrawPolyBezier= appMeta_PolyBezierPs;
972     dc->dcDrawString= appMetaDrawStringPs;
973     dc->dcPatBlt= appMetaPatBltPs;
974     dc->dcDrawPie= appMetaDrawPiePs;
975     dc->dcDrawArc= appMetaDrawArcPs;
976     dc->dcDrawChord= appMetaDrawChordPs;
977     dc->dcDrawEllipse= appMetaDrawEllipsePs;
978     dc->dcDrawRoundedRectangle= appMetaDrawRoundedRectanglePs;
979     dc->dcSetTextColor= appMetaIgnoreColorPs;
980     dc->dcSetBkColor= appMetaIgnoreColorPs;
981     dc->dcSetPolyFillMode= appMetaSetPolyFillModePs;
982 
983     return 0;
984     }
985 
appMetaPlayWmfPs(PrintingState * ps,const MetafilePlayer * player)986 int appMetaPlayWmfPs(	PrintingState *			ps,
987 			const MetafilePlayer *		player )
988     {
989     int			rval= 0;
990 
991     WmfHeader		wh;
992     DeviceContext	dc;
993 
994     DocumentRectangle	drLogical;
995 
996     drLogical.drX0= 0;
997     drLogical.drY0= 0;
998     drLogical.drX1= player->mpXWinExt;
999     drLogical.drY1= player->mpYWinExt;
1000 
1001     utilRGB8SolidBlack( &(dc.dcColorSet) );
1002     psSetRgb8Color( ps, &(dc.dcColorSet) );
1003 
1004     if  ( sioInGetByte( player->mpInputStream ) == EOF )
1005 	{ return 0;	}
1006     sioInUngetLastRead( player->mpInputStream );
1007 
1008     if  ( bmMetaReadWmfHeader( &wh, player->mpInputStream ) )
1009 	{ LDEB(1); return -1;		}
1010 
1011     if  ( appMetaStartPs( &dc, wh.wh_objectCount, player, &drLogical,
1012 							player->mpMapMode ) )
1013 	{ LDEB(wh.wh_objectCount); return -1;	}
1014 
1015     WMFDEB(appDebug( "PS WMF LOGICAL: [%d x %d] TWIPS: [%d x %d]\n",
1016 				player->mpXWinExt, player->mpYWinExt,
1017 				player->mpTwipsWide, player->mpTwipsHigh ));
1018 
1019     if  ( appMetaPlayWmf( &dc, (void *)ps ) )
1020 	{ rval= -1;	}
1021 
1022     appMetaCleanDeviceContext( &dc, (void *)ps );
1023 
1024     return rval;
1025     }
1026 
appMetaPlayEmfPs(PrintingState * ps,const MetafilePlayer * player)1027 int appMetaPlayEmfPs(	PrintingState *			ps,
1028 			const MetafilePlayer *		player )
1029     {
1030     int			rval= 0;
1031 
1032     int			done;
1033     EmfHeader		eh;
1034     DeviceContext	dc;
1035 
1036     done= bmMetaReadEmfHeader( &eh, player->mpInputStream );
1037     if  ( done < 0 )
1038 	{ LDEB(done); return -1;		}
1039     while( done < eh.eh_headerSize )
1040 	{ (void)sioInGetByte( player->mpInputStream ); done++; }
1041 
1042     if  ( appMetaStartPs( &dc, eh.eh_numOfHandles, player, &(eh.ehBounds),
1043 							    MM_ANISOTROPIC ) )
1044 	{ LDEB(eh.eh_numOfHandles); return -1;	}
1045 
1046     WMFDEB(appDebug( "PS EMF LOGICAL: [%d..%d x %d..%d] TWIPS: [%d x %d]\n",
1047 				    eh.ehBounds.drX0, eh.ehBounds.drX1,
1048 				    eh.ehBounds.drY0, eh.ehBounds.drY1,
1049 				    player->mpTwipsWide, player->mpTwipsHigh ));
1050 
1051     if  ( appMetaPlayEmf( &dc, (void *)ps ) )
1052 	{ rval= -1;	}
1053 
1054     appMetaCleanDeviceContext( &dc, (void *)ps );
1055 
1056     return rval;
1057     }
1058 
appMacPictPlayFilePs(PrintingState * ps,const MetafilePlayer * player)1059 int appMacPictPlayFilePs(	PrintingState *			ps,
1060 				const MetafilePlayer *		player )
1061     {
1062     MacPictHeader	mph;
1063     int			rval= 0;
1064 
1065     int			done;
1066     DeviceContext	dc;
1067     const int		handleCount= MACPICThandle_COUNT;
1068 
1069     done= appMacPictGetDeviceHeader( &mph,  player->mpInputStream );
1070     if  ( done < 0 )
1071 	{ LDEB(done); return -1;		}
1072 
1073     if  ( appMetaStartPs( &dc, handleCount, player,
1074 					&(mph.mphFrame), MM_ANISOTROPIC ) )
1075 	{ LDEB(handleCount); return -1;	}
1076 
1077     dc.dcMacPictVersion= mph.mphVersion;
1078 
1079     WMFDEB(appDebug( "PS PICT LOGICAL: [%d..%d x %d..%d] TWIPS: [%d x %d]\n",
1080 				mph.mphFrame.drX0, mph.mphFrame.drX1,
1081 				mph.mphFrame.drY0, mph.mphFrame.drY1,
1082 				player->mpTwipsWide, player->mpTwipsHigh ));
1083 
1084     if  ( appMacPictPlayPict( &dc, (void *)ps ) )
1085 	{ rval= -1;	}
1086 
1087     appMetaCleanDeviceContext( &dc, (void *)ps );
1088 
1089     return rval;
1090     }
1091