merged tag ooo/OOO330_m14
[LibreOffice.git] / extensions / source / svg / svgaction.cxx
blobdc2c47ecb9379708b8ce0f3c145eb07de9e3e68a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
31 #include "svgaction.hxx"
32 #include <vcl/virdev.hxx>
33 #include <vcl/cvtgrf.hxx>
34 #include <vcl/metric.hxx>
36 #undef _SVG_USE_NATIVE_TEXTDECORATION
37 #undef _SVG_USE_TSPANS
39 // -----------
40 // - statics -
41 // -----------
43 static const char aXMLElemSVG[] = "svg";
44 static const char aXMLElemG[] = "g";
45 static const char aXMLElemDefs[] = "defs";
46 static const char aXMLElemClipPath[] = "clipPath";
47 static const char aXMLElemLine[] = "line";
48 static const char aXMLElemRect[] = "rect";
49 static const char aXMLElemEllipse[] = "ellipse";
50 static const char aXMLElemPath[] = "path";
51 static const char aXMLElemPolygon[] = "polygon";
52 static const char aXMLElemPolyLine[] = "polyline";
53 static const char aXMLElemText[] = "text";
54 static const char aXMLElemTSpan[] = "tspan";
55 static const char aXMLElemImage[] = "image";
57 static const char aXMLAttrTransform[] = "transform";
58 static const char aXMLAttrStyle[] = "style";
59 static const char aXMLAttrId[] = "id";
61 static const char aXMLAttrD[] = "d";
62 static const char aXMLAttrX[] = "x";
63 static const char aXMLAttrY[] = "y";
64 static const char aXMLAttrX1[] = "x1";
65 static const char aXMLAttrY1[] = "y1";
66 static const char aXMLAttrX2[] = "x2";
67 static const char aXMLAttrY2[] = "y2";
68 static const char aXMLAttrCX[] = "cx";
69 static const char aXMLAttrCY[] = "cy";
70 static const char aXMLAttrRX[] = "rx";
71 static const char aXMLAttrRY[] = "ry";
72 static const char aXMLAttrWidth[] = "width";
73 static const char aXMLAttrHeight[] = "height";
74 static const char aXMLAttrPoints[] = "points";
75 static const char aXMLAttrXLinkHRef[] = "xlink:href";
77 static const sal_Unicode pBase64[] =
79 //0 1 2 3 4 5 6 7
80 'A','B','C','D','E','F','G','H', // 0
81 'I','J','K','L','M','N','O','P', // 1
82 'Q','R','S','T','U','V','W','X', // 2
83 'Y','Z','a','b','c','d','e','f', // 3
84 'g','h','i','j','k','l','m','n', // 4
85 'o','p','q','r','s','t','u','v', // 5
86 'w','x','y','z','0','1','2','3', // 6
87 '4','5','6','7','8','9','+','/' // 7
90 // --------------
91 // - FastString -
92 // --------------
94 FastString::FastString( sal_uInt32 nInitLen, sal_uInt32 nIncrement ) :
95 mpBuffer( new sal_Unicode[ nInitLen * sizeof( sal_Unicode ) ] ),
96 mnBufLen( nInitLen ),
97 mnCurLen( 0 ),
98 mnBufInc( nIncrement ),
99 mnPartPos( 0 )
101 DBG_ASSERT( nInitLen, "invalid initial length" );
102 DBG_ASSERT( nIncrement, "invalid increment" );
105 // -----------------------------------------------------------------------------
107 FastString::FastString( sal_Char* pBufferForBase64Encoding, sal_uInt32 nBufLen ) :
108 mnBufInc( 2048 ),
109 mnPartPos( 0 )
111 DBG_ASSERT( pBufferForBase64Encoding && nBufLen, "invalid arguments" );
113 const sal_uInt32 nQuadCount = nBufLen / 3;
114 const sal_uInt32 nRest = nBufLen % 3;
116 if( nQuadCount || nRest )
118 mnBufLen = mnCurLen = ( ( nQuadCount + ( nRest ? 1 : 0 ) ) << 2 );
119 mpBuffer = new sal_Unicode[ mnBufLen * sizeof( sal_Unicode ) ];
121 sal_Char* pTmpSrc = pBufferForBase64Encoding;
122 sal_Unicode* pTmpDst = mpBuffer;
124 for( sal_uInt32 i = 0; i < nQuadCount; i++ )
126 const sal_Int32 nA = *pTmpSrc++;
127 const sal_Int32 nB = *pTmpSrc++;
128 const sal_Int32 nC = *pTmpSrc++;
130 *pTmpDst++ = pBase64[ ( nA >> 2 ) & 0x3f ];
131 *pTmpDst++ = pBase64[ ( ( nA << 4 ) & 0x30 ) + ( ( nB >> 4 ) & 0xf ) ];
132 *pTmpDst++ = pBase64[ ( ( nB << 2 ) & 0x3c ) + ( ( nC >> 6 ) & 0x3 ) ];
133 *pTmpDst++ = pBase64[ nC & 0x3f ];
136 if( 1 == nRest )
138 const sal_Int32 nA = *pTmpSrc;
140 *pTmpDst++ = pBase64[ ( nA >> 2 ) & 0x3f ];
141 *pTmpDst++ = pBase64[ ( nA << 4 ) & 0x30 ];
142 *pTmpDst++ = '=';
143 *pTmpDst = '=';
145 else if( 2 == nRest )
147 const sal_Int32 nA = *pTmpSrc++;
148 const sal_Int32 nB = *pTmpSrc;
150 *pTmpDst++ = pBase64[ ( nA >> 2 ) & 0x3f ];
151 *pTmpDst++ = pBase64[ ( ( nA << 4 ) & 0x30 ) + ( ( nB >> 4 ) & 0xf ) ];
152 *pTmpDst++ = pBase64[ ( nB << 2 ) & 0x3c ];
153 *pTmpDst = '=';
156 else
158 mpBuffer = new sal_Unicode[ ( mnBufLen = 1 ) * sizeof( sal_Unicode ) ];
159 mnCurLen = 0;
163 // -----------------------------------------------------------------------------
165 FastString::~FastString()
167 delete[] mpBuffer;
170 // -----------------------------------------------------------------------------
172 FastString& FastString::operator+=( const NMSP_RTL::OUString& rStr )
174 if( rStr.getLength() )
176 if( ( mnCurLen + rStr.getLength() ) > mnBufLen )
178 const sal_uInt32 nNewBufLen = ( mnBufLen + ( ( ( mnCurLen + rStr.getLength() ) - mnBufLen ) / mnBufInc + 1 ) * mnBufInc );
179 sal_Unicode* pNewBuffer = new sal_Unicode[ nNewBufLen * sizeof( sal_Unicode ) ];
181 memcpy( pNewBuffer, mpBuffer, mnBufLen * sizeof( sal_Unicode ) );
182 delete[] mpBuffer;
183 mpBuffer = pNewBuffer;
184 mnBufLen = nNewBufLen;
187 memcpy( mpBuffer + mnCurLen, rStr.getStr(), rStr.getLength() * sizeof( sal_Unicode ) );
188 mnCurLen += rStr.getLength();
190 if( maString.getLength() )
191 maString = NMSP_RTL::OUString();
194 return *this;
197 // -----------------------------------------------------------------------------
199 const NMSP_RTL::OUString& FastString::GetString() const
201 if( !maString.getLength() && mnCurLen )
202 ( (FastString*) this )->maString = NMSP_RTL::OUString( mpBuffer, mnCurLen );
204 return maString;
207 // -----------------------------------------------------------------------------
209 sal_Bool FastString::GetFirstPartString( const sal_uInt32 nPartLen, NMSP_RTL::OUString& rPartString )
211 const sal_uInt32 nLength = Min( mnCurLen, nPartLen );
213 mnPartPos = 0;
215 if( nLength )
217 rPartString = NMSP_RTL::OUString( mpBuffer, nLength );
218 mnPartPos = nLength;
221 return( rPartString.getLength() > 0 );
224 // -----------------------------------------------------------------------------
226 sal_Bool FastString::GetNextPartString( const sal_uInt32 nPartLen, NMSP_RTL::OUString& rPartString )
228 if( mnPartPos < mnCurLen )
230 const sal_uInt32 nLength = Min( mnCurLen - mnPartPos, nPartLen );
231 rPartString = NMSP_RTL::OUString( mpBuffer + mnPartPos, nLength );
232 mnPartPos += nLength;
234 else
235 rPartString = NMSP_RTL::OUString();
237 return( rPartString.getLength() > 0 );
240 // ----------------------
241 // - SVGAttributeWriter -
242 // ----------------------
244 SVGAttributeWriter::SVGAttributeWriter( SVGActionWriter& rParent, SvXMLExport& rExport ) :
245 mrParent( rParent ),
246 mrExport( rExport ),
247 mpElemFont( NULL ),
248 mpElemPaint( NULL )
252 // -----------------------------------------------------------------------------
254 SVGAttributeWriter::~SVGAttributeWriter()
256 delete mpElemPaint;
257 delete mpElemFont;
260 // -----------------------------------------------------------------------------
262 NMSP_RTL::OUString SVGAttributeWriter::GetFontStyle( const Font& rFont )
264 FastString aStyle;
266 // font family
267 aStyle += B2UCONST( "font-family:" );
268 aStyle += NMSP_RTL::OUString( rFont.GetName().GetToken( 0, ';' ) );
270 // font size
271 aStyle += B2UCONST( ";" );
272 aStyle += B2UCONST( "font-size:" );
273 aStyle += mrParent.GetValueString( mrParent.ImplMap( Size( 0, rFont.GetHeight() ) ).Height(), mrParent.HasDoublePoints() );
275 // font style
276 if( rFont.GetItalic() != ITALIC_NONE )
278 aStyle += B2UCONST( ";" );
279 aStyle += B2UCONST( "font-style:" );
281 if( rFont.GetItalic() == ITALIC_OBLIQUE )
282 aStyle += B2UCONST( "oblique" );
283 else
284 aStyle += B2UCONST( "italic" );
287 // font weight
288 sal_Int32 nFontWeight;
290 switch( rFont.GetWeight() )
292 case WEIGHT_THIN: nFontWeight = 100; break;
293 case WEIGHT_ULTRALIGHT: nFontWeight = 200; break;
294 case WEIGHT_LIGHT: nFontWeight = 300; break;
295 case WEIGHT_SEMILIGHT: nFontWeight = 400; break;
296 case WEIGHT_NORMAL: nFontWeight = 400; break;
297 case WEIGHT_MEDIUM: nFontWeight = 500; break;
298 case WEIGHT_SEMIBOLD: nFontWeight = 600; break;
299 case WEIGHT_BOLD: nFontWeight = 700; break;
300 case WEIGHT_ULTRABOLD: nFontWeight = 800; break;
301 case WEIGHT_BLACK: nFontWeight = 900; break;
302 default: nFontWeight = 400; break;
305 aStyle += B2UCONST( ";" );
306 aStyle += B2UCONST( "font-weight:" );
307 aStyle += NMSP_RTL::OUString::valueOf( nFontWeight );
309 // !!!
310 // font-variant
311 // font-stretch
312 // font-size-adjust
314 #ifdef _SVG_USE_NATIVE_TEXTDECORATION
316 if( rFont.GetUnderline() != UNDERLINE_NONE || rFont.GetStrikeout() != STRIKEOUT_NONE )
318 aStyle += B2UCONST( ";" );
319 aStyle += B2UCONST( "text-decoration:" );
321 if( rFont.GetUnderline() != UNDERLINE_NONE )
322 aStyle += B2UCONST( " underline" );
324 if( rFont.GetStrikeout() != STRIKEOUT_NONE )
325 aStyle += B2UCONST( " line-through" );
328 #endif // _SVG_USE_NATIVE_TEXTDECORATION
330 return aStyle.GetString();
333 // -----------------------------------------------------------------------------
335 NMSP_RTL::OUString SVGAttributeWriter::GetPaintStyle( const Color& rLineColor, const Color& rFillColor )
337 FastString aStyle;
339 // line color
340 aStyle += B2UCONST( "stroke:" );
342 if( rLineColor.GetTransparency() == 255 )
343 aStyle += B2UCONST( "none" );
344 else
346 // line color value in rgb
347 aStyle += B2UCONST( "rgb(" );
348 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rLineColor.GetRed() );
349 aStyle += B2UCONST( "," );
350 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rLineColor.GetGreen() );
351 aStyle += B2UCONST( "," );
352 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rLineColor.GetBlue() );
353 aStyle += B2UCONST( ")" );
355 // line color opacity in percent if neccessary
356 if( rLineColor.GetTransparency() )
358 aStyle += B2UCONST( ";" );
359 aStyle += B2UCONST( "stroke-opacity:" );
360 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) ( ( 255 - (double) rLineColor.GetTransparency() ) / 2.55 ) );
361 aStyle += B2UCONST( "%" );
365 // fill color
366 aStyle += B2UCONST( ";" );
367 aStyle += B2UCONST( "fill:" );
369 if( rFillColor.GetTransparency() == 255 )
370 aStyle += B2UCONST( "none" );
371 else
373 // fill color value in rgb
374 aStyle += B2UCONST( "rgb(" );
375 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rFillColor.GetRed() );
376 aStyle += B2UCONST( "," );
377 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rFillColor.GetGreen() );
378 aStyle += B2UCONST( "," );
379 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rFillColor.GetBlue() );
380 aStyle += B2UCONST( ")" );
382 // fill color opacity in percent if neccessary
383 if( rFillColor.GetTransparency() )
385 aStyle += B2UCONST( ";" );
386 aStyle += B2UCONST( "fill-opacity:" );
387 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) ( ( 255 - (double) rFillColor.GetTransparency() ) / 2.55 ) );
388 aStyle += B2UCONST( "%" );
392 return aStyle.GetString();
395 // -----------------------------------------------------------------------------
397 void SVGAttributeWriter::SetFontAttr( const Font& rFont )
399 if( !mpElemFont || ( rFont != maCurFont ) )
401 delete mpElemPaint, mpElemPaint = NULL;
402 delete mpElemFont;
403 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, GetFontStyle( maCurFont = rFont ) );
404 mpElemFont = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
408 // -----------------------------------------------------------------------------
410 void SVGAttributeWriter::SetPaintAttr( const Color& rLineColor, const Color& rFillColor )
412 if( !mpElemPaint || ( rLineColor != maCurLineColor ) || ( rFillColor != maCurFillColor ) )
414 delete mpElemPaint;
415 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, GetPaintStyle( maCurLineColor = rLineColor, maCurFillColor = rFillColor ) );
416 mpElemPaint = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
420 // -------------------
421 // - SVGActionWriter -
422 // -------------------
424 SVGActionWriter::SVGActionWriter( SvXMLExport& rExport, const GDIMetaFile& rMtf,
425 VirtualDevice* pParentVDev, sal_Bool bWriteDoublePoints ) :
426 mrExport( rExport ),
427 mrMtf( rMtf ),
428 mpContext( NULL ),
429 mnCurClipId( 1 ),
430 mbClipAttrChanged( sal_False ),
431 mbDoublePoints( bWriteDoublePoints )
433 if( pParentVDev )
435 mpVDev = pParentVDev;
436 mbDestroyVDev = sal_False;
437 maTargetMapMode = mpVDev->GetMapMode();
439 else
441 mpVDev = new VirtualDevice;
442 mpVDev->EnableOutput( sal_False );
443 mbDestroyVDev = sal_True;
444 maTargetMapMode = MAP_100TH_MM;
447 mpVDev->Push();
448 mpVDev->SetMapMode( mrMtf.GetPrefMapMode() );
449 ImplWriteActions( mrMtf );
450 mpVDev->Pop();
453 // -----------------------------------------------------------------------------
455 SVGActionWriter::~SVGActionWriter()
457 DBG_ASSERT( !mpContext, "Not all contexts are closed" );
459 if( mbDestroyVDev )
460 delete mpVDev;
463 // -----------------------------------------------------------------------------
465 long SVGActionWriter::ImplMap( sal_Int32 nVal ) const
467 return ImplMap( Size( nVal, nVal ) ).Width();
470 // -----------------------------------------------------------------------------
472 Point SVGActionWriter::ImplMap( const Point& rPt ) const
474 return mpVDev->LogicToLogic( rPt, mpVDev->GetMapMode(), maTargetMapMode );
477 // -----------------------------------------------------------------------------
479 Size SVGActionWriter::ImplMap( const Size& rSz ) const
481 return mpVDev->LogicToLogic( rSz, mpVDev->GetMapMode(), maTargetMapMode );
484 // -----------------------------------------------------------------------------
486 NMSP_RTL::OUString SVGActionWriter::GetValueString( sal_Int32 nVal, sal_Bool bDoublePoints )
488 if( !bDoublePoints )
489 return NMSP_RTL::OUString::valueOf( nVal );
490 else
492 const double fPoints = nVal * 72.0 / 2540.0;
493 const sal_Int32 nInt = (sal_Int32) fPoints;
495 return( ( NMSP_RTL::OUString::valueOf( nInt ) +=
496 NMSP_RTL::OUString::valueOf( (sal_Unicode) '.' ) ) +=
497 NMSP_RTL::OUString::valueOf( labs( (sal_Int32) ( ( fPoints - nInt ) * 100.0 ) ) ) );
501 // -----------------------------------------------------------------------------
503 void SVGActionWriter::ImplWriteLine( const Point& rPt1, const Point& rPt2, const Color* pLineColor,
504 const NMSP_RTL::OUString* pStyle )
506 const Point aPt1( ImplMap( rPt1 ) );
507 const Point aPt2( ImplMap( rPt2 ) );
509 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX1, GetValueString( aPt1.X(), mbDoublePoints ) );
510 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY1, GetValueString( aPt1.Y(), mbDoublePoints ) );
511 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX2, GetValueString( aPt2.X(), mbDoublePoints ) );
512 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY2, GetValueString( aPt2.Y(), mbDoublePoints ) );
514 // add additional style if requested
515 if( pStyle )
516 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle );
518 if( pLineColor )
520 // !!! mrExport.AddAttribute( XML_NAMESPACE_NONE, ... )
521 DBG_ERROR( "SVGActionWriter::ImplWriteLine: Line color not implemented" );
525 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemLine, TRUE, TRUE );
529 // -----------------------------------------------------------------------------
531 void SVGActionWriter::ImplWriteRect( const Rectangle& rRect, long nRadX, long nRadY,
532 const NMSP_RTL::OUString* pStyle )
534 const Rectangle aRect( ImplMap( rRect ) );
536 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, GetValueString( aRect.Left(), mbDoublePoints ) );
537 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, GetValueString( aRect.Top(), mbDoublePoints ) );
538 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrWidth, GetValueString( aRect.GetWidth(), mbDoublePoints ) );
539 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrHeight, GetValueString( aRect.GetHeight(), mbDoublePoints ) );
541 if( nRadX )
542 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRX, GetValueString( ImplMap( nRadX ), mbDoublePoints ) );
544 if( nRadY )
545 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRY, GetValueString( ImplMap( nRadY ), mbDoublePoints ) );
547 // add additional style if requested
548 if( pStyle )
549 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle );
552 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemRect, TRUE, TRUE );
556 // -----------------------------------------------------------------------------
558 void SVGActionWriter::ImplWriteEllipse( const Point& rCenter, long nRadX, long nRadY,
559 const NMSP_RTL::OUString* pStyle )
561 const Point aCenter( ImplMap( rCenter ) );
563 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCX, GetValueString( aCenter.X(), mbDoublePoints ) );
564 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCY, GetValueString( aCenter.Y(), mbDoublePoints ) );
565 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRX, GetValueString( ImplMap( nRadX ), mbDoublePoints ) );
566 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRY, GetValueString( ImplMap( nRadY ), mbDoublePoints ) );
568 // add additional style if requested
569 if( pStyle )
570 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle );
573 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemEllipse, TRUE, TRUE );
577 // -----------------------------------------------------------------------------
579 void SVGActionWriter::ImplWritePolygon( const Polygon& rPoly, sal_Bool bLineOnly,
580 const NMSP_RTL::OUString* pStyle )
582 if( rPoly.GetSize() )
584 if( rPoly.HasFlags() )
585 ImplWritePolyPolygon( rPoly, bLineOnly, pStyle );
586 else
588 FastString aStyle;
589 FastString aPoints;
590 USHORT i = 0, nSize = rPoly.GetSize();
591 const NMSP_RTL::OUString aBlank( B2UCONST( " " ) );
593 // points
594 while( i < nSize )
596 const Point aPolyPoint( ImplMap( rPoly[ i ] ) );
598 aPoints += GetValueString( aPolyPoint.X(), mbDoublePoints );
599 aPoints += B2UCONST( "," );
600 aPoints += GetValueString( aPolyPoint.Y(), mbDoublePoints );
602 if( ++i < nSize )
603 aPoints += aBlank;
606 // style
607 if( bLineOnly )
609 aStyle += B2UCONST( "fill:none" );
611 if( pStyle )
613 aStyle += B2UCONST( ";" );
614 aStyle += *pStyle;
617 else if( pStyle )
618 aStyle += *pStyle;
620 // add point attribute
621 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrPoints, aPoints.GetString() );
623 // add style attribute
624 if( aStyle.GetLength() )
625 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aStyle.GetString() );
628 // write polyline/polygon element
629 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, bLineOnly ? aXMLElemPolyLine : aXMLElemPolygon, TRUE, TRUE );
635 // -----------------------------------------------------------------------------
637 void SVGActionWriter::ImplWritePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bLineOnly,
638 const NMSP_RTL::OUString* pStyle )
640 if( rPolyPoly.Count() )
642 if( ( rPolyPoly.Count() == 1 ) && ( rPolyPoly[ 0 ].HasFlags() == sal_False ) )
643 ImplWritePolygon( rPolyPoly[ 0 ], bLineOnly, pStyle );
644 else
646 FastString aStyle;
647 FastString aPathData;
648 const NMSP_RTL::OUString aBlank( B2UCONST( " " ) );
649 const NMSP_RTL::OUString aComma( B2UCONST( "," ) );
650 Point aPolyPoint;
652 for( long i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ )
654 const Polygon& rPoly = rPolyPoly[ (USHORT) i ];
655 USHORT n = 1, nSize = rPoly.GetSize();
657 if( nSize > 1 )
659 aPathData += B2UCONST( "M " );
660 aPathData += GetValueString( ( aPolyPoint = ImplMap( rPoly[ 0 ] ) ).X(), mbDoublePoints );
661 aPathData += aComma;
662 aPathData += GetValueString( aPolyPoint.Y(), mbDoublePoints );
663 sal_Char nCurrentMode = 0;
665 while( n < nSize )
667 aPathData += aBlank;
668 if ( ( rPoly.GetFlags( n ) == POLY_CONTROL ) && ( ( n + 2 ) < nSize ) )
670 if ( nCurrentMode != 'C' )
672 nCurrentMode = 'C';
673 aPathData += B2UCONST( "C " );
675 for ( int j = 0; j < 3; j++ )
677 if ( j )
678 aPathData += aBlank;
679 aPathData += GetValueString( ( aPolyPoint = ImplMap( rPoly[ n++ ] ) ).X(), mbDoublePoints );
680 aPathData += aComma;
681 aPathData += GetValueString( aPolyPoint.Y(), mbDoublePoints );
684 else
686 if ( nCurrentMode != 'L' )
688 nCurrentMode = 'L';
689 aPathData += B2UCONST( "L " );
691 aPathData += GetValueString( ( aPolyPoint = ImplMap( rPoly[ n++ ] ) ).X(), mbDoublePoints );
692 aPathData += aComma;
693 aPathData += GetValueString( aPolyPoint.Y(), mbDoublePoints );
696 aPathData += B2UCONST( " Z" );
698 if( i < ( nCount - 1 ) )
699 aPathData += aBlank;
702 if( bLineOnly )
704 aStyle += B2UCONST( "fill:none" );
705 if( pStyle )
706 aStyle += B2UCONST( ";" );
708 if( pStyle )
709 aStyle += *pStyle;
711 // add style attribute
712 if( aStyle.GetLength() )
713 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aStyle.GetString() );
715 // add path data attribute
716 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrD, aPathData.GetString() );
718 // write polyline/polygon element
719 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemPath, TRUE, TRUE );
725 // -----------------------------------------------------------------------------
727 void SVGActionWriter::ImplWriteGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient,
728 const NMSP_RTL::OUString* pStyle )
730 if( rPolyPoly.Count() )
732 SvXMLElementExport aElemG( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
733 FastString aClipId;
734 FastString aClipStyle;
736 aClipId += B2UCONST( "clip" );
737 aClipId += NMSP_RTL::OUString::valueOf( ImplGetNextClipId() );
740 SvXMLElementExport aElemDefs( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, TRUE, TRUE );
742 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aClipId.GetString() );
745 SvXMLElementExport aElemClipPath( mrExport, XML_NAMESPACE_NONE, aXMLElemClipPath, TRUE, TRUE );
746 ImplWritePolyPolygon( rPolyPoly, sal_False );
750 // create new context with clippath set
751 aClipStyle += B2UCONST( "clip-path:URL(#" );
752 aClipStyle += aClipId.GetString();
753 aClipStyle += B2UCONST( ")" );
755 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aClipStyle.GetString() );
758 GDIMetaFile aTmpMtf;
759 SvXMLElementExport aElemG2( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
761 mpVDev->AddGradientActions( rPolyPoly.GetBoundRect(), rGradient, aTmpMtf );
762 ImplWriteActions( aTmpMtf, pStyle );
767 // -----------------------------------------------------------------------------
769 void SVGActionWriter::ImplWriteText( const Point& rPos, const String& rText,
770 const sal_Int32* pDXArray, long nWidth,
771 const NMSP_RTL::OUString* pStyle )
773 String aText( rText ); aText.EraseLeadingChars( ' ' );
774 UINT32 nLen = aText.Len(), i;
776 if( nLen )
778 Size aNormSize;
779 sal_Int32* pOwnArray;
780 sal_Int32* pDX;
782 // get text sizes
783 if( pDXArray )
785 pOwnArray = NULL;
786 aNormSize = Size( mpVDev->GetTextWidth( aText ), 0 );
787 pDX = const_cast< sal_Int32* >( pDXArray );
789 else
791 pOwnArray = new sal_Int32[ nLen ];
792 aNormSize = Size( mpVDev->GetTextArray( aText, pOwnArray ), 0 );
793 pDX = pOwnArray;
796 if( nLen > 1 )
798 aNormSize.Width() = pDX[ nLen - 2 ] + mpVDev->GetTextWidth( aText.GetChar( (USHORT) nLen - 1 ) );
800 if( nWidth && aNormSize.Width() && ( nWidth != aNormSize.Width() ) )
802 const double fFactor = (double) nWidth / aNormSize.Width();
804 for( i = 0; i < ( nLen - 1 ); i++ )
805 pDX[ i ] = FRound( pDX[ i ] * fFactor );
809 FastString aStyle;
810 const Font& rFont = mpVDev->GetFont();
811 const FontMetric aMetric( mpVDev->GetFontMetric() );
812 Point aBaseLinePos( rPos );
813 SvXMLElementExport* pTransform = NULL;
815 // leading whitespaces erased? => adjust position
816 if( nLen < rText.Len() )
818 aBaseLinePos.X() += mpVDev->GetTextWidth( ' ' ) * ( rText.Len() - nLen );
821 // always adjust text position to match baseline alignment
822 switch( rFont.GetAlign() )
824 case( ALIGN_TOP ):
825 aBaseLinePos.Y() += aMetric.GetAscent();
826 break;
828 case( ALIGN_BOTTOM ):
829 aBaseLinePos.Y() -= aMetric.GetDescent();
830 break;
832 default:
833 break;
836 // get mapped text position
837 const Point aPt( ImplMap( aBaseLinePos ) );
839 // if text is rotated, set transform at new g element
840 if( rFont.GetOrientation() )
842 String aTransform;
844 aTransform = NMSP_RTL::OUString::createFromAscii( "translate" );
845 aTransform += '(';
846 aTransform += String( GetValueString( aPt.X(), mbDoublePoints ) );
847 aTransform += ',';
848 aTransform += String( GetValueString( aPt.Y(), mbDoublePoints ) );
849 aTransform += ')';
851 aTransform += String( NMSP_RTL::OUString::createFromAscii( " rotate" ) );
852 aTransform += '(';
853 aTransform += String( NMSP_RTL::OUString::valueOf( rFont.GetOrientation() * -0.1 ) );
854 aTransform += ')';
856 aTransform += String( NMSP_RTL::OUString::createFromAscii( " translate" ) );
857 aTransform += '(';
858 aTransform += String( GetValueString( -aPt.X(), mbDoublePoints ) );
859 aTransform += ',';
860 aTransform += String( GetValueString( -aPt.Y(), mbDoublePoints ) );
861 aTransform += ')';
863 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTransform, aTransform );
864 pTransform = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
867 // add additional style if requested
868 if( pStyle && pStyle->getLength() )
869 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle );
871 // write text element
872 #ifdef _SVG_USE_TSPANS
873 if( pDXArray )
875 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemText, TRUE, TRUE );
876 FastString aTSpanX;
877 const NMSP_RTL::OUString aSpace( ' ' );
878 long i, nX, nCount;
880 aTSpanX += GetValueString( aPt.X(), mbDoublePoints );
881 aTSpanX += aSpace;
883 for( i = 0, nX = aPt.X(), nCount = ( nLen - 1 ); i < nCount; )
885 aTSpanX += GetValueString( aPt.X() + pDX[ i++ ], mbDoublePoints );
886 aTSpanX += aSpace;
889 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, aTSpanX.GetString() );
890 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, GetValueString( aPt.Y(), mbDoublePoints ) );
897 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTSpan, TRUE, TRUE );
898 mrExport.GetDocHandler()->characters( NMSP_RTL::OUString( UniString( aText ) ) );
900 catch( ::com::sun::star::xml::sax::SAXException& )
902 // string seems to contain invalid characters
907 else
908 #endif
910 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, GetValueString( aPt.X(), mbDoublePoints ) );
911 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, GetValueString( aPt.Y(), mbDoublePoints ) );
915 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemText, TRUE, TRUE );
916 mrExport.GetDocHandler()->characters( NMSP_RTL::OUString( UniString( aText ) ) );
918 catch( ::com::sun::star::xml::sax::SAXException& )
920 // string seems to contain invalid characters
924 #ifndef _SVG_USE_NATIVE_TEXTDECORATION
926 // write strikeout if neccessary
927 if( ( rFont.GetStrikeout() != STRIKEOUT_NONE ) || ( rFont.GetUnderline() != UNDERLINE_NONE ) )
929 Polygon aPoly( 4 );
930 const long nLineHeight = Max( (long) FRound( aMetric.GetLineHeight() * 0.05 ), (long) 1 );
932 if( rFont.GetStrikeout() )
934 const long nYLinePos = aBaseLinePos.Y() - FRound( aMetric.GetAscent() * 0.26 );
936 aPoly[ 0 ].X() = aBaseLinePos.X(); aPoly[ 0 ].Y() = nYLinePos - ( nLineHeight >> 1 );
937 aPoly[ 1 ].X() = aBaseLinePos.X() + aNormSize.Width() - 1; aPoly[ 1 ].Y() = aPoly[ 0 ].Y();
938 aPoly[ 2 ].X() = aPoly[ 1 ].X(); aPoly[ 2 ].Y() = aPoly[ 0 ].Y() + nLineHeight - 1;
939 aPoly[ 3 ].X() = aPoly[ 0 ].X(); aPoly[ 3 ].Y() = aPoly[ 2 ].Y();
941 ImplWritePolygon( aPoly, FALSE );
944 if( rFont.GetUnderline() )
946 const long nYLinePos = aBaseLinePos.Y() + ( nLineHeight << 1 );
948 aPoly[ 0 ].X() = aBaseLinePos.X(); aPoly[ 0 ].Y() = nYLinePos - ( nLineHeight >> 1 );
949 aPoly[ 1 ].X() = aBaseLinePos.X() + aNormSize.Width() - 1; aPoly[ 1 ].Y() = aPoly[ 0 ].Y();
950 aPoly[ 2 ].X() = aPoly[ 1 ].X(); aPoly[ 2 ].Y() = aPoly[ 0 ].Y() + nLineHeight - 1;
951 aPoly[ 3 ].X() = aPoly[ 0 ].X(); aPoly[ 3 ].Y() = aPoly[ 2 ].Y();
953 ImplWritePolygon( aPoly, FALSE );
957 #endif // _SVG_USE_NATIVE_TEXTDECORATION
959 delete[] pOwnArray;
960 delete pTransform;
964 // -----------------------------------------------------------------------------
966 void SVGActionWriter::ImplWriteBmp( const BitmapEx& rBmpEx,
967 const Point& rPt, const Size& rSz,
968 const Point& rSrcPt, const Size& rSrcSz,
969 const NMSP_RTL::OUString* /*pStyle*/ )
971 if( !!rBmpEx )
973 BitmapEx aBmpEx( rBmpEx );
974 Point aPoint = Point();
975 const Rectangle aBmpRect( aPoint, rBmpEx.GetSizePixel() );
976 const Rectangle aSrcRect( rSrcPt, rSrcSz );
978 if( aSrcRect != aBmpRect )
979 aBmpEx.Crop( aSrcRect );
981 if( !!aBmpEx )
983 SvMemoryStream aOStm( 65535, 65535 );
985 if( GraphicConverter::Export( aOStm, rBmpEx, CVT_PNG ) == ERRCODE_NONE )
987 const Point aPt( ImplMap( rPt ) );
988 const Size aSz( ImplMap( rSz ) );
989 FastString aImageData( (sal_Char*) aOStm.GetData(), aOStm.Tell() );
990 REF( NMSP_SAX::XExtendedDocumentHandler ) xExtDocHandler( mrExport.GetDocHandler(), NMSP_UNO::UNO_QUERY );
992 if( xExtDocHandler.is() )
994 static const sal_uInt32 nPartLen = 64;
995 const NMSP_RTL::OUString aSpace( ' ' );
996 const NMSP_RTL::OUString aLineFeed( NMSP_RTL::OUString::valueOf( (sal_Unicode) 0x0a ) );
997 NMSP_RTL::OUString aString;
998 NMSP_RTL::OUString aImageString;
1000 aString = aLineFeed;
1001 aString += B2UCONST( "<" );
1002 aString += NMSP_RTL::OUString::createFromAscii( aXMLElemImage );
1003 aString += aSpace;
1005 aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrX );
1006 aString += B2UCONST( "=\"" );
1007 aString += GetValueString( aPt.X(), mbDoublePoints );
1008 aString += B2UCONST( "\" " );
1010 aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrY );
1011 aString += B2UCONST( "=\"" );
1012 aString += GetValueString( aPt.Y(), mbDoublePoints );
1013 aString += B2UCONST( "\" " );
1015 aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrWidth );
1016 aString += B2UCONST( "=\"" );
1017 aString += GetValueString( aSz.Width(), mbDoublePoints );
1018 aString += B2UCONST( "\" " );
1020 aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrHeight );
1021 aString += B2UCONST( "=\"" );
1022 aString += GetValueString( aSz.Height(), mbDoublePoints );
1023 aString += B2UCONST( "\" " );
1025 aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrXLinkHRef );
1026 aString += B2UCONST( "=\"data:image/png;base64," );
1028 if( aImageData.GetFirstPartString( nPartLen, aImageString ) )
1030 xExtDocHandler->unknown( aString += aImageString );
1032 while( aImageData.GetNextPartString( nPartLen, aImageString ) )
1034 xExtDocHandler->unknown( aLineFeed );
1035 xExtDocHandler->unknown( aImageString );
1039 xExtDocHandler->unknown( B2UCONST( "\"/>" ) );
1046 // -----------------------------------------------------------------------------
1048 void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, const NMSP_RTL::OUString* pStyle )
1050 ImplAcquireContext();
1052 for( ULONG i = 0, nCount = rMtf.GetActionCount(); i < nCount; i++ )
1054 const MetaAction* pAction = rMtf.GetAction( i );
1055 const USHORT nType = pAction->GetType();
1057 switch( nType )
1059 case( META_PIXEL_ACTION ):
1061 const MetaPixelAction* pA = (const MetaPixelAction*) pAction;
1063 mpContext->SetPaintAttr( pA->GetColor(), pA->GetColor() );
1064 ImplWriteLine( pA->GetPoint(), pA->GetPoint(), &pA->GetColor(), pStyle );
1066 break;
1068 case( META_POINT_ACTION ):
1070 const MetaPointAction* pA = (const MetaPointAction*) pAction;
1072 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() );
1073 ImplWriteLine( pA->GetPoint(), pA->GetPoint(), NULL, pStyle );
1075 break;
1077 case( META_LINE_ACTION ):
1079 const MetaLineAction* pA = (const MetaLineAction*) pAction;
1081 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() );
1082 ImplWriteLine( pA->GetStartPoint(), pA->GetEndPoint(), NULL, pStyle );
1084 break;
1086 case( META_RECT_ACTION ):
1088 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1089 ImplWriteRect( ( (const MetaRectAction*) pAction )->GetRect(), 0, 0, pStyle );
1091 break;
1093 case( META_ROUNDRECT_ACTION ):
1095 const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pAction;
1097 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1098 ImplWriteRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound(), pStyle );
1100 break;
1102 case( META_ELLIPSE_ACTION ):
1104 const MetaEllipseAction* pA = (const MetaEllipseAction*) pAction;
1105 const Rectangle& rRect = pA->GetRect();
1107 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1108 ImplWriteEllipse( rRect.Center(), rRect.GetWidth() >> 1, rRect.GetHeight() >> 1, pStyle );
1110 break;
1112 case( META_ARC_ACTION ):
1113 case( META_PIE_ACTION ):
1114 case( META_CHORD_ACTION ):
1115 case( META_POLYGON_ACTION ):
1117 Polygon aPoly;
1119 switch( nType )
1121 case( META_ARC_ACTION ):
1123 const MetaArcAction* pA = (const MetaArcAction*) pAction;
1124 aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_ARC );
1126 break;
1128 case( META_PIE_ACTION ):
1130 const MetaPieAction* pA = (const MetaPieAction*) pAction;
1131 aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_PIE );
1133 break;
1135 case( META_CHORD_ACTION ):
1137 const MetaChordAction* pA = (const MetaChordAction*) pAction;
1138 aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_CHORD );
1140 break;
1142 case( META_POLYGON_ACTION ):
1143 aPoly = ( (const MetaPolygonAction*) pAction )->GetPolygon();
1144 break;
1147 if( aPoly.GetSize() )
1149 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1150 ImplWritePolygon( aPoly, sal_False, pStyle );
1153 break;
1155 case( META_POLYLINE_ACTION ):
1157 const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pAction;
1158 const Polygon& rPoly = pA->GetPolygon();
1160 if( rPoly.GetSize() )
1162 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1163 ImplWritePolygon( rPoly, sal_True, pStyle );
1166 break;
1168 case( META_POLYPOLYGON_ACTION ):
1170 const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pAction;
1171 const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
1173 if( rPolyPoly.Count() )
1175 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1176 ImplWritePolyPolygon( rPolyPoly, sal_False, pStyle );
1179 break;
1181 case( META_GRADIENT_ACTION ):
1183 const MetaGradientAction* pA = (const MetaGradientAction*) pAction;
1184 GDIMetaFile aTmpMtf;
1186 mpVDev->AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
1187 ImplWriteActions( aTmpMtf, pStyle );
1189 break;
1191 case( META_GRADIENTEX_ACTION ):
1193 const MetaGradientExAction* pA = (const MetaGradientExAction*) pAction;
1194 ImplWriteGradientEx( pA->GetPolyPolygon(), pA->GetGradient(), pStyle );
1196 break;
1198 case META_HATCH_ACTION:
1200 const MetaHatchAction* pA = (const MetaHatchAction*) pAction;
1201 GDIMetaFile aTmpMtf;
1203 mpVDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
1204 ImplWriteActions( aTmpMtf, pStyle );
1206 break;
1208 case( META_TRANSPARENT_ACTION ):
1210 const MetaTransparentAction* pA = (const MetaTransparentAction*) pAction;
1211 const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
1213 if( rPolyPoly.Count() )
1215 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1216 ImplWritePolyPolygon( rPolyPoly, sal_False, pStyle );
1219 break;
1221 case( META_FLOATTRANSPARENT_ACTION ):
1223 const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pAction;
1224 GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
1225 Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
1226 const Size aSrcSize( aTmpMtf.GetPrefSize() );
1227 const Point aDestPt( pA->GetPoint() );
1228 const Size aDestSize( pA->GetSize() );
1229 const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
1230 const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
1231 long nMoveX, nMoveY;
1233 if( fScaleX != 1.0 || fScaleY != 1.0 )
1235 aTmpMtf.Scale( fScaleX, fScaleY );
1236 aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
1239 nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
1241 if( nMoveX || nMoveY )
1242 aTmpMtf.Move( nMoveX, nMoveY );
1244 mpVDev->Push();
1245 ImplWriteActions( aTmpMtf, pStyle );
1246 mpVDev->Pop();
1248 break;
1250 case( META_EPS_ACTION ):
1252 const MetaEPSAction* pA = (const MetaEPSAction*) pAction;
1253 const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
1254 sal_Bool bFound = sal_False;
1256 for( ULONG j = 0, nCount2 = aGDIMetaFile.GetActionCount(); ( j < nCount2 ) && !bFound; j++ )
1258 const MetaAction* pSubstAct = aGDIMetaFile.GetAction( j );
1260 if( pSubstAct->GetType() == META_BMPSCALE_ACTION )
1262 bFound = sal_True;
1263 const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*) pSubstAct;
1264 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1265 ImplWriteBmp( pBmpScaleAction->GetBitmap(),
1266 pA->GetPoint(), pA->GetSize(),
1267 Point(), pBmpScaleAction->GetBitmap().GetSizePixel(), pStyle );
1271 break;
1273 case( META_COMMENT_ACTION ):
1275 const MetaCommentAction* pA = (const MetaCommentAction*) pAction;
1276 String aSkipComment;
1278 if( pA->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL )
1280 const MetaGradientExAction* pGradAction = NULL;
1281 sal_Bool bDone = sal_False;
1283 while( !bDone && ( ++i < nCount ) )
1285 pAction = rMtf.GetAction( i );
1287 if( pAction->GetType() == META_GRADIENTEX_ACTION )
1288 pGradAction = (const MetaGradientExAction*) pAction;
1289 else if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
1290 ( ( (const MetaCommentAction*) pAction )->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_END" ) == COMPARE_EQUAL ) )
1292 bDone = sal_True;
1296 if( pGradAction )
1297 ImplWriteGradientEx( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), pStyle );
1300 break;
1302 case( META_BMP_ACTION ):
1304 const MetaBmpAction* pA = (const MetaBmpAction*) pAction;
1306 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1307 ImplWriteBmp( pA->GetBitmap(),
1308 pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmap().GetSizePixel() ),
1309 Point(), pA->GetBitmap().GetSizePixel(), pStyle );
1311 break;
1313 case( META_BMPSCALE_ACTION ):
1315 const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
1317 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1318 ImplWriteBmp( pA->GetBitmap(),
1319 pA->GetPoint(), pA->GetSize(),
1320 Point(), pA->GetBitmap().GetSizePixel(), pStyle );
1322 break;
1324 case( META_BMPSCALEPART_ACTION ):
1326 const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pAction;
1328 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1329 ImplWriteBmp( pA->GetBitmap(),
1330 pA->GetDestPoint(), pA->GetDestSize(),
1331 pA->GetSrcPoint(), pA->GetSrcSize(), pStyle );
1333 break;
1335 case( META_BMPEX_ACTION ):
1337 const MetaBmpExAction* pA = (const MetaBmpExAction*) pAction;
1339 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1340 ImplWriteBmp( pA->GetBitmapEx(),
1341 pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmapEx().GetSizePixel() ),
1342 Point(), pA->GetBitmapEx().GetSizePixel(), pStyle );
1344 break;
1346 case( META_BMPEXSCALE_ACTION ):
1348 const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
1350 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1351 ImplWriteBmp( pA->GetBitmapEx(),
1352 pA->GetPoint(), pA->GetSize(),
1353 Point(), pA->GetBitmapEx().GetSizePixel(), pStyle );
1355 break;
1357 case( META_BMPEXSCALEPART_ACTION ):
1359 const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pAction;
1361 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1362 ImplWriteBmp( pA->GetBitmapEx(),
1363 pA->GetDestPoint(), pA->GetDestSize(),
1364 pA->GetSrcPoint(), pA->GetSrcSize(), pStyle );
1366 break;
1368 case( META_TEXT_ACTION ):
1370 const MetaTextAction* pA = (const MetaTextAction*) pAction;
1372 mpContext->SetFontAttr( mpVDev->GetFont() );
1373 mpContext->SetPaintAttr( COL_TRANSPARENT, mpVDev->GetFont().GetColor() );
1374 ImplWriteText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), NULL, 0, pStyle );
1376 break;
1378 case( META_TEXTRECT_ACTION ):
1380 const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
1382 mpContext->SetFontAttr( mpVDev->GetFont() );
1383 mpContext->SetPaintAttr( COL_TRANSPARENT, mpVDev->GetFont().GetColor() );
1384 ImplWriteText( pA->GetRect().TopLeft(), pA->GetText(), NULL, 0, pStyle );
1386 break;
1388 case( META_TEXTARRAY_ACTION ):
1390 const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction;
1391 const Point aPos( ImplMap( pA->GetPoint() ) );
1393 mpContext->SetFontAttr( mpVDev->GetFont() );
1394 mpContext->SetPaintAttr( COL_TRANSPARENT, mpVDev->GetFont().GetColor() );
1395 ImplWriteText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), pA->GetDXArray(), 0, pStyle );
1397 break;
1399 case( META_STRETCHTEXT_ACTION ):
1401 const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction;
1403 mpContext->SetFontAttr( mpVDev->GetFont() );
1404 mpContext->SetPaintAttr( COL_TRANSPARENT, mpVDev->GetFont().GetColor() );
1405 ImplWriteText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), NULL, pA->GetWidth(), pStyle );
1407 break;
1409 case( META_CLIPREGION_ACTION ):
1410 case( META_ISECTRECTCLIPREGION_ACTION ):
1411 case( META_ISECTREGIONCLIPREGION_ACTION ):
1412 case( META_MOVECLIPREGION_ACTION ):
1414 ( (MetaAction*) pAction )->Execute( mpVDev );
1415 mbClipAttrChanged = sal_True;
1417 break;
1419 case( META_REFPOINT_ACTION ):
1420 case( META_MAPMODE_ACTION ):
1421 case( META_LINECOLOR_ACTION ):
1422 case( META_FILLCOLOR_ACTION ):
1423 case( META_TEXTLINECOLOR_ACTION ):
1424 case( META_TEXTFILLCOLOR_ACTION ):
1425 case( META_TEXTCOLOR_ACTION ):
1426 case( META_TEXTALIGN_ACTION ):
1427 case( META_FONT_ACTION ):
1428 case( META_PUSH_ACTION ):
1429 case( META_POP_ACTION ):
1431 ( (MetaAction*) pAction )->Execute( mpVDev );
1433 break;
1435 case( META_RASTEROP_ACTION ):
1436 case( META_MASK_ACTION ):
1437 case( META_MASKSCALE_ACTION ):
1438 case( META_MASKSCALEPART_ACTION ):
1439 case( META_WALLPAPER_ACTION ):
1440 case( META_TEXTLINE_ACTION ):
1441 case( META_LAYOUTMODE_ACTION ):
1443 // !!! >>> we don't want to support these actions
1445 break;
1447 #ifdef DBG_UTIL
1448 default :
1449 ByteString aDbgOut( "SVGActionWriter::ImplWriteActions: unsupported MetaAction #" );
1450 aDbgOut.Append( ByteString::CreateFromInt32( nType ) );
1451 DBG_ERROR( aDbgOut.GetBuffer() );
1452 break;
1453 #endif
1457 ImplReleaseContext();