update dev300-m58
[ooovba.git] / extensions / source / svg / svgaction.cxx
blob9646ba69ce7f957b0364ec86009895cb3e9fcd86
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: svgaction.cxx,v $
10 * $Revision: 1.13 $
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_extensions.hxx"
34 #include "svgaction.hxx"
35 #include <vcl/virdev.hxx>
36 #include <vcl/cvtgrf.hxx>
37 #include <vcl/metric.hxx>
39 #undef _SVG_USE_NATIVE_TEXTDECORATION
40 #undef _SVG_USE_TSPANS
42 // -----------
43 // - statics -
44 // -----------
46 static const char aXMLElemSVG[] = "svg";
47 static const char aXMLElemG[] = "g";
48 static const char aXMLElemDefs[] = "defs";
49 static const char aXMLElemClipPath[] = "clipPath";
50 static const char aXMLElemLine[] = "line";
51 static const char aXMLElemRect[] = "rect";
52 static const char aXMLElemEllipse[] = "ellipse";
53 static const char aXMLElemPath[] = "path";
54 static const char aXMLElemPolygon[] = "polygon";
55 static const char aXMLElemPolyLine[] = "polyline";
56 static const char aXMLElemText[] = "text";
57 static const char aXMLElemTSpan[] = "tspan";
58 static const char aXMLElemImage[] = "image";
60 static const char aXMLAttrTransform[] = "transform";
61 static const char aXMLAttrStyle[] = "style";
62 static const char aXMLAttrId[] = "id";
64 static const char aXMLAttrD[] = "d";
65 static const char aXMLAttrX[] = "x";
66 static const char aXMLAttrY[] = "y";
67 static const char aXMLAttrX1[] = "x1";
68 static const char aXMLAttrY1[] = "y1";
69 static const char aXMLAttrX2[] = "x2";
70 static const char aXMLAttrY2[] = "y2";
71 static const char aXMLAttrCX[] = "cx";
72 static const char aXMLAttrCY[] = "cy";
73 static const char aXMLAttrRX[] = "rx";
74 static const char aXMLAttrRY[] = "ry";
75 static const char aXMLAttrWidth[] = "width";
76 static const char aXMLAttrHeight[] = "height";
77 static const char aXMLAttrPoints[] = "points";
78 static const char aXMLAttrXLinkHRef[] = "xlink:href";
80 static const sal_Unicode pBase64[] =
82 //0 1 2 3 4 5 6 7
83 'A','B','C','D','E','F','G','H', // 0
84 'I','J','K','L','M','N','O','P', // 1
85 'Q','R','S','T','U','V','W','X', // 2
86 'Y','Z','a','b','c','d','e','f', // 3
87 'g','h','i','j','k','l','m','n', // 4
88 'o','p','q','r','s','t','u','v', // 5
89 'w','x','y','z','0','1','2','3', // 6
90 '4','5','6','7','8','9','+','/' // 7
93 // --------------
94 // - FastString -
95 // --------------
97 FastString::FastString( sal_uInt32 nInitLen, sal_uInt32 nIncrement ) :
98 mpBuffer( new sal_Unicode[ nInitLen * sizeof( sal_Unicode ) ] ),
99 mnBufLen( nInitLen ),
100 mnCurLen( 0 ),
101 mnBufInc( nIncrement ),
102 mnPartPos( 0 )
104 DBG_ASSERT( nInitLen, "invalid initial length" );
105 DBG_ASSERT( nIncrement, "invalid increment" );
108 // -----------------------------------------------------------------------------
110 FastString::FastString( sal_Char* pBufferForBase64Encoding, sal_uInt32 nBufLen ) :
111 mnBufInc( 2048 ),
112 mnPartPos( 0 )
114 DBG_ASSERT( pBufferForBase64Encoding && nBufLen, "invalid arguments" );
116 const sal_uInt32 nQuadCount = nBufLen / 3;
117 const sal_uInt32 nRest = nBufLen % 3;
119 if( nQuadCount || nRest )
121 mnBufLen = mnCurLen = ( ( nQuadCount + ( nRest ? 1 : 0 ) ) << 2 );
122 mpBuffer = new sal_Unicode[ mnBufLen * sizeof( sal_Unicode ) ];
124 sal_Char* pTmpSrc = pBufferForBase64Encoding;
125 sal_Unicode* pTmpDst = mpBuffer;
127 for( sal_uInt32 i = 0; i < nQuadCount; i++ )
129 const sal_Int32 nA = *pTmpSrc++;
130 const sal_Int32 nB = *pTmpSrc++;
131 const sal_Int32 nC = *pTmpSrc++;
133 *pTmpDst++ = pBase64[ ( nA >> 2 ) & 0x3f ];
134 *pTmpDst++ = pBase64[ ( ( nA << 4 ) & 0x30 ) + ( ( nB >> 4 ) & 0xf ) ];
135 *pTmpDst++ = pBase64[ ( ( nB << 2 ) & 0x3c ) + ( ( nC >> 6 ) & 0x3 ) ];
136 *pTmpDst++ = pBase64[ nC & 0x3f ];
139 if( 1 == nRest )
141 const sal_Int32 nA = *pTmpSrc;
143 *pTmpDst++ = pBase64[ ( nA >> 2 ) & 0x3f ];
144 *pTmpDst++ = pBase64[ ( nA << 4 ) & 0x30 ];
145 *pTmpDst++ = '=';
146 *pTmpDst = '=';
148 else if( 2 == nRest )
150 const sal_Int32 nA = *pTmpSrc++;
151 const sal_Int32 nB = *pTmpSrc;
153 *pTmpDst++ = pBase64[ ( nA >> 2 ) & 0x3f ];
154 *pTmpDst++ = pBase64[ ( ( nA << 4 ) & 0x30 ) + ( ( nB >> 4 ) & 0xf ) ];
155 *pTmpDst++ = pBase64[ ( nB << 2 ) & 0x3c ];
156 *pTmpDst = '=';
159 else
161 mpBuffer = new sal_Unicode[ ( mnBufLen = 1 ) * sizeof( sal_Unicode ) ];
162 mnCurLen = 0;
166 // -----------------------------------------------------------------------------
168 FastString::~FastString()
170 delete[] mpBuffer;
173 // -----------------------------------------------------------------------------
175 FastString& FastString::operator+=( const NMSP_RTL::OUString& rStr )
177 if( rStr.getLength() )
179 if( ( mnCurLen + rStr.getLength() ) > mnBufLen )
181 const sal_uInt32 nNewBufLen = ( mnBufLen + ( ( ( mnCurLen + rStr.getLength() ) - mnBufLen ) / mnBufInc + 1 ) * mnBufInc );
182 sal_Unicode* pNewBuffer = new sal_Unicode[ nNewBufLen * sizeof( sal_Unicode ) ];
184 memcpy( pNewBuffer, mpBuffer, mnBufLen * sizeof( sal_Unicode ) );
185 delete[] mpBuffer;
186 mpBuffer = pNewBuffer;
187 mnBufLen = nNewBufLen;
190 memcpy( mpBuffer + mnCurLen, rStr.getStr(), rStr.getLength() * sizeof( sal_Unicode ) );
191 mnCurLen += rStr.getLength();
193 if( maString.getLength() )
194 maString = NMSP_RTL::OUString();
197 return *this;
200 // -----------------------------------------------------------------------------
202 const NMSP_RTL::OUString& FastString::GetString() const
204 if( !maString.getLength() && mnCurLen )
205 ( (FastString*) this )->maString = NMSP_RTL::OUString( mpBuffer, mnCurLen );
207 return maString;
210 // -----------------------------------------------------------------------------
212 sal_Bool FastString::GetFirstPartString( const sal_uInt32 nPartLen, NMSP_RTL::OUString& rPartString )
214 const sal_uInt32 nLength = Min( mnCurLen, nPartLen );
216 mnPartPos = 0;
218 if( nLength )
220 rPartString = NMSP_RTL::OUString( mpBuffer, nLength );
221 mnPartPos = nLength;
224 return( rPartString.getLength() > 0 );
227 // -----------------------------------------------------------------------------
229 sal_Bool FastString::GetNextPartString( const sal_uInt32 nPartLen, NMSP_RTL::OUString& rPartString )
231 if( mnPartPos < mnCurLen )
233 const sal_uInt32 nLength = Min( mnCurLen - mnPartPos, nPartLen );
234 rPartString = NMSP_RTL::OUString( mpBuffer + mnPartPos, nLength );
235 mnPartPos += nLength;
237 else
238 rPartString = NMSP_RTL::OUString();
240 return( rPartString.getLength() > 0 );
243 // ----------------------
244 // - SVGAttributeWriter -
245 // ----------------------
247 SVGAttributeWriter::SVGAttributeWriter( SVGActionWriter& rParent, SvXMLExport& rExport ) :
248 mrParent( rParent ),
249 mrExport( rExport ),
250 mpElemFont( NULL ),
251 mpElemPaint( NULL )
255 // -----------------------------------------------------------------------------
257 SVGAttributeWriter::~SVGAttributeWriter()
259 delete mpElemPaint;
260 delete mpElemFont;
263 // -----------------------------------------------------------------------------
265 NMSP_RTL::OUString SVGAttributeWriter::GetFontStyle( const Font& rFont )
267 FastString aStyle;
269 // font family
270 aStyle += B2UCONST( "font-family:" );
271 aStyle += NMSP_RTL::OUString( rFont.GetName().GetToken( 0, ';' ) );
273 // font size
274 aStyle += B2UCONST( ";" );
275 aStyle += B2UCONST( "font-size:" );
276 aStyle += mrParent.GetValueString( mrParent.ImplMap( Size( 0, rFont.GetHeight() ) ).Height(), mrParent.HasDoublePoints() );
278 // font style
279 if( rFont.GetItalic() != ITALIC_NONE )
281 aStyle += B2UCONST( ";" );
282 aStyle += B2UCONST( "font-style:" );
284 if( rFont.GetItalic() == ITALIC_OBLIQUE )
285 aStyle += B2UCONST( "oblique" );
286 else
287 aStyle += B2UCONST( "italic" );
290 // font weight
291 sal_Int32 nFontWeight;
293 switch( rFont.GetWeight() )
295 case WEIGHT_THIN: nFontWeight = 100; break;
296 case WEIGHT_ULTRALIGHT: nFontWeight = 200; break;
297 case WEIGHT_LIGHT: nFontWeight = 300; break;
298 case WEIGHT_SEMILIGHT: nFontWeight = 400; break;
299 case WEIGHT_NORMAL: nFontWeight = 400; break;
300 case WEIGHT_MEDIUM: nFontWeight = 500; break;
301 case WEIGHT_SEMIBOLD: nFontWeight = 600; break;
302 case WEIGHT_BOLD: nFontWeight = 700; break;
303 case WEIGHT_ULTRABOLD: nFontWeight = 800; break;
304 case WEIGHT_BLACK: nFontWeight = 900; break;
305 default: nFontWeight = 400; break;
308 aStyle += B2UCONST( ";" );
309 aStyle += B2UCONST( "font-weight:" );
310 aStyle += NMSP_RTL::OUString::valueOf( nFontWeight );
312 // !!!
313 // font-variant
314 // font-stretch
315 // font-size-adjust
317 #ifdef _SVG_USE_NATIVE_TEXTDECORATION
319 if( rFont.GetUnderline() != UNDERLINE_NONE || rFont.GetStrikeout() != STRIKEOUT_NONE )
321 aStyle += B2UCONST( ";" );
322 aStyle += B2UCONST( "text-decoration:" );
324 if( rFont.GetUnderline() != UNDERLINE_NONE )
325 aStyle += B2UCONST( " underline" );
327 if( rFont.GetStrikeout() != STRIKEOUT_NONE )
328 aStyle += B2UCONST( " line-through" );
331 #endif // _SVG_USE_NATIVE_TEXTDECORATION
333 return aStyle.GetString();
336 // -----------------------------------------------------------------------------
338 NMSP_RTL::OUString SVGAttributeWriter::GetPaintStyle( const Color& rLineColor, const Color& rFillColor )
340 FastString aStyle;
342 // line color
343 aStyle += B2UCONST( "stroke:" );
345 if( rLineColor.GetTransparency() == 255 )
346 aStyle += B2UCONST( "none" );
347 else
349 // line color value in rgb
350 aStyle += B2UCONST( "rgb(" );
351 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rLineColor.GetRed() );
352 aStyle += B2UCONST( "," );
353 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rLineColor.GetGreen() );
354 aStyle += B2UCONST( "," );
355 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rLineColor.GetBlue() );
356 aStyle += B2UCONST( ")" );
358 // line color opacity in percent if neccessary
359 if( rLineColor.GetTransparency() )
361 aStyle += B2UCONST( ";" );
362 aStyle += B2UCONST( "stroke-opacity:" );
363 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) ( ( 255 - (double) rLineColor.GetTransparency() ) / 2.55 ) );
364 aStyle += B2UCONST( "%" );
368 // fill color
369 aStyle += B2UCONST( ";" );
370 aStyle += B2UCONST( "fill:" );
372 if( rFillColor.GetTransparency() == 255 )
373 aStyle += B2UCONST( "none" );
374 else
376 // fill color value in rgb
377 aStyle += B2UCONST( "rgb(" );
378 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rFillColor.GetRed() );
379 aStyle += B2UCONST( "," );
380 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rFillColor.GetGreen() );
381 aStyle += B2UCONST( "," );
382 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rFillColor.GetBlue() );
383 aStyle += B2UCONST( ")" );
385 // fill color opacity in percent if neccessary
386 if( rFillColor.GetTransparency() )
388 aStyle += B2UCONST( ";" );
389 aStyle += B2UCONST( "fill-opacity:" );
390 aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) ( ( 255 - (double) rFillColor.GetTransparency() ) / 2.55 ) );
391 aStyle += B2UCONST( "%" );
395 return aStyle.GetString();
398 // -----------------------------------------------------------------------------
400 void SVGAttributeWriter::SetFontAttr( const Font& rFont )
402 if( !mpElemFont || ( rFont != maCurFont ) )
404 delete mpElemPaint, mpElemPaint = NULL;
405 delete mpElemFont;
406 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, GetFontStyle( maCurFont = rFont ) );
407 mpElemFont = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
411 // -----------------------------------------------------------------------------
413 void SVGAttributeWriter::SetPaintAttr( const Color& rLineColor, const Color& rFillColor )
415 if( !mpElemPaint || ( rLineColor != maCurLineColor ) || ( rFillColor != maCurFillColor ) )
417 delete mpElemPaint;
418 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, GetPaintStyle( maCurLineColor = rLineColor, maCurFillColor = rFillColor ) );
419 mpElemPaint = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
423 // -------------------
424 // - SVGActionWriter -
425 // -------------------
427 SVGActionWriter::SVGActionWriter( SvXMLExport& rExport, const GDIMetaFile& rMtf,
428 VirtualDevice* pParentVDev, sal_Bool bWriteDoublePoints ) :
429 mrExport( rExport ),
430 mrMtf( rMtf ),
431 mpContext( NULL ),
432 mnCurClipId( 1 ),
433 mbClipAttrChanged( sal_False ),
434 mbDoublePoints( bWriteDoublePoints )
436 if( pParentVDev )
438 mpVDev = pParentVDev;
439 mbDestroyVDev = sal_False;
440 maTargetMapMode = mpVDev->GetMapMode();
442 else
444 mpVDev = new VirtualDevice;
445 mpVDev->EnableOutput( sal_False );
446 mbDestroyVDev = sal_True;
447 maTargetMapMode = MAP_100TH_MM;
450 mpVDev->Push();
451 mpVDev->SetMapMode( mrMtf.GetPrefMapMode() );
452 ImplWriteActions( mrMtf );
453 mpVDev->Pop();
456 // -----------------------------------------------------------------------------
458 SVGActionWriter::~SVGActionWriter()
460 DBG_ASSERT( !mpContext, "Not all contexts are closed" );
462 if( mbDestroyVDev )
463 delete mpVDev;
466 // -----------------------------------------------------------------------------
468 long SVGActionWriter::ImplMap( sal_Int32 nVal ) const
470 return ImplMap( Size( nVal, nVal ) ).Width();
473 // -----------------------------------------------------------------------------
475 Point SVGActionWriter::ImplMap( const Point& rPt ) const
477 return mpVDev->LogicToLogic( rPt, mpVDev->GetMapMode(), maTargetMapMode );
480 // -----------------------------------------------------------------------------
482 Size SVGActionWriter::ImplMap( const Size& rSz ) const
484 return mpVDev->LogicToLogic( rSz, mpVDev->GetMapMode(), maTargetMapMode );
487 // -----------------------------------------------------------------------------
489 NMSP_RTL::OUString SVGActionWriter::GetValueString( sal_Int32 nVal, sal_Bool bDoublePoints )
491 if( !bDoublePoints )
492 return NMSP_RTL::OUString::valueOf( nVal );
493 else
495 const double fPoints = nVal * 72.0 / 2540.0;
496 const sal_Int32 nInt = (sal_Int32) fPoints;
498 return( ( NMSP_RTL::OUString::valueOf( nInt ) +=
499 NMSP_RTL::OUString::valueOf( (sal_Unicode) '.' ) ) +=
500 NMSP_RTL::OUString::valueOf( labs( (sal_Int32) ( ( fPoints - nInt ) * 100.0 ) ) ) );
504 // -----------------------------------------------------------------------------
506 void SVGActionWriter::ImplWriteLine( const Point& rPt1, const Point& rPt2, const Color* pLineColor,
507 const NMSP_RTL::OUString* pStyle )
509 const Point aPt1( ImplMap( rPt1 ) );
510 const Point aPt2( ImplMap( rPt2 ) );
512 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX1, GetValueString( aPt1.X(), mbDoublePoints ) );
513 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY1, GetValueString( aPt1.Y(), mbDoublePoints ) );
514 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX2, GetValueString( aPt2.X(), mbDoublePoints ) );
515 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY2, GetValueString( aPt2.Y(), mbDoublePoints ) );
517 // add additional style if requested
518 if( pStyle )
519 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle );
521 if( pLineColor )
523 // !!! mrExport.AddAttribute( XML_NAMESPACE_NONE, ... )
524 DBG_ERROR( "SVGActionWriter::ImplWriteLine: Line color not implemented" );
528 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemLine, TRUE, TRUE );
532 // -----------------------------------------------------------------------------
534 void SVGActionWriter::ImplWriteRect( const Rectangle& rRect, long nRadX, long nRadY,
535 const NMSP_RTL::OUString* pStyle )
537 const Rectangle aRect( ImplMap( rRect ) );
539 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, GetValueString( aRect.Left(), mbDoublePoints ) );
540 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, GetValueString( aRect.Top(), mbDoublePoints ) );
541 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrWidth, GetValueString( aRect.GetWidth(), mbDoublePoints ) );
542 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrHeight, GetValueString( aRect.GetHeight(), mbDoublePoints ) );
544 if( nRadX )
545 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRX, GetValueString( ImplMap( nRadX ), mbDoublePoints ) );
547 if( nRadY )
548 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRY, GetValueString( ImplMap( nRadY ), mbDoublePoints ) );
550 // add additional style if requested
551 if( pStyle )
552 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle );
555 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemRect, TRUE, TRUE );
559 // -----------------------------------------------------------------------------
561 void SVGActionWriter::ImplWriteEllipse( const Point& rCenter, long nRadX, long nRadY,
562 const NMSP_RTL::OUString* pStyle )
564 const Point aCenter( ImplMap( rCenter ) );
566 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCX, GetValueString( aCenter.X(), mbDoublePoints ) );
567 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCY, GetValueString( aCenter.Y(), mbDoublePoints ) );
568 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRX, GetValueString( ImplMap( nRadX ), mbDoublePoints ) );
569 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRY, GetValueString( ImplMap( nRadY ), mbDoublePoints ) );
571 // add additional style if requested
572 if( pStyle )
573 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle );
576 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemEllipse, TRUE, TRUE );
580 // -----------------------------------------------------------------------------
582 void SVGActionWriter::ImplWritePolygon( const Polygon& rPoly, sal_Bool bLineOnly,
583 const NMSP_RTL::OUString* pStyle )
585 if( rPoly.GetSize() )
587 if( rPoly.HasFlags() )
588 ImplWritePolyPolygon( rPoly, bLineOnly, pStyle );
589 else
591 FastString aStyle;
592 FastString aPoints;
593 USHORT i = 0, nSize = rPoly.GetSize();
594 const NMSP_RTL::OUString aBlank( B2UCONST( " " ) );
596 // points
597 while( i < nSize )
599 const Point aPolyPoint( ImplMap( rPoly[ i ] ) );
601 aPoints += GetValueString( aPolyPoint.X(), mbDoublePoints );
602 aPoints += B2UCONST( "," );
603 aPoints += GetValueString( aPolyPoint.Y(), mbDoublePoints );
605 if( ++i < nSize )
606 aPoints += aBlank;
609 // style
610 if( bLineOnly )
612 aStyle += B2UCONST( "fill:none" );
614 if( pStyle )
616 aStyle += B2UCONST( ";" );
617 aStyle += *pStyle;
620 else if( pStyle )
621 aStyle += *pStyle;
623 // add point attribute
624 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrPoints, aPoints.GetString() );
626 // add style attribute
627 if( aStyle.GetLength() )
628 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aStyle.GetString() );
631 // write polyline/polygon element
632 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, bLineOnly ? aXMLElemPolyLine : aXMLElemPolygon, TRUE, TRUE );
638 // -----------------------------------------------------------------------------
640 void SVGActionWriter::ImplWritePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bLineOnly,
641 const NMSP_RTL::OUString* pStyle )
643 if( rPolyPoly.Count() )
645 if( ( rPolyPoly.Count() == 1 ) && ( rPolyPoly[ 0 ].HasFlags() == sal_False ) )
646 ImplWritePolygon( rPolyPoly[ 0 ], bLineOnly, pStyle );
647 else
649 FastString aStyle;
650 FastString aPathData;
651 const NMSP_RTL::OUString aBlank( B2UCONST( " " ) );
652 const NMSP_RTL::OUString aComma( B2UCONST( "," ) );
653 Point aPolyPoint;
655 for( long i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ )
657 const Polygon& rPoly = rPolyPoly[ (USHORT) i ];
658 USHORT n = 1, nSize = rPoly.GetSize();
660 if( nSize > 1 )
662 aPathData += B2UCONST( "M " );
663 aPathData += GetValueString( ( aPolyPoint = ImplMap( rPoly[ 0 ] ) ).X(), mbDoublePoints );
664 aPathData += aComma;
665 aPathData += GetValueString( aPolyPoint.Y(), mbDoublePoints );
666 sal_Char nCurrentMode = 0;
668 while( n < nSize )
670 aPathData += aBlank;
671 if ( ( rPoly.GetFlags( n ) == POLY_CONTROL ) && ( ( n + 2 ) < nSize ) )
673 if ( nCurrentMode != 'C' )
675 nCurrentMode = 'C';
676 aPathData += B2UCONST( "C " );
678 for ( int j = 0; j < 3; j++ )
680 if ( j )
681 aPathData += aBlank;
682 aPathData += GetValueString( ( aPolyPoint = ImplMap( rPoly[ n++ ] ) ).X(), mbDoublePoints );
683 aPathData += aComma;
684 aPathData += GetValueString( aPolyPoint.Y(), mbDoublePoints );
687 else
689 if ( nCurrentMode != 'L' )
691 nCurrentMode = 'L';
692 aPathData += B2UCONST( "L " );
694 aPathData += GetValueString( ( aPolyPoint = ImplMap( rPoly[ n++ ] ) ).X(), mbDoublePoints );
695 aPathData += aComma;
696 aPathData += GetValueString( aPolyPoint.Y(), mbDoublePoints );
699 aPathData += B2UCONST( " Z" );
701 if( i < ( nCount - 1 ) )
702 aPathData += aBlank;
705 if( bLineOnly )
707 aStyle += B2UCONST( "fill:none" );
708 if( pStyle )
709 aStyle += B2UCONST( ";" );
711 if( pStyle )
712 aStyle += *pStyle;
714 // add style attribute
715 if( aStyle.GetLength() )
716 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aStyle.GetString() );
718 // add path data attribute
719 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrD, aPathData.GetString() );
721 // write polyline/polygon element
722 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemPath, TRUE, TRUE );
728 // -----------------------------------------------------------------------------
730 void SVGActionWriter::ImplWriteGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient,
731 const NMSP_RTL::OUString* pStyle )
733 if( rPolyPoly.Count() )
735 SvXMLElementExport aElemG( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
736 FastString aClipId;
737 FastString aClipStyle;
739 aClipId += B2UCONST( "clip" );
740 aClipId += NMSP_RTL::OUString::valueOf( ImplGetNextClipId() );
743 SvXMLElementExport aElemDefs( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, TRUE, TRUE );
745 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aClipId.GetString() );
748 SvXMLElementExport aElemClipPath( mrExport, XML_NAMESPACE_NONE, aXMLElemClipPath, TRUE, TRUE );
749 ImplWritePolyPolygon( rPolyPoly, sal_False );
753 // create new context with clippath set
754 aClipStyle += B2UCONST( "clip-path:URL(#" );
755 aClipStyle += aClipId.GetString();
756 aClipStyle += B2UCONST( ")" );
758 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aClipStyle.GetString() );
761 GDIMetaFile aTmpMtf;
762 SvXMLElementExport aElemG2( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
764 mpVDev->AddGradientActions( rPolyPoly.GetBoundRect(), rGradient, aTmpMtf );
765 ImplWriteActions( aTmpMtf, pStyle );
770 // -----------------------------------------------------------------------------
772 void SVGActionWriter::ImplWriteText( const Point& rPos, const String& rText,
773 const sal_Int32* pDXArray, long nWidth,
774 const NMSP_RTL::OUString* pStyle )
776 String aText( rText ); aText.EraseLeadingChars( ' ' );
777 UINT32 nLen = aText.Len(), i;
779 if( nLen )
781 Size aNormSize;
782 sal_Int32* pOwnArray;
783 sal_Int32* pDX;
785 // get text sizes
786 if( pDXArray )
788 pOwnArray = NULL;
789 aNormSize = Size( mpVDev->GetTextWidth( aText ), 0 );
790 pDX = const_cast< sal_Int32* >( pDXArray );
792 else
794 pOwnArray = new sal_Int32[ nLen ];
795 aNormSize = Size( mpVDev->GetTextArray( aText, pOwnArray ), 0 );
796 pDX = pOwnArray;
799 if( nLen > 1 )
801 aNormSize.Width() = pDX[ nLen - 2 ] + mpVDev->GetTextWidth( aText.GetChar( (USHORT) nLen - 1 ) );
803 if( nWidth && aNormSize.Width() && ( nWidth != aNormSize.Width() ) )
805 const double fFactor = (double) nWidth / aNormSize.Width();
807 for( i = 0; i < ( nLen - 1 ); i++ )
808 pDX[ i ] = FRound( pDX[ i ] * fFactor );
812 FastString aStyle;
813 const Font& rFont = mpVDev->GetFont();
814 const FontMetric aMetric( mpVDev->GetFontMetric() );
815 Point aBaseLinePos( rPos );
816 SvXMLElementExport* pTransform = NULL;
818 // leading whitespaces erased? => adjust position
819 if( nLen < rText.Len() )
821 aBaseLinePos.X() += mpVDev->GetTextWidth( ' ' ) * ( rText.Len() - nLen );
824 // always adjust text position to match baseline alignment
825 switch( rFont.GetAlign() )
827 case( ALIGN_TOP ):
828 aBaseLinePos.Y() += aMetric.GetAscent();
829 break;
831 case( ALIGN_BOTTOM ):
832 aBaseLinePos.Y() -= aMetric.GetDescent();
833 break;
835 default:
836 break;
839 // get mapped text position
840 const Point aPt( ImplMap( aBaseLinePos ) );
842 // if text is rotated, set transform at new g element
843 if( rFont.GetOrientation() )
845 String aTransform;
847 aTransform = NMSP_RTL::OUString::createFromAscii( "translate" );
848 aTransform += '(';
849 aTransform += String( GetValueString( aPt.X(), mbDoublePoints ) );
850 aTransform += ',';
851 aTransform += String( GetValueString( aPt.Y(), mbDoublePoints ) );
852 aTransform += ')';
854 aTransform += String( NMSP_RTL::OUString::createFromAscii( " rotate" ) );
855 aTransform += '(';
856 aTransform += String( NMSP_RTL::OUString::valueOf( rFont.GetOrientation() * -0.1 ) );
857 aTransform += ')';
859 aTransform += String( NMSP_RTL::OUString::createFromAscii( " translate" ) );
860 aTransform += '(';
861 aTransform += String( GetValueString( -aPt.X(), mbDoublePoints ) );
862 aTransform += ',';
863 aTransform += String( GetValueString( -aPt.Y(), mbDoublePoints ) );
864 aTransform += ')';
866 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTransform, aTransform );
867 pTransform = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
870 // add additional style if requested
871 if( pStyle && pStyle->getLength() )
872 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, *pStyle );
874 // write text element
875 #ifdef _SVG_USE_TSPANS
876 if( pDXArray )
878 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemText, TRUE, TRUE );
879 FastString aTSpanX;
880 const NMSP_RTL::OUString aSpace( ' ' );
881 long i, nX, nCount;
883 aTSpanX += GetValueString( aPt.X(), mbDoublePoints );
884 aTSpanX += aSpace;
886 for( i = 0, nX = aPt.X(), nCount = ( nLen - 1 ); i < nCount; )
888 aTSpanX += GetValueString( aPt.X() + pDX[ i++ ], mbDoublePoints );
889 aTSpanX += aSpace;
892 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, aTSpanX.GetString() );
893 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, GetValueString( aPt.Y(), mbDoublePoints ) );
900 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTSpan, TRUE, TRUE );
901 mrExport.GetDocHandler()->characters( NMSP_RTL::OUString( UniString( aText ) ) );
903 catch( ::com::sun::star::xml::sax::SAXException& )
905 // string seems to contain invalid characters
910 else
911 #endif
913 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, GetValueString( aPt.X(), mbDoublePoints ) );
914 mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, GetValueString( aPt.Y(), mbDoublePoints ) );
918 SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemText, TRUE, TRUE );
919 mrExport.GetDocHandler()->characters( NMSP_RTL::OUString( UniString( aText ) ) );
921 catch( ::com::sun::star::xml::sax::SAXException& )
923 // string seems to contain invalid characters
927 #ifndef _SVG_USE_NATIVE_TEXTDECORATION
929 // write strikeout if neccessary
930 if( ( rFont.GetStrikeout() != STRIKEOUT_NONE ) || ( rFont.GetUnderline() != UNDERLINE_NONE ) )
932 Polygon aPoly( 4 );
933 const long nLineHeight = Max( (long) FRound( aMetric.GetLineHeight() * 0.05 ), (long) 1 );
935 if( rFont.GetStrikeout() )
937 const long nYLinePos = aBaseLinePos.Y() - FRound( aMetric.GetAscent() * 0.26 );
939 aPoly[ 0 ].X() = aBaseLinePos.X(); aPoly[ 0 ].Y() = nYLinePos - ( nLineHeight >> 1 );
940 aPoly[ 1 ].X() = aBaseLinePos.X() + aNormSize.Width() - 1; aPoly[ 1 ].Y() = aPoly[ 0 ].Y();
941 aPoly[ 2 ].X() = aPoly[ 1 ].X(); aPoly[ 2 ].Y() = aPoly[ 0 ].Y() + nLineHeight - 1;
942 aPoly[ 3 ].X() = aPoly[ 0 ].X(); aPoly[ 3 ].Y() = aPoly[ 2 ].Y();
944 ImplWritePolygon( aPoly, FALSE );
947 if( rFont.GetUnderline() )
949 const long nYLinePos = aBaseLinePos.Y() + ( nLineHeight << 1 );
951 aPoly[ 0 ].X() = aBaseLinePos.X(); aPoly[ 0 ].Y() = nYLinePos - ( nLineHeight >> 1 );
952 aPoly[ 1 ].X() = aBaseLinePos.X() + aNormSize.Width() - 1; aPoly[ 1 ].Y() = aPoly[ 0 ].Y();
953 aPoly[ 2 ].X() = aPoly[ 1 ].X(); aPoly[ 2 ].Y() = aPoly[ 0 ].Y() + nLineHeight - 1;
954 aPoly[ 3 ].X() = aPoly[ 0 ].X(); aPoly[ 3 ].Y() = aPoly[ 2 ].Y();
956 ImplWritePolygon( aPoly, FALSE );
960 #endif // _SVG_USE_NATIVE_TEXTDECORATION
962 delete[] pOwnArray;
963 delete pTransform;
967 // -----------------------------------------------------------------------------
969 void SVGActionWriter::ImplWriteBmp( const BitmapEx& rBmpEx,
970 const Point& rPt, const Size& rSz,
971 const Point& rSrcPt, const Size& rSrcSz,
972 const NMSP_RTL::OUString* /*pStyle*/ )
974 if( !!rBmpEx )
976 BitmapEx aBmpEx( rBmpEx );
977 Point aPoint = Point();
978 const Rectangle aBmpRect( aPoint, rBmpEx.GetSizePixel() );
979 const Rectangle aSrcRect( rSrcPt, rSrcSz );
981 if( aSrcRect != aBmpRect )
982 aBmpEx.Crop( aSrcRect );
984 if( !!aBmpEx )
986 SvMemoryStream aOStm( 65535, 65535 );
988 if( GraphicConverter::Export( aOStm, rBmpEx, CVT_PNG ) == ERRCODE_NONE )
990 const Point aPt( ImplMap( rPt ) );
991 const Size aSz( ImplMap( rSz ) );
992 FastString aImageData( (sal_Char*) aOStm.GetData(), aOStm.Tell() );
993 REF( NMSP_SAX::XExtendedDocumentHandler ) xExtDocHandler( mrExport.GetDocHandler(), NMSP_UNO::UNO_QUERY );
995 if( xExtDocHandler.is() )
997 static const sal_uInt32 nPartLen = 64;
998 const NMSP_RTL::OUString aSpace( ' ' );
999 const NMSP_RTL::OUString aLineFeed( NMSP_RTL::OUString::valueOf( (sal_Unicode) 0x0a ) );
1000 NMSP_RTL::OUString aString;
1001 NMSP_RTL::OUString aImageString;
1003 aString = aLineFeed;
1004 aString += B2UCONST( "<" );
1005 aString += NMSP_RTL::OUString::createFromAscii( aXMLElemImage );
1006 aString += aSpace;
1008 aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrX );
1009 aString += B2UCONST( "=\"" );
1010 aString += GetValueString( aPt.X(), mbDoublePoints );
1011 aString += B2UCONST( "\" " );
1013 aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrY );
1014 aString += B2UCONST( "=\"" );
1015 aString += GetValueString( aPt.Y(), mbDoublePoints );
1016 aString += B2UCONST( "\" " );
1018 aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrWidth );
1019 aString += B2UCONST( "=\"" );
1020 aString += GetValueString( aSz.Width(), mbDoublePoints );
1021 aString += B2UCONST( "\" " );
1023 aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrHeight );
1024 aString += B2UCONST( "=\"" );
1025 aString += GetValueString( aSz.Height(), mbDoublePoints );
1026 aString += B2UCONST( "\" " );
1028 aString += NMSP_RTL::OUString::createFromAscii( aXMLAttrXLinkHRef );
1029 aString += B2UCONST( "=\"data:image/png;base64," );
1031 if( aImageData.GetFirstPartString( nPartLen, aImageString ) )
1033 xExtDocHandler->unknown( aString += aImageString );
1035 while( aImageData.GetNextPartString( nPartLen, aImageString ) )
1037 xExtDocHandler->unknown( aLineFeed );
1038 xExtDocHandler->unknown( aImageString );
1042 xExtDocHandler->unknown( B2UCONST( "\"/>" ) );
1049 // -----------------------------------------------------------------------------
1051 void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, const NMSP_RTL::OUString* pStyle )
1053 ImplAcquireContext();
1055 for( ULONG i = 0, nCount = rMtf.GetActionCount(); i < nCount; i++ )
1057 const MetaAction* pAction = rMtf.GetAction( i );
1058 const USHORT nType = pAction->GetType();
1060 switch( nType )
1062 case( META_PIXEL_ACTION ):
1064 const MetaPixelAction* pA = (const MetaPixelAction*) pAction;
1066 mpContext->SetPaintAttr( pA->GetColor(), pA->GetColor() );
1067 ImplWriteLine( pA->GetPoint(), pA->GetPoint(), &pA->GetColor(), pStyle );
1069 break;
1071 case( META_POINT_ACTION ):
1073 const MetaPointAction* pA = (const MetaPointAction*) pAction;
1075 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() );
1076 ImplWriteLine( pA->GetPoint(), pA->GetPoint(), NULL, pStyle );
1078 break;
1080 case( META_LINE_ACTION ):
1082 const MetaLineAction* pA = (const MetaLineAction*) pAction;
1084 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() );
1085 ImplWriteLine( pA->GetStartPoint(), pA->GetEndPoint(), NULL, pStyle );
1087 break;
1089 case( META_RECT_ACTION ):
1091 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1092 ImplWriteRect( ( (const MetaRectAction*) pAction )->GetRect(), 0, 0, pStyle );
1094 break;
1096 case( META_ROUNDRECT_ACTION ):
1098 const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pAction;
1100 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1101 ImplWriteRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound(), pStyle );
1103 break;
1105 case( META_ELLIPSE_ACTION ):
1107 const MetaEllipseAction* pA = (const MetaEllipseAction*) pAction;
1108 const Rectangle& rRect = pA->GetRect();
1110 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1111 ImplWriteEllipse( rRect.Center(), rRect.GetWidth() >> 1, rRect.GetHeight() >> 1, pStyle );
1113 break;
1115 case( META_ARC_ACTION ):
1116 case( META_PIE_ACTION ):
1117 case( META_CHORD_ACTION ):
1118 case( META_POLYGON_ACTION ):
1120 Polygon aPoly;
1122 switch( nType )
1124 case( META_ARC_ACTION ):
1126 const MetaArcAction* pA = (const MetaArcAction*) pAction;
1127 aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_ARC );
1129 break;
1131 case( META_PIE_ACTION ):
1133 const MetaPieAction* pA = (const MetaPieAction*) pAction;
1134 aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_PIE );
1136 break;
1138 case( META_CHORD_ACTION ):
1140 const MetaChordAction* pA = (const MetaChordAction*) pAction;
1141 aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_CHORD );
1143 break;
1145 case( META_POLYGON_ACTION ):
1146 aPoly = ( (const MetaPolygonAction*) pAction )->GetPolygon();
1147 break;
1150 if( aPoly.GetSize() )
1152 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1153 ImplWritePolygon( aPoly, sal_False, pStyle );
1156 break;
1158 case( META_POLYLINE_ACTION ):
1160 const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pAction;
1161 const Polygon& rPoly = pA->GetPolygon();
1163 if( rPoly.GetSize() )
1165 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1166 ImplWritePolygon( rPoly, sal_True, pStyle );
1169 break;
1171 case( META_POLYPOLYGON_ACTION ):
1173 const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pAction;
1174 const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
1176 if( rPolyPoly.Count() )
1178 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1179 ImplWritePolyPolygon( rPolyPoly, sal_False, pStyle );
1182 break;
1184 case( META_GRADIENT_ACTION ):
1186 const MetaGradientAction* pA = (const MetaGradientAction*) pAction;
1187 GDIMetaFile aTmpMtf;
1189 mpVDev->AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
1190 ImplWriteActions( aTmpMtf, pStyle );
1192 break;
1194 case( META_GRADIENTEX_ACTION ):
1196 const MetaGradientExAction* pA = (const MetaGradientExAction*) pAction;
1197 ImplWriteGradientEx( pA->GetPolyPolygon(), pA->GetGradient(), pStyle );
1199 break;
1201 case META_HATCH_ACTION:
1203 const MetaHatchAction* pA = (const MetaHatchAction*) pAction;
1204 GDIMetaFile aTmpMtf;
1206 mpVDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
1207 ImplWriteActions( aTmpMtf, pStyle );
1209 break;
1211 case( META_TRANSPARENT_ACTION ):
1213 const MetaTransparentAction* pA = (const MetaTransparentAction*) pAction;
1214 const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
1216 if( rPolyPoly.Count() )
1218 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1219 ImplWritePolyPolygon( rPolyPoly, sal_False, pStyle );
1222 break;
1224 case( META_FLOATTRANSPARENT_ACTION ):
1226 const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pAction;
1227 GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
1228 Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
1229 const Size aSrcSize( aTmpMtf.GetPrefSize() );
1230 const Point aDestPt( pA->GetPoint() );
1231 const Size aDestSize( pA->GetSize() );
1232 const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
1233 const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
1234 long nMoveX, nMoveY;
1236 if( fScaleX != 1.0 || fScaleY != 1.0 )
1238 aTmpMtf.Scale( fScaleX, fScaleY );
1239 aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
1242 nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
1244 if( nMoveX || nMoveY )
1245 aTmpMtf.Move( nMoveX, nMoveY );
1247 mpVDev->Push();
1248 ImplWriteActions( aTmpMtf, pStyle );
1249 mpVDev->Pop();
1251 break;
1253 case( META_EPS_ACTION ):
1255 const MetaEPSAction* pA = (const MetaEPSAction*) pAction;
1256 const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
1257 sal_Bool bFound = sal_False;
1259 for( ULONG j = 0, nCount2 = aGDIMetaFile.GetActionCount(); ( j < nCount2 ) && !bFound; j++ )
1261 const MetaAction* pSubstAct = aGDIMetaFile.GetAction( j );
1263 if( pSubstAct->GetType() == META_BMPSCALE_ACTION )
1265 bFound = sal_True;
1266 const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*) pSubstAct;
1267 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1268 ImplWriteBmp( pBmpScaleAction->GetBitmap(),
1269 pA->GetPoint(), pA->GetSize(),
1270 Point(), pBmpScaleAction->GetBitmap().GetSizePixel(), pStyle );
1274 break;
1276 case( META_COMMENT_ACTION ):
1278 const MetaCommentAction* pA = (const MetaCommentAction*) pAction;
1279 String aSkipComment;
1281 if( pA->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL )
1283 const MetaGradientExAction* pGradAction = NULL;
1284 sal_Bool bDone = sal_False;
1286 while( !bDone && ( ++i < nCount ) )
1288 pAction = rMtf.GetAction( i );
1290 if( pAction->GetType() == META_GRADIENTEX_ACTION )
1291 pGradAction = (const MetaGradientExAction*) pAction;
1292 else if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
1293 ( ( (const MetaCommentAction*) pAction )->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_END" ) == COMPARE_EQUAL ) )
1295 bDone = sal_True;
1299 if( pGradAction )
1300 ImplWriteGradientEx( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), pStyle );
1303 break;
1305 case( META_BMP_ACTION ):
1307 const MetaBmpAction* pA = (const MetaBmpAction*) pAction;
1309 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1310 ImplWriteBmp( pA->GetBitmap(),
1311 pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmap().GetSizePixel() ),
1312 Point(), pA->GetBitmap().GetSizePixel(), pStyle );
1314 break;
1316 case( META_BMPSCALE_ACTION ):
1318 const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
1320 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1321 ImplWriteBmp( pA->GetBitmap(),
1322 pA->GetPoint(), pA->GetSize(),
1323 Point(), pA->GetBitmap().GetSizePixel(), pStyle );
1325 break;
1327 case( META_BMPSCALEPART_ACTION ):
1329 const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pAction;
1331 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1332 ImplWriteBmp( pA->GetBitmap(),
1333 pA->GetDestPoint(), pA->GetDestSize(),
1334 pA->GetSrcPoint(), pA->GetSrcSize(), pStyle );
1336 break;
1338 case( META_BMPEX_ACTION ):
1340 const MetaBmpExAction* pA = (const MetaBmpExAction*) pAction;
1342 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1343 ImplWriteBmp( pA->GetBitmapEx(),
1344 pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmapEx().GetSizePixel() ),
1345 Point(), pA->GetBitmapEx().GetSizePixel(), pStyle );
1347 break;
1349 case( META_BMPEXSCALE_ACTION ):
1351 const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
1353 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1354 ImplWriteBmp( pA->GetBitmapEx(),
1355 pA->GetPoint(), pA->GetSize(),
1356 Point(), pA->GetBitmapEx().GetSizePixel(), pStyle );
1358 break;
1360 case( META_BMPEXSCALEPART_ACTION ):
1362 const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pAction;
1364 mpContext->SetPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
1365 ImplWriteBmp( pA->GetBitmapEx(),
1366 pA->GetDestPoint(), pA->GetDestSize(),
1367 pA->GetSrcPoint(), pA->GetSrcSize(), pStyle );
1369 break;
1371 case( META_TEXT_ACTION ):
1373 const MetaTextAction* pA = (const MetaTextAction*) pAction;
1375 mpContext->SetFontAttr( mpVDev->GetFont() );
1376 mpContext->SetPaintAttr( COL_TRANSPARENT, mpVDev->GetFont().GetColor() );
1377 ImplWriteText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), NULL, 0, pStyle );
1379 break;
1381 case( META_TEXTRECT_ACTION ):
1383 const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
1385 mpContext->SetFontAttr( mpVDev->GetFont() );
1386 mpContext->SetPaintAttr( COL_TRANSPARENT, mpVDev->GetFont().GetColor() );
1387 ImplWriteText( pA->GetRect().TopLeft(), pA->GetText(), NULL, 0, pStyle );
1389 break;
1391 case( META_TEXTARRAY_ACTION ):
1393 const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction;
1394 const Point aPos( ImplMap( pA->GetPoint() ) );
1396 mpContext->SetFontAttr( mpVDev->GetFont() );
1397 mpContext->SetPaintAttr( COL_TRANSPARENT, mpVDev->GetFont().GetColor() );
1398 ImplWriteText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), pA->GetDXArray(), 0, pStyle );
1400 break;
1402 case( META_STRETCHTEXT_ACTION ):
1404 const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction;
1406 mpContext->SetFontAttr( mpVDev->GetFont() );
1407 mpContext->SetPaintAttr( COL_TRANSPARENT, mpVDev->GetFont().GetColor() );
1408 ImplWriteText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), NULL, pA->GetWidth(), pStyle );
1410 break;
1412 case( META_CLIPREGION_ACTION ):
1413 case( META_ISECTRECTCLIPREGION_ACTION ):
1414 case( META_ISECTREGIONCLIPREGION_ACTION ):
1415 case( META_MOVECLIPREGION_ACTION ):
1417 ( (MetaAction*) pAction )->Execute( mpVDev );
1418 mbClipAttrChanged = sal_True;
1420 break;
1422 case( META_REFPOINT_ACTION ):
1423 case( META_MAPMODE_ACTION ):
1424 case( META_LINECOLOR_ACTION ):
1425 case( META_FILLCOLOR_ACTION ):
1426 case( META_TEXTLINECOLOR_ACTION ):
1427 case( META_TEXTFILLCOLOR_ACTION ):
1428 case( META_TEXTCOLOR_ACTION ):
1429 case( META_TEXTALIGN_ACTION ):
1430 case( META_FONT_ACTION ):
1431 case( META_PUSH_ACTION ):
1432 case( META_POP_ACTION ):
1434 ( (MetaAction*) pAction )->Execute( mpVDev );
1436 break;
1438 case( META_RASTEROP_ACTION ):
1439 case( META_MASK_ACTION ):
1440 case( META_MASKSCALE_ACTION ):
1441 case( META_MASKSCALEPART_ACTION ):
1442 case( META_WALLPAPER_ACTION ):
1443 case( META_TEXTLINE_ACTION ):
1444 case( META_LAYOUTMODE_ACTION ):
1446 // !!! >>> we don't want to support these actions
1448 break;
1450 #ifdef DBG_UTIL
1451 default :
1452 ByteString aDbgOut( "SVGActionWriter::ImplWriteActions: unsupported MetaAction #" );
1453 aDbgOut.Append( ByteString::CreateFromInt32( nType ) );
1454 DBG_ERROR( aDbgOut.GetBuffer() );
1455 break;
1456 #endif
1460 ImplReleaseContext();