merge the formfield patch from ooo-build
[ooovba.git] / applied_patches / 0397-svg-import-filter-gfxfilter.diff
blob38e32285897810bfd36357f18eb27dcb6bf79e7a
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 = \
16 sgf_Import \
17 sgv_Import \
18 svg_Export \
19 + svg_Import \
20 svm_Export \
21 svm_Import \
22 tga_Import \
23 diff --git a/filter/source/config/fragments/internalgraphicfilters/svg_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/svg_Import.xcu
24 new file mode 100644
25 index 0000000..f0285be
26 --- /dev/null
27 +++ filter/source/config/fragments/internalgraphicfilters/svg_Import.xcu
28 @@ -0,0 +1,10 @@
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>
36 + </prop>
37 + <prop oor:name="Flags"><value>IMPORT</value></prop>
38 + </node>
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;
45 component_getFactory;
46 component_writeInfo;
47 + GraphicImport;
49 local:
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=\
56 $(UNOTOOLSLIB) \
57 $(TOOLSLIB) \
58 $(COMPHELPERLIB) \
59 + $(SVTOOLLIB) \
60 $(CPPUHELPERLIB) \
61 $(CPPULIB) \
62 $(SALLIB) \
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 +// -----------------------------------------------------------------------------
97 +class SvStream;
98 +class Graphic;
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
107 @@ -7,6 +7,7 @@
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.
115 @@ -41,6 +42,17 @@
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>
131 #include <hash_set>
132 #include <map>
133 @@ -424,6 +436,9 @@ struct AnnotatingVisitor
134 // start&end color)
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 )
146 aPolys.push_back(
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()
161 return sal_True;
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),
174 + mrOutDev(rOutDev),
175 + mrGradientVector(rGradientVector),
176 + mrGradientStopVector(rGradientStopVector)
177 + {}
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()));
200 + switch(nTokenId)
202 + case XML_LINE:
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()));
213 + switch(nAttribId)
215 + case XML_X1:
216 + x1= convLength(sAttributeValue,maCurrState,'h');
217 + break;
218 + case XML_X2:
219 + x2 = convLength(sAttributeValue,maCurrState,'h');
220 + break;
221 + case XML_Y1:
222 + y1 = convLength(sAttributeValue,maCurrState,'v');
223 + break;
224 + case XML_Y2:
225 + y2 = convLength(sAttributeValue,maCurrState,'v');
226 + break;
227 + default:
228 + // skip
229 + break;
233 + basegfx::B2DPolygon aPoly;
234 + aPoly.append(basegfx::B2DPoint(x1,y1));
235 + aPoly.append(basegfx::B2DPoint(x2,y2));
237 + renderPathShape(basegfx::B2DPolyPolygon(aPoly));
238 + break;
240 + case XML_POLYGON:
241 + case XML_POLYLINE:
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));
250 + break;
252 + case XML_RECT:
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()));
264 + switch(nAttribId)
266 + case XML_X:
267 + x = convLength(sAttributeValue,maCurrState,'h');
268 + break;
269 + case XML_Y:
270 + y = convLength(sAttributeValue,maCurrState,'v');
271 + break;
272 + case XML_WIDTH:
273 + width = convLength(sAttributeValue,maCurrState,'h');
274 + break;
275 + case XML_HEIGHT:
276 + height = convLength(sAttributeValue,maCurrState,'v');
277 + break;
278 + case XML_RX:
279 + rx = convLength(sAttributeValue,maCurrState,'h');
280 + bRxSeen=true;
281 + break;
282 + case XML_RY:
283 + ry = convLength(sAttributeValue,maCurrState,'v');
284 + bRySeen=true;
285 + break;
286 + default:
287 + // skip
288 + break;
292 + if( bRxSeen && !bRySeen )
293 + ry = rx;
294 + else if( bRySeen && !bRxSeen )
295 + rx = ry;
297 + basegfx::B2DPolygon aPoly;
298 + aPoly = basegfx::tools::createPolygonFromRect(
299 + basegfx::B2DRange(x,y,x+width,y+height),
300 + rx, ry );
302 + renderPathShape(basegfx::B2DPolyPolygon(aPoly));
303 + break;
305 + case XML_PATH:
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);
312 + break;
314 + case XML_CIRCLE:
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()));
325 + switch(nAttribId)
327 + case XML_CX:
328 + cx = convLength(sAttributeValue,maCurrState,'h');
329 + break;
330 + case XML_CY:
331 + cy = convLength(sAttributeValue,maCurrState,'v');
332 + break;
333 + case XML_R:
334 + r = convLength(sAttributeValue,maCurrState,'o');
335 + default:
336 + // skip
337 + break;
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));
348 + break;
350 + case XML_ELLIPSE:
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()));
361 + switch(nAttribId)
363 + case XML_CX:
364 + cx = convLength(sAttributeValue,maCurrState,'h');
365 + break;
366 + case XML_CY:
367 + cy = convLength(sAttributeValue,maCurrState,'v');
368 + break;
369 + case XML_RX:
370 + rx = convLength(sAttributeValue,maCurrState,'h');
371 + break;
372 + case XML_RY:
373 + ry = convLength(sAttributeValue,maCurrState,'v');
374 + default:
375 + // skip
376 + break;
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));
387 + break;
389 + case XML_IMAGE:
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()));
400 + switch(nAttribId)
402 + case XML_X:
403 + x = convLength(sAttributeValue,maCurrState,'h');
404 + break;
405 + case XML_Y:
406 + y = convLength(sAttributeValue,maCurrState,'v');
407 + break;
408 + case XML_WIDTH:
409 + width = convLength(sAttributeValue,maCurrState,'h');
410 + break;
411 + case XML_HEIGHT:
412 + height = convLength(sAttributeValue,maCurrState,'v');
413 + break;
414 + default:
415 + // skip
416 + break;
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
428 + Graphic aGraphic;
430 + uno::Sequence<sal_Int8> aData;
431 + SvXMLUnitConverter::decodeBase64(aData,
432 + rtl::OUString::createFromAscii(sLinkValue.c_str()));
433 + SvMemoryStream aSrc(aData.getArray(),
434 + aData.getLength(),
435 + STREAM_READ);
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();
449 + aSrc.Seek( 0 );
451 + if ( !nStreamLen )
453 + SvLockBytes* pLockBytes = aSrc.GetLockBytes();
454 + if ( pLockBytes )
455 + pLockBytes->SetSynchronMode( TRUE );
457 + aSrc.Seek( STREAM_SEEK_TO_END );
458 + nStreamLen = aSrc.Tell();
459 + aSrc.Seek( 0 );
461 + if( nStreamLen >= 2 )
463 + //read two byte
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);
471 + aSrc.Seek( 0 );
472 + aZCodec.Decompress( aSrc, *pDest );
474 + if (aZCodec.EndCompression() && pDest )
476 + pDest->Seek( STREAM_SEEK_TO_END );
477 + ULONG nStreamLen_ = pDest->Tell();
478 + if (nStreamLen_)
480 + pDest->Seek(0L);
481 + GetGrfFilter()->ImportGraphic( aGraphic, String(), *pDest ,nFormat,&pDeterminedFormat );
484 + delete pDest;
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,
496 + aBounds.TopLeft(),
497 + aBounds.GetSize());
498 + maBounds.Union(aBounds);
500 + break;
502 + case XML_TEXT:
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,
508 + boost::ref(sText),
509 + boost::bind(&xml::dom::XNode::getNodeValue,
510 + _1)),
511 + xElem,
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()));
523 + switch(nAttribId)
525 + case XML_X:
526 + x = convLength(sAttributeValue,maCurrState,'h');
527 + break;
528 + case XML_Y:
529 + y = convLength(sAttributeValue,maCurrState,'v');
530 + break;
531 + case XML_WIDTH:
532 + width = convLength(sAttributeValue,maCurrState,'h');
533 + break;
534 + case XML_HEIGHT:
535 + height = convLength(sAttributeValue,maCurrState,'v');
536 + break;
537 + default:
538 + // skip
539 + break;
543 + // actually export text
544 + Font aFont(maCurrState.maFontFamily,
545 + Size(0,
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();
558 + aFont.SetSize(
559 + Size(basegfx::fround(aFont.GetWidth()*aScale.getX()),
560 + basegfx::fround(aFont.GetHeight()*aScale.getY())));
562 + if( fRotate )
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());
571 + break;
576 + void push()
580 + void pop()
584 + bool hasGradientOpacity( const Gradient& rGradient )
586 + return
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);
622 + maBounds.Union(
623 + Rectangle(
624 + basegfx::fround(aBounds.getMinX()),
625 + basegfx::fround(aBounds.getMinY()),
626 + basegfx::fround(aBounds.getMaxX()),
627 + basegfx::fround(aBounds.getMaxY())));
629 + // fill first
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 ?
643 + GRADIENT_AXIAL :
644 + GRADIENT_LINEAR );
646 + else
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;
683 + GDIMetaFile aMtf;
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());
700 + aMtf.Stop();
701 + aMtf.WindStart();
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);
711 + else
713 + mrOutDev.DrawGradient(::PolyPolygon(aPoly),aGradient);
716 + else
718 + if( aState.meFillType == NONE )
719 + mrOutDev.SetFillColor();
720 + else
721 + mrOutDev.SetFillColor(getVclColor(aState.maFillColor));
723 + if( aState.mnFillOpacity != 1.0 )
724 + mrOutDev.DrawTransparent(::PolyPolygon(aPoly),
725 + basegfx::fround(
726 + (1.0-aState.mnFillOpacity)*100.0));
727 + else
728 + mrOutDev.DrawPolyPolygon(::PolyPolygon(aPoly));
731 + // Stroking now
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
739 + // polygon instead
740 + std::vector<basegfx::B2DPolyPolygon> aPolys;
741 + aPoly = rPoly;
742 + if( !aState.maDashArray.empty() )
744 + aPoly.clear();
745 + basegfx::B2DPolyPolygon aSegment;
746 + for( sal_uInt32 i=0; i<rPoly.count(); ++i )
748 + basegfx::tools::applyLineDashing(rPoly,
749 + aState.maDashArray,
750 + &aSegment);
751 + aPoly.append(aSegment);
755 + // applied line dashing to original rPoly above, to get
756 + // correctly transformed lengths - need to transform
757 + // again, now
758 + aPoly.transform(aState.maCTM);
760 + for( sal_uInt32 i=0; i<aPoly.count(); ++i )
761 + {
762 + // ugly. convert to integer-based tools polygon
763 + // first, and only _then_ remove intersections (we
764 + // might get new ones from the rounding)
765 + aPolys.push_back(
766 + basegfx::tools::stripNeutralPolygons(
767 + basegfx::tools::prepareForPolygonOperation(
768 + ::PolyPolygon(
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]),
783 + basegfx::fround(
784 + (1.0-aState.mnStrokeOpacity)*100.0));
785 + else
786 + mrOutDev.DrawPolyPolygon(::PolyPolygon(aPolys[i]));
788 + const basegfx::B2DRange aStrokeBounds=basegfx::tools::getRange(aPolys[i]);
789 + maBounds.Union(
790 + Rectangle(
791 + basegfx::fround(aStrokeBounds.getMinX()),
792 + basegfx::fround(aStrokeBounds.getMinY()),
793 + basegfx::fround(aStrokeBounds.getMaxX()),
794 + basegfx::fround(aStrokeBounds.getMaxY())));
797 + else
799 + if( aState.meStrokeType == NONE )
800 + mrOutDev.SetLineColor();
801 + else
802 + mrOutDev.SetLineColor(getVclColor(aState.maStrokeColor));
804 + if( aState.mnStrokeOpacity != 1.0 )
805 + mrOutDev.DrawTransparent(::PolyPolygon(aPoly),
806 + basegfx::fround(
807 + (1.0-aState.mnStrokeOpacity)*100.0));
808 + else
809 + mrOutDev.DrawPolyPolygon(::PolyPolygon(aPoly));
813 + State maCurrState;
814 + StateMap& mrStateMap;
815 + OutputDevice& mrOutDev;
816 + const std::vector< Gradient >& mrGradientVector;
817 + const std::vector< GradientStop >& mrGradientStopVector;
818 + Rectangle maBounds;
821 } // namespace svgi
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")),
831 + uno::UNO_QUERY );
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;
844 + GDIMetaFile aMtf;
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,
854 + aStateMap,
855 + aInitialState,
856 + uno::Reference<xml::sax::XDocumentHandler>());
857 + svgi::visitElements(aVisitor, xDocElem);
859 +#ifdef VERBOSE
860 + dumpTree(xDocElem);
861 +#endif
863 + // render all shapes to mtf
864 + svgi::ShapeRenderingVisitor aRenderer(aStatePool,aStateMap,aVDev,
865 + aVisitor.maGradientVector,
866 + aVisitor.maGradientStopVector);
867 + svgi::visitElements(aRenderer, xDocElem);
869 + aMtf.Stop();
871 + aMtf.WindStart();
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"));
883 + aMtf.SetPrefSize(
884 + Size(
885 + std::max(
886 + sal_Int32(aRenderer.maBounds.Right()),
887 + basegfx::fround( svgi::pt100thmm(svgi::convLength(xDocElem->getAttribute(USTR("width")),aInitialState,'h')) )),
888 + std::max(
889 + sal_Int32(aRenderer.maBounds.Bottom()),
890 + basegfx::fround( svgi::pt100thmm(svgi::convLength(xDocElem->getAttribute(USTR("height")),aInitialState,'v')) ))));
892 + rGraphic = aMtf;
894 + return sal_True;
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= \
903 $(UNOTOOLSLIB) \
904 $(TOOLSLIB) \
905 $(COMPHELPERLIB) \
906 + $(SVTOOLLIB) \
907 $(CPPUHELPERLIB) \
908 $(CPPULIB) \
909 $(SALLIB) \