1 /************************************************************************/
2 /*									*/
3 /*  Draw Scalable Vector Graphics.					*/
4 /*									*/
5 /************************************************************************/
6 
7 #   include	"docHtmlConfig.h"
8 
9 #   include	<stddef.h>
10 #   include	<stdio.h>
11 #   include	<string.h>
12 
13 #   include	<docDraw.h>
14 #   include	<docShape.h>
15 #   include	<docLayout.h>
16 #   include	"docSvgDrawImpl.h"
17 #   include	"docWriteCss.h"
18 #   include	"docSvgDraw.h"
19 #   include	<psShading.h>
20 #   include	<docTreeNode.h>
21 
22 #   include	<appDebugon.h>
23 
24 /************************************************************************/
25 /*									*/
26 /*  Cause subsequent drawing to be done in a certain color.		*/
27 /*									*/
28 /*  NOTE that background drawing with color= 0 is against the RTF idea	*/
29 /*	of the default background color: transparent.			*/
30 /*									*/
31 /************************************************************************/
32 
docSvgSetColorRgb(DrawingContext * dc,void * vsw,const RGB8Color * rgb8)33 static int docSvgSetColorRgb(	DrawingContext *	dc,
34 				void *			vsw,
35 				const RGB8Color *	rgb8 )
36     {
37     return 0;
38     }
39 
docSvgSetFont(DrawingContext * dc,void * vsw,int textAttrNumber,const TextAttribute * ta)40 static int docSvgSetFont(	DrawingContext *	dc,
41 				void *			vsw,
42 				int			textAttrNumber,
43 				const TextAttribute *	ta )
44     {
45     const LayoutContext *	lc= &(dc->dcLayoutContext);
46     BufferDocument *		bd= lc->lcDocument;
47     DocumentFontList *		dfl= bd->bdProperties.dpFontList;
48     const AfmFontInfo *		afi;
49     const IndexSet *		unicodesWanted;
50 
51     const PostScriptFontList *	psfl= lc->lcPostScriptFontList;
52 
53     afi= (*lc->lcGetFontForAttribute)( &unicodesWanted, ta, dfl, psfl );
54     if  ( ! afi )
55 	{ LDEB(textAttrNumber); return -1; }
56 
57     return 0;
58     }
59 
60 /************************************************************************/
61 /*									*/
62 /*  Printing of borders.						*/
63 /*									*/
64 /*  1)  The border is around paragraphs. Both the border and its	*/
65 /*      are outside the frame.						*/
66 /*									*/
67 /************************************************************************/
68 
docSvgWriteBorderAttributes(SvgWriter * sw,const BufferDocument * bd,const BorderProperties * bp,int thick)69 static void docSvgWriteBorderAttributes(
70 				SvgWriter *			sw,
71 				const BufferDocument *		bd,
72 				const BorderProperties *	bp,
73 				int				thick )
74     {
75     RGB8Color			rgb8;
76     XmlWriter *			xw= &(sw->swXmlWriter);
77 
78     if  ( thick < 8 )
79 	{ thick= 8;	}
80 
81     docGetColorByNumber( &rgb8, bd, bp->bpColor );
82 
83     xmlWriteRgb8Attribute( xw, "stroke", &rgb8 );
84     xmlWriteIntAttribute( xw, "stroke-width", thick );
85 
86     return;
87     }
88 
docSvgDrawHorizontalBorder(SvgWriter * sw,const BufferDocument * bd,const BorderProperties * bp,const DocumentRectangle * drBorder)89 static void docSvgDrawHorizontalBorder(
90 				SvgWriter *			sw,
91 				const BufferDocument *		bd,
92 				const BorderProperties *	bp,
93 				const DocumentRectangle *	drBorder )
94     {
95     XmlWriter *			xw= &(sw->swXmlWriter);
96 
97     sioOutPutString( "<line", xw->xwSos );
98 
99     xmlWriteIntAttribute( xw, "x1", drBorder->drX0 );
100     xmlWriteIntAttribute( xw, "x2", drBorder->drX1 );
101     xmlWriteIntAttribute( xw, "y1", ( drBorder->drY0+ drBorder->drY1 )/ 2 );
102     xmlWriteIntAttribute( xw, "y2", ( drBorder->drY0+ drBorder->drY1 )/ 2 );
103     docSvgWriteBorderAttributes( sw, bd, bp,
104 					drBorder->drY1- drBorder->drY0+ 1 );
105 
106     sioOutPutString( "/>", xw->xwSos );
107     return;
108     }
109 
docSvgDrawVerticalBorder(SvgWriter * sw,const BufferDocument * bd,const BorderProperties * bp,const DocumentRectangle * drBorder)110 static void docSvgDrawVerticalBorder(
111 				SvgWriter *			sw,
112 				const BufferDocument *		bd,
113 				const BorderProperties *	bp,
114 				const DocumentRectangle *	drBorder )
115     {
116     XmlWriter *			xw= &(sw->swXmlWriter);
117 
118     sioOutPutString( "<line", xw->xwSos );
119 
120     xmlWriteIntAttribute( xw, "x1", ( drBorder->drX0+ drBorder->drX1 )/ 2 );
121     xmlWriteIntAttribute( xw, "x2", ( drBorder->drX0+ drBorder->drX1 )/ 2 );
122     xmlWriteIntAttribute( xw, "y1", drBorder->drY0 );
123     xmlWriteIntAttribute( xw, "y2", drBorder->drY1 );
124     docSvgWriteBorderAttributes( sw, bd, bp,
125 					drBorder->drX1- drBorder->drX0+ 1 );
126 
127     sioOutPutString( "/>", xw->xwSos );
128     return;
129     }
130 
131 /************************************************************************/
132 /*									*/
133 /*  Draw background ornaments.						*/
134 /*									*/
135 /************************************************************************/
136 
docSvgDrawOrnaments(const BlockOrnaments * bo,int page,const DocumentRectangle * drOutside,const DocumentRectangle * drInside,void * through,struct DrawingContext * dc)137 static int docSvgDrawOrnaments(	const BlockOrnaments *		bo,
138 				int				page,
139 				const DocumentRectangle *	drOutside,
140 				const DocumentRectangle *	drInside,
141 				void *				through,
142 				struct DrawingContext *		dc )
143     {
144     SvgWriter *			sw= (SvgWriter *)through;
145     XmlWriter *			xw= &(sw->swXmlWriter);
146     const LayoutContext *	lc= &(dc->dcLayoutContext);
147     const BufferDocument *	bd= lc->lcDocument;
148 
149     int				rectBorder= 0;
150     DocumentRectangle		drRectBorder;
151 
152     drRectBorder.drX0= ( 3* drOutside->drX0- drInside->drX0 )/ 2;
153     drRectBorder.drX1= ( 3* drOutside->drX1- drInside->drX1 )/ 2;
154     drRectBorder.drY0= ( 3* drOutside->drY0- drInside->drY0 )/ 2;
155     drRectBorder.drY1= ( 3* drOutside->drY1- drInside->drY1 )/ 2;
156 
157 #   if 0
158     if  ( PROPmaskISSET( &(bo->boPropMask), ORNdrawTOP_BORDER )		&&
159 	  PROPmaskISSET( &(bo->boPropMask), ORNdrawLEFT_BORDER )	&&
160 	  PROPmaskISSET( &(bo->boPropMask), ORNdrawRIGHT_BORDER )	&&
161 	  PROPmaskISSET( &(bo->boPropMask), ORNdrawBOTTOM_BORDER )	&&
162 	  bo->boLeftBorderNumber == bo->boTopBorderNumber		&&
163 	  bo->boRightBorderNumber == bo->boTopBorderNumber		&&
164 	  bo->boBottomBorderNumber == bo->boTopBorderNumber		)
165 	{ rectBorder= 1;	}
166 #   endif
167 
168     if  ( PROPmaskISSET( &(bo->boPropMask), ORNdrawSHADE ) )
169 	{
170 	int				isFilled= 0;
171 	RGB8Color			rgb8;
172 	const DocumentRectangle *	drShade= drInside;
173 
174 	if  ( rectBorder )
175 	    { drShade= &drRectBorder;	}
176 
177 	if  ( docGetSolidRgbShadeOfItem( &isFilled, &rgb8,
178 						bd, &(bo->boShading) ) )
179 	    { LDEB(1);	}
180 
181 	if  ( isFilled )
182 	    {
183 	    sioOutPutString( "<rect", xw->xwSos );
184 	    svgWriteRectangleAttributes( sw, drShade );
185 	    xmlWriteRgb8Attribute( xw, "fill", &rgb8 );
186 
187 	    if  ( rectBorder )
188 		{
189 		docSvgWriteBorderAttributes( sw, bd, &(bo->boTopBorder),
190 					    drOutside->drY0- drInside->drY0 );
191 		}
192 
193 	    sioOutPutString( "/>", xw->xwSos );
194 	    xmlNewLine( xw );
195 	    }
196 
197 	if  ( bo->boShading.isPattern != DOCspSOLID )
198 	    { LDEB(bo->boShading.isPattern);	}
199 	}
200     else{
201 	if  ( rectBorder )
202 	    {
203 	    sioOutPutString( "<rect", xw->xwSos );
204 	    svgWriteRectangleAttributes( sw, &drRectBorder );
205 	    xmlWriteStringAttribute( xw, "fill", "none" );
206 	    docSvgWriteBorderAttributes( sw, bd, &(bo->boTopBorder),
207 					    drOutside->drY0- drInside->drY0 );
208 	    sioOutPutString( "/>", xw->xwSos );
209 	    xmlNewLine( xw );
210 	    }
211 	}
212 
213     if  ( ! rectBorder							&&
214 	  PROPmaskISSET( &(bo->boPropMask), ORNdrawTOP_BORDER )		)
215 	{
216 	DocumentRectangle	drBorder= *drOutside;
217 
218 	drBorder.drY1= drInside->drY0- 1;
219 
220 	docSvgDrawHorizontalBorder( sw, bd, &(bo->boTopBorder), &drBorder );
221 	xmlNewLine( xw );
222 	/*done= 1;*/
223 	}
224 
225     if  ( ! rectBorder						&&
226 	  PROPmaskISSET( &(bo->boPropMask), ORNdrawLEFT_BORDER ) )
227 	{
228 	DocumentRectangle	drBorder= *drOutside;
229 
230 	drBorder.drY0= drInside->drY0;
231 	drBorder.drY1= drInside->drY1;
232 	drBorder.drX1= drInside->drX0- 1;
233 
234 	docSvgDrawVerticalBorder( sw, bd, &(bo->boLeftBorder), &drBorder );
235 	/*done= 1;*/
236 	}
237 
238     if  ( ! rectBorder						&&
239 	  PROPmaskISSET( &(bo->boPropMask), ORNdrawRIGHT_BORDER ) )
240 	{
241 	DocumentRectangle	drBorder= *drOutside;
242 
243 	drBorder.drY0= drInside->drY0;
244 	drBorder.drY1= drInside->drY1;
245 	drBorder.drX0= drInside->drX1+ 1;
246 
247 	docSvgDrawVerticalBorder( sw, bd, &(bo->boRightBorder), &drBorder );
248 	/*done= 1;*/
249 	}
250 
251     if  ( ! rectBorder							&&
252 	  PROPmaskISSET( &(bo->boPropMask), ORNdrawBOTTOM_BORDER )	)
253 	{
254 	DocumentRectangle	drBorder= *drOutside;
255 
256 	drBorder.drY0= drInside->drY1+ 1;
257 
258 	docSvgDrawHorizontalBorder( sw, bd, &(bo->boBottomBorder), &drBorder );
259 	/*done= 1;*/
260 	}
261 
262     return 0;
263     }
264 
265 /************************************************************************/
266 
docSvgEmitFill(SvgWriter * sw,const struct DrawingShape * ds)267 int docSvgEmitFill(	SvgWriter *			sw,
268 			const struct DrawingShape *	ds )
269     {
270     XmlWriter *		xw= &(sw->swXmlWriter);
271     RGB8Color		rgb8Fill;
272     int			fill;
273 
274     if  ( docShapeGetFill( &fill, &rgb8Fill, ds ) )
275 	{ LDEB(ds->dsDrawing.sdShapeType); return -1;	}
276 
277     if  ( fill )
278 	{ xmlWriteRgb8Attribute( xw, "fill", &rgb8Fill );	}
279     else{ xmlWriteStringAttribute( xw, "fill", "none" );	}
280 
281     return 0;
282     }
283 
docSvgEmitStroke(SvgWriter * sw,const DrawingShape * ds)284 int docSvgEmitStroke(	SvgWriter *			sw,
285 			const DrawingShape *		ds )
286     {
287     const ShapeDrawing *	sd= &(ds->dsDrawing);
288     XmlWriter *			xw= &(sw->swXmlWriter);
289     RGB8Color			rgb8Stroke;
290     int				stroke;
291 
292     if  ( docShapeGetLine( &stroke, &rgb8Stroke, ds ) )
293 	{ LDEB(sd->sdShapeType); return -1;	}
294 
295     if  ( stroke )
296 	{
297 	int		widthTwips= EMUtoTWIPS( sd->sdLineWidthEmu );
298 	char		dashArray[100];
299 
300 	xmlWriteRgb8Attribute( xw, "stroke", &rgb8Stroke );
301 	xmlWriteIntAttribute( xw, "stroke-width", widthTwips );
302 
303 	dashArray[0]= '\0';
304 
305 	switch( sd->sdLineDashing )
306 	    {
307 	    case DSdashSOLID:
308 		break;
309 
310 	    case DSdashDASHED:
311 	    case DSdashDASHED_X:
312 	    case DSdashDASHED_L:
313 		sprintf( dashArray, "%d %d", 6* widthTwips, 4* widthTwips );
314 		break;
315 
316 	    case DSdashDOT:
317 	    case DSdashDOT_X:
318 		sprintf( dashArray, "%d %d", 1* widthTwips, 2* widthTwips );
319 		break;
320 
321 	    case DSdashDASHDOT:
322 	    case DSdashDASHDOT_X:
323 	    case DSdashDASHDOT_L:
324 		sprintf( dashArray, "%d %d %d %d",
325 					6* widthTwips, 2* widthTwips,
326 					1* widthTwips, 2* widthTwips );
327 		break;
328 
329 	    case DSdashDASHDOTDOT:
330 	    case DSdashDASHDOTDOT_L:
331 		sprintf( dashArray, "%d %d %d %d %d %d",
332 						6* widthTwips,
333 						2* widthTwips,
334 						1* widthTwips,
335 						2* widthTwips,
336 						1* widthTwips,
337 						2* widthTwips );
338 		break;
339 
340 	    default:
341 		LDEB(sd->sdLineDashing);
342 	    }
343 
344 	if  ( dashArray[0] )
345 	    { xmlWriteStringAttribute( xw, "dash-array", dashArray ); }
346 	}
347 
348     return 0;
349     }
350 
351 /************************************************************************/
352 /*									*/
353 /*  Skip to the next page.						*/
354 /*									*/
355 /************************************************************************/
356 
docSvgFinishPage(void * vsw,DrawingContext * dc,BufferItem * bodySectNode,int page,int asLast)357 static int docSvgFinishPage(	void *				vsw,
358 				DrawingContext *		dc,
359 				BufferItem *			bodySectNode,
360 				int				page,
361 				int				asLast )
362     {
363     SvgWriter *		sw= (SvgWriter *)vsw;
364     XmlWriter *		xw= &(sw->swXmlWriter);
365 
366 #   if 0
367     if  ( sw->swMultiPage )
368 	{
369 	xmlPutString( "</page>", xw );
370 	xmlNewLine( xw );
371 	}
372 #   else
373     if  ( sw->swMultiPage )
374 	{
375 	xmlPutString( "</g>", xw );
376 	xmlNewLine( xw );
377 	}
378 #   endif
379 
380     return 0;
381     }
382 
docSvgDrawStartPage(void * vsw,const DocumentGeometry * dgPage,DrawingContext * dc,int page)383 static int docSvgDrawStartPage(	void *				vsw,
384 				const DocumentGeometry *	dgPage,
385 				DrawingContext *		dc,
386 				int				page )
387     {
388     SvgWriter *		sw= (SvgWriter *)vsw;
389     XmlWriter *		xw= &(sw->swXmlWriter);
390 
391     char		scratch[120];
392 
393     sprintf( scratch, "page%d", page+ 1 );
394 
395 #   if 0
396     if  ( sw->swMultiPage )
397 	{
398 	xmlPutString( "<page", xw );
399 	xmlWriteStringAttribute( xw, "id", scratch );
400 	xmlPutString( ">", xw );
401 	xmlNewLine( xw );
402 	}
403 #   else
404     if  ( sw->swMultiPage )
405 	{
406 	xmlPutString( "<g", xw );
407 	xmlWriteStringAttribute( xw, "id", scratch );
408 	if  ( page != dc->dcFirstPage )
409 	    { xmlWriteStringAttribute( xw, "visibility", "hidden" );	}
410 	xmlPutString( ">", xw );
411 	xmlNewLine( xw );
412 
413 	xmlPutString( "<path", xw );
414 	xmlWriteStringAttribute( xw, "d",
415 				    "M75,225 l225,-150 l0,300 l-225,-150z" );
416 	if  ( page > dc->dcFirstPage )
417 	    {
418 	    sprintf( scratch, "switchPage( evt, \"page%d\", \"page%d\" );",
419 						    page+ 1, page );
420 
421 	    xmlWriteStringAttribute( xw, "fill", "#000000" );
422 	    xmlWriteStringAttribute( xw, "onclick", scratch );
423 	    }
424 	else{
425 	    xmlWriteStringAttribute( xw, "fill", "#cccccc" );
426 	    }
427 	xmlPutString( "/>", xw );
428 	xmlNewLine( xw );
429 
430 	xmlPutString( "<path", xw );
431 	xmlWriteStringAttribute( xw, "d",
432 				    "M625,225 l-225,-150 l0,300 l225,-150z" );
433 	if  ( page < dc->dcLastPage )
434 	    {
435 	    sprintf( scratch, "switchPage( evt, \"page%d\", \"page%d\" );",
436 						    page+ 1, page+ 2 );
437 
438 	    xmlWriteStringAttribute( xw, "fill", "#000000" );
439 	    xmlWriteStringAttribute( xw, "onclick", scratch );
440 	    }
441 	else{
442 	    xmlWriteStringAttribute( xw, "fill", "#cccccc" );
443 	    }
444 	xmlPutString( "/>", xw );
445 	xmlNewLine( xw );
446 	}
447 #   endif
448 
449     return 0;
450     }
451 
452 /************************************************************************/
453 /*									*/
454 /*  Save a range of pages in a document.				*/
455 /*									*/
456 /************************************************************************/
457 
docSvgDrawPageRange(SvgWriter * sw,DrawingContext * dc,BufferItem * bodyBi,int firstPage,int lastPage,int asLast)458 static int docSvgDrawPageRange(	SvgWriter *		sw,
459 				DrawingContext *	dc,
460 				BufferItem *		bodyBi,
461 				int			firstPage,
462 				int			lastPage,
463 				int			asLast )
464     {
465     int				i;
466     LayoutPosition		lpBelow;
467 
468     docInitLayoutPosition( &lpBelow );
469 
470     for ( i= 0; i < bodyBi->biChildCount; i++ )
471 	{
472 	if  ( bodyBi->biChildren[i]->biBelowPosition.lpPage >= firstPage )
473 	    { break;	}
474 	}
475 
476     if  ( i >= bodyBi->biChildCount )
477 	{ LDEB(i); return -1; }
478 
479     docSvgDrawStartPage( (void *)sw,
480 	    &(bodyBi->biChildren[i]->biSectDocumentGeometry), dc, firstPage );
481 
482     if  ( ! dc->dcPostponeHeadersFooters )
483 	{
484 	docDrawPageHeader( bodyBi->biChildren[i], (void *)sw, dc, firstPage );
485 	}
486 
487     if  ( docDrawShapesForPage( (void *)sw, dc, 1, firstPage ) )
488 	{ LDEB(firstPage);	}
489 
490     docDrawNode( &lpBelow, bodyBi, (void *)sw, dc );
491 
492     if  ( lastPage < 0 )
493 	{ lastPage= bodyBi->biBelowPosition.lpPage;	}
494 
495     for ( i= bodyBi->biChildCount- 1; i >= 0; i-- )
496 	{
497 	if  ( bodyBi->biChildren[i]->biTopPosition.lpPage <= lastPage )
498 	    { break;	}
499 	}
500 
501     if  ( i < 0 )
502 	{ LDEB(i); return -1;	}
503 
504     if  ( docDrawShapesForPage( (void *)sw, dc, 0, lastPage ) )
505 	{ LDEB(lastPage);	}
506 
507     if  ( ! dc->dcPostponeHeadersFooters )
508 	{
509 	docDrawPageFooter( bodyBi->biChildren[i], (void *)sw, dc, lastPage );
510 	}
511 
512     docSvgFinishPage( (void *)sw, dc, bodyBi->biChildren[i],
513 						    lastPage, asLast );
514 
515     return 0;
516     }
517 
518 /************************************************************************/
519 
docSvgSetDrawingContext(DrawingContext * dc,const LayoutContext * lc,int firstPage,int lastPage)520 static void docSvgSetDrawingContext(	DrawingContext *	dc,
521 					const LayoutContext *	lc,
522 					int			firstPage,
523 					int			lastPage )
524     {
525     INIT_LAYOUT_EXTERNAL	initLayoutExternal= (INIT_LAYOUT_EXTERNAL)0;
526 
527     dc->dcSetColorRgb= docSvgSetColorRgb;
528     dc->dcSetFont= docSvgSetFont;
529     dc->dcDrawShape= docSvgDrawDrawDrawingShape;
530     dc->dcDrawObject= docSvgDrawObject;
531     dc->dcDrawTab= docSvgDrawTab;
532     dc->dcDrawFtnsep= docSvgDrawFtnsep;
533     dc->dcDrawSpan= docSvgDrawSpan;
534 
535     dc->dcDrawTextLine= docSvgDrawTextLine;
536     dc->dcDrawOrnaments= docSvgDrawOrnaments;
537     dc->dcFinishPage= docSvgFinishPage;
538     dc->dcStartPage= docSvgDrawStartPage;
539     dc->dcInitLayoutExternal= initLayoutExternal;
540 
541     dc->dcLayoutContext= *lc;
542 
543     dc->dcFirstPage= firstPage;
544     dc->dcLastPage= lastPage;
545     dc->dcDrawExternalItems= 1;
546     dc->dcPostponeHeadersFooters= 0;
547 
548     return;
549     }
550 
551 
552 /************************************************************************/
553 /*									*/
554 /*  Save a document as a SVG drawing.					*/
555 /*									*/
556 /************************************************************************/
557 
docSvgDrawDocument(SimpleOutputStream * sos,const char * applicationName,const char * applicationReference,const LayoutContext * lc)558 int docSvgDrawDocument(	SimpleOutputStream *		sos,
559 			const char *			applicationName,
560 			const char *			applicationReference,
561 			const LayoutContext *		lc )
562     {
563     BufferDocument *		bd= lc->lcDocument;
564     DocumentProperties *	dp= &(bd->bdProperties);
565     DocumentGeometry *		dg= &(dp->dpGeometry);
566     BufferItem *		bodyBi= bd->bdBody.dtRoot;
567 
568     DrawingContext		dc;
569     SvgWriter			sw;
570     XmlWriter *			xw= &(sw.swXmlWriter);
571 
572     docInitDrawingContext( &dc );
573     docSvgSetDrawingContext( &dc, lc, 0, bodyBi->biBelowPosition.lpPage );
574 
575     svgInitSvgWriter( &sw );
576     sw.swXmlWriter.xwSos= sos;
577     strcpy( sw.swUnit, "pt" );
578     sw.swWide= ( dg->dgPageWideTwips+ 19 )/ 20;
579     sw.swHigh= ( dg->dgPageHighTwips+ 19 )/ 20;
580     sw.swViewBox.drX0= 0;
581     sw.swViewBox.drY0= 0;
582     sw.swViewBox.drX1= dg->dgPageWideTwips- 1;
583     sw.swViewBox.drY1= dg->dgPageHighTwips- 1;
584     sw.swMultiPage= dc.dcLastPage > dc.dcFirstPage;
585 
586     docInquireHeadersFooters( &(dc.dcDocHasPageHeaders),
587 				    &(dc.dcDocHasPageFooters), bd );
588 
589     svgStartDocument( &sw );
590 
591     if  ( sw.swMultiPage )
592 	{
593 #	if 0
594 	xmlPutString( "<pageSet>", xw );
595 #	else
596 	xmlPutString( "<script type=\"text/ecmascript\"><![CDATA[", xw );
597 	xmlNewLine( xw );
598 	xmlPutString( "function switchPage( evt, fr, to ) {", xw );
599 	xmlNewLine( xw );
600 	xmlPutString( "    var efr= document.getElementById( fr );", xw );
601 	xmlNewLine( xw );
602 	xmlPutString( "    var eto= document.getElementById( to );", xw );
603 	xmlNewLine( xw );
604 	xmlPutString( "    eto.removeAttribute( \"visibility\" );", xw );
605 	xmlNewLine( xw );
606 	xmlPutString( "    efr.setAttribute( \"visibility\", \"hidden\" );", xw );
607 	xmlNewLine( xw );
608 	xmlPutString( "}", xw );
609 	xmlNewLine( xw );
610 	xmlPutString( "]]></script>", xw );
611 #	endif
612 	xmlNewLine( xw );
613 	}
614 
615     if  ( docSvgDrawPageRange( &sw, &dc, bodyBi,
616 			    dc.dcFirstPage, dc.dcLastPage, /* asLast */ 1 ) )
617 	{ LDEB(dc.dcFirstPage); return -1;	}
618 
619 #   if 0
620     if  ( sw.swMultiPage )
621 	{
622 	xmlPutString( "</pageSet>", xw );
623 	xmlNewLine( xw );
624 	}
625 #   endif
626 
627     svgFinishDocument( &sw );
628 
629     docResetExternalTreeLayout( bd );
630 
631     return 0;
632     }
633 
634 /************************************************************************/
635 
docSvgSaveShapeObject(SimpleOutputStream * sos,int page,int pixelsWide,int pixelsHigh,const InsertedObject * io,BufferItem * bodySectNode,const LayoutContext * lc)636 int docSvgSaveShapeObject(	SimpleOutputStream *	sos,
637 				int			page,
638 				int			pixelsWide,
639 				int			pixelsHigh,
640 				const InsertedObject *	io,
641 				BufferItem *		bodySectNode,
642 				const LayoutContext *	lc )
643     {
644     int				rval= 0;
645     const DrawingShape *	ds= io->ioDrawingShape;
646 
647     DrawingContext		dc;
648     SvgWriter			sw;
649     IndexSet			attrUsed;
650     XmlWriter *			xw= &(sw.swXmlWriter);
651 
652     utilInitIndexSet( &attrUsed );
653 
654     svgInitSvgWriter( &sw );
655 
656     docInitDrawingContext( &dc );
657     docSvgSetDrawingContext( &dc, lc, page, page );
658 
659     sw.swXmlWriter.xwSos= sos;
660 
661     if  ( docGetAttributesUsedInShape( lc->lcDocument, ds, &attrUsed ) )
662 	{ LDEB(1); rval= -1; goto ready;	}
663 
664     /* This is an independent image: Subtract the drawing origin */
665     docPlaceRootShapeRect( &(sw.swViewBox),
666 			    &(io->ioDrawingShape->dsShapeProperties),
667 			    io->ioX0Twips, io->ioY0Position.lpPageYTwips );
668     sw.swWide= pixelsWide;
669     sw.swHigh= pixelsHigh;
670 
671     svgStartDocument( &sw );
672 
673     xmlPutString( "<defs>", xw ); xmlNewLine( xw );
674     xmlPutString( "    <style type=\"text/css\"><![CDATA[", xw );
675     xmlNewLine( xw );
676 
677     docCssSaveTextAttributeStyles( xw->xwSos, &attrUsed, lc->lcDocument );
678 
679     xmlPutString( "div { margin:-2px 0; }", xw ); xmlNewLine( xw );
680 
681     xmlPutString( "    ]]></style>", xw ); xmlNewLine( xw );
682     xmlPutString( "</defs>", xw ); xmlNewLine( xw );
683 
684     if  ( docDrawShape( &dc, &sw, bodySectNode, io ) )
685 	{ LDEB(1); rval= -1; goto ready;;	}
686 
687     svgFinishDocument( &sw );
688 
689   ready:
690 
691     utilCleanIndexSet( &attrUsed );
692 
693     return rval;
694     }
695 
696