merge the formfield patch from ooo-build
[ooovba.git] / filter / source / svg / svgwriter.cxx
blobf97cc2162954f403f25674bbfbd616cd20f4b75e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: svgwriter.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_filter.hxx"
34 #include "svgfontexport.hxx"
35 #include "svgwriter.hxx"
37 // -----------
38 // - statics -
39 // -----------
41 static const char aXMLElemG[] = "g";
42 static const char aXMLElemDefs[] = "defs";
43 static const char aXMLElemClipPath[] = "clipPath";
44 static const char aXMLElemLine[] = "line";
45 static const char aXMLElemRect[] = "rect";
46 static const char aXMLElemEllipse[] = "ellipse";
47 static const char aXMLElemPath[] = "path";
48 static const char aXMLElemPolygon[] = "polygon";
49 static const char aXMLElemPolyLine[] = "polyline";
50 static const char aXMLElemText[] = "text";
51 static const char aXMLElemTSpan[] = "tspan";
52 static const char aXMLElemImage[] = "image";
54 static const char aXMLAttrTransform[] = "transform";
55 static const char aXMLAttrStyle[] = "style";
56 static const char aXMLAttrId[] = "id";
57 static const char aXMLAttrD[] = "d";
58 static const char aXMLAttrX[] = "x";
59 static const char aXMLAttrY[] = "y";
60 static const char aXMLAttrX1[] = "x1";
61 static const char aXMLAttrY1[] = "y1";
62 static const char aXMLAttrX2[] = "x2";
63 static const char aXMLAttrY2[] = "y2";
64 static const char aXMLAttrCX[] = "cx";
65 static const char aXMLAttrCY[] = "cy";
66 static const char aXMLAttrRX[] = "rx";
67 static const char aXMLAttrRY[] = "ry";
68 static const char aXMLAttrWidth[] = "width";
69 static const char aXMLAttrHeight[] = "height";
70 static const char aXMLAttrPoints[] = "points";
71 static const char aXMLAttrXLinkHRef[] = "xlink:href";
73 static const sal_Unicode pBase64[] =
75 //0 1 2 3 4 5 6 7
76 'A','B','C','D','E','F','G','H', // 0
77 'I','J','K','L','M','N','O','P', // 1
78 'Q','R','S','T','U','V','W','X', // 2
79 'Y','Z','a','b','c','d','e','f', // 3
80 'g','h','i','j','k','l','m','n', // 4
81 'o','p','q','r','s','t','u','v', // 5
82 'w','x','y','z','0','1','2','3', // 6
83 '4','5','6','7','8','9','+','/' // 7
86 // --------------
87 // - FastString -
88 // --------------
90 FastString::FastString( sal_uInt32 nInitLen, sal_uInt32 nIncrement ) :
91 mnBufLen( nInitLen ),
92 mnCurLen( 0 ),
93 mnBufInc( nIncrement ),
94 mpBuffer( new sal_Unicode[ nInitLen * sizeof( sal_Unicode ) ] ),
95 mnPartPos( 0 )
97 DBG_ASSERT( nInitLen, "invalid initial length" );
98 DBG_ASSERT( nIncrement, "invalid increment" );
101 // -----------------------------------------------------------------------------
103 FastString::FastString( sal_Char* pBufferForBase64Encoding, sal_uInt32 nBufLen ) :
104 mnBufInc( 2048 ),
105 mnPartPos( 0 )
107 DBG_ASSERT( pBufferForBase64Encoding && nBufLen, "invalid arguments" );
109 const sal_uInt32 nQuadCount = nBufLen / 3;
110 const sal_uInt32 nRest = nBufLen % 3;
112 if( nQuadCount || nRest )
114 mnBufLen = mnCurLen = ( ( nQuadCount + ( nRest ? 1 : 0 ) ) << 2 );
115 mpBuffer = new sal_Unicode[ mnBufLen * sizeof( sal_Unicode ) ];
117 sal_Char* pTmpSrc = pBufferForBase64Encoding;
118 sal_Unicode* pTmpDst = mpBuffer;
120 for( sal_uInt32 i = 0; i < nQuadCount; i++ )
122 const sal_Int32 nA = *pTmpSrc++;
123 const sal_Int32 nB = *pTmpSrc++;
124 const sal_Int32 nC = *pTmpSrc++;
126 *pTmpDst++ = pBase64[ ( nA >> 2 ) & 0x3f ];
127 *pTmpDst++ = pBase64[ ( ( nA << 4 ) & 0x30 ) + ( ( nB >> 4 ) & 0xf ) ];
128 *pTmpDst++ = pBase64[ ( ( nB << 2 ) & 0x3c ) + ( ( nC >> 6 ) & 0x3 ) ];
129 *pTmpDst++ = pBase64[ nC & 0x3f ];
132 if( 1 == nRest )
134 const sal_Int32 nA = *pTmpSrc;
136 *pTmpDst++ = pBase64[ ( nA >> 2 ) & 0x3f ];
137 *pTmpDst++ = pBase64[ ( nA << 4 ) & 0x30 ];
138 *pTmpDst++ = '=';
139 *pTmpDst = '=';
141 else if( 2 == nRest )
143 const sal_Int32 nA = *pTmpSrc++;
144 const sal_Int32 nB = *pTmpSrc;
146 *pTmpDst++ = pBase64[ ( nA >> 2 ) & 0x3f ];
147 *pTmpDst++ = pBase64[ ( ( nA << 4 ) & 0x30 ) + ( ( nB >> 4 ) & 0xf ) ];
148 *pTmpDst++ = pBase64[ ( nB << 2 ) & 0x3c ];
149 *pTmpDst = '=';
152 else
154 mpBuffer = new sal_Unicode[ ( mnBufLen = 1 ) * sizeof( sal_Unicode ) ];
155 mnCurLen = 0;
159 // -----------------------------------------------------------------------------
161 FastString::~FastString()
163 delete[] mpBuffer;
166 // -----------------------------------------------------------------------------
168 FastString& FastString::operator+=( const NMSP_RTL::OUString& rStr )
170 if( rStr.getLength() )
172 if( ( mnCurLen + rStr.getLength() ) > mnBufLen )
174 const sal_uInt32 nNewBufLen = ( mnBufLen + ( ( ( mnCurLen + rStr.getLength() ) - mnBufLen ) / mnBufInc + 1 ) * mnBufInc );
175 sal_Unicode* pNewBuffer = new sal_Unicode[ nNewBufLen * sizeof( sal_Unicode ) ];
177 memcpy( pNewBuffer, mpBuffer, mnBufLen * sizeof( sal_Unicode ) );
178 delete[] mpBuffer;
179 mpBuffer = pNewBuffer;
180 mnBufLen = nNewBufLen;
183 memcpy( mpBuffer + mnCurLen, rStr.getStr(), rStr.getLength() * sizeof( sal_Unicode ) );
184 mnCurLen += rStr.getLength();
186 if( maString.getLength() )
187 maString = NMSP_RTL::OUString();
190 return *this;
193 // -----------------------------------------------------------------------------
195 const NMSP_RTL::OUString& FastString::GetString() const
197 if( !maString.getLength() && mnCurLen )
198 ( (FastString*) this )->maString = NMSP_RTL::OUString( mpBuffer, mnCurLen );
200 return maString;
203 // -----------------------------------------------------------------------------
205 sal_Bool FastString::GetFirstPartString( const sal_uInt32 nPartLen, NMSP_RTL::OUString& rPartString )
207 const sal_uInt32 nLength = Min( mnCurLen, nPartLen );
209 mnPartPos = 0;
211 if( nLength )
213 rPartString = NMSP_RTL::OUString( mpBuffer, nLength );
214 mnPartPos = nLength;
217 return( rPartString.getLength() > 0 );
220 // -----------------------------------------------------------------------------
222 sal_Bool FastString::GetNextPartString( const sal_uInt32 nPartLen, NMSP_RTL::OUString& rPartString )
224 if( mnPartPos < mnCurLen )
226 const sal_uInt32 nLength = Min( mnCurLen - mnPartPos, nPartLen );
227 rPartString = NMSP_RTL::OUString( mpBuffer + mnPartPos, nLength );
228 mnPartPos += nLength;
230 else
231 rPartString = NMSP_RTL::OUString();
233 return( rPartString.getLength() > 0 );
236 // ----------------------
237 // - SVGAttributeWriter -
238 // ----------------------
240 SVGAttributeWriter::SVGAttributeWriter( SvXMLExport& rExport, SVGFontExport& rFontExport ) :
241 mrExport( rExport ),
242 mrFontExport( rFontExport ),
243 mpElemFont( NULL ),
244 mpElemPaint( NULL )
248 // -----------------------------------------------------------------------------
250 SVGAttributeWriter::~SVGAttributeWriter()
252 delete mpElemPaint;
253 delete mpElemFont;
256 // -----------------------------------------------------------------------------
258 NMSP_RTL::OUString SVGAttributeWriter::GetFontStyle( const Font& rFont )
260 FastString aStyle;
262 // font family
263 aStyle += B2UCONST( "font-family:" );
264 aStyle += mrFontExport.GetMappedFontName( rFont.GetName() );
266 // font size
267 aStyle += B2UCONST( ";" );
268 aStyle += B2UCONST( "font-size:" );
269 aStyle += SVGActionWriter::GetValueString( rFont.GetHeight() );
271 // font style
273 if( rFont.GetItalic() != ITALIC_NONE )
275 aStyle += B2UCONST( ";" );
276 aStyle += B2UCONST( "font-style:" );
278 if( rFont.GetItalic() == ITALIC_OBLIQUE )
279 aStyle += B2UCONST( "oblique" );
280 else
281 aStyle += B2UCONST( "italic" );
285 // font weight
286 sal_Int32 nFontWeight;
288 switch( rFont.GetWeight() )
290 case WEIGHT_THIN: nFontWeight = 100; break;
291 case WEIGHT_ULTRALIGHT: nFontWeight = 200; break;
292 case WEIGHT_LIGHT: nFontWeight = 300; break;
293 case WEIGHT_SEMILIGHT: nFontWeight = 400; break;
294 case WEIGHT_NORMAL: nFontWeight = 400; break;
295 case WEIGHT_MEDIUM: nFontWeight = 500; break;
296 case WEIGHT_SEMIBOLD: nFontWeight = 600; break;
297 case WEIGHT_BOLD: nFontWeight = 700; break;
298 case WEIGHT_ULTRABOLD: nFontWeight = 800; break;
299 case WEIGHT_BLACK: nFontWeight = 900; break;
300 default: nFontWeight = 400; break;
303 aStyle += B2UCONST( ";" );
304 aStyle += B2UCONST( "font-weight:" );
305 aStyle += NMSP_RTL::OUString::valueOf( nFontWeight );
307 // !!!
308 // font-variant
309 // font-stretch
310 // font-size-adjust
312 #ifdef _SVG_USE_NATIVE_TEXTDECORATION
314 if( rFont.GetUnderline() != UNDERLINE_NONE || rFont.GetStrikeout() != STRIKEOUT_NONE )
316 aStyle += B2UCONST( ";" );
317 aStyle += B2UCONST( "text-decoration:" );
319 if( rFont.GetUnderline() != UNDERLINE_NONE )
320 aStyle += B2UCONST( " underline" );
322 if( rFont.GetStrikeout() != STRIKEOUT_NONE )
323 aStyle += B2UCONST( " line-through" );
326 #endif // _SVG_USE_NATIVE_TEXTDECORATION
328 return aStyle.GetString();
331 // -----------------------------------------------------------------------------
333 NMSP_RTL::OUString SVGAttributeWriter::GetPaintStyle( const Color& rLineColor, const Color& rFillColor )
335 FastString aStyle;
337 // line color
338 aStyle += B2UCONST( "stroke:" );
340 if( rLineColor.GetTransparency() == 255 )
341 aStyle += B2UCONST( "none" );
342 else
344 // line color value in rgb
345 aStyle += B2UCONST( "rgb(" );
346 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rLineColor.GetRed() );
347 aStyle += B2UCONST( "," );
348 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rLineColor.GetGreen() );
349 aStyle += B2UCONST( "," );
350 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rLineColor.GetBlue() );
351 aStyle += B2UCONST( ")" );
353 // line color opacity in percent if neccessary
354 if( rLineColor.GetTransparency() )
356 aStyle += B2UCONST( ";" );
357 aStyle += B2UCONST( "stroke-opacity:" );
358 aStyle += NMSP_RTL::OUString::valueOf( ( 255 - (double) rLineColor.GetTransparency() ) / 255.0 );
362 // fill color
363 aStyle += B2UCONST( ";" );
364 aStyle += B2UCONST( "fill:" );
366 if( rFillColor.GetTransparency() == 255 )
367 aStyle += B2UCONST( "none" );
368 else
370 // fill color value in rgb
371 aStyle += B2UCONST( "rgb(" );
372 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rFillColor.GetRed() );
373 aStyle += B2UCONST( "," );
374 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rFillColor.GetGreen() );
375 aStyle += B2UCONST( "," );
376 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rFillColor.GetBlue() );
377 aStyle += B2UCONST( ")" );
379 // fill color opacity in percent if neccessary
380 if( rFillColor.GetTransparency() )
382 aStyle += B2UCONST( ";" );
383 aStyle += B2UCONST( "fill-opacity:" );
384 aStyle += NMSP_RTL::OUString::valueOf( ( 255 - (double) rFillColor.GetTransparency() ) / 255.0 );
388 return aStyle.GetString();
391 // -----------------------------------------------------------------------------
393 void SVGAttributeWriter::SetFontAttr( const Font& rFont )
395 if( !mpElemFont || ( rFont != maCurFont ) )
397 delete mpElemPaint, mpElemPaint = NULL;
398 delete mpElemFont;
399 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, GetFontStyle( maCurFont = rFont ) );
400 mpElemFont = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
404 // -----------------------------------------------------------------------------
406 void SVGAttributeWriter::SetPaintAttr( const Color& rLineColor, const Color& rFillColor )
408 if( !mpElemPaint || ( rLineColor != maCurLineColor ) || ( rFillColor != maCurFillColor ) )
410 delete mpElemPaint;
411 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, GetPaintStyle( maCurLineColor = rLineColor, maCurFillColor = rFillColor ) );
412 mpElemPaint = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
416 // -------------------
417 // - SVGActionWriter -
418 // -------------------
420 SVGActionWriter::SVGActionWriter( SvXMLExport& rExport, SVGFontExport& rFontExport ) :
421 mrExport( rExport ),
422 mrFontExport( rFontExport ),
423 mpContext( NULL ),
424 mbClipAttrChanged( sal_False ),
425 mnCurClipId( 1 )
427 mpVDev = new VirtualDevice;
428 mpVDev->EnableOutput( sal_False );
429 maTargetMapMode = MAP_100TH_MM;
432 // -----------------------------------------------------------------------------
434 SVGActionWriter::~SVGActionWriter()
436 DBG_ASSERT( !mpContext, "Not all contexts are closed" );
437 delete mpVDev;
440 // -----------------------------------------------------------------------------
442 long SVGActionWriter::ImplMap( sal_Int32 nVal ) const
444 return ImplMap( Size( nVal, nVal ) ).Width();
447 // -----------------------------------------------------------------------------
449 Point SVGActionWriter::ImplMap( const Point& rPt ) const
451 return mpVDev->LogicToLogic( rPt, mpVDev->GetMapMode(), maTargetMapMode );
454 // -----------------------------------------------------------------------------
456 Size SVGActionWriter::ImplMap( const Size& rSz ) const
458 return mpVDev->LogicToLogic( rSz, mpVDev->GetMapMode(), maTargetMapMode );
461 // -----------------------------------------------------------------------------
463 NMSP_RTL::OUString SVGActionWriter::GetValueString( sal_Int32 nVal )
465 return ::rtl::OUString::valueOf( nVal );
468 // -----------------------------------------------------------------------------
470 NMSP_RTL::OUString SVGActionWriter::GetPathString( const PolyPolygon& rPolyPoly, sal_Bool bLine )
472 FastString aPathData;
473 const NMSP_RTL::OUString aBlank( B2UCONST( " " ) );
474 const NMSP_RTL::OUString aComma( B2UCONST( "," ) );
475 Point aPolyPoint;
477 for( long i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ )
479 const Polygon& rPoly = rPolyPoly[ (USHORT) i ];
480 USHORT n = 1, nSize = rPoly.GetSize();
482 if( nSize > 1 )
484 aPathData += B2UCONST( "M " );
485 aPathData += GetValueString( ( aPolyPoint = rPoly[ 0 ] ).X() );
486 aPathData += aComma;
487 aPathData += GetValueString( aPolyPoint.Y() );
488 sal_Char nCurrentMode = 0;
490 while( n < nSize )
492 aPathData += aBlank;
493 if ( ( rPoly.GetFlags( n ) == POLY_CONTROL ) && ( ( n + 2 ) < nSize ) )
495 if ( nCurrentMode != 'C' )
497 nCurrentMode = 'C';
498 aPathData += B2UCONST( "C " );
500 for ( int j = 0; j < 3; j++ )
502 if ( j )
503 aPathData += aBlank;
504 aPathData += GetValueString( ( aPolyPoint = rPoly[ n++ ] ).X() );
505 aPathData += aComma;
506 aPathData += GetValueString( aPolyPoint.Y() );
509 else
511 if ( nCurrentMode != 'L' )
513 nCurrentMode = 'L';
514 aPathData += B2UCONST( "L " );
516 aPathData += GetValueString( ( aPolyPoint = rPoly[ n++ ] ).X() );
517 aPathData += aComma;
518 aPathData += GetValueString( aPolyPoint.Y() );
522 if( !bLine )
523 aPathData += B2UCONST( " Z" );
525 if( i < ( nCount - 1 ) )
526 aPathData += aBlank;
530 return aPathData.GetString();
533 // -----------------------------------------------------------------------------
535 void SVGActionWriter::ImplWriteLine( const Point& rPt1, const Point& rPt2, const Color* pLineColor,
536 const NMSP_RTL::OUString* pStyle )
538 const Point aPt1( ImplMap( rPt1 ) );
539 const Point aPt2( ImplMap( rPt2 ) );
541 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX1, GetValueString( aPt1.X() ) );
542 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY1, GetValueString( aPt1.Y() ) );
543 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX2, GetValueString( aPt2.X() ) );
544 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY2, GetValueString( aPt2.Y() ) );
546 // add additional style if requested
547 if( pStyle )
548 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle );
550 if( pLineColor )
552 // !!! mrExport.AddAttribute( XML_NAMESPACE_NONE, ... )
553 DBG_ERROR( "SVGActionWriter::ImplWriteLine: Line color not implemented" );
557 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemLine, TRUE, TRUE );
561 // -----------------------------------------------------------------------------
563 void SVGActionWriter::ImplWriteRect( const Rectangle& rRect, long nRadX, long nRadY,
564 const NMSP_RTL::OUString* pStyle )
566 const Rectangle aRect( ImplMap( rRect ) );
568 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, GetValueString( aRect.Left() ) );
569 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, GetValueString( aRect.Top() ) );
570 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrWidth, GetValueString( aRect.GetWidth() ) );
571 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrHeight, GetValueString( aRect.GetHeight() ) );
573 if( nRadX )
574 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRX, GetValueString( ImplMap( nRadX ) ) );
576 if( nRadY )
577 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRY, GetValueString( ImplMap( nRadY ) ) );
579 // add additional style if requested
580 if( pStyle )
581 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle );
584 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemRect, TRUE, TRUE );
588 // -----------------------------------------------------------------------------
590 void SVGActionWriter::ImplWriteEllipse( const Point& rCenter, long nRadX, long nRadY,
591 const NMSP_RTL::OUString* pStyle )
593 const Point aCenter( ImplMap( rCenter ) );
595 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCX, GetValueString( aCenter.X() ) );
596 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCY, GetValueString( aCenter.Y() ) );
597 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRX, GetValueString( ImplMap( nRadX ) ) );
598 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRY, GetValueString( ImplMap( nRadY ) ) );
600 // add additional style if requested
601 if( pStyle )
602 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle );
605 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemEllipse, TRUE, TRUE );
609 // -----------------------------------------------------------------------------
611 void SVGActionWriter::ImplWritePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bLineOnly,
612 const NMSP_RTL::OUString* pStyle )
614 if( rPolyPoly.Count() )
616 PolyPolygon aMappedPolyPoly;
617 FastString aStyle;
619 for( USHORT i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ )
621 const Polygon& rPoly = rPolyPoly[ i ];
622 const USHORT nSize = rPoly.GetSize();
623 Polygon aMappedPoly( nSize );
625 for( USHORT n = 0; n < nSize; n++ )
626 aMappedPoly[ n ] = ImplMap( rPoly[ n ] );
628 aMappedPolyPoly.Insert( aMappedPoly );
631 if( bLineOnly )
633 aStyle += B2UCONST( "fill:none" );
634 if( pStyle )
635 aStyle += B2UCONST( ";" );
637 if( pStyle )
638 aStyle += *pStyle;
640 // add style attribute
641 if( aStyle.GetLength() )
642 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aStyle.GetString() );
644 // add path data attribute
645 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrD, GetPathString( aMappedPolyPoly, bLineOnly ) );
647 // write polyline/polygon element
648 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemPath, TRUE, TRUE );
653 // -----------------------------------------------------------------------------
655 void SVGActionWriter::ImplWriteGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient,
656 const NMSP_RTL::OUString* pStyle, sal_uInt32 nWriteFlags )
658 if( rPolyPoly.Count() )
660 SvXMLElementExport aElemG( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
661 FastString aClipId;
662 FastString aClipStyle;
664 aClipId += B2UCONST( "clip" );
665 aClipId += NMSP_RTL::OUString::valueOf( ImplGetNextClipId() );
668 SvXMLElementExport aElemDefs( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, TRUE, TRUE );
670 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aClipId.GetString() );
673 SvXMLElementExport aElemClipPath( mrExport, XML_NAMESPACE_NONE, aXMLElemClipPath, TRUE, TRUE );
674 ImplWritePolyPolygon( rPolyPoly, sal_False );
678 // create new context with clippath set
679 aClipStyle += B2UCONST( "clip-path:URL(#" );
680 aClipStyle += aClipId.GetString();
681 aClipStyle += B2UCONST( ")" );
683 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aClipStyle.GetString() );
686 GDIMetaFile aTmpMtf;
687 SvXMLElementExport aElemG2( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
689 mpVDev->AddGradientActions( rPolyPoly.GetBoundRect(), rGradient, aTmpMtf );
690 ImplWriteActions( aTmpMtf, pStyle, nWriteFlags );
695 // -----------------------------------------------------------------------------
697 void SVGActionWriter::ImplWriteText( const Point& rPos, const String& rText,
698 const sal_Int32* pDXArray, long nWidth,
699 const NMSP_RTL::OUString* pStyle )
701 long nLen = rText.Len(), i;
703 if( nLen )
705 Size aNormSize;
706 sal_Int32* pOwnArray;
707 sal_Int32* pDX;
709 // get text sizes
710 if( pDXArray )
712 pOwnArray = NULL;
713 aNormSize = Size( mpVDev->GetTextWidth( rText ), 0 );
714 pDX = (sal_Int32*) pDXArray;
716 else
718 pOwnArray = new sal_Int32[ nLen ];
719 aNormSize = Size( mpVDev->GetTextArray( rText, pOwnArray ), 0 );
720 pDX = pOwnArray;
723 if( nLen > 1 )
725 aNormSize.Width() = pDX[ nLen - 2 ] + mpVDev->GetTextWidth( rText.GetChar( sal::static_int_cast<USHORT>( nLen - 1 ) ) );
727 if( nWidth && aNormSize.Width() && ( nWidth != aNormSize.Width() ) )
729 const double fFactor = (double) nWidth / aNormSize.Width();
731 for( i = 0; i < ( nLen - 1 ); i++ )
732 pDX[ i ] = FRound( pDX[ i ] * fFactor );
736 FastString aStyle;
737 const Font& rFont = mpVDev->GetFont();
738 const FontMetric aMetric( mpVDev->GetFontMetric() );
739 Point aBaseLinePos( rPos );
740 SvXMLElementExport* pTransform = NULL;
742 // always adjust text position to match baseline alignment
743 switch( rFont.GetAlign() )
745 case( ALIGN_TOP ):
746 aBaseLinePos.Y() += aMetric.GetAscent();
747 break;
749 case( ALIGN_BOTTOM ):
750 aBaseLinePos.Y() -= aMetric.GetDescent();
751 break;
753 default:
754 break;
757 // get mapped text position
758 const Point aPt( ImplMap( aBaseLinePos ) );
760 // if text is italic, set transform at new g element
761 if( ( rFont.GetItalic() != ITALIC_NONE ) || rFont.GetOrientation() )
763 String aTransform;
765 aTransform = NMSP_RTL::OUString::createFromAscii( "translate" );
766 aTransform += '(';
767 aTransform += String( GetValueString( aPt.X() ) );
768 aTransform += ',';
769 aTransform += String( GetValueString( aPt.Y() ) );
770 aTransform += ')';
772 if( rFont.GetOrientation() )
774 aTransform += String( NMSP_RTL::OUString::createFromAscii( " rotate" ) );
775 aTransform += '(';
776 aTransform += String( NMSP_RTL::OUString::valueOf( rFont.GetOrientation() * -0.1 ) );
777 aTransform += ')';
780 if( rFont.GetItalic() != ITALIC_NONE )
782 aTransform += String( NMSP_RTL::OUString::createFromAscii( " skewX" ) );
783 aTransform += '(';
784 aTransform += String( NMSP_RTL::OUString::valueOf( (sal_Int32) -10 ) );
785 aTransform += ')';
788 aTransform += String( NMSP_RTL::OUString::createFromAscii( " translate" ) );
789 aTransform += '(';
790 aTransform += String( GetValueString( -aPt.X() ) );
791 aTransform += ',';
792 aTransform += String( GetValueString( -aPt.Y() ) );
793 aTransform += ')';
795 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTransform, aTransform );
796 pTransform = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
799 // add additional style if requested
800 if( pStyle && pStyle->getLength() )
801 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle );
803 // write text element
805 #ifdef _SVG_USE_TSPANS
806 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemText, TRUE, TRUE );
807 FastString aTSpanX;
808 const NMSP_RTL::OUString aSpace( ' ' );
809 String aOutputText( rText );
810 long nCurPos = 0;
811 bool bIgnoreWhitespace = true;
813 for( long j = 0, nX = aPt.X(); j < nLen; ++j )
815 const sal_Unicode cCode = rText.GetChar( sal::static_int_cast<USHORT>( j ) );
817 // don't take more than one whitespace into account
818 if( !bIgnoreWhitespace || ( ' ' != cCode ) )
820 aOutputText.SetChar( sal::static_int_cast<USHORT>( nCurPos++ ), cCode );
821 ( aTSpanX += GetValueString( nX + ( ( j > 0 ) ? pDX[ j - 1 ] : 0 ) ) ) += aSpace;
822 bIgnoreWhitespace = ( ' ' == cCode );
826 if( nCurPos < nLen )
827 aOutputText.Erase( sal::static_int_cast<USHORT>( nCurPos ) );
829 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, aTSpanX.GetString() );
830 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, GetValueString( aPt.Y() ) );
833 SvXMLElementExport aElem2( mrExport, XML_NAMESPACE_NONE, aXMLElemTSpan, TRUE, TRUE );
834 mrExport.GetDocHandler()->characters( aOutputText );
836 #else
837 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, GetValueString( aPt.X() ) );
838 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, GetValueString( aPt.Y() ) );
841 SvXMLElementExport aElem2( mrExport, XML_NAMESPACE_NONE, aXMLElemText, TRUE, TRUE );
842 mrExport.GetDocHandler()->characters( rText );
844 #endif
847 #ifndef _SVG_USE_NATIVE_TEXTDECORATION
848 // write strikeout if neccessary
849 if( rFont.GetStrikeout() || rFont.GetUnderline() )
851 Polygon aPoly( 4 );
852 const long nLineHeight = Max( (long) FRound( aMetric.GetLineHeight() * 0.05 ), (long) 1 );
854 if( rFont.GetStrikeout() )
856 const long nYLinePos = aBaseLinePos.Y() - FRound( aMetric.GetAscent() * 0.26 );
858 aPoly[ 0 ].X() = aBaseLinePos.X(); aPoly[ 0 ].Y() = nYLinePos - ( nLineHeight >> 1 );
859 aPoly[ 1 ].X() = aBaseLinePos.X() + aNormSize.Width() - 1; aPoly[ 1 ].Y() = aPoly[ 0 ].Y();
860 aPoly[ 2 ].X() = aPoly[ 1 ].X(); aPoly[ 2 ].Y() = aPoly[ 0 ].Y() + nLineHeight - 1;
861 aPoly[ 3 ].X() = aPoly[ 0 ].X(); aPoly[ 3 ].Y() = aPoly[ 2 ].Y();
863 ImplWritePolyPolygon( aPoly, sal_False );
866 if( rFont.GetUnderline() )
868 const long nYLinePos = aBaseLinePos.Y() + ( nLineHeight << 1 );
870 aPoly[ 0 ].X() = aBaseLinePos.X(); aPoly[ 0 ].Y() = nYLinePos - ( nLineHeight >> 1 );
871 aPoly[ 1 ].X() = aBaseLinePos.X() + aNormSize.Width() - 1; aPoly[ 1 ].Y() = aPoly[ 0 ].Y();
872 aPoly[ 2 ].X() = aPoly[ 1 ].X(); aPoly[ 2 ].Y() = aPoly[ 0 ].Y() + nLineHeight - 1;
873 aPoly[ 3 ].X() = aPoly[ 0 ].X(); aPoly[ 3 ].Y() = aPoly[ 2 ].Y();
875 ImplWritePolyPolygon( aPoly, sal_False );
878 #endif // _SVG_USE_NATIVE_TEXTDECORATION
880 delete[] pOwnArray;
881 delete pTransform;
885 // -----------------------------------------------------------------------------
887 void SVGActionWriter::ImplWriteBmp( const BitmapEx& rBmpEx,
888 const Point& rPt, const Size& rSz,
889 const Point& rSrcPt, const Size& rSrcSz,
890 const NMSP_RTL::OUString* /* pStyle */ )
892 if( !!rBmpEx )
894 BitmapEx aBmpEx( rBmpEx );
895 Point aPoint = Point();
896 const Rectangle aBmpRect( aPoint, rBmpEx.GetSizePixel() );
897 const Rectangle aSrcRect( rSrcPt, rSrcSz );
899 if( aSrcRect != aBmpRect )
900 aBmpEx.Crop( aSrcRect );
902 if( !!aBmpEx )
904 SvMemoryStream aOStm( 65535, 65535 );
906 if( GraphicConverter::Export( aOStm, rBmpEx, CVT_PNG ) == ERRCODE_NONE )
908 const Point aPt( ImplMap( rPt ) );
909 const Size aSz( ImplMap( rSz ) );
910 FastString aImageData( (sal_Char*) aOStm.GetData(), aOStm.Tell() );
911 REF( NMSP_SAX::XExtendedDocumentHandler ) xExtDocHandler( mrExport.GetDocHandler(), NMSP_UNO::UNO_QUERY );
913 if( xExtDocHandler.is() )
915 static const sal_uInt32 nPartLen = 64;
916 const NMSP_RTL::OUString aSpace( ' ' );
917 const NMSP_RTL::OUString aLineFeed( NMSP_RTL::OUString::valueOf( (sal_Unicode) 0x0a ) );
918 NMSP_RTL::OUString aString;
919 NMSP_RTL::OUString aImageString;
921 aString = aLineFeed;
922 aString += B2UCONST( "<" );
923 aString += NMSP_RTL::OUString::createFromAscii( aXMLElemImage );
924 aString += aSpace;
926 aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrX );
927 aString += B2UCONST( "=\"" );
928 aString += GetValueString( aPt.X() );
929 aString += B2UCONST( "\" " );
931 aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrY );
932 aString += B2UCONST( "=\"" );
933 aString += GetValueString( aPt.Y() );
934 aString += B2UCONST( "\" " );
936 aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrWidth );
937 aString += B2UCONST( "=\"" );
938 aString += GetValueString( aSz.Width() );
939 aString += B2UCONST( "\" " );
941 aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrHeight );
942 aString += B2UCONST( "=\"" );
943 aString += GetValueString( aSz.Height() );
944 aString += B2UCONST( "\" " );
946 aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrXLinkHRef );
947 aString += B2UCONST( "=\"data:image/png;base64," );
949 if( aImageData.GetFirstPartString( nPartLen, aImageString ) )
951 xExtDocHandler->unknown( aString += aImageString );
953 while( aImageData.GetNextPartString( nPartLen, aImageString ) )
955 xExtDocHandler->unknown( aLineFeed );
956 xExtDocHandler->unknown( aImageString );
960 xExtDocHandler->unknown( B2UCONST( "\"/>" ) );
967 // -----------------------------------------------------------------------------
969 void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
970 const NMSP_RTL::OUString* pStyle,
971 sal_uInt32 nWriteFlags )
973 ImplAcquireContext();
975 for( ULONG i = 0, nCount = rMtf.GetActionCount(); i < nCount; i++ )
977 const MetaAction* pAction = rMtf.GetAction( i );
978 const USHORT nType = pAction->GetType();
980 switch( nType )
982 case( META_PIXEL_ACTION ):
984 if( nWriteFlags & SVGWRITER_WRITE_FILL )
986 const MetaPixelAction* pA = (const MetaPixelAction*) pAction;
988 mpContext->SetPaintAttr( pA->GetColor(), pA->GetColor() );
989 ImplWriteLine( pA->GetPoint(), pA->GetPoint(), &pA->GetColor(), pStyle );
992 break;
994 case( META_POINT_ACTION ):
996 if( nWriteFlags & SVGWRITER_WRITE_FILL )
998 const MetaPointAction* pA = (const MetaPointAction*) pAction;
1000 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() );
1001 ImplWriteLine( pA->GetPoint(), pA->GetPoint(), NULL, pStyle );
1004 break;
1006 case( META_LINE_ACTION ):
1008 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1010 const MetaLineAction* pA = (const MetaLineAction*) pAction;
1012 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() );
1013 ImplWriteLine( pA->GetStartPoint(), pA->GetEndPoint(), NULL, pStyle );
1016 break;
1018 case( META_RECT_ACTION ):
1020 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1022 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1023 ImplWriteRect( ( (const MetaRectAction*) pAction )->GetRect(), 0, 0, pStyle );
1026 break;
1028 case( META_ROUNDRECT_ACTION ):
1030 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1032 const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pAction;
1034 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1035 ImplWriteRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound(), pStyle );
1038 break;
1040 case( META_ELLIPSE_ACTION ):
1042 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1044 const MetaEllipseAction* pA = (const MetaEllipseAction*) pAction;
1045 const Rectangle& rRect = pA->GetRect();
1047 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1048 ImplWriteEllipse( rRect.Center(), rRect.GetWidth() >> 1, rRect.GetHeight() >> 1, pStyle );
1051 break;
1053 case( META_ARC_ACTION ):
1054 case( META_PIE_ACTION ):
1055 case( META_CHORD_ACTION ):
1056 case( META_POLYGON_ACTION ):
1058 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1060 Polygon aPoly;
1062 switch( nType )
1064 case( META_ARC_ACTION ):
1066 const MetaArcAction* pA = (const MetaArcAction*) pAction;
1067 aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_ARC );
1069 break;
1071 case( META_PIE_ACTION ):
1073 const MetaPieAction* pA = (const MetaPieAction*) pAction;
1074 aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_PIE );
1076 break;
1078 case( META_CHORD_ACTION ):
1080 const MetaChordAction* pA = (const MetaChordAction*) pAction;
1081 aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_CHORD );
1083 break;
1085 case( META_POLYGON_ACTION ):
1086 aPoly = ( (const MetaPolygonAction*) pAction )->GetPolygon();
1087 break;
1090 if( aPoly.GetSize() )
1092 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1093 ImplWritePolyPolygon( aPoly, sal_False, pStyle );
1097 break;
1099 case( META_POLYLINE_ACTION ):
1101 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1103 const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pAction;
1104 const Polygon& rPoly = pA->GetPolygon();
1106 if( rPoly.GetSize() )
1108 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1109 ImplWritePolyPolygon( rPoly, sal_True, pStyle );
1113 break;
1115 case( META_POLYPOLYGON_ACTION ):
1117 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1119 const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pAction;
1120 const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
1122 if( rPolyPoly.Count() )
1124 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1125 ImplWritePolyPolygon( rPolyPoly, sal_False, pStyle );
1129 break;
1131 case( META_GRADIENT_ACTION ):
1133 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1135 const MetaGradientAction* pA = (const MetaGradientAction*) pAction;
1136 const Polygon aRectPoly( pA->GetRect() );
1137 const PolyPolygon aRectPolyPoly( aRectPoly );
1139 ImplWriteGradientEx( aRectPolyPoly, pA->GetGradient(), pStyle, nWriteFlags );
1142 break;
1144 case( META_GRADIENTEX_ACTION ):
1146 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1148 const MetaGradientExAction* pA = (const MetaGradientExAction*) pAction;
1149 ImplWriteGradientEx( pA->GetPolyPolygon(), pA->GetGradient(), pStyle, nWriteFlags );
1152 break;
1154 case META_HATCH_ACTION:
1156 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1158 const MetaHatchAction* pA = (const MetaHatchAction*) pAction;
1159 GDIMetaFile aTmpMtf;
1161 mpVDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
1162 ImplWriteActions( aTmpMtf, pStyle, nWriteFlags );
1165 break;
1167 case( META_TRANSPARENT_ACTION ):
1169 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1171 const MetaTransparentAction* pA = (const MetaTransparentAction*) pAction;
1172 const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
1174 if( rPolyPoly.Count() )
1176 const Color aOldLineColor( mpVDev->GetLineColor() ), aOldFillColor( mpVDev->GetFillColor() );
1177 Color aNewLineColor( aOldLineColor ), aNewFillColor( aOldFillColor );
1179 aNewLineColor.SetTransparency( sal::static_int_cast<UINT8>( FRound( pA->GetTransparence() * 2.55 ) ) );
1180 aNewFillColor.SetTransparency( sal::static_int_cast<UINT8>( FRound( pA->GetTransparence() * 2.55 ) ) );
1182 mpContext->SetPaintAttr( aNewLineColor, aNewFillColor );
1183 ImplWritePolyPolygon( rPolyPoly, sal_False, pStyle );
1184 mpContext->SetPaintAttr( aOldLineColor, aOldFillColor );
1188 break;
1190 case( META_FLOATTRANSPARENT_ACTION ):
1192 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1194 const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pAction;
1195 GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
1196 Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
1197 const Size aSrcSize( aTmpMtf.GetPrefSize() );
1198 const Point aDestPt( pA->GetPoint() );
1199 const Size aDestSize( pA->GetSize() );
1200 const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
1201 const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
1202 long nMoveX, nMoveY;
1204 if( fScaleX != 1.0 || fScaleY != 1.0 )
1206 aTmpMtf.Scale( fScaleX, fScaleY );
1207 aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
1210 nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
1212 if( nMoveX || nMoveY )
1213 aTmpMtf.Move( nMoveX, nMoveY );
1215 mpVDev->Push();
1216 ImplWriteActions( aTmpMtf, pStyle, nWriteFlags );
1217 mpVDev->Pop();
1220 break;
1222 case( META_EPS_ACTION ):
1224 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1226 const MetaEPSAction* pA = (const MetaEPSAction*) pAction;
1227 const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
1228 sal_Bool bFound = sal_False;
1230 for( ULONG j = 0, nC = aGDIMetaFile.GetActionCount(); ( j < nC ) && !bFound; j++ )
1232 const MetaAction* pSubstAct = aGDIMetaFile.GetAction( j );
1234 if( pSubstAct->GetType() == META_BMPSCALE_ACTION )
1236 bFound = sal_True;
1237 const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*) pSubstAct;
1238 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1239 ImplWriteBmp( pBmpScaleAction->GetBitmap(),
1240 pA->GetPoint(), pA->GetSize(),
1241 Point(), pBmpScaleAction->GetBitmap().GetSizePixel(), pStyle );
1246 break;
1248 case( META_COMMENT_ACTION ):
1250 const MetaCommentAction* pA = (const MetaCommentAction*) pAction;
1251 String aSkipComment;
1253 if( ( pA->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL ) &&
1254 ( nWriteFlags & SVGWRITER_WRITE_FILL ) )
1256 const MetaGradientExAction* pGradAction = NULL;
1257 sal_Bool bDone = sal_False;
1259 while( !bDone && ( ++i < nCount ) )
1261 pAction = rMtf.GetAction( i );
1263 if( pAction->GetType() == META_GRADIENTEX_ACTION )
1264 pGradAction = (const MetaGradientExAction*) pAction;
1265 else if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
1266 ( ( (const MetaCommentAction*) pAction )->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_END" ) == COMPARE_EQUAL ) )
1268 bDone = sal_True;
1272 if( pGradAction )
1273 ImplWriteGradientEx( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), pStyle, nWriteFlags );
1276 break;
1278 case( META_BMP_ACTION ):
1280 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1282 const MetaBmpAction* pA = (const MetaBmpAction*) pAction;
1284 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1285 ImplWriteBmp( pA->GetBitmap(),
1286 pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmap().GetSizePixel() ),
1287 Point(), pA->GetBitmap().GetSizePixel(), pStyle );
1290 break;
1292 case( META_BMPSCALE_ACTION ):
1294 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1296 const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
1298 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1299 ImplWriteBmp( pA->GetBitmap(),
1300 pA->GetPoint(), pA->GetSize(),
1301 Point(), pA->GetBitmap().GetSizePixel(), pStyle );
1304 break;
1306 case( META_BMPSCALEPART_ACTION ):
1308 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1310 const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pAction;
1312 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1313 ImplWriteBmp( pA->GetBitmap(),
1314 pA->GetDestPoint(), pA->GetDestSize(),
1315 pA->GetSrcPoint(), pA->GetSrcSize(), pStyle );
1318 break;
1320 case( META_BMPEX_ACTION ):
1322 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1324 const MetaBmpExAction* pA = (const MetaBmpExAction*) pAction;
1326 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1327 ImplWriteBmp( pA->GetBitmapEx(),
1328 pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmapEx().GetSizePixel() ),
1329 Point(), pA->GetBitmapEx().GetSizePixel(), pStyle );
1332 break;
1334 case( META_BMPEXSCALE_ACTION ):
1336 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1338 const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
1340 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1341 ImplWriteBmp( pA->GetBitmapEx(),
1342 pA->GetPoint(), pA->GetSize(),
1343 Point(), pA->GetBitmapEx().GetSizePixel(), pStyle );
1346 break;
1348 case( META_BMPEXSCALEPART_ACTION ):
1350 if( nWriteFlags & SVGWRITER_WRITE_FILL )
1352 const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pAction;
1354 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1355 ImplWriteBmp( pA->GetBitmapEx(),
1356 pA->GetDestPoint(), pA->GetDestSize(),
1357 pA->GetSrcPoint(), pA->GetSrcSize(), pStyle );
1360 break;
1362 case( META_TEXT_ACTION ):
1364 if( nWriteFlags & SVGWRITER_WRITE_TEXT )
1366 const MetaTextAction* pA = (const MetaTextAction*) pAction;
1367 Font aFont( mpVDev->GetFont() );
1369 aFont.SetHeight( ImplMap( Size( 0, aFont.GetHeight() ) ).Height() );
1370 mpContext->SetFontAttr( aFont );
1371 mpContext->SetPaintAttr( COL_TRANSPARENT, aFont.GetColor() );
1372 ImplWriteText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), NULL, 0, pStyle );
1375 break;
1377 case( META_TEXTRECT_ACTION ):
1379 if( nWriteFlags & SVGWRITER_WRITE_TEXT )
1381 const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
1382 Font aFont( mpVDev->GetFont() );
1384 aFont.SetHeight( ImplMap( Size( 0, aFont.GetHeight() ) ).Height() );
1385 mpContext->SetFontAttr( aFont );
1386 mpContext->SetPaintAttr( COL_TRANSPARENT, aFont.GetColor() );
1387 ImplWriteText( pA->GetRect().TopLeft(), pA->GetText(), NULL, 0, pStyle );
1390 break;
1392 case( META_TEXTARRAY_ACTION ):
1394 if( nWriteFlags & SVGWRITER_WRITE_TEXT )
1396 const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction;
1397 const Point aPos( ImplMap( pA->GetPoint() ) );
1398 Font aFont( mpVDev->GetFont() );
1400 aFont.SetHeight( ImplMap( Size( 0, aFont.GetHeight() ) ).Height() );
1401 mpContext->SetFontAttr( aFont );
1402 mpContext->SetPaintAttr( COL_TRANSPARENT, aFont.GetColor() );
1403 ImplWriteText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), pA->GetDXArray(), 0, pStyle );
1406 break;
1408 case( META_STRETCHTEXT_ACTION ):
1410 if( nWriteFlags & SVGWRITER_WRITE_TEXT )
1412 const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction;
1413 Font aFont( mpVDev->GetFont() );
1415 aFont.SetHeight( ImplMap( Size( 0, aFont.GetHeight() ) ).Height() );
1416 mpContext->SetFontAttr( aFont );
1417 mpContext->SetPaintAttr( COL_TRANSPARENT, aFont.GetColor() );
1418 ImplWriteText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), NULL, pA->GetWidth(), pStyle );
1421 break;
1423 case( META_CLIPREGION_ACTION ):
1424 case( META_ISECTRECTCLIPREGION_ACTION ):
1425 case( META_ISECTREGIONCLIPREGION_ACTION ):
1426 case( META_MOVECLIPREGION_ACTION ):
1428 ( (MetaAction*) pAction )->Execute( mpVDev );
1429 mbClipAttrChanged = sal_True;
1431 break;
1433 case( META_REFPOINT_ACTION ):
1434 case( META_MAPMODE_ACTION ):
1435 case( META_LINECOLOR_ACTION ):
1436 case( META_FILLCOLOR_ACTION ):
1437 case( META_TEXTLINECOLOR_ACTION ):
1438 case( META_TEXTFILLCOLOR_ACTION ):
1439 case( META_TEXTCOLOR_ACTION ):
1440 case( META_TEXTALIGN_ACTION ):
1441 case( META_FONT_ACTION ):
1442 case( META_PUSH_ACTION ):
1443 case( META_POP_ACTION ):
1444 case( META_LAYOUTMODE_ACTION ):
1446 ( (MetaAction*) pAction )->Execute( mpVDev );
1448 break;
1450 case( META_RASTEROP_ACTION ):
1451 case( META_MASK_ACTION ):
1452 case( META_MASKSCALE_ACTION ):
1453 case( META_MASKSCALEPART_ACTION ):
1454 case( META_WALLPAPER_ACTION ):
1455 case( META_TEXTLINE_ACTION ):
1457 // !!! >>> we don't want to support these actions
1459 break;
1461 default:
1462 DBG_ERROR( "SVGActionWriter::ImplWriteActions: unsupported MetaAction #" );
1463 break;
1467 ImplReleaseContext();
1470 // -----------------------------------------------------------------------------
1472 void SVGActionWriter::WriteMetaFile( const Point& rPos100thmm,
1473 const Size& rSize100thmm,
1474 const GDIMetaFile& rMtf,
1475 sal_uInt32 nWriteFlags )
1477 MapMode aMapMode( rMtf.GetPrefMapMode() );
1478 Size aPrefSize( rMtf.GetPrefSize() );
1479 Fraction aFractionX( aMapMode.GetScaleX() );
1480 Fraction aFractionY( aMapMode.GetScaleY() );
1482 mpVDev->Push();
1484 Size aSize( OutputDevice::LogicToLogic( rSize100thmm, MAP_100TH_MM, aMapMode ) );
1485 aMapMode.SetScaleX( aFractionX *= Fraction( aSize.Width(), aPrefSize.Width() ) );
1486 aMapMode.SetScaleY( aFractionY *= Fraction( aSize.Height(), aPrefSize.Height() ) );
1488 Point aOffset( OutputDevice::LogicToLogic( rPos100thmm, MAP_100TH_MM, aMapMode ) );
1489 aMapMode.SetOrigin( aOffset += aMapMode.GetOrigin() );
1491 mpVDev->SetMapMode( aMapMode );
1493 ImplWriteActions( rMtf, NULL, nWriteFlags );
1495 mpVDev->Pop();