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