1 .../config/fragments/fcfg_internalgraphics.mk | 1
2 .../internalgraphicfilters/svg_Import.xcu | 10
3 filter/source/svg/exports.map | 1
4 filter/source/svg/makefile.mk | 1
5 filter/source/svg/svgfilter.cxx | 9
6 filter/source/svg/svgfilter.hxx | 7
7 filter/source/svg/svgreader.cxx | 745 ++++++++++++++++++++
8 filter/source/svg/test/makefile.mk | 1
9 8 files changed, 771 insertions(+), 4 deletions(-)
11 diff --git a/filter/source/config/fragments/fcfg_internalgraphics.mk b/filter/source/config/fragments/fcfg_internalgraphics.mk
12 index ae978f0..d1f628a 100644
13 --- filter/source/config/fragments/fcfg_internalgraphics.mk
14 +++ filter/source/config/fragments/fcfg_internalgraphics.mk
15 @@ -68,6 +68,7 @@ F4_INTERNALGRAPHICS = \
23 diff --git a/filter/source/config/fragments/internalgraphicfilters/svg_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/svg_Import.xcu
25 index 0000000..f0285be
27 +++ filter/source/config/fragments/internalgraphicfilters/svg_Import.xcu
29 + <node oor:name="svg_Import" oor:op="replace" >
30 + <prop oor:name="Type"><value>svg_Scalable_Vector_Graphics</value></prop>
31 + <prop oor:name="FormatName"><value>svgfilter</value></prop>
32 + <prop oor:name="RealFilterName"/>
33 + <prop oor:name="UIComponent"/>
34 + <prop oor:name="UIName">
35 + <value xml:lang="en-US">SVG - Scalable Vector Graphics</value>
37 + <prop oor:name="Flags"><value>IMPORT</value></prop>
39 diff --git a/filter/source/svg/exports.map b/filter/source/svg/exports.map
40 index acb4748..d56c225 100644
41 --- filter/source/svg/exports.map
42 +++ filter/source/svg/exports.map
43 @@ -3,6 +3,7 @@ SVGFILTER_1_0 {
44 component_getImplementationEnvironment;
51 diff --git a/filter/source/svg/makefile.mk b/filter/source/svg/makefile.mk
52 index aa54c9e..6474385 100644
53 --- filter/source/svg/makefile.mk
54 +++ filter/source/svg/makefile.mk
55 @@ -74,6 +74,7 @@ SHL1STDLIBS=\
63 diff --git a/filter/source/svg/svgfilter.cxx b/filter/source/svg/svgfilter.cxx
64 index 5b3c985..2ac5eb1 100644
65 --- filter/source/svg/svgfilter.cxx
66 +++ filter/source/svg/svgfilter.cxx
67 @@ -208,6 +208,14 @@ rtl::OUString SAL_CALL SVGFilter::detect( Sequence< PropertyValue >& io_rDescrip
69 // -----------------------------------------------------------------------------
71 +class FilterConfigItem;
72 +extern "C" SAL_DLLPUBLIC_EXPORT BOOL __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, BOOL )
74 + return importSvg( rStream, rGraphic );
77 +// -----------------------------------------------------------------------------
79 namespace sdecl = comphelper::service_decl;
80 sdecl::class_<SVGFilter> serviceImpl;
81 const sdecl::ServiceDecl svgFilter(
82 @@ -219,3 +227,4 @@ namespace sdecl = comphelper::service_decl;
84 // The C shared lib entry points
85 COMPHELPER_SERVICEDECL_EXPORTS1(svgFilter)
87 diff --git a/filter/source/svg/svgfilter.hxx b/filter/source/svg/svgfilter.hxx
88 index b1123cc..1557dc5 100644
89 --- filter/source/svg/svgfilter.hxx
90 +++ filter/source/svg/svgfilter.hxx
91 @@ -271,4 +271,11 @@ sal_Bool SAL_CALL SVGFilter_supportsService( const ::rtl::OUString& ServiceName
92 SAL_CALL SVGFilter_createInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rSMgr)
93 throw ( ::com::sun::star::uno::Exception );
95 +// -----------------------------------------------------------------------------
100 +bool importSvg(SvStream & rStream, Graphic & rGraphic );
102 #endif // SVGFILTER_HXX
103 diff --git a/filter/source/svg/svgreader.cxx b/filter/source/svg/svgreader.cxx
104 index 2714f05..cb2b455 100644
105 --- filter/source/svg/svgreader.cxx
106 +++ filter/source/svg/svgreader.cxx
108 * Thorsten Behrens <tbehrens@novell.com>
110 * Copyright (C) 2008, Novell Inc.
111 + * Parts copyright 2005 by Sun Microsystems, Inc.
113 * The Contents of this file are made available subject to
114 * the terms of GNU Lesser General Public License Version 2.1.
116 #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
117 #include <com/sun/star/xml/dom/NodeType.hpp>
119 +#include <comphelper/processfactory.hxx>
120 +#include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
121 +#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
122 +#include <unotools/streamwrap.hxx>
123 +#include <xmloff/xmluconv.hxx>
124 +#include <vcl/graph.hxx>
125 +#include <vcl/virdev.hxx>
126 +#include <vcl/gradient.hxx>
127 +#include <svx/impgrf.hxx>
128 +#include <tools/zcodec.hxx>
130 #include <boost/bind.hpp>
133 @@ -424,6 +436,9 @@ struct AnnotatingVisitor
135 optimizeGradientStops(rState.maFillGradient);
137 + if( !mxDocumentHandler.is() )
138 + return true; // cannot write style, svm import case
140 // do we have a gradient fill? then write out gradient as well
141 if( rState.meFillType == GRADIENT && rState.maFillGradient.maStops.size() > 1 )
143 @@ -1505,10 +1520,12 @@ struct ShapeWritingVisitor
144 for( sal_uInt32 i=0; i<rPoly.count(); ++i )
147 - basegfx::tools::createAreaGeometryForPolygon(
148 - rPoly.getB2DPolygon(i),
149 - aState.mnStrokeWidth/2.0,
150 - aState.meLineJoin));
151 + basegfx::tools::stripNeutralPolygons(
152 + basegfx::tools::prepareForPolygonOperation(
153 + basegfx::tools::createAreaGeometry(
154 + rPoly.getB2DPolygon(i),
155 + aState.mnStrokeWidth/2.0,
156 + aState.meLineJoin))));
157 // TODO(F2): line ends
160 @@ -1873,4 +1891,737 @@ sal_Bool SVGReader::parseAndConvert()
164 +///////////////////////////////////////////////////////////////
166 +struct ShapeRenderingVisitor
168 + ShapeRenderingVisitor(StatePool& /*rStatePool*/,
169 + StateMap& rStateMap,
170 + OutputDevice& rOutDev,
171 + const std::vector< Gradient >& rGradientVector,
172 + const std::vector< GradientStop >& rGradientStopVector) :
173 + mrStateMap(rStateMap),
175 + mrGradientVector(rGradientVector),
176 + mrGradientStopVector(rGradientStopVector)
179 + void operator()( const uno::Reference<xml::dom::XElement>& )
183 + void operator()( const uno::Reference<xml::dom::XElement>& xElem,
184 + const uno::Reference<xml::dom::XNamedNodeMap>& xAttributes )
186 + sal_Int32 nDummyIndex(0);
187 + rtl::OUString sStyleId(
188 + xElem->getAttribute(
189 + USTR("internal-style-ref")).getToken(
190 + 0,'$',nDummyIndex));
191 + StateMap::iterator pOrigState=mrStateMap.find(
192 + sStyleId.toInt32());
194 + if( pOrigState == mrStateMap.end() )
195 + return; // non-exportable element, e.g. linearGradient
197 + maCurrState = pOrigState->second;
199 + const sal_Int32 nTokenId(getTokenId(xElem->getNodeName()));
204 + // collect attributes
205 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
206 + rtl::OUString sAttributeValue;
207 + double x1=0.0,y1=0.0,x2=0.0,y2=0.0;
208 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
210 + sAttributeValue = xAttributes->item(i)->getNodeValue();
211 + const sal_Int32 nAttribId(
212 + getTokenId(xAttributes->item(i)->getNodeName()));
216 + x1= convLength(sAttributeValue,maCurrState,'h');
219 + x2 = convLength(sAttributeValue,maCurrState,'h');
222 + y1 = convLength(sAttributeValue,maCurrState,'v');
225 + y2 = convLength(sAttributeValue,maCurrState,'v');
233 + basegfx::B2DPolygon aPoly;
234 + aPoly.append(basegfx::B2DPoint(x1,y1));
235 + aPoly.append(basegfx::B2DPoint(x2,y2));
237 + renderPathShape(basegfx::B2DPolyPolygon(aPoly));
243 + rtl::OUString sPoints = xElem->hasAttribute(USTR("points")) ? xElem->getAttribute(USTR("points")) : USTR("");
244 + basegfx::B2DPolygon aPoly;
245 + basegfx::tools::importFromSvgPoints(aPoly, sPoints);
246 + if( nTokenId == XML_POLYGON || maCurrState.meFillType != NONE )
247 + aPoly.setClosed(true);
249 + renderPathShape(basegfx::B2DPolyPolygon(aPoly));
254 + // collect attributes
255 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
256 + rtl::OUString sAttributeValue;
257 + bool bRxSeen=false, bRySeen=false;
258 + double x=0.0,y=0.0,width=0.0,height=0.0,rx=0.0,ry=0.0;
259 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
261 + sAttributeValue = xAttributes->item(i)->getNodeValue();
262 + const sal_Int32 nAttribId(
263 + getTokenId(xAttributes->item(i)->getNodeName()));
267 + x = convLength(sAttributeValue,maCurrState,'h');
270 + y = convLength(sAttributeValue,maCurrState,'v');
273 + width = convLength(sAttributeValue,maCurrState,'h');
276 + height = convLength(sAttributeValue,maCurrState,'v');
279 + rx = convLength(sAttributeValue,maCurrState,'h');
283 + ry = convLength(sAttributeValue,maCurrState,'v');
292 + if( bRxSeen && !bRySeen )
294 + else if( bRySeen && !bRxSeen )
297 + basegfx::B2DPolygon aPoly;
298 + aPoly = basegfx::tools::createPolygonFromRect(
299 + basegfx::B2DRange(x,y,x+width,y+height),
302 + renderPathShape(basegfx::B2DPolyPolygon(aPoly));
307 + rtl::OUString sPath = xElem->hasAttribute(USTR("d")) ? xElem->getAttribute(USTR("d")) : USTR("");
308 + basegfx::B2DPolyPolygon aPoly;
309 + basegfx::tools::importFromSvgD(aPoly, sPath);
311 + renderPathShape(aPoly);
316 + // collect attributes
317 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
318 + rtl::OUString sAttributeValue;
319 + double cx=0.0,cy=0.0,r=0.0;
320 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
322 + sAttributeValue = xAttributes->item(i)->getNodeValue();
323 + const sal_Int32 nAttribId(
324 + getTokenId(xAttributes->item(i)->getNodeName()));
328 + cx = convLength(sAttributeValue,maCurrState,'h');
331 + cy = convLength(sAttributeValue,maCurrState,'v');
334 + r = convLength(sAttributeValue,maCurrState,'o');
341 + basegfx::B2DEllipse aEllipse(basegfx::B2DPoint(cx, cy), basegfx::B2DTuple(r,r));
342 + basegfx::B2DPolygon aPoly = basegfx::tools::createPolygonFromEllipse(
343 + aEllipse.getB2DEllipseCenter(),
344 + aEllipse.getB2DEllipseRadius().getX(),
345 + aEllipse.getB2DEllipseRadius().getY());
347 + renderPathShape(basegfx::B2DPolyPolygon(aPoly));
352 + // collect attributes
353 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
354 + rtl::OUString sAttributeValue;
355 + double cx=0.0,cy=0.0,rx=0.0, ry=0.0;
356 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
358 + sAttributeValue = xAttributes->item(i)->getNodeValue();
359 + const sal_Int32 nAttribId(
360 + getTokenId(xAttributes->item(i)->getNodeName()));
364 + cx = convLength(sAttributeValue,maCurrState,'h');
367 + cy = convLength(sAttributeValue,maCurrState,'v');
370 + rx = convLength(sAttributeValue,maCurrState,'h');
373 + ry = convLength(sAttributeValue,maCurrState,'v');
380 + basegfx::B2DEllipse aEllipse(basegfx::B2DPoint(cx, cy), basegfx::B2DTuple(rx,ry));
381 + basegfx::B2DPolygon aPoly = basegfx::tools::createPolygonFromEllipse(
382 + aEllipse.getB2DEllipseCenter(),
383 + aEllipse.getB2DEllipseRadius().getX(),
384 + aEllipse.getB2DEllipseRadius().getY());
386 + renderPathShape(basegfx::B2DPolyPolygon(aPoly));
391 + // collect attributes
392 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
393 + rtl::OUString sAttributeValue;
394 + double x=0.0,y=0.0,width=0.0,height=0.0;
395 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
397 + sAttributeValue = xAttributes->item(i)->getNodeValue();
398 + const sal_Int32 nAttribId(
399 + getTokenId(xAttributes->item(i)->getNodeName()));
403 + x = convLength(sAttributeValue,maCurrState,'h');
406 + y = convLength(sAttributeValue,maCurrState,'v');
409 + width = convLength(sAttributeValue,maCurrState,'h');
412 + height = convLength(sAttributeValue,maCurrState,'v');
420 + rtl::OUString sValue = xElem->hasAttribute(USTR("href")) ? xElem->getAttribute(USTR("href")) : USTR("");
421 + rtl::OString aValueUtf8( sValue.getStr(), sValue.getLength(), RTL_TEXTENCODING_UTF8 );
422 + std::string sLinkValue;
423 + parseXlinkHref(aValueUtf8.getStr(), sLinkValue);
425 + if (!sLinkValue.empty())
427 + // <- blatant copy from svx/source/xml/xmlgrhlp.cxx
430 + uno::Sequence<sal_Int8> aData;
431 + SvXMLUnitConverter::decodeBase64(aData,
432 + rtl::OUString::createFromAscii(sLinkValue.c_str()));
433 + SvMemoryStream aSrc(aData.getArray(),
436 + USHORT nFormat = GRFILTER_FORMAT_DONTKNOW;
437 + USHORT pDeterminedFormat = GRFILTER_FORMAT_DONTKNOW;
438 + GetGrfFilter()->ImportGraphic( aGraphic, String(), aSrc ,nFormat,&pDeterminedFormat );
440 + if (pDeterminedFormat == GRFILTER_FORMAT_DONTKNOW)
442 + //Read the first two byte to check whether it is a gzipped stream, is so it may be in wmz or emz format
443 + //unzip them and try again
445 + BYTE sFirstBytes[ 2 ];
447 + aSrc.Seek( STREAM_SEEK_TO_END );
448 + ULONG nStreamLen = aSrc.Tell();
453 + SvLockBytes* pLockBytes = aSrc.GetLockBytes();
455 + pLockBytes->SetSynchronMode( TRUE );
457 + aSrc.Seek( STREAM_SEEK_TO_END );
458 + nStreamLen = aSrc.Tell();
461 + if( nStreamLen >= 2 )
464 + aSrc.Read( sFirstBytes, 2 );
466 + if( sFirstBytes[0] == 0x1f && sFirstBytes[1] == 0x8b )
468 + SvMemoryStream* pDest = new SvMemoryStream;
469 + ZCodec aZCodec( 0x8000, 0x8000 );
470 + aZCodec.BeginCompression(ZCODEC_GZ_LIB);
472 + aZCodec.Decompress( aSrc, *pDest );
474 + if (aZCodec.EndCompression() && pDest )
476 + pDest->Seek( STREAM_SEEK_TO_END );
477 + ULONG nStreamLen_ = pDest->Tell();
481 + GetGrfFilter()->ImportGraphic( aGraphic, String(), *pDest ,nFormat,&pDeterminedFormat );
488 + // -> blatant copy from svx/source/xml/xmlgrhlp.cxx
490 + const Rectangle aBounds(
491 + Point(basegfx::fround(pt100thmm(x)),
492 + basegfx::fround(pt100thmm(y))),
493 + Size(basegfx::fround(pt100thmm(width)),
494 + basegfx::fround(pt100thmm(height))));
495 + aGraphic.Draw(&mrOutDev,
497 + aBounds.GetSize());
498 + maBounds.Union(aBounds);
504 + // collect text from all TEXT_NODE children into sText
505 + rtl::OUStringBuffer sText;
506 + visitChildren(boost::bind(
507 + (rtl::OUStringBuffer& (rtl::OUStringBuffer::*)(const sal_Unicode* str))&rtl::OUStringBuffer::append,
509 + boost::bind(&xml::dom::XNode::getNodeValue,
512 + xml::dom::NodeType_TEXT_NODE);
514 + // collect attributes
515 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
516 + rtl::OUString sAttributeValue;
517 + double x=0.0,y=0.0,width=0.0,height=0.0;
518 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
520 + sAttributeValue = xAttributes->item(i)->getNodeValue();
521 + const sal_Int32 nAttribId(
522 + getTokenId(xAttributes->item(i)->getNodeName()));
526 + x = convLength(sAttributeValue,maCurrState,'h');
529 + y = convLength(sAttributeValue,maCurrState,'v');
532 + width = convLength(sAttributeValue,maCurrState,'h');
535 + height = convLength(sAttributeValue,maCurrState,'v');
543 + // actually export text
544 + Font aFont(maCurrState.maFontFamily,
546 + basegfx::fround(pt100thmm(maCurrState.mnFontSize))));
548 + // extract basic transformations out of CTM
549 + basegfx::B2DTuple aScale, aTranslate;
550 + double fRotate, fShearX;
551 + ::rtl::OUString sTransformValue;
552 + if (maCurrState.maCTM.decompose(aScale, aTranslate, fRotate, fShearX))
554 + rtl::OUString sTransform;
555 + x += aTranslate.getX();
556 + y += aTranslate.getY();
559 + Size(basegfx::fround(aFont.GetWidth()*aScale.getX()),
560 + basegfx::fround(aFont.GetHeight()*aScale.getY())));
563 + aFont.SetOrientation(basegfx::fround(fRotate*1800.0/M_PI));
566 + // TODO(F2): update bounds
567 + mrOutDev.SetFont(aFont);
568 + mrOutDev.DrawText(Point(basegfx::fround(pt100thmm(x)),
569 + basegfx::fround(pt100thmm(y))),
570 + sText.makeStringAndClear());
584 + bool hasGradientOpacity( const Gradient& rGradient )
587 + mrGradientStopVector[
588 + rGradient.maStops[0]].maStopColor.a != 1.0 ||
589 + mrGradientStopVector[
590 + rGradient.maStops[1]].maStopColor.a != 1.0;
593 + sal_Int8 toByteColor( double val )
595 + // TODO(Q3): duplicated from vcl::unotools
596 + return sal::static_int_cast<sal_Int8>(
597 + basegfx::fround(val*255.0));
600 + ::Color getVclColor( const ARGBColor& rColor )
602 + const sal_uInt8 nRed ( toByteColor(rColor.r) );
603 + const sal_uInt8 nGreen( toByteColor(rColor.g) );
604 + const sal_uInt8 nBlue ( toByteColor(rColor.b) );
606 + return ::Color(nRed,nGreen,nBlue);
609 + void renderPathShape(const basegfx::B2DPolyPolygon& rPoly)
611 + // we might need to split up polypolygon into multiple path
612 + // shapes (e.g. when emulating line stroking)
613 + State aState = maCurrState;
615 + // bring polygon from pt coordinate system to 100th millimeter
616 + aState.maCTM.scale(2540.0/72.0,2540.0/72.0);
618 + basegfx::B2DPolyPolygon aPoly(rPoly);
619 + aPoly.transform(aState.maCTM);
621 + const basegfx::B2DRange aBounds=basegfx::tools::getRange(aPoly);
624 + basegfx::fround(aBounds.getMinX()),
625 + basegfx::fround(aBounds.getMinY()),
626 + basegfx::fround(aBounds.getMaxX()),
627 + basegfx::fround(aBounds.getMaxY())));
630 + mrOutDev.SetLineColor();
632 + // do we have a gradient fill?
633 + if( aState.meFillType == GRADIENT && aState.maFillGradient.maStops.size() > 1 )
635 + ::Gradient aGradient;
637 + if( aState.maFillGradient.meType == Gradient::LINEAR )
639 + // should the optimizeGradientStops method decide that
640 + // this is a three-color gradient, it prolly wanted us
641 + // to take axial instead
642 + aGradient = ::Gradient( aState.maFillGradient.maStops.size() == 3 ?
648 + aGradient = ::Gradient( GRADIENT_ELLIPTICAL );
651 + basegfx::B2DTuple rScale, rTranslate;
652 + double rRotate, rShearX;
653 + if( aState.maFillGradient.maTransform.decompose(rScale, rTranslate, rRotate, rShearX) )
654 + aGradient.SetAngle( basegfx::fround(rRotate*1800.0/M_PI) );
655 + aGradient.SetStartColor( getVclColor(
656 + mrGradientStopVector[
657 + aState.maFillGradient.maStops[0]].maStopColor) );
658 + aGradient.SetEndColor( getVclColor(
659 + mrGradientStopVector[
660 + aState.maFillGradient.maStops[1]].maStopColor) );
662 + if( hasGradientOpacity(aState.maFillGradient) )
664 + ::Gradient aTransparencyGradient=aGradient;
666 + const BYTE cTransStart( 255-
667 + basegfx::fround(mrGradientStopVector[
668 + aState.maFillGradient.maStops[1]].maStopColor.a*
669 + aState.mnFillOpacity*255.0));
670 + const Color aTransStart( cTransStart, cTransStart, cTransStart );
672 + const BYTE cTransEnd( 255-
673 + basegfx::fround(mrGradientStopVector[
674 + aState.maFillGradient.maStops[0]].maStopColor.a*
675 + aState.mnFillOpacity*255.0));
676 + const Color aTransEnd( cTransEnd, cTransEnd, cTransEnd );
678 + // modulate gradient opacity with overall fill opacity
679 + aTransparencyGradient.SetStartColor(aTransStart);
680 + aTransparencyGradient.SetEndColor(aTransEnd);
682 + VirtualDevice aVDev;
685 + aVDev.EnableOutput( FALSE );
686 + aVDev.SetMapMode( mrOutDev.GetMapMode() );
687 + aMtf.Record( &aVDev );
689 + aVDev.SetLineColor();
690 + aVDev.SetFillColor();
691 + aVDev.DrawGradient(::PolyPolygon(aPoly),aGradient);
693 + const Rectangle aMtfBounds(
694 + basegfx::fround(aBounds.getMinX()),
695 + basegfx::fround(aBounds.getMinY()),
696 + basegfx::fround(aBounds.getMaxX()),
697 + basegfx::fround(aBounds.getMaxY()));
699 + MapMode aMap(mrOutDev.GetMapMode());
702 + aMap.SetOrigin( aMtfBounds.TopLeft() );
703 + aMtf.SetPrefMapMode( aMap );
704 + aMtf.SetPrefSize( aMtfBounds.GetSize() );
706 + mrOutDev.DrawTransparent(aMtf,
707 + aMtfBounds.TopLeft(),
708 + aMtfBounds.GetSize(),
709 + aTransparencyGradient);
713 + mrOutDev.DrawGradient(::PolyPolygon(aPoly),aGradient);
718 + if( aState.meFillType == NONE )
719 + mrOutDev.SetFillColor();
721 + mrOutDev.SetFillColor(getVclColor(aState.maFillColor));
723 + if( aState.mnFillOpacity != 1.0 )
724 + mrOutDev.DrawTransparent(::PolyPolygon(aPoly),
726 + (1.0-aState.mnFillOpacity)*100.0));
728 + mrOutDev.DrawPolyPolygon(::PolyPolygon(aPoly));
732 + mrOutDev.SetFillColor();
734 + if( aState.meStrokeType != NONE &&
735 + (aState.maDashArray.size() ||
736 + aState.mnStrokeWidth != 1.0) )
738 + // vcl thick lines are severly borked - generate filled
740 + std::vector<basegfx::B2DPolyPolygon> aPolys;
742 + if( !aState.maDashArray.empty() )
745 + basegfx::B2DPolyPolygon aSegment;
746 + for( sal_uInt32 i=0; i<rPoly.count(); ++i )
748 + basegfx::tools::applyLineDashing(rPoly,
749 + aState.maDashArray,
751 + aPoly.append(aSegment);
755 + // applied line dashing to original rPoly above, to get
756 + // correctly transformed lengths - need to transform
758 + aPoly.transform(aState.maCTM);
760 + for( sal_uInt32 i=0; i<aPoly.count(); ++i )
762 + // ugly. convert to integer-based tools polygon
763 + // first, and only _then_ remove intersections (we
764 + // might get new ones from the rounding)
766 + basegfx::tools::stripNeutralPolygons(
767 + basegfx::tools::prepareForPolygonOperation(
769 + basegfx::tools::createAreaGeometry(
770 + aPoly.getB2DPolygon(i),
771 + pt100thmm(aState.mnStrokeWidth/2.0),
772 + aState.meLineJoin)).getB2DPolyPolygon())));
773 + // TODO(F2): line ends
776 + mrOutDev.SetLineColor();
777 + mrOutDev.SetFillColor(getVclColor(aState.maStrokeColor));
779 + for( sal_uInt32 i=0; i<aPolys.size(); ++i )
781 + if( aState.mnStrokeOpacity != 1.0 )
782 + mrOutDev.DrawTransparent(::PolyPolygon(aPolys[i]),
784 + (1.0-aState.mnStrokeOpacity)*100.0));
786 + mrOutDev.DrawPolyPolygon(::PolyPolygon(aPolys[i]));
788 + const basegfx::B2DRange aStrokeBounds=basegfx::tools::getRange(aPolys[i]);
791 + basegfx::fround(aStrokeBounds.getMinX()),
792 + basegfx::fround(aStrokeBounds.getMinY()),
793 + basegfx::fround(aStrokeBounds.getMaxX()),
794 + basegfx::fround(aStrokeBounds.getMaxY())));
799 + if( aState.meStrokeType == NONE )
800 + mrOutDev.SetLineColor();
802 + mrOutDev.SetLineColor(getVclColor(aState.maStrokeColor));
804 + if( aState.mnStrokeOpacity != 1.0 )
805 + mrOutDev.DrawTransparent(::PolyPolygon(aPoly),
807 + (1.0-aState.mnStrokeOpacity)*100.0));
809 + mrOutDev.DrawPolyPolygon(::PolyPolygon(aPoly));
814 + StateMap& mrStateMap;
815 + OutputDevice& mrOutDev;
816 + const std::vector< Gradient >& mrGradientVector;
817 + const std::vector< GradientStop >& mrGradientStopVector;
818 + Rectangle maBounds;
823 +bool importSvg(SvStream & rStream, Graphic & rGraphic )
825 + const uno::Reference<lang::XMultiServiceFactory> xServiceFactory(
826 + ::comphelper::getProcessServiceFactory());
828 + uno::Reference<xml::dom::XDocumentBuilder> xDomBuilder(
829 + xServiceFactory->createInstance(
830 + rtl::OUString::createFromAscii("com.sun.star.xml.dom.DocumentBuilder")),
833 + uno::Reference<io::XInputStream> xStream(
834 + new utl::OInputStreamWrapper(rStream) );
836 + uno::Reference<xml::dom::XDocument> xDom(
837 + xDomBuilder->parse(xStream),
838 + uno::UNO_QUERY_THROW );
840 + uno::Reference<xml::dom::XElement> xDocElem( xDom->getDocumentElement(),
841 + uno::UNO_QUERY_THROW );
843 + VirtualDevice aVDev;
846 + aVDev.EnableOutput( FALSE );
847 + aMtf.Record( &aVDev );
849 + // parse styles and fill state stack
850 + svgi::State aInitialState;
851 + svgi::StatePool aStatePool;
852 + svgi::StateMap aStateMap;
853 + svgi::AnnotatingVisitor aVisitor(aStatePool,
856 + uno::Reference<xml::sax::XDocumentHandler>());
857 + svgi::visitElements(aVisitor, xDocElem);
860 + dumpTree(xDocElem);
863 + // render all shapes to mtf
864 + svgi::ShapeRenderingVisitor aRenderer(aStatePool,aStateMap,aVDev,
865 + aVisitor.maGradientVector,
866 + aVisitor.maGradientStopVector);
867 + svgi::visitElements(aRenderer, xDocElem);
872 + aMtf.SetPrefMapMode( MAP_100TH_MM );
874 + // get the document dimensions
876 + // if the "width" and "height" attributes are missing, inkscape fakes
877 + // A4 portrait for. Let's do the same.
878 + if (!xDocElem->hasAttribute(USTR("width")))
879 + xDocElem->setAttribute(USTR("width"), USTR("210mm"));
880 + if (!xDocElem->hasAttribute(USTR("height")))
881 + xDocElem->setAttribute(USTR("height"), USTR("297mm"));
886 + sal_Int32(aRenderer.maBounds.Right()),
887 + basegfx::fround( svgi::pt100thmm(svgi::convLength(xDocElem->getAttribute(USTR("width")),aInitialState,'h')) )),
889 + sal_Int32(aRenderer.maBounds.Bottom()),
890 + basegfx::fround( svgi::pt100thmm(svgi::convLength(xDocElem->getAttribute(USTR("height")),aInitialState,'v')) ))));
898 diff --git a/filter/source/svg/test/makefile.mk b/filter/source/svg/test/makefile.mk
899 index 3f14c88..1d743c6 100644
900 --- filter/source/svg/test/makefile.mk
901 +++ filter/source/svg/test/makefile.mk
902 @@ -41,6 +41,7 @@ SHL1STDLIBS= \