1 # include "drawMetaConfig.h"
2
3 # include <stddef.h>
4 # include <string.h>
5
6 # include "drawMetafileImpl.h"
7 # include "drawMetafileSvg.h"
8 # include "drawWinMetaImpl.h"
9 # include <psFontMetrics.h>
10 # include <utilMatchFont.h>
11 # include <utilDocFont.h>
12 # include <bmWmfIo.h>
13 # include <bmEmfIo.h>
14 # include "drawMacPictImpl.h"
15 # include "drawImageSvg.h"
16 # include <psShading.h>
17
18 # include <appDebugon.h>
19
20 # if 0
21 # define WMFDEB(x) (x)
22 # else
23 # define WMFDEB(x) /*nothing*/
24 # endif
25
26 # if 0
27 # define WMFLOG(x) (x)
28 # else
29 # define WMFLOG(x) /*nothing*/
30 # endif
31
32 /************************************************************************/
33 /* */
34 /* Find out whether we must use a hash. */
35 /* */
36 /************************************************************************/
37
appMetaSelectBrushObjectSvg(DeviceContext * dc,void * through,LogicalBrush * lb)38 static int appMetaSelectBrushObjectSvg( DeviceContext * dc,
39 void * through,
40 LogicalBrush * lb )
41 {
42 SvgWriter * sw= (SvgWriter *)through;
43
44 WMFDEB(appDebug( "SelectObject() " ));
45 WMFDEB(appDebug( "BRUSH\n" ));
46
47 appMetaSelectBrushObjectImpl( dc, through, lb );
48
49 if ( dc->dcFillHatched && lb->lbTileNumber < 0 )
50 {
51 lb->lbTileNumber= sw->swPatternCount++;
52
53 switch( lb->lbHatch )
54 {
55 case HS_HORIZONTAL:
56 svgDefineShading( sw, lb->lbTileNumber, PSshdHORIZ,
57 &(lb->lbColor) );
58 break;
59 case HS_VERTICAL:
60 svgDefineShading( sw, lb->lbTileNumber, PSshdVERT,
61 &(lb->lbColor) );
62 break;
63 case HS_FDIAGONAL:
64 svgDefineShading( sw, lb->lbTileNumber, PSshdFDIAG,
65 &(lb->lbColor) );
66 break;
67 case HS_BDIAGONAL:
68 svgDefineShading( sw, lb->lbTileNumber, PSshdBDIAG,
69 &(lb->lbColor) );
70 break;
71 case HS_CROSS:
72 svgDefineShading( sw, lb->lbTileNumber, PSshdCROSS,
73 &(lb->lbColor) );
74 break;
75 case HS_DIAGCROSS:
76 svgDefineShading( sw, lb->lbTileNumber, PSshdDCROSS,
77 &(lb->lbColor) );
78 break;
79 default:
80 LDEB(dc->dcBrush.lbHatch);
81 }
82 }
83
84 return 0;
85 }
86
87 /************************************************************************/
88 /* */
89 /* Play a windows metafile to SVG. */
90 /* */
91 /************************************************************************/
92
appMetaSvgEmitFill(XmlWriter * xw,int fillInsides,const DeviceContext * dc)93 static int appMetaSvgEmitFill( XmlWriter * xw,
94 int fillInsides,
95 const DeviceContext * dc )
96 {
97 if ( ! fillInsides )
98 {
99 xmlWriteStringAttribute( xw, "fill", "none" );
100 return 0;
101 }
102
103 if ( dc->dcFillPattern )
104 {
105 char url[20];
106 const MetaFileObject * mfo;
107 const PatternBrush * pb;
108
109 mfo= &(dc->dcObjects[dc->dcCurrentBrushObject]);
110 pb= &(mfo->mfoPatternBrush);
111
112 sprintf( url, "url(#pat%d)", pb->pbTileNumber );
113 xmlWriteStringAttribute( xw, "fill", url );
114 return 0;
115 }
116
117 if ( dc->dcFillHatched )
118 {
119 char url[20];
120 const MetaFileObject * mfo;
121 const LogicalBrush * lb;
122
123 mfo= &(dc->dcObjects[dc->dcCurrentBrushObject]);
124 lb= &(mfo->mfoLogicalBrush);
125
126 sprintf( url, "url(#pat%d)", lb->lbTileNumber );
127 xmlWriteStringAttribute( xw, "fill", url );
128 return 0;
129 }
130
131 xmlWriteRgb8Attribute( xw, "fill", &(dc->dcBrush.lbColor) );
132 return 0;
133 }
134
appMetaSvgEmitStroke(XmlWriter * xw,int drawBorders,DeviceContext * dc)135 static int appMetaSvgEmitStroke(XmlWriter * xw,
136 int drawBorders,
137 DeviceContext * dc )
138 {
139 int widthTwips;
140 unsigned char dots[6];
141 int dotCount;
142
143 if ( ! drawBorders )
144 { return 0; }
145
146 widthTwips= appMetaGetPenWidth( dc, &(dc->dcPen) );
147
148 xmlWriteRgb8Attribute( xw, "stroke", &(dc->dcPen.lpColor) );
149 xmlWriteIntAttribute( xw, "stroke-width", widthTwips );
150
151 dotCount= appMetaGetPenDots( dc, dots, &(dc->dcPen) );
152 if ( dotCount > 0 )
153 {
154 char dasharray[100];
155 char * to= dasharray;
156 int i;
157 const char * before= "";
158
159 for ( i= 0; i < dotCount; i++ )
160 {
161 sprintf( to, "%s%d", before, dots[i] );
162 to += strlen( to );
163 before= ",";
164 }
165
166 xmlWriteStringAttribute( xw, "stroke-dasharray", dasharray );
167 }
168
169 return 0;
170 }
171
172 /************************************************************************/
173 /* */
174 /* Insert a bitmap image in the SVG output for a metafile. */
175 /* */
176 /************************************************************************/
177
appDrawMetaBitmapImageSvg(DeviceContext * dc,void * through,const RasterImage * abiSrc,const DocumentRectangle * drSrc,const DocumentRectangle * drDest)178 static int appDrawMetaBitmapImageSvg(
179 DeviceContext * dc,
180 void * through,
181 const RasterImage * abiSrc,
182 const DocumentRectangle * drSrc,
183 const DocumentRectangle * drDest )
184 {
185 SvgWriter * sw= (SvgWriter *)through;
186
187 return drawRasterImageSvg( sw, abiSrc, drSrc, drDest );
188 }
189
appCleanObjectSvg(DeviceContext * dc,void * through,MetaFileObject * mfo)190 static int appCleanObjectSvg( DeviceContext * dc,
191 void * through,
192 MetaFileObject * mfo )
193 { return 0; }
194
appMeta_PolyPolygonSvg(DeviceContext * dc,void * through,int polyCount,const int * pointCounts,const Point2DI * points,int fillInsides,int drawBorders,int closePath)195 static int appMeta_PolyPolygonSvg( DeviceContext * dc,
196 void * through,
197 int polyCount,
198 const int * pointCounts,
199 const Point2DI * points,
200 int fillInsides,
201 int drawBorders,
202 int closePath )
203 {
204 SvgWriter * sw= (SvgWriter *)through;
205 XmlWriter * xw= &(sw->swXmlWriter);
206
207 int poly;
208 const char * sep= "";
209
210 xmlPutString( "<path d=\"", xw );
211
212 for ( poly= 0; poly < polyCount; poly++ )
213 {
214 int x0= 0;
215 int y0= 0;
216 const char * command= "M";
217
218 int point;
219
220 for ( point= 0; point < pointCounts[poly]; point++ )
221 {
222 sioOutPrintf( xw->xwSos, "%s%s %d,%d", sep,
223 command, points->x- x0, points->y- y0 );
224
225 sep= "\n\t";
226 command= "l";
227 x0= points->x;
228 y0= points->y;
229 points++;
230 }
231
232 if ( closePath )
233 { xmlPutString( "Z", xw ); }
234 }
235
236 xmlPutString( "\"", xw );
237 xmlNewLine( xw );
238
239 appMetaSvgEmitStroke( xw, drawBorders, dc );
240 appMetaSvgEmitFill( xw, fillInsides, dc );
241
242 xmlPutString( "/>", xw );
243 xmlNewLine( xw );
244
245 return 0;
246 }
247
appMeta_PolyBezierSvg(DeviceContext * dc,void * through,int count,const Point2DI * points,int startPath,int fillInsides,int drawBorders,int closePath)248 static int appMeta_PolyBezierSvg( DeviceContext * dc,
249 void * through,
250 int count,
251 const Point2DI * points,
252 int startPath,
253 int fillInsides,
254 int drawBorders,
255 int closePath )
256 {
257 return 0;
258 }
259
appMetaDrawStringSvg(DeviceContext * dc,void * through,int x0,int y0,const MemoryBuffer * text)260 static int appMetaDrawStringSvg( DeviceContext * dc,
261 void * through,
262 int x0,
263 int y0,
264 const MemoryBuffer * text )
265 {
266 SvgWriter * sw= (SvgWriter *)through;
267 XmlWriter * xw= &(sw->swXmlWriter);
268
269 const AfmFontInfo * afi= dc->dcAfi;
270 LogicalFont * lf= &(dc->dcFont);
271
272 int wide;
273 DocumentRectangle drText;
274 const int withKerning= 0;
275 const int vswap= 1;
276 int fontSizeTwipsGeo;
277 int fontSizeTwipsText;
278
279 const char * s= utilMemoryBufferGetString( text );
280 int len= text->mbSize;
281
282 char transform[100];
283
284 if ( ! afi )
285 { XDEB(afi); return -1; }
286
287 fontSizeTwipsGeo= appWinMetaOutputSize( dc, lf->lfHeight );
288 fontSizeTwipsText= appWinMetaOutputSize( dc, ( 85* lf->lfHeight ) / 100 );
289
290 wide= psCalculateStringExtents( &drText, s, len,
291 fontSizeTwipsGeo, withKerning, vswap, afi );
292 drText.drX0 += x0;
293 drText.drX1 += x0;
294 drText.drY0 += y0;
295 drText.drY1 += y0;
296
297 switch( dc->dcTextAlignment & 0x01 )
298 {
299 case TA_NOUPDATECP:
300 break;
301
302 case TA_UPDATECP:
303 x0= DC_xViewport( dc->dcX, dc->dcY, dc );
304 y0= DC_yViewport( dc->dcX, dc->dcY, dc );
305 break;
306
307 default:
308 XDEB(dc->dcTextAlignment & 0x01 );
309 break;
310 }
311
312 switch( dc->dcTextAlignment & 0x06 )
313 {
314 int xshift;
315
316 case TA_LEFT:
317 break;
318
319 case TA_RIGHT:
320 xshift= -wide;
321 drText.drX0 += xshift;
322 drText.drX1 += xshift;
323 break;
324
325 case TA_CENTER:
326 xshift= -wide/ 2;
327 drText.drX0 += xshift;
328 drText.drX1 += xshift;
329 break;
330
331 default:
332 XDEB(dc->dcTextAlignment & 0x06);
333 break;
334 }
335
336 switch( dc->dcTextAlignment & 0x18 )
337 {
338 int yshift;
339 DocumentRectangle drFontBBox;
340 DocumentRectangle drFontAscDesc;
341
342 case TA_TOP:
343 psFontBBox( &drFontBBox, &drFontAscDesc, fontSizeTwipsGeo,
344 vswap, afi );
345 yshift= -drFontAscDesc.drY0;
346 y0 += yshift;
347 drText.drY0 += yshift;
348 drText.drY1 += yshift;
349 break;
350
351 case TA_BOTTOM:
352 psFontBBox( &drFontBBox, &drFontAscDesc, fontSizeTwipsGeo,
353 vswap, afi );
354 yshift= -drFontAscDesc.drY1;
355 y0 += yshift;
356 drText.drY0 += yshift;
357 drText.drY1 += yshift;
358 break;
359
360 case TA_BASELINE:
361 break;
362
363 default:
364 WMFDEB(appDebug(" 0x%x", dc->dcTextAlignment & 0x18 ));
365 break;
366 }
367
368 if ( dc->dcFont.lfOrientation != 0 )
369 {
370 sprintf( transform, "translate(%d,%d)", x0, y0 );
371
372 xmlPutString( "<g ", xw );
373 xmlWriteStringAttribute( xw, "transform", transform );
374 xmlPutString( ">", xw );
375
376 drText.drX0 -= x0;
377 drText.drX1 -= x0;
378 drText.drY0 -= y0;
379 drText.drY1 -= y0;
380
381 x0= y0= 0;
382
383 sprintf( transform, "rotate(%g)", -0.1* dc->dcFont.lfOrientation );
384 }
385
386 if ( dc->dcBkMode == OPAQUE )
387 {
388 xmlPutString( "<rect ", xw );
389
390 if ( dc->dcFont.lfOrientation != 0 )
391 { xmlWriteStringAttribute( xw, "transform", transform ); }
392 svgWriteRectangleAttributes( sw, &drText );
393
394 xmlWriteRgb8Attribute( xw, "fill", &(dc->dcBkColor) );
395
396 xmlPutString( "/>", xw );
397 xmlNewLine( xw );
398 }
399
400 xmlPutString( "<text ", xw );
401
402 xmlWriteStringAttribute( xw, "font-family", dc->dcFont.lfFaceNameUtf8 );
403 xmlWriteIntAttribute( xw, "font-size", fontSizeTwipsText );
404 xmlWriteRgb8Attribute( xw, "fill", &(dc->dcTextColor) );
405
406 if ( dc->dcFont.lfTextAttribute.taFontIsSlanted )
407 { xmlWriteStringAttribute( xw, "font-style", "italic" ); }
408 if ( dc->dcFont.lfTextAttribute.taFontIsBold )
409 { xmlWriteStringAttribute( xw, "font-weight", "bold" ); }
410 if ( dc->dcFont.lfTextAttribute.taTextIsUnderlined )
411 {
412 /* Does not work with Firefox */
413 xmlWriteRgb8Attribute( xw, "stroke", &(dc->dcTextColor) );
414 xmlWriteStringAttribute( xw, "text-decoration", "underline" );
415 }
416
417 if ( dc->dcFont.lfOrientation != 0 )
418 { xmlWriteStringAttribute( xw, "transform", transform ); }
419 if ( x0 != 0 )
420 { xmlWriteIntAttribute( xw, "x", x0 ); }
421 if ( y0 != 0 )
422 { xmlWriteIntAttribute( xw, "y", y0 ); }
423
424 switch( dc->dcTextAlignment & 0x06 )
425 {
426 case TA_LEFT:
427 /* xmlWriteStringAttribute( xw, "text-anchor", "start" ); */
428 break;
429 case TA_RIGHT:
430 xmlWriteStringAttribute( xw, "text-anchor", "end" );
431 break;
432 case TA_CENTER:
433 xmlWriteStringAttribute( xw, "text-anchor", "middle" );
434 break;
435 default:
436 XDEB(dc->dcTextAlignment & 0x06);
437 break;
438 }
439
440 xmlPutString( ">", xw );
441 xmlNewLine( xw );
442
443 xmlEscapeCharacters( xw, s, len );
444
445 xmlPutString( "</text>", xw );
446 xmlNewLine( xw );
447
448 if ( dc->dcFont.lfOrientation != 0 )
449 {
450 xmlPutString( "</g>", xw );
451 xmlNewLine( xw );
452 }
453
454 return 0;
455 }
456
appMetaPatBltSvg(DeviceContext * dc,void * through,long rop,const DocumentRectangle * drOutput)457 static int appMetaPatBltSvg( DeviceContext * dc,
458 void * through,
459 long rop,
460 const DocumentRectangle * drOutput )
461 {
462 SvgWriter * sw= (SvgWriter *)through;
463 XmlWriter * xw= &(sw->swXmlWriter);
464
465 if ( dc->dcFillInsides )
466 {
467 DocumentRectangle drNorm;
468
469 geoNormalizeRectangle( &drNorm, drOutput );
470
471 xmlPutString( "<rect ", xw );
472
473 svgWriteRectangleAttributes( sw, &drNorm );
474 appMetaSvgEmitFill( xw, dc->dcFillInsides, dc );
475
476 xmlPutString( "/>", xw );
477 xmlNewLine( xw );
478 }
479
480 return 0;
481 }
482
appMetaDrawArcSvg(DeviceContext * dc,void * through,const DocumentRectangle * dr,int xs,int ys,int xe,int ye,int fillInside,int drawBorder)483 static int appMetaDrawArcSvg( DeviceContext * dc,
484 void * through,
485 const DocumentRectangle * dr,
486 int xs,
487 int ys,
488 int xe,
489 int ye,
490 int fillInside,
491 int drawBorder )
492 {
493 SvgWriter * sw= (SvgWriter *)through;
494 XmlWriter * xw= &(sw->swXmlWriter);
495
496 int rx= ( dr->drX1- dr->drX0+ 1 )/ 2;
497 int ry= ( dr->drY1- dr->drY0+ 1 )/ 2;
498
499 const int xAxisRotation= 0;
500 const int largeArcFlag= 0;
501 const int sweepFlag= 0;
502
503 xmlPutString( "<path d=\"", xw );
504
505 sioOutPrintf( xw->xwSos, "M %d,%d A %d,%d "
506 "%d %d %d "
507 "%d,%d",
508 xs, ys, rx, ry,
509 xAxisRotation, largeArcFlag, sweepFlag,
510 xe, ye );
511
512 xmlPutString( "\"", xw );
513 xmlNewLine( xw );
514
515 appMetaSvgEmitStroke( xw, drawBorder, dc );
516 appMetaSvgEmitFill( xw, fillInside, dc );
517
518 xmlPutString( "/>", xw );
519 xmlNewLine( xw );
520
521 return 0;
522 }
523
appMetaDrawPieSvg(DeviceContext * dc,void * through,const DocumentRectangle * dr,int xs,int ys,int xe,int ye,int fillInside,int drawBorder)524 static int appMetaDrawPieSvg( DeviceContext * dc,
525 void * through,
526 const DocumentRectangle * dr,
527 int xs,
528 int ys,
529 int xe,
530 int ye,
531 int fillInside,
532 int drawBorder )
533 {
534 SvgWriter * sw= (SvgWriter *)through;
535 XmlWriter * xw= &(sw->swXmlWriter);
536
537 int cx= ( dr->drX1+ dr->drX0+ 1 )/ 2;
538 int cy= ( dr->drY1+ dr->drY0+ 1 )/ 2;
539 int rx= ( dr->drX1- dr->drX0+ 1 )/ 2;
540 int ry= ( dr->drY1- dr->drY0+ 1 )/ 2;
541
542 const int xAxisRotation= 0;
543 const int largeArcFlag= 0;
544 const int sweepFlag= 0;
545
546 xmlPutString( "<path d=\"", xw );
547
548 sioOutPrintf( xw->xwSos, "M %d,%d A %d,%d "
549 "%d %d %d "
550 "%d,%d "
551 "l %d,%d "
552 "l %d,%d",
553 xs, ys, rx, ry,
554 xAxisRotation, largeArcFlag, sweepFlag,
555 xe, ye,
556 cx- xe, cy- ye,
557 xs- cx, ys- ys );
558
559 xmlPutString( "\"", xw );
560 xmlNewLine( xw );
561
562 appMetaSvgEmitStroke( xw, drawBorder, dc );
563 appMetaSvgEmitFill( xw, fillInside, dc );
564
565 xmlPutString( "/>", xw );
566 xmlNewLine( xw );
567
568 return 0;
569 }
570
appMetaDrawChordSvg(DeviceContext * dc,void * through,const DocumentRectangle * dr,int xs,int ys,int xe,int ye,int fillInside,int drawBorder)571 static int appMetaDrawChordSvg( DeviceContext * dc,
572 void * through,
573 const DocumentRectangle * dr,
574 int xs,
575 int ys,
576 int xe,
577 int ye,
578 int fillInside,
579 int drawBorder )
580 {
581 SvgWriter * sw= (SvgWriter *)through;
582 XmlWriter * xw= &(sw->swXmlWriter);
583
584 int rx= ( dr->drX1- dr->drX0+ 1 )/ 2;
585 int ry= ( dr->drY1- dr->drY0+ 1 )/ 2;
586
587 const int xAxisRotation= 0;
588 const int largeArcFlag= 0;
589 const int sweepFlag= 0;
590
591 xmlPutString( "<path d=\"", xw );
592
593 sioOutPrintf( xw->xwSos, "M %d,%d A %d,%d "
594 "%d %d %d "
595 "%d,%d "
596 "l %d,%d",
597 xs, ys, rx, ry,
598 xAxisRotation, largeArcFlag, sweepFlag,
599 xe, ye,
600 xs- xe, ys- ye );
601
602 xmlPutString( "\"", xw );
603 xmlNewLine( xw );
604
605 appMetaSvgEmitStroke( xw, drawBorder, dc );
606 appMetaSvgEmitFill( xw, fillInside, dc );
607
608 xmlPutString( "/>", xw );
609 xmlNewLine( xw );
610
611 return 0;
612 }
613
appMetaDrawEllipseSvg(DeviceContext * dc,void * through,const DocumentRectangle * dr,int fillInside,int drawBorder)614 static int appMetaDrawEllipseSvg(DeviceContext * dc,
615 void * through,
616 const DocumentRectangle * dr,
617 int fillInside,
618 int drawBorder )
619 {
620 SvgWriter * sw= (SvgWriter *)through;
621 XmlWriter * xw= &(sw->swXmlWriter);
622
623 xmlPutString( "<ellipse ", xw );
624
625 xmlWriteIntAttribute( xw, "cx", ( dr->drX0+ dr->drX1 )/ 2 );
626 xmlWriteIntAttribute( xw, "cy", ( dr->drY0+ dr->drY1 )/ 2 );
627 xmlWriteIntAttribute( xw, "rx", ( dr->drX1- dr->drX0+ 1 )/ 2 );
628 xmlWriteIntAttribute( xw, "ry", ( dr->drY1- dr->drY0+ 1 )/ 2 );
629
630 appMetaSvgEmitStroke( xw, drawBorder, dc );
631 appMetaSvgEmitFill( xw, fillInside, dc );
632
633 xmlPutString( "/>", xw );
634 xmlNewLine( xw );
635 return 0;
636 }
637
appMetaDrawRoundedRectangleSvg(DeviceContext * dc,void * through,const DocumentRectangle * dr,int wide,int high,int fillInside,int drawBorder)638 static int appMetaDrawRoundedRectangleSvg(
639 DeviceContext * dc,
640 void * through,
641 const DocumentRectangle * dr,
642 int wide,
643 int high,
644 int fillInside,
645 int drawBorder )
646 {
647 SvgWriter * sw= (SvgWriter *)through;
648 XmlWriter * xw= &(sw->swXmlWriter);
649
650 xmlPutString( "<rect ", xw );
651
652 svgWriteRectangleAttributes( sw, dr );
653 xmlWriteIntAttribute( xw, "rx", wide );
654 xmlWriteIntAttribute( xw, "ry", high );
655
656 appMetaSvgEmitStroke( xw, drawBorder, dc );
657 appMetaSvgEmitFill( xw, fillInside, dc );
658
659 xmlPutString( "/>", xw );
660 xmlNewLine( xw );
661 return 0;
662 }
663
appMetaIgnoreColorSvg(DeviceContext * dc,void * through,int r,int g,int b)664 static int appMetaIgnoreColorSvg( DeviceContext * dc,
665 void * through,
666 int r,
667 int g,
668 int b )
669 { return 0; }
670
appMetaSetPolyFillModeSvg(DeviceContext * dc,void * through,int mode)671 static int appMetaSetPolyFillModeSvg( DeviceContext * dc,
672 void * through,
673 int mode )
674 { return 0; }
675
676 /************************************************************************/
677 /* */
678 /* Start a pattern fill. */
679 /* */
680 /************************************************************************/
681
appMetaSelectPatternBrushObjectSvg(DeviceContext * dc,void * through,PatternBrush * pb)682 static int appMetaSelectPatternBrushObjectSvg( DeviceContext * dc,
683 void * through,
684 PatternBrush * pb )
685 {
686 SvgWriter * sw= (SvgWriter *)through;
687 XmlWriter * xw= &(sw->swXmlWriter);
688 char id[20];
689 char viewBox[20];
690
691 if ( pb->pbTileNumber < 0 )
692 {
693 const RasterImage * abi= pb->pbAbi;
694 DocumentRectangle drSrc;
695 DocumentRectangle drDest;
696
697 drSrc.drX0= 0;
698 drSrc.drY0= 0;
699 drSrc.drX1= abi->riDescription.bdPixelsWide- 1;
700 drSrc.drY1= abi->riDescription.bdPixelsHigh- 1;
701
702 drDest.drX0= 0;
703 drDest.drY0= 0;
704 drDest.drX1= 20* abi->riDescription.bdPixelsWide- 1;
705 drDest.drY1= 20* abi->riDescription.bdPixelsHigh- 1;
706
707 pb->pbTileNumber= sw->swPatternCount++;
708
709 sprintf( id, "pat%d", pb->pbTileNumber );
710 sprintf( viewBox, "0 0 %d %d",
711 drSrc.drX1- drSrc.drX0+ 1,
712 drSrc.drX1- drSrc.drX0+ 1 );
713
714 xmlPutString( "<pattern ", xw );
715 xmlWriteStringAttribute( xw, "id", id );
716 xmlWriteStringAttribute( xw, "patternUnits", "userSpaceOnUse" );
717 xmlWriteIntAttribute( xw, "width", drDest.drX1- drDest.drX0+ 1 );
718 xmlWriteIntAttribute( xw, "height", drDest.drY1- drDest.drY0+ 1 );
719 xmlWriteStringAttribute( xw, "viewBox", viewBox );
720 xmlPutString( ">", xw );
721 xmlNewLine( xw );
722
723 if ( appDrawMetaBitmapImageSvg( dc, through, abi, &drSrc, &drSrc ) )
724 { LDEB(1); }
725
726 xmlPutString( "</pattern>", xw );
727 xmlNewLine( xw );
728 }
729
730 dc->dcFillHatched= 0;
731 dc->dcFillPattern= 1;
732 dc->dcFillInsides= 1;
733
734 return 0;
735 }
736
appMetaStartSvg(DeviceContext * dc,int objectCount,const MetafilePlayer * player,const DocumentRectangle * drLogical,int mapMode)737 static int appMetaStartSvg( DeviceContext * dc,
738 int objectCount,
739 const MetafilePlayer * player,
740 const DocumentRectangle * drLogical,
741 int mapMode )
742 {
743 if ( appMetaInitDeviceContext( dc, player, objectCount,
744 drLogical, mapMode,
745 player->mpTwipsWide, player->mpTwipsHigh,
746 player->mpTwipsWide, player->mpTwipsHigh ) )
747 { LDEB(objectCount); return -1; }
748
749 dc->dcCleanObject= appCleanObjectSvg;
750 dc->dcDrawRasterImage= appDrawMetaBitmapImageSvg;
751 dc->dcSelectPenObject= appMetaSelectPenObjectImpl;
752 dc->dcSelectBrushObject= appMetaSelectBrushObjectSvg;
753 dc->dcSelectFontObject= appMetaSelectFontObjectImpl;
754 dc->dcSelectPatternBrushObject= appMetaSelectPatternBrushObjectSvg;
755 dc->dcDrawPolyPolygon= appMeta_PolyPolygonSvg;
756 dc->dcDrawPolyBezier= appMeta_PolyBezierSvg;
757 dc->dcDrawString= appMetaDrawStringSvg;
758 dc->dcPatBlt= appMetaPatBltSvg;
759 dc->dcDrawPie= appMetaDrawPieSvg;
760 dc->dcDrawArc= appMetaDrawArcSvg;
761 dc->dcDrawChord= appMetaDrawChordSvg;
762 dc->dcDrawEllipse= appMetaDrawEllipseSvg;
763 dc->dcDrawRoundedRectangle= appMetaDrawRoundedRectangleSvg;
764 dc->dcSetTextColor= appMetaIgnoreColorSvg;
765 dc->dcSetBkColor= appMetaIgnoreColorSvg;
766 dc->dcSetPolyFillMode= appMetaSetPolyFillModeSvg;
767
768 return 0;
769 }
770
appMetaPlayWmfSvg(SvgWriter * sw,const MetafilePlayer * player)771 int appMetaPlayWmfSvg( SvgWriter * sw,
772 const MetafilePlayer * player )
773 {
774 int rval= 0;
775
776 WmfHeader wh;
777 DeviceContext dc;
778
779 DocumentRectangle drLogical;
780
781 drLogical.drX0= 0;
782 drLogical.drY0= 0;
783 drLogical.drX1= player->mpXWinExt;
784 drLogical.drY1= player->mpYWinExt;
785
786 utilRGB8SolidBlack( &(dc.dcColorSet) );
787
788 if ( sioInGetByte( player->mpInputStream ) == EOF )
789 { return 0; }
790 sioInUngetLastRead( player->mpInputStream );
791
792 if ( bmMetaReadWmfHeader( &wh, player->mpInputStream ) )
793 { LDEB(1); return -1; }
794
795 if ( appMetaStartSvg( &dc, wh.wh_objectCount, player, &drLogical,
796 player->mpMapMode ) )
797 { LDEB(wh.wh_objectCount); return -1; }
798
799 WMFDEB(appDebug( "SVG WMF LOGICAL: [%d x %d] TWIPS: [%d x %d]\n",
800 player->mpXWinExt, player->mpYWinExt,
801 player->mpTwipsWide, player->mpTwipsHigh ));
802
803 if ( appMetaPlayWmf( &dc, (void *)sw ) )
804 { rval= -1; goto ready; }
805
806 ready:
807
808 appMetaCleanDeviceContext( &dc, (void *)sw );
809
810 return rval;
811 }
812
appMetaPlayEmfSvg(SvgWriter * sw,const MetafilePlayer * player)813 int appMetaPlayEmfSvg( SvgWriter * sw,
814 const MetafilePlayer * player )
815 {
816 int rval= 0;
817
818 int done;
819 EmfHeader eh;
820 DeviceContext dc;
821
822 done= bmMetaReadEmfHeader( &eh, player->mpInputStream );
823 if ( done < 0 )
824 { LDEB(done); return -1; }
825 while( done < eh.eh_headerSize )
826 { (void)sioInGetByte( player->mpInputStream ); done++; }
827
828 if ( appMetaStartSvg( &dc, eh.eh_numOfHandles, player, &(eh.ehBounds),
829 MM_ANISOTROPIC ) )
830 { LDEB(eh.eh_numOfHandles); return -1; }
831
832 WMFDEB(appDebug( "SVG EMF LOGICAL: [%d..%d x %d..%d] TWIPS: [%d x %d]\n",
833 eh.ehBounds.drX0, eh.ehBounds.drX1,
834 eh.ehBounds.drY0, eh.ehBounds.drY1,
835 player->mpTwipsWide, player->mpTwipsHigh ));
836
837 if ( appMetaPlayEmf( &dc, (void *)sw ) )
838 { rval= -1; goto ready; }
839
840 ready:
841
842 appMetaCleanDeviceContext( &dc, (void *)sw );
843
844 return rval;
845 }
846
appMacPictPlayFileSvg(SvgWriter * sw,const MetafilePlayer * player)847 int appMacPictPlayFileSvg( SvgWriter * sw,
848 const MetafilePlayer * player )
849 {
850 MacPictHeader mph;
851 int rval= 0;
852
853 int done;
854 DeviceContext dc;
855 const int handleCount= MACPICThandle_COUNT;
856
857 done= appMacPictGetDeviceHeader( &mph, player->mpInputStream );
858 if ( done < 0 )
859 { LDEB(done); return -1; }
860
861 if ( appMetaStartSvg( &dc, handleCount, player,
862 &(mph.mphFrame), MM_ANISOTROPIC ) )
863 { LDEB(handleCount); return -1; }
864
865 dc.dcMacPictVersion= mph.mphVersion;
866
867 WMFDEB(appDebug( "SVG PICT LOGICAL: [%d..%d x %d..%d] TWIPS: [%d x %d]\n",
868 mph.mphFrame.drX0, mph.mphFrame.drX1,
869 mph.mphFrame.drY0, mph.mphFrame.drY1,
870 player->mpTwipsWide, player->mpTwipsHigh ));
871
872 if ( appMacPictPlayPict( &dc, (void *)sw ) )
873 { rval= -1; goto ready; }
874
875 ready:
876
877 appMetaCleanDeviceContext( &dc, (void *)sw );
878
879 return rval;
880 }
881