1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: svgwriter.cxx,v $
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"
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
[] =
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
90 FastString::FastString( sal_uInt32 nInitLen
, sal_uInt32 nIncrement
) :
93 mnBufInc( nIncrement
),
94 mpBuffer( new sal_Unicode
[ nInitLen
* sizeof( sal_Unicode
) ] ),
97 DBG_ASSERT( nInitLen
, "invalid initial length" );
98 DBG_ASSERT( nIncrement
, "invalid increment" );
101 // -----------------------------------------------------------------------------
103 FastString::FastString( sal_Char
* pBufferForBase64Encoding
, sal_uInt32 nBufLen
) :
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 ];
134 const sal_Int32 nA
= *pTmpSrc
;
136 *pTmpDst
++ = pBase64
[ ( nA
>> 2 ) & 0x3f ];
137 *pTmpDst
++ = pBase64
[ ( nA
<< 4 ) & 0x30 ];
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 ];
154 mpBuffer
= new sal_Unicode
[ ( mnBufLen
= 1 ) * sizeof( sal_Unicode
) ];
159 // -----------------------------------------------------------------------------
161 FastString::~FastString()
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
) );
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();
193 // -----------------------------------------------------------------------------
195 const NMSP_RTL::OUString
& FastString::GetString() const
197 if( !maString
.getLength() && mnCurLen
)
198 ( (FastString
*) this )->maString
= NMSP_RTL::OUString( mpBuffer
, mnCurLen
);
203 // -----------------------------------------------------------------------------
205 sal_Bool
FastString::GetFirstPartString( const sal_uInt32 nPartLen
, NMSP_RTL::OUString
& rPartString
)
207 const sal_uInt32 nLength
= Min( mnCurLen
, nPartLen
);
213 rPartString
= NMSP_RTL::OUString( mpBuffer
, 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
;
231 rPartString
= NMSP_RTL::OUString();
233 return( rPartString
.getLength() > 0 );
236 // ----------------------
237 // - SVGAttributeWriter -
238 // ----------------------
240 SVGAttributeWriter::SVGAttributeWriter( SvXMLExport
& rExport
, SVGFontExport
& rFontExport
) :
242 mrFontExport( rFontExport
),
248 // -----------------------------------------------------------------------------
250 SVGAttributeWriter::~SVGAttributeWriter()
256 // -----------------------------------------------------------------------------
258 NMSP_RTL::OUString
SVGAttributeWriter::GetFontStyle( const Font
& rFont
)
263 aStyle
+= B2UCONST( "font-family:" );
264 aStyle
+= mrFontExport
.GetMappedFontName( rFont
.GetName() );
267 aStyle
+= B2UCONST( ";" );
268 aStyle
+= B2UCONST( "font-size:" );
269 aStyle
+= SVGActionWriter::GetValueString( rFont
.GetHeight() );
273 if( rFont.GetItalic() != ITALIC_NONE )
275 aStyle += B2UCONST( ";" );
276 aStyle += B2UCONST( "font-style:" );
278 if( rFont.GetItalic() == ITALIC_OBLIQUE )
279 aStyle += B2UCONST( "oblique" );
281 aStyle += B2UCONST( "italic" );
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
);
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
)
338 aStyle
+= B2UCONST( "stroke:" );
340 if( rLineColor
.GetTransparency() == 255 )
341 aStyle
+= B2UCONST( "none" );
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 );
363 aStyle
+= B2UCONST( ";" );
364 aStyle
+= B2UCONST( "fill:" );
366 if( rFillColor
.GetTransparency() == 255 )
367 aStyle
+= B2UCONST( "none" );
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
;
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
) )
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
) :
422 mrFontExport( rFontExport
),
424 mbClipAttrChanged( sal_False
),
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" );
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( "," ) );
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();
484 aPathData
+= B2UCONST( "M " );
485 aPathData
+= GetValueString( ( aPolyPoint
= rPoly
[ 0 ] ).X() );
487 aPathData
+= GetValueString( aPolyPoint
.Y() );
488 sal_Char nCurrentMode
= 0;
493 if ( ( rPoly
.GetFlags( n
) == POLY_CONTROL
) && ( ( n
+ 2 ) < nSize
) )
495 if ( nCurrentMode
!= 'C' )
498 aPathData
+= B2UCONST( "C " );
500 for ( int j
= 0; j
< 3; j
++ )
504 aPathData
+= GetValueString( ( aPolyPoint
= rPoly
[ n
++ ] ).X() );
506 aPathData
+= GetValueString( aPolyPoint
.Y() );
511 if ( nCurrentMode
!= 'L' )
514 aPathData
+= B2UCONST( "L " );
516 aPathData
+= GetValueString( ( aPolyPoint
= rPoly
[ n
++ ] ).X() );
518 aPathData
+= GetValueString( aPolyPoint
.Y() );
523 aPathData
+= B2UCONST( " Z" );
525 if( i
< ( nCount
- 1 ) )
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
548 mrExport
.AddAttribute( XML_NAMESPACE_NONE
, aXMLAttrStyle
, *pStyle
);
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() ) );
574 mrExport
.AddAttribute( XML_NAMESPACE_NONE
, aXMLAttrRX
, GetValueString( ImplMap( nRadX
) ) );
577 mrExport
.AddAttribute( XML_NAMESPACE_NONE
, aXMLAttrRY
, GetValueString( ImplMap( nRadY
) ) );
579 // add additional style if requested
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
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
;
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
);
633 aStyle
+= B2UCONST( "fill:none" );
635 aStyle
+= B2UCONST( ";" );
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
);
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() );
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
;
706 sal_Int32
* pOwnArray
;
713 aNormSize
= Size( mpVDev
->GetTextWidth( rText
), 0 );
714 pDX
= (sal_Int32
*) pDXArray
;
718 pOwnArray
= new sal_Int32
[ nLen
];
719 aNormSize
= Size( mpVDev
->GetTextArray( rText
, pOwnArray
), 0 );
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
);
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() )
746 aBaseLinePos
.Y() += aMetric
.GetAscent();
749 case( ALIGN_BOTTOM
):
750 aBaseLinePos
.Y() -= aMetric
.GetDescent();
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() )
765 aTransform
= NMSP_RTL::OUString::createFromAscii( "translate" );
767 aTransform
+= String( GetValueString( aPt
.X() ) );
769 aTransform
+= String( GetValueString( aPt
.Y() ) );
772 if( rFont
.GetOrientation() )
774 aTransform
+= String( NMSP_RTL::OUString::createFromAscii( " rotate" ) );
776 aTransform
+= String( NMSP_RTL::OUString::valueOf( rFont
.GetOrientation() * -0.1 ) );
780 if( rFont
.GetItalic() != ITALIC_NONE
)
782 aTransform
+= String( NMSP_RTL::OUString::createFromAscii( " skewX" ) );
784 aTransform
+= String( NMSP_RTL::OUString::valueOf( (sal_Int32
) -10 ) );
788 aTransform
+= String( NMSP_RTL::OUString::createFromAscii( " translate" ) );
790 aTransform
+= String( GetValueString( -aPt
.X() ) );
792 aTransform
+= String( GetValueString( -aPt
.Y() ) );
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
);
808 const NMSP_RTL::OUString
aSpace( ' ' );
809 String
aOutputText( rText
);
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
);
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
);
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
);
847 #ifndef _SVG_USE_NATIVE_TEXTDECORATION
848 // write strikeout if neccessary
849 if( rFont
.GetStrikeout() || rFont
.GetUnderline() )
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
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 */ )
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
);
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
;
922 aString
+= B2UCONST( "<" );
923 aString
+= NMSP_RTL::OUString::createFromAscii( aXMLElemImage
);
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();
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
);
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
);
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
);
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
);
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
);
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
);
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
)
1064 case( META_ARC_ACTION
):
1066 const MetaArcAction
* pA
= (const MetaArcAction
*) pAction
;
1067 aPoly
= Polygon( pA
->GetRect(), pA
->GetStartPoint(), pA
->GetEndPoint(), POLY_ARC
);
1071 case( META_PIE_ACTION
):
1073 const MetaPieAction
* pA
= (const MetaPieAction
*) pAction
;
1074 aPoly
= Polygon( pA
->GetRect(), pA
->GetStartPoint(), pA
->GetEndPoint(), POLY_PIE
);
1078 case( META_CHORD_ACTION
):
1080 const MetaChordAction
* pA
= (const MetaChordAction
*) pAction
;
1081 aPoly
= Polygon( pA
->GetRect(), pA
->GetStartPoint(), pA
->GetEndPoint(), POLY_CHORD
);
1085 case( META_POLYGON_ACTION
):
1086 aPoly
= ( (const MetaPolygonAction
*) pAction
)->GetPolygon();
1090 if( aPoly
.GetSize() )
1092 mpContext
->SetPaintAttr( mpVDev
->GetLineColor(), mpVDev
->GetFillColor() );
1093 ImplWritePolyPolygon( aPoly
, sal_False
, pStyle
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
1216 ImplWriteActions( aTmpMtf
, pStyle
, nWriteFlags
);
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
)
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
);
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
) )
1273 ImplWriteGradientEx( pGradAction
->GetPolyPolygon(), pGradAction
->GetGradient(), pStyle
, nWriteFlags
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
;
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
);
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
1462 DBG_ERROR( "SVGActionWriter::ImplWriteActions: unsupported MetaAction #" );
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() );
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
);