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