merge the formfield patch from ooo-build
[ooovba.git] / applied_patches / 0396-svg-import-filter.diff
blobf71d02f8e5566778d35dc3246b8e5b65fbe5ea91
1 diff --git filter/source/config/fragments/fcfg_drawgraphics.mk filter/source/config/fragments/fcfg_drawgraphics.mk
2 index 7038e27..41a4625 100644
3 --- filter/source/config/fragments/fcfg_drawgraphics.mk
4 +++ filter/source/config/fragments/fcfg_drawgraphics.mk
5 @@ -54,6 +54,7 @@ F4_DRAWGRAPHICS = \
6 SGF___StarOffice_Writer_SGF \
7 SGV___StarDraw_2_0 \
8 SVM___StarView_Metafile \
9 + SVG___Scalable_Vector_Graphics \
10 TGA___Truevision_TARGA \
11 TIF___Tag_Image_File \
12 WMF___MS_Windows_Metafile \
13 diff --git filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics.xcu filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics.xcu
14 new file mode 100644
15 index 0000000..7a1b9a5
16 --- /dev/null
17 +++ filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics.xcu
18 @@ -0,0 +1,13 @@
19 + <node oor:name="SVG - Scalable Vector Graphics" oor:op="replace">
20 + <prop oor:name="Flags"><value>IMPORT ALIEN USESOPTIONS 3RDPARTYFILTER PREFERRED</value></prop>
21 + <prop oor:name="UIComponent"/>
22 + <prop oor:name="FilterService"><value>com.sun.star.comp.Draw.SVGFilter</value></prop>
23 + <prop oor:name="UserData"><value></value></prop>
24 + <prop oor:name="UIName">
25 + <value xml:lang="x-default">SVG - Scalable Vector Graphics</value>
26 + </prop>
27 + <prop oor:name="FileFormatVersion"><value>0</value></prop>
28 + <prop oor:name="Type"><value>svg_Scalable_Vector_Graphics</value></prop>
29 + <prop oor:name="TemplateName"/>
30 + <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
31 + </node>
32 diff --git filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu
33 index 31fc7fc..910ebe9 100644
34 --- filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu
35 +++ filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu
36 @@ -1,10 +1,10 @@
37 <node oor:name="svg_Scalable_Vector_Graphics" oor:op="replace" >
38 - <prop oor:name="DetectService"/>
39 + <prop oor:name="DetectService"><value>com.sun.star.comp.Draw.SVGFilter</value></prop>
40 <prop oor:name="URLPattern"/>
41 <prop oor:name="Extensions"><value>svg</value></prop>
42 <prop oor:name="MediaType"><value>image/svg+xml</value></prop>
43 - <prop oor:name="Preferred"><value>false</value></prop>
44 - <prop oor:name="PreferredFilter"/>
45 + <prop oor:name="Preferred"><value>true</value></prop>
46 + <prop oor:name="PreferredFilter"><value>SVG - Scalable Vector Graphics</value></prop>
47 <prop oor:name="UIName">
48 <value>SVG - Scalable Vector Graphics</value>
49 </prop>
50 diff --git filter/source/svg/b2dellipse.cxx filter/source/svg/b2dellipse.cxx
51 new file mode 100644
52 index 0000000..a93beb2
53 --- /dev/null
54 +++ filter/source/svg/b2dellipse.cxx
55 @@ -0,0 +1,139 @@
56 +/*************************************************************************
57 + *
58 + * OpenOffice.org - a multi-platform office productivity suite
59 + *
60 + * Author:
61 + * Fridrich Strba <fridrich.strba@bluewin.ch>
62 + * Thorsten Behrens <tbehrens@novell.com>
63 + *
64 + * Copyright (C) 2008, Novell Inc.
65 + *
66 + * The Contents of this file are made available subject to
67 + * the terms of GNU Lesser General Public License Version 2.1.
68 + *
69 + ************************************************************************/
71 +#include "b2dellipse.hxx"
73 +#include <osl/diagnose.h>
75 +#include <basegfx/point/b2dpoint.hxx>
77 +#include <basegfx/matrix/b2dhommatrix.hxx>
79 +#include <rtl/instance.hxx>
81 +#include <boost/scoped_ptr.hpp>
82 +#include <vector>
83 +#include <algorithm>
85 +class ImplB2DEllipse
87 + basegfx::B2DPoint maCenter;
88 + basegfx::B2DTuple maRadius;
90 +public:
91 + ImplB2DEllipse()
92 + : maCenter(0.0f, 0.0f),
93 + maRadius(0.0f, 0.0f)
94 + {}
96 + ImplB2DEllipse(const ImplB2DEllipse& rToBeCopied)
97 + : maCenter(rToBeCopied.maCenter),
98 + maRadius(rToBeCopied.maRadius)
99 + {}
101 + ImplB2DEllipse& operator=( const ImplB2DEllipse& rToBeCopied )
103 + maCenter = rToBeCopied.maCenter;
104 + maRadius = rToBeCopied.maRadius;
106 + return *this;
109 + bool isEqual(const ImplB2DEllipse& rCandidate) const
111 + return (maCenter == rCandidate.maCenter)
112 + && (maRadius == rCandidate.maRadius);
115 + basegfx::B2DPoint getCenter() const
117 + return maCenter;
120 + void setCenter(const basegfx::B2DPoint& rCenter)
122 + maCenter = rCenter;
125 + basegfx::B2DTuple getRadius() const
127 + return maRadius;
130 + void setRadius(const basegfx::B2DTuple& rRadius)
132 + maRadius = rRadius;
136 + void transform(const basegfx::B2DHomMatrix& /* rMatrix */)
141 +//////////////////////////////////////////////////////////////////////////////
143 +namespace basegfx
146 + B2DEllipse::B2DEllipse()
147 + {}
149 + B2DEllipse::B2DEllipse(const basegfx::B2DPoint& rCenter, const basegfx::B2DTuple& rRadius)
150 + : maCenter(rCenter), maRadius(rRadius)
154 + B2DEllipse::~B2DEllipse()
158 + bool B2DEllipse::operator==(const B2DEllipse& rEllipse) const
160 + return (maCenter == rEllipse.maCenter) && (maRadius == rEllipse.maRadius);
163 + bool B2DEllipse::operator!=(const B2DEllipse& rEllipse) const
165 + return !(*this == rEllipse);
168 + basegfx::B2DPoint B2DEllipse::getB2DEllipseCenter() const
170 + return maCenter;
173 + void B2DEllipse::setB2DEllipseCenter(const basegfx::B2DPoint& rCenter)
175 + maCenter = rCenter;
178 + basegfx::B2DTuple B2DEllipse::getB2DEllipseRadius() const
180 + return maRadius;
183 + void B2DEllipse::setB2DEllipseRadius(const basegfx::B2DTuple& rRadius)
185 + maRadius = rRadius;
188 + void B2DEllipse::transform(const basegfx::B2DHomMatrix& /* rMatrix */)
191 +} // end of namespace basegfx
193 +//////////////////////////////////////////////////////////////////////////////
194 +// eof
195 diff --git filter/source/svg/b2dellipse.hxx filter/source/svg/b2dellipse.hxx
196 new file mode 100644
197 index 0000000..0708fdf
198 --- /dev/null
199 +++ filter/source/svg/b2dellipse.hxx
200 @@ -0,0 +1,77 @@
201 +/*************************************************************************
203 + * OpenOffice.org - a multi-platform office productivity suite
205 + * Author:
206 + * Fridrich Strba <fridrich.strba@bluewin.ch>
207 + * Thorsten Behrens <tbehrens@novell.com>
209 + * Copyright (C) 2008, Novell Inc.
211 + * The Contents of this file are made available subject to
212 + * the terms of GNU Lesser General Public License Version 2.1.
214 + ************************************************************************/
216 +#ifndef _BASEGFX_B2DELLIPSE_HXX
217 +#define _BASEGFX_B2DELLIPSE_HXX
219 +#include <sal/types.h>
221 +#include <o3tl/cow_wrapper.hxx>
223 +#include <basegfx/point/b2dpoint.hxx>
225 +#include <basegfx/tuple/b2dtuple.hxx>
227 +#include <basegfx/vector/b2enums.hxx>
229 +//////////////////////////////////////////////////////////////////////////////
230 +// predeclarations
231 +class ImplB2DEllipse;
233 +namespace basegfx
235 + class B2DPoint;
236 + class B2DVector;
237 + class B2DHomMatrix;
238 +} // end of namespace basegfx
240 +//////////////////////////////////////////////////////////////////////////////
242 +namespace basegfx
244 + class B2DEllipse
246 + private:
247 + basegfx::B2DPoint maCenter;
248 + basegfx::B2DTuple maRadius;
250 + public:
251 + B2DEllipse();
252 + B2DEllipse(const B2DEllipse& rEllipse);
253 + B2DEllipse(const basegfx::B2DPoint& rCenter, const basegfx::B2DTuple& rRadius);
254 + ~B2DEllipse();
256 + // assignment operator
257 + B2DEllipse& operator=(const B2DEllipse& rEllipse);
259 + // compare operators
260 + bool operator==(const B2DEllipse& rEllipse) const;
261 + bool operator!=(const B2DEllipse& rEllipse) const;
263 + // Coordinate interface
264 + basegfx::B2DPoint getB2DEllipseCenter() const;
265 + void setB2DEllipseCenter(const basegfx::B2DPoint& rCenter);
267 + basegfx::B2DTuple getB2DEllipseRadius() const;
268 + void setB2DEllipseRadius(const basegfx::B2DTuple& rRadius);
270 + // apply transformation given in matrix form to the Ellipse
271 + void transform(const basegfx::B2DHomMatrix& rMatrix);
272 + };
273 +} // end of namespace basegfx
275 +//////////////////////////////////////////////////////////////////////////////
277 +#endif /* _BASEGFX_B2DELLIPSE_HXX */
278 diff --git filter/source/svg/exports.map filter/source/svg/exports.map
279 index c673092..acb4748 100644
280 --- filter/source/svg/exports.map
281 +++ filter/source/svg/exports.map
282 @@ -1,4 +1,4 @@
283 -PDFFILTER_1_0 {
284 +SVGFILTER_1_0 {
285 global:
286 component_getImplementationEnvironment;
287 component_getFactory;
288 @@ -6,4 +6,4 @@ PDFFILTER_1_0 {
290 local:
292 -};
293 \ No newline at end of file
294 +};
295 diff --git filter/source/svg/gentoken.pl filter/source/svg/gentoken.pl
296 new file mode 100644
297 index 0000000..124457f
298 --- /dev/null
299 +++ filter/source/svg/gentoken.pl
300 @@ -0,0 +1,58 @@
301 +# from oox/source/token - should really put this into solenv
303 +$ARGV0 = shift @ARGV;
304 +$ARGV1 = shift @ARGV;
305 +$ARGV2 = shift @ARGV;
307 +open ( TOKENS, $ARGV0 ) || die "can't open token file: $!";
308 +my %tokens;
310 +while ( defined ($line = <TOKENS>) )
312 + if( !($line =~ /^#/) )
314 + chomp($line);
315 + @token = split(/\s+/,$line);
316 + if ( not defined ($token[1]) )
318 + $token[1] = "XML_".$token[0];
319 + $token[1] =~ tr/\-\.\:/___/;
320 + $token[1] =~ s/\+/PLUS/g;
321 + $token[1] =~ s/\-/MINUS/g;
324 + $tokens{$token[0]} = uc($token[1]);
327 +close ( TOKENS );
329 +open ( HXX, ">$ARGV1" ) || die "can't open tokens.hxx file: $!";
330 +open ( GPERF, ">$ARGV2" ) || die "can't open tokens.gperf file: $!";
332 +print ( GPERF "%language=C++\n" );
333 +print ( GPERF "%global-table\n" );
334 +print ( GPERF "%null-strings\n" );
335 +print ( GPERF "%struct-type\n" );
336 +print ( GPERF "struct xmltoken\n" );
337 +print ( GPERF "{\n" );
338 +print ( GPERF " const sal_Char *name; sal_Int32 nToken; \n" );
339 +print ( GPERF "};\n" );
340 +print ( GPERF "%%\n" );
342 +print ( HXX "#ifndef INCLUDED_AUTOGEN_TOKEN_HXX\n" );
343 +print ( HXX "#define INCLUDED_AUTOGEN_TOKEN_HXX\n\n" );
344 +print ( HXX "#include <sal/types.h>\n\n" );
346 +$i = 0;
347 +foreach( sort(keys(%tokens)) )
349 + print( HXX "const sal_Int32 $tokens{$_} = $i;\n" );
350 + print( GPERF "$_,$tokens{$_}\n" );
351 + $i = $i + 1;
353 +print ( GPERF "%%\n" );
354 +print ( HXX "const sal_Int32 XML_TOKEN_COUNT = $i;\n" );
355 +print ( HXX "const sal_Int32 XML_TOKEN_INVALID = -1;\n\n" );
356 +print ( HXX "#endif\n" );
357 +close ( HXX );
358 +close ( GPERF );
359 diff --git filter/source/svg/gfxtypes.hxx filter/source/svg/gfxtypes.hxx
360 new file mode 100644
361 index 0000000..09a6660
362 --- /dev/null
363 +++ filter/source/svg/gfxtypes.hxx
364 @@ -0,0 +1,356 @@
365 +/*************************************************************************
367 + * OpenOffice.org - a multi-platform office productivity suite
369 + * Author:
370 + * Fridrich Strba <fridrich.strba@bluewin.ch>
371 + * Thorsten Behrens <tbehrens@novell.com>
373 + * Copyright (C) 2008, Novell Inc.
375 + * The Contents of this file are made available subject to
376 + * the terms of GNU Lesser General Public License Version 2.1.
378 + ************************************************************************/
380 +#ifndef INCLUDED_GFXTYPES_HXX
381 +#define INCLUDED_GFXTYPES_HXX
383 +#include <basegfx/range/b2drange.hxx>
384 +#include <basegfx/matrix/b2dhommatrix.hxx>
385 +#include <basegfx/polygon/b2dlinegeometry.hxx>
387 +#include <hash_set>
388 +#include <hash_map>
389 +#include <rtl/ustring.hxx>
391 +namespace svgi
394 +struct ARGBColor
396 + double toDoubleColor( sal_uInt8 val ) { return val/255.0; }
398 + ARGBColor() : a(1.0), r(0.0), g(0.0), b(0.0)
399 + {}
400 + explicit ARGBColor(double fGrey) : a(1.0), r(fGrey), g(fGrey), b(fGrey)
401 + {}
402 + ARGBColor( double r_, double g_, double b_ ) :
403 + a(1.0), r(r_), g(g_), b(b_)
404 + {}
405 + ARGBColor( double a_, double r_, double g_, double b_ ) :
406 + a(a_), r(r_), g(g_), b(b_)
407 + {}
408 + ARGBColor( int r_, int g_, int b_ ) :
409 + a(1.0),
410 + r(toDoubleColor(sal::static_int_cast<sal_uInt8>(r_))),
411 + g(toDoubleColor(sal::static_int_cast<sal_uInt8>(g_))),
412 + b(toDoubleColor(sal::static_int_cast<sal_uInt8>(b_)))
413 + {}
414 + ARGBColor( int a_, int r_, int g_, int b_ ) :
415 + a(toDoubleColor(sal::static_int_cast<sal_uInt8>(a_))),
416 + r(toDoubleColor(sal::static_int_cast<sal_uInt8>(r_))),
417 + g(toDoubleColor(sal::static_int_cast<sal_uInt8>(g_))),
418 + b(toDoubleColor(sal::static_int_cast<sal_uInt8>(b_)))
419 + {}
420 + double a;
421 + double r;
422 + double g;
423 + double b;
425 +inline bool operator==( const ARGBColor& rLHS, const ARGBColor& rRHS )
426 +{ return rLHS.a==rRHS.a && rLHS.r==rRHS.r && rLHS.g==rRHS.g && rLHS.b==rRHS.b; }
427 +inline bool operator!=( const ARGBColor& rLHS, const ARGBColor& rRHS )
428 +{ return !(rLHS==rRHS); }
430 +struct GradientStop
432 + GradientStop() : maStopColor(), mnStopPosition(0.0)
433 + {}
434 + ARGBColor maStopColor;
435 + double mnStopPosition;
437 +inline bool operator==( const GradientStop& rLHS, const GradientStop& rRHS )
438 +{ return rLHS.mnStopPosition==rRHS.mnStopPosition && rLHS.maStopColor==rRHS.maStopColor; }
440 +struct Gradient
442 + enum GradientType { LINEAR, RADIAL};
443 + std::vector<sal_Size> maStops;
444 + basegfx::B2DHomMatrix maTransform;
445 + GradientType meType;
446 + union
448 + double test;
449 + struct
451 + double mfX1;
452 + double mfX2;
453 + double mfY1;
454 + double mfY2;
455 + } linear;
456 + struct
458 + double mfCX;
459 + double mfCY;
460 + double mfFX;
461 + double mfFY;
462 + double mfR;
463 + } radial;
464 + } maCoords;
465 + sal_Int32 mnId;
466 + bool mbBoundingBoxUnits;
467 + bool mbLinearBoundingBoxUnits;
469 +// explicit Gradient(GradientType eType) : maStops(), maTransform(), meType(eType), maCoords.mfCX(0.0), maCoords.mfCY(0.0), maCoords.mfFX(0.0), maCoords.mfFY(0.0), maCoords.mfR(0.0), mnId(0), mbBoundingBoxUnits(false)
470 + explicit Gradient(GradientType eType) : maStops(), maTransform(), meType(eType), mnId(0), mbBoundingBoxUnits(false)
472 + maCoords.radial.mfCX = 0.0;
473 + maCoords.radial.mfCY = 0.0;
474 + maCoords.radial.mfFX = 0.0;
475 + maCoords.radial.mfFY = 0.0;
476 + maCoords.radial.mfR = 0.0;
480 +inline bool operator==( const Gradient& rLHS, const Gradient& rRHS )
482 + if( rLHS.meType != rRHS.meType )
483 + return false;
484 + if( rLHS.meType == Gradient::LINEAR )
485 + return rLHS.mbBoundingBoxUnits==rRHS.mbBoundingBoxUnits && rLHS.maStops==rRHS.maStops &&
486 + rLHS.maCoords.linear.mfX1 == rRHS.maCoords.linear.mfX1 && rLHS.maCoords.linear.mfX2 == rRHS.maCoords.linear.mfX2 &&
487 + rLHS.maCoords.linear.mfY1 == rRHS.maCoords.linear.mfY1 && rLHS.maCoords.linear.mfY2 == rRHS.maCoords.linear.mfY2;
488 + else
489 + return rLHS.mbBoundingBoxUnits==rRHS.mbBoundingBoxUnits && rLHS.maStops==rRHS.maStops &&
490 + rLHS.maCoords.radial.mfCX == rRHS.maCoords.radial.mfCX && rLHS.maCoords.radial.mfCY == rRHS.maCoords.radial.mfCY &&
491 + rLHS.maCoords.radial.mfFX == rRHS.maCoords.radial.mfFX && rLHS.maCoords.radial.mfFY == rRHS.maCoords.radial.mfFY &&
492 + rLHS.maCoords.radial.mfR == rRHS.maCoords.radial.mfR;
495 +enum PaintType
497 + NONE,
498 + SOLID,
499 + GRADIENT
502 +enum FillRule
504 + NON_ZERO,
505 + EVEN_ODD
508 +enum TextAlign
510 + BEFORE,
511 + CENTER,
512 + AFTER
515 +enum CapStyle
517 + BUTT,
518 + RECT,
519 + ROUND
522 +enum FontStyle
524 + STYLE_NORMAL,
525 + STYLE_OBLIQUE,
526 + STYLE_ITALIC
529 +enum FontVariant
531 + VARIANT_NORMAL,
532 + VARIANT_SMALLCAPS
535 +struct State
537 + State() :
538 + maCTM(),
539 + maTransform(),
540 + maViewport(),
541 + maViewBox(),
542 + maFontFamily(), // app-default
543 + mnFontSize(12.0),
544 + meFontStyle(STYLE_NORMAL),
545 + meFontVariant(VARIANT_NORMAL),
546 + mnFontWeight(400.0),
547 + meTextAnchor(BEFORE),
548 + meTextDisplayAlign(BEFORE),
549 + mnTextLineIncrement(0.0),
550 + maCurrentColor(1.0),
551 + mbVisibility(true),
552 + meFillType(SOLID),
553 + mnFillOpacity(1.0),
554 + meStrokeType(NONE),
555 + mnStrokeOpacity(1.0),
556 + meViewportFillType(NONE),
557 + mnViewportFillOpacity(1.0),
558 + maFillColor(0.0),
559 + maFillGradient(Gradient::LINEAR),
560 + meFillRule(NON_ZERO),
561 + maStrokeColor(0.0),
562 + maStrokeGradient(Gradient::LINEAR),
563 + maDashArray(),
564 + mnDashOffset(0.0),
565 + meLineCap(BUTT),
566 + meLineJoin(basegfx::B2DLINEJOIN_MITER),
567 + mnMiterLimit(4.0),
568 + mnStrokeWidth(1.0),
569 + maViewportFillColor(1.0),
570 + maViewportFillGradient(Gradient::LINEAR),
571 + mnStyleId(0)
572 + {}
574 + basegfx::B2DHomMatrix maCTM;
575 + basegfx::B2DHomMatrix maTransform;
576 + basegfx::B2DRange maViewport;
577 + basegfx::B2DRange maViewBox;
579 + rtl::OUString maFontFamily;
580 + /** Absolute: xx-small=6.94 | x-small=8.33 | small=10 | medium=12 | large=14.4 | x-large=17.28 | xx-large=20.736
582 + Relative(to parent): larger (enlarge by 1.2)
583 + smaller (shrink by 1.2)
585 + */
586 + double mnFontSize;
587 + FontStyle meFontStyle;
588 + FontVariant meFontVariant;
589 + double mnFontWeight;
591 + TextAlign meTextAnchor; // text-anchor
592 + TextAlign meTextDisplayAlign; // display-align
593 + double mnTextLineIncrement; // 0.0 means auto
595 + ARGBColor maCurrentColor;
596 + bool mbVisibility;
598 + PaintType meFillType;
599 + double mnFillOpacity;
600 + PaintType meStrokeType;
601 + double mnStrokeOpacity;
602 + PaintType meViewportFillType;
603 + double mnViewportFillOpacity;
605 + ARGBColor maFillColor;
606 + Gradient maFillGradient;
607 + FillRule meFillRule;
609 + ARGBColor maStrokeColor;
610 + Gradient maStrokeGradient;
611 + std::vector<double> maDashArray;
612 + double mnDashOffset;
613 + CapStyle meLineCap;
614 + basegfx::B2DLineJoin meLineJoin;
615 + double mnMiterLimit;
616 + double mnStrokeWidth;
618 + ARGBColor maViewportFillColor;
619 + Gradient maViewportFillGradient;
621 + sal_Int32 mnStyleId;
624 +inline bool operator==(const State& rLHS, const State& rRHS )
626 + return rLHS.maCTM==rRHS.maCTM &&
627 + rLHS.maTransform==rRHS.maTransform &&
628 + rLHS.maViewport==rRHS.maViewport &&
629 + rLHS.maViewBox==rRHS.maViewBox &&
630 + rLHS.maFontFamily==rRHS.maFontFamily &&
631 + rLHS.mnFontSize==rRHS.mnFontSize &&
632 + rLHS.meFontStyle==rRHS.meFontStyle &&
633 + rLHS.meFontVariant==rRHS.meFontVariant &&
634 + rLHS.mnFontWeight==rRHS.mnFontWeight &&
635 + rLHS.meTextAnchor==rRHS.meTextAnchor &&
636 + rLHS.meTextDisplayAlign==rRHS.meTextDisplayAlign &&
637 + rLHS.mnTextLineIncrement==rRHS.mnTextLineIncrement &&
638 + rLHS.maCurrentColor==rRHS.maCurrentColor &&
639 + rLHS.mbVisibility==rRHS.mbVisibility &&
640 + rLHS.meFillType==rRHS.meFillType &&
641 + rLHS.mnFillOpacity==rRHS.mnFillOpacity &&
642 + rLHS.meStrokeType==rRHS.meStrokeType &&
643 + rLHS.mnStrokeOpacity==rRHS.mnStrokeOpacity &&
644 + rLHS.meViewportFillType==rRHS.meViewportFillType &&
645 + rLHS.mnViewportFillOpacity==rRHS.mnViewportFillOpacity &&
646 + rLHS.maFillColor==rRHS.maFillColor &&
647 + rLHS.maFillGradient==rRHS.maFillGradient &&
648 + rLHS.meFillRule==rRHS.meFillRule &&
649 + rLHS.maStrokeColor==rRHS.maStrokeColor &&
650 + rLHS.maStrokeGradient==rRHS.maStrokeGradient &&
651 + rLHS.maDashArray==rRHS.maDashArray &&
652 + rLHS.mnDashOffset==rRHS.mnDashOffset &&
653 + rLHS.meLineCap==rRHS.meLineCap &&
654 + rLHS.meLineJoin==rRHS.meLineJoin &&
655 + rLHS.mnMiterLimit==rRHS.mnMiterLimit &&
656 + rLHS.mnStrokeWidth==rRHS.mnStrokeWidth &&
657 + rLHS.maViewportFillColor==rRHS.maViewportFillColor &&
658 + rLHS.maViewportFillGradient==rRHS.maViewportFillGradient;
661 +struct StateHash
663 + size_t operator()(const State& rState ) const
665 + return size_t(rState.maCTM.get( 0, 0 ))
666 + ^ size_t(rState.maCTM.get( 1, 0 ))
667 + ^ size_t(rState.maCTM.get( 0, 1 ))
668 + ^ size_t(rState.maCTM.get( 1, 1 ))
669 + ^ size_t(rState.maCTM.get( 0, 2 ))
670 + ^ size_t(rState.maCTM.get( 1, 2 ))
671 + ^ size_t(rState.maViewport.getWidth())
672 + ^ size_t(rState.maViewport.getHeight())
673 + ^ size_t(rState.maViewBox.getWidth())
674 + ^ size_t(rState.maViewBox.getHeight())
675 + ^ size_t(rState.maFontFamily.hashCode())
676 + ^ size_t(rState.mnFontSize)
677 + ^ size_t(rState.meFontStyle)
678 + ^ size_t(rState.meFontVariant)
679 + ^ size_t(rState.mnFontWeight)
680 + ^ size_t(rState.meTextAnchor)
681 + ^ size_t(rState.meTextDisplayAlign)
682 + ^ size_t(rState.mnTextLineIncrement)
683 + ^ size_t(rState.mbVisibility)
684 + ^ size_t(rState.meFillType)
685 + ^ size_t(rState.mnFillOpacity)
686 + ^ size_t(rState.meStrokeType)
687 + ^ size_t(rState.mnStrokeOpacity)
688 + ^ size_t(rState.meViewportFillType)
689 + ^ size_t(rState.mnViewportFillOpacity)
690 + ^ size_t(rState.maFillColor.a)
691 + ^ size_t(rState.maFillColor.r)
692 + ^ size_t(rState.maFillColor.g)
693 + ^ size_t(rState.maFillColor.b)
694 + ^ size_t(rState.maFillGradient.maStops.size())
695 + ^ size_t(rState.meFillRule)
696 + ^ size_t(rState.maStrokeColor.a)
697 + ^ size_t(rState.maStrokeColor.r)
698 + ^ size_t(rState.maStrokeColor.g)
699 + ^ size_t(rState.maStrokeColor.b)
700 + ^ size_t(rState.maStrokeGradient.maStops.size())
701 + ^ size_t(rState.maDashArray.size())
702 + ^ size_t(rState.mnDashOffset)
703 + ^ size_t(rState.meLineCap)
704 + ^ size_t(rState.meLineJoin)
705 + ^ size_t(rState.mnMiterLimit)
706 + ^ size_t(rState.mnStrokeWidth)
707 + ^ size_t(rState.maViewportFillColor.a)
708 + ^ size_t(rState.maViewportFillColor.r)
709 + ^ size_t(rState.maViewportFillColor.g)
710 + ^ size_t(rState.maViewportFillColor.b)
711 + ^ size_t(rState.maViewportFillGradient.maStops.size());
715 +typedef std::hash_set<State, StateHash> StatePool;
716 +typedef std::hash_map<sal_Int32, State> StateMap;
718 +} // namespace svgi
720 +#endif
721 --- filter/source/svg/makefile.mk
722 +++ filter/source/svg/makefile.mk
723 @@ -30,26 +30,39 @@
724 #*************************************************************************
726 PRJ=..$/..
728 PRJNAME=filter
729 TARGET=svgfilter
731 ENABLE_EXCEPTIONS=TRUE
732 VISIBILITY_HIDDEN=TRUE
734 # --- Settings ----------------------------------
736 -.INCLUDE : settings.mk
737 +.INCLUDE : settings.mk
738 +.INCLUDE : libs.mk
740 # --- Types -------------------------------------
742 -SLOFILES= $(SLO)$/svguno.obj \
743 - $(SLO)$/svgfilter.obj \
744 +SLOFILES= \
745 + $(SLO)$/b2dellipse.obj \
746 + $(SLO)$/parserfragments.obj \
747 $(SLO)$/svgexport.obj \
748 + $(SLO)$/svgfilter.obj \
749 $(SLO)$/svgfontexport.obj \
750 - $(SLO)$/svgwriter.obj
751 -.IF "$(SOLAR_JAVA)"!=""
752 -SLOFILES+= $(SLO)$/svgimport.obj
753 + $(SLO)$/svgimport.obj \
754 + $(SLO)$/svgreader.obj \
755 + $(SLO)$/svgwriter.obj \
756 + $(SLO)$/tokenmap.obj \
757 + $(SLO)$/units.obj
759 +.IF "$(COMID)"=="gcc3"
760 +.IF "$(CCNUMVER)">="000400000000" || "$(SYSTEM_BOOST)"=="YES"
761 +CFLAGS+=-DUSE_MODERN_SPIRIT
762 +.ENDIF
763 .ENDIF
764 +.IF "$(SYSTEM_BOOST)"=="NO"
765 +CFLAGS+=-DUSE_MODERN_SPIRIT
766 +.ENDIF
768 # --- Library -----------------------------------
770 @@ -56,22 +66,19 @@ SLOFILES+= $(SLO)$/svgimport.obj
771 SHL1TARGET=$(TARGET)$(DLLPOSTFIX)
773 SHL1STDLIBS=\
774 + $(BASEGFXLIB) \
775 $(SVXCORELIB) \
776 $(XMLOFFLIB) \
777 - $(GOODIESLIB) \
778 + $(SVTOOLLIB) \
779 + $(BASEGFXLIB) \
780 $(VCLLIB) \
781 $(UNOTOOLSLIB) \
782 $(TOOLSLIB) \
783 $(COMPHELPERLIB) \
784 $(CPPUHELPERLIB) \
785 $(CPPULIB) \
786 - $(SALLIB)
788 -.IF "$(SOLAR_JAVA)"!=""
789 -SHL1STDLIBS+=\
790 - $(JVMACCESSLIB)
791 -.ENDIF
793 + $(SALLIB) \
794 + $(LIBXML)
796 SHL1DEPN=
797 SHL1IMPLIB= i$(SHL1TARGET)
798 @@ -84,3 +91,16 @@ DEF1NAME=$(SHL1TARGET)
799 # --- Targets ----------------------------------
801 .INCLUDE : target.mk
803 +# Generate gperf files - from oox/source/token
804 +$(INCCOM)$/tokens.hxx $(MISC)$/tokens.gperf : tokens.txt gentoken.pl
805 + $(PERL) gentoken.pl tokens.txt $(INCCOM)$/tokens.hxx $(MISC)$/tokens.gperf
807 +$(INCCOM)$/tokens.cxx : $(MISC)$/tokens.gperf makefile.mk
808 + gperf --compare-strncmp -C -m 20 $(MISC)$/tokens.gperf | $(SED) -e "s/(char\*)0/(char\*)0, 0/g" >$(INCCOM)$/tokens.cxx
810 +$(SLO)$/tokenmap.obj : $(INCCOM)$/tokens.cxx $(INCCOM)$/tokens.hxx
812 +$(SLO)$/parserfragments.obj : $(INCCOM)$/tokens.cxx $(INCCOM)$/tokens.hxx
814 +$(SLO)$/svgreader.obj : $(INCCOM)$/tokens.cxx $(INCCOM)$/tokens.hxx
815 diff --git filter/source/svg/parserfragments.cxx filter/source/svg/parserfragments.cxx
816 new file mode 100644
817 index 0000000..9d78625
818 --- /dev/null
819 +++ filter/source/svg/parserfragments.cxx
820 @@ -0,0 +1,553 @@
821 +/*************************************************************************
823 + * OpenOffice.org - a multi-platform office productivity suite
825 + * Author:
826 + * Fridrich Strba <fridrich.strba@bluewin.ch>
827 + * Thorsten Behrens <tbehrens@novell.com>
829 + * Copyright (C) 2008, Novell Inc.
831 + * The Contents of this file are made available subject to
832 + * the terms of GNU Lesser General Public License Version 2.1.
834 + ************************************************************************/
836 +// MARKER(update_precomp.py): autogen include statement, do not remove
837 +#include "precompiled_filter.hxx"
839 +#include "parserfragments.hxx"
840 +#include "spirit_supplements.hxx"
841 +#include "gfxtypes.hxx"
843 +#include <basegfx/tools/canvastools.hxx>
844 +#include <com/sun/star/geometry/AffineMatrix2D.hpp>
846 +#include <string.h>
847 +#include <limits.h>
848 +#include <boost/bind.hpp>
849 +#include <boost/spirit.hpp>
850 +#include <boost/spirit/dynamic/while.hpp>
851 +#include <numeric>
852 +#include <algorithm>
854 +#include "units.hxx"
855 +#include "tokenmap.hxx"
857 +using namespace ::com::sun::star;
859 +namespace svgi
862 +inline sal_uInt8 hex2int( char val )
864 + return val <= '9' ? val-'0' : (val < 'a' ? val+10-'A' : val+10-'a');
867 +void setFourBitColor( double& rChannel, char nChar )
869 + const sal_uInt8 nVal(hex2int(nChar));
870 + OSL_TRACE( "setFourBitCOlor %d color", nVal );
871 + rChannel = (nVal*16+nVal)/255.0;
874 +void setEightBitColor( double& rChannel, const char* pStart, const char* )
876 + const sal_uInt8 nVal0(hex2int(pStart[0]));
877 + const sal_uInt8 nVal1(hex2int(pStart[1]));
878 + OSL_TRACE( "setEightbitCOlor %d, %d color", nVal0, nVal1 );
879 + rChannel = (nVal0*16+nVal1)/255.0;
882 +void setIntColor( double& rChannel, sal_uInt8 nVal )
884 + OSL_TRACE( "setIntColor %d color", nVal );
885 + rChannel = nVal/255.0;
888 +void calcRotation(std::vector<geometry::AffineMatrix2D>& rTransforms,
889 + geometry::AffineMatrix2D& rCurrTransform,
890 + double fRotationAngle)
892 + ::basegfx::B2DHomMatrix aCurr;
893 + aCurr.translate(-rCurrTransform.m02,-rCurrTransform.m12);
894 + aCurr.rotate(fRotationAngle*M_PI/180);
895 + aCurr.translate(rCurrTransform.m02,rCurrTransform.m12);
897 + OSL_TRACE("calcRotation - fRotationAngle - %f", fRotationAngle);
898 + rTransforms.push_back(
899 + basegfx::unotools::affineMatrixFromHomMatrix(
900 + rCurrTransform,
901 + aCurr));
904 +void calcSkewX(std::vector<geometry::AffineMatrix2D>& rTransforms,
905 + double fSkewAngle)
907 + geometry::AffineMatrix2D aMat(1.0,0.0,0.0,
908 + tan(fSkewAngle*M_PI/180),1.0,0.0);
909 + rTransforms.push_back(aMat);
912 +void calcSkewY(std::vector<geometry::AffineMatrix2D>& rTransforms,
913 + double fSkewAngle)
915 + geometry::AffineMatrix2D aMat(1.0,tan(fSkewAngle*M_PI/180),0.0,
916 + 0.0,1.0,0.0);
917 + rTransforms.push_back(aMat);
920 +void assign_twice(double& r_oVal1, double& r_oVal2, const double& rInVal )
922 + r_oVal1 = r_oVal2 = rInVal;
925 +geometry::AffineMatrix2D multiplyMatrix( const geometry::AffineMatrix2D& rLHS,
926 + const geometry::AffineMatrix2D& rRHS )
928 + basegfx::B2DHomMatrix aLHS;
929 + basegfx::B2DHomMatrix aRHS;
931 + basegfx::unotools::homMatrixFromAffineMatrix(aLHS,rLHS);
932 + basegfx::unotools::homMatrixFromAffineMatrix(aRHS,rRHS);
934 + aRHS*=aLHS;
936 + geometry::AffineMatrix2D aRet;
937 + return basegfx::unotools::affineMatrixFromHomMatrix(aRet,aRHS);
940 +bool parseColor( const char* sColor, ARGBColor& rColor )
942 + using namespace ::boost::spirit;
944 + int_parser<sal_uInt8,10,1,3> byte_p;
946 + if( parse(sColor,
947 + // Begin grammar
949 + // the #rrggbb form
950 + ('#' >> (xdigit_p >> xdigit_p)[boost::bind(&setEightBitColor,
951 + boost::ref(rColor.r),_1,_2)]
952 + >> (xdigit_p >> xdigit_p)[boost::bind(&setEightBitColor,
953 + boost::ref(rColor.g),_1,_2)]
954 + >> (xdigit_p >> xdigit_p)[boost::bind(&setEightBitColor,
955 + boost::ref(rColor.b),_1,_2)])
957 + // the #rgb form
958 + ('#' >> xdigit_p[boost::bind(&setFourBitColor,
959 + boost::ref(rColor.r),_1)]
960 + >> xdigit_p[boost::bind(&setFourBitColor,
961 + boost::ref(rColor.g),_1)]
962 + >> xdigit_p[boost::bind(&setFourBitColor,
963 + boost::ref(rColor.b),_1)])
965 + // rgb() form
966 + (str_p("rgb")
967 + >> '(' >>
969 + // rgb(int,int,int)
970 + (byte_p[boost::bind(&setIntColor,
971 + boost::ref(rColor.r),_1)] >> ',' >>
972 + byte_p[boost::bind(&setIntColor,
973 + boost::ref(rColor.g),_1)] >> ',' >>
974 + byte_p[boost::bind(&setIntColor,
975 + boost::ref(rColor.b),_1)])
976 + |
977 + // rgb(double,double,double)
978 + (real_p[assign_a(rColor.r)] >> ',' >>
979 + real_p[assign_a(rColor.g)] >> ',' >>
980 + real_p[assign_a(rColor.b)])
982 + >> ')')
983 + ) >> end_p,
984 + // End grammar
985 + space_p).full )
987 + // free-form color found & parsed
988 + return true;
991 + // no free-form color - maybe a color name?
992 + // trim white space before
993 + while( *sColor &&
994 + (*sColor==' ' || *sColor=='\t' || *sColor=='\r' || *sColor=='\n') )
995 + ++sColor;
996 + // trim white space after
997 + int nLen=strlen(sColor)-1;
998 + while( nLen &&
999 + (sColor[nLen]==' ' || sColor[nLen]=='\t' || sColor[nLen]=='\r' || sColor[nLen]=='\n') )
1000 + --nLen;
1001 + switch (getTokenId(sColor, nLen+1))
1003 + case XML_ALICEBLUE: rColor = ARGBColor(240,248,255); return true;
1004 + case XML_ANTIQUEWHITE: rColor = ARGBColor(250,235,215); return true;
1005 + case XML_AQUA: rColor = ARGBColor(0,255,255); return true;
1006 + case XML_AQUAMARINE: rColor = ARGBColor(127,255,212); return true;
1007 + case XML_AZURE: rColor = ARGBColor(240,255,255); return true;
1008 + case XML_BEIGE: rColor = ARGBColor(245,245,220); return true;
1009 + case XML_BISQUE: rColor = ARGBColor(255,228,196); return true;
1010 + case XML_BLACK: rColor = ARGBColor(0,0,0); return true;
1011 + case XML_BLANCHEDALMOND: rColor = ARGBColor(255,235,205); return true;
1012 + case XML_BLUE: rColor = ARGBColor(0,0,255); return true;
1013 + case XML_BLUEVIOLET: rColor = ARGBColor(138,43,226); return true;
1014 + case XML_BROWN: rColor = ARGBColor(165,42,42); return true;
1015 + case XML_BURLYWOOD: rColor = ARGBColor(222,184,135); return true;
1016 + case XML_CADETBLUE: rColor = ARGBColor(95,158,160); return true;
1017 + case XML_CHARTREUSE: rColor = ARGBColor(127,255,0); return true;
1018 + case XML_CHOCOLATE: rColor = ARGBColor(210,105,30); return true;
1019 + case XML_CORAL: rColor = ARGBColor(255,127,80); return true;
1020 + case XML_CORNFLOWERBLUE: rColor = ARGBColor(100,149,237); return true;
1021 + case XML_CORNSILK: rColor = ARGBColor(255,248,220); return true;
1022 + case XML_CRIMSON: rColor = ARGBColor(220,20,60); return true;
1023 + case XML_CYAN: rColor = ARGBColor(0,255,255); return true;
1024 + case XML_DARKBLUE: rColor = ARGBColor(0,0,139); return true;
1025 + case XML_DARKCYAN: rColor = ARGBColor(0,139,139); return true;
1026 + case XML_DARKGOLDENROD: rColor = ARGBColor(184,134,11); return true;
1027 + case XML_DARKGRAY: rColor = ARGBColor(169,169,169); return true;
1028 + case XML_DARKGREEN: rColor = ARGBColor(0,100,0); return true;
1029 + case XML_DARKGREY: rColor = ARGBColor(169,169,169); return true;
1030 + case XML_DARKKHAKI: rColor = ARGBColor(189,183,107); return true;
1031 + case XML_DARKMAGENTA: rColor = ARGBColor(139,0,139); return true;
1032 + case XML_DARKOLIVEGREEN: rColor = ARGBColor(85,107,47); return true;
1033 + case XML_DARKORANGE: rColor = ARGBColor(255,140,0); return true;
1034 + case XML_DARKORCHID: rColor = ARGBColor(153,50,204); return true;
1035 + case XML_DARKRED: rColor = ARGBColor(139,0,0); return true;
1036 + case XML_DARKSALMON: rColor = ARGBColor(233,150,122); return true;
1037 + case XML_DARKSEAGREEN: rColor = ARGBColor(143,188,143); return true;
1038 + case XML_DARKSLATEBLUE: rColor = ARGBColor(72,61,139); return true;
1039 + case XML_DARKSLATEGRAY: rColor = ARGBColor(47,79,79); return true;
1040 + case XML_DARKSLATEGREY: rColor = ARGBColor(47,79,79); return true;
1041 + case XML_DARKTURQUOISE: rColor = ARGBColor(0,206,209); return true;
1042 + case XML_DARKVIOLET: rColor = ARGBColor(148,0,211); return true;
1043 + case XML_DEEPPINK: rColor = ARGBColor(255,20,147); return true;
1044 + case XML_DEEPSKYBLUE: rColor = ARGBColor(0,191,255); return true;
1045 + case XML_DIMGRAY: rColor = ARGBColor(105,105,105); return true;
1046 + case XML_DIMGREY: rColor = ARGBColor(105,105,105); return true;
1047 + case XML_DODGERBLUE: rColor = ARGBColor(30,144,255); return true;
1048 + case XML_FIREBRICK: rColor = ARGBColor(178,34,34); return true;
1049 + case XML_FLORALWHITE: rColor = ARGBColor(255,250,240); return true;
1050 + case XML_FORESTGREEN: rColor = ARGBColor(34,139,34); return true;
1051 + case XML_FUCHSIA: rColor = ARGBColor(255,0,255); return true;
1052 + case XML_GAINSBORO: rColor = ARGBColor(220,220,220); return true;
1053 + case XML_GHOSTWHITE: rColor = ARGBColor(248,248,255); return true;
1054 + case XML_GOLD: rColor = ARGBColor(255,215,0); return true;
1055 + case XML_GOLDENROD: rColor = ARGBColor(218,165,32); return true;
1056 + case XML_GRAY: rColor = ARGBColor(128,128,128); return true;
1057 + case XML_GREY: rColor = ARGBColor(128,128,128); return true;
1058 + case XML_GREEN: rColor = ARGBColor(0,128,0); return true;
1059 + case XML_GREENYELLOW: rColor = ARGBColor(173,255,47); return true;
1060 + case XML_HONEYDEW: rColor = ARGBColor(240,255,240); return true;
1061 + case XML_HOTPINK: rColor = ARGBColor(255,105,180); return true;
1062 + case XML_INDIANRED: rColor = ARGBColor(205,92,92); return true;
1063 + case XML_INDIGO: rColor = ARGBColor(75,0,130); return true;
1064 + case XML_IVORY: rColor = ARGBColor(255,255,240); return true;
1065 + case XML_KHAKI: rColor = ARGBColor(240,230,140); return true;
1066 + case XML_LAVENDER: rColor = ARGBColor(230,230,250); return true;
1067 + case XML_LAVENDERBLUSH: rColor = ARGBColor(255,240,245); return true;
1068 + case XML_LAWNGREEN: rColor = ARGBColor(124,252,0); return true;
1069 + case XML_LEMONCHIFFON: rColor = ARGBColor(255,250,205); return true;
1070 + case XML_LIGHTBLUE: rColor = ARGBColor(173,216,230); return true;
1071 + case XML_LIGHTCORAL: rColor = ARGBColor(240,128,128); return true;
1072 + case XML_LIGHTCYAN: rColor = ARGBColor(224,255,255); return true;
1073 + case XML_LIGHTGOLDENRODYELLOW: rColor = ARGBColor(250,250,210); return true;
1074 + case XML_LIGHTGRAY: rColor = ARGBColor(211,211,211); return true;
1075 + case XML_LIGHTGREEN: rColor = ARGBColor(144,238,144); return true;
1076 + case XML_LIGHTGREY: rColor = ARGBColor(211,211,211); return true;
1077 + case XML_LIGHTPINK: rColor = ARGBColor(255,182,193); return true;
1078 + case XML_LIGHTSALMON: rColor = ARGBColor(255,160,122); return true;
1079 + case XML_LIGHTSEAGREEN: rColor = ARGBColor(32,178,170); return true;
1080 + case XML_LIGHTSKYBLUE: rColor = ARGBColor(135,206,250); return true;
1081 + case XML_LIGHTSLATEGRAY: rColor = ARGBColor(119,136,153); return true;
1082 + case XML_LIGHTSLATEGREY: rColor = ARGBColor(119,136,153); return true;
1083 + case XML_LIGHTSTEELBLUE: rColor = ARGBColor(176,196,222); return true;
1084 + case XML_LIGHTYELLOW: rColor = ARGBColor(255,255,224); return true;
1085 + case XML_LIME: rColor = ARGBColor(0,255,0); return true;
1086 + case XML_LIMEGREEN: rColor = ARGBColor(50,205,50); return true;
1087 + case XML_LINEN: rColor = ARGBColor(250,240,230); return true;
1088 + case XML_MAGENTA: rColor = ARGBColor(255,0,255); return true;
1089 + case XML_MAROON: rColor = ARGBColor(128,0,0); return true;
1090 + case XML_MEDIUMAQUAMARINE: rColor = ARGBColor(102,205,170); return true;
1091 + case XML_MEDIUMBLUE: rColor = ARGBColor(0,0,205); return true;
1092 + case XML_MEDIUMORCHID: rColor = ARGBColor(186,85,211); return true;
1093 + case XML_MEDIUMPURPLE: rColor = ARGBColor(147,112,219); return true;
1094 + case XML_MEDIUMSEAGREEN: rColor = ARGBColor(60,179,113); return true;
1095 + case XML_MEDIUMSLATEBLUE: rColor = ARGBColor(123,104,238); return true;
1096 + case XML_MEDIUMSPRINGGREEN: rColor = ARGBColor(0,250,154); return true;
1097 + case XML_MEDIUMTURQUOISE: rColor = ARGBColor(72,209,204); return true;
1098 + case XML_MEDIUMVIOLETRED: rColor = ARGBColor(199,21,133); return true;
1099 + case XML_MIDNIGHTBLUE: rColor = ARGBColor(25,25,112); return true;
1100 + case XML_MINTCREAM: rColor = ARGBColor(245,255,250); return true;
1101 + case XML_MISTYROSE: rColor = ARGBColor(255,228,225); return true;
1102 + case XML_MOCCASIN: rColor = ARGBColor(255,228,181); return true;
1103 + case XML_NAVAJOWHITE: rColor = ARGBColor(255,222,173); return true;
1104 + case XML_NAVY: rColor = ARGBColor(0,0,128); return true;
1105 + case XML_OLDLACE: rColor = ARGBColor(253,245,230); return true;
1106 + case XML_OLIVE: rColor = ARGBColor(128,128,0); return true;
1107 + case XML_OLIVEDRAB: rColor = ARGBColor(107,142,35); return true;
1108 + case XML_ORANGE: rColor = ARGBColor(255,165,0); return true;
1109 + case XML_ORANGERED: rColor = ARGBColor(255,69,0); return true;
1110 + case XML_ORCHID: rColor = ARGBColor(218,112,214); return true;
1111 + case XML_PALEGOLDENROD: rColor = ARGBColor(238,232,170); return true;
1112 + case XML_PALEGREEN: rColor = ARGBColor(152,251,152); return true;
1113 + case XML_PALETURQUOISE: rColor = ARGBColor(175,238,238); return true;
1114 + case XML_PALEVIOLETRED: rColor = ARGBColor(219,112,147); return true;
1115 + case XML_PAPAYAWHIP: rColor = ARGBColor(255,239,213); return true;
1116 + case XML_PEACHPUFF: rColor = ARGBColor(255,218,185); return true;
1117 + case XML_PERU: rColor = ARGBColor(205,133,63); return true;
1118 + case XML_PINK: rColor = ARGBColor(255,192,203); return true;
1119 + case XML_PLUM: rColor = ARGBColor(221,160,221); return true;
1120 + case XML_POWDERBLUE: rColor = ARGBColor(176,224,230); return true;
1121 + case XML_PURPLE: rColor = ARGBColor(128,0,128); return true;
1122 + case XML_RED: rColor = ARGBColor(255,0,0); return true;
1123 + case XML_ROSYBROWN: rColor = ARGBColor(188,143,143); return true;
1124 + case XML_ROYALBLUE: rColor = ARGBColor(65,105,225); return true;
1125 + case XML_SADDLEBROWN: rColor = ARGBColor(139,69,19); return true;
1126 + case XML_SALMON: rColor = ARGBColor(250,128,114); return true;
1127 + case XML_SANDYBROWN: rColor = ARGBColor(244,164,96); return true;
1128 + case XML_SEAGREEN: rColor = ARGBColor(46,139,87); return true;
1129 + case XML_SEASHELL: rColor = ARGBColor(255,245,238); return true;
1130 + case XML_SIENNA: rColor = ARGBColor(160,82,45); return true;
1131 + case XML_SILVER: rColor = ARGBColor(192,192,192); return true;
1132 + case XML_SKYBLUE: rColor = ARGBColor(135,206,235); return true;
1133 + case XML_SLATEBLUE: rColor = ARGBColor(106,90,205); return true;
1134 + case XML_SLATEGRAY: rColor = ARGBColor(112,128,144); return true;
1135 + case XML_SLATEGREY: rColor = ARGBColor(112,128,144); return true;
1136 + case XML_SNOW: rColor = ARGBColor(255,250,250); return true;
1137 + case XML_SPRINGGREEN: rColor = ARGBColor(0,255,127); return true;
1138 + case XML_STEELBLUE: rColor = ARGBColor(70,130,180); return true;
1139 + case XML_TAN: rColor = ARGBColor(210,180,140); return true;
1140 + case XML_TEAL: rColor = ARGBColor(0,128,128); return true;
1141 + case XML_THISTLE: rColor = ARGBColor(216,191,216); return true;
1142 + case XML_TOMATO: rColor = ARGBColor(255,99,71); return true;
1143 + case XML_TURQUOISE: rColor = ARGBColor(64,224,208); return true;
1144 + case XML_VIOLET: rColor = ARGBColor(238,130,238); return true;
1145 + case XML_WHEAT: rColor = ARGBColor(245,222,179); return true;
1146 + case XML_WHITE: rColor = ARGBColor(255,255,255); return true;
1147 + case XML_WHITESMOKE: rColor = ARGBColor(245,245,245); return true;
1148 + case XML_YELLOW: rColor = ARGBColor(255,255,0); return true;
1149 + case XML_YELLOWGREEN: rColor = ARGBColor(154,205,50); return true;
1151 + default:
1152 + return false; // no color at all, I'd guess.
1156 +bool parseOpacity (const char* sOpacity, ARGBColor& rColor )
1158 + using namespace ::boost::spirit;
1160 + if( parse(sOpacity,
1161 + // Begin grammar
1163 + real_p[assign_a(rColor.a)]
1164 + ) >> end_p,
1165 + // End grammar
1166 + space_p).full )
1168 + return true;
1170 + return false;
1173 +//////////////////////////////////////////////////////////////
1175 +bool parseTransform( const char* sTransform, basegfx::B2DHomMatrix& rTransform )
1177 + using namespace ::boost::spirit;
1179 + double fRefOffsetX(0.0);
1180 + double fRefOffsetY(0.0);
1181 + bool bRefTransform(false);
1183 + double fRotationAngle=0.0;
1184 + double fSkewAngle=0.0;
1185 + geometry::AffineMatrix2D aIdentityTransform;
1186 + geometry::AffineMatrix2D aCurrTransform;
1187 + std::vector<geometry::AffineMatrix2D> aTransforms;
1188 + aIdentityTransform.m00 = 1.0; aIdentityTransform.m11 = 1.0;
1189 + aCurrTransform = aIdentityTransform;
1191 + const bool bRes = parse(sTransform,
1192 + // Begin grammar
1194 + // identity transform
1195 + str_p("none")
1197 + // the ref() form
1198 + (str_p("ref")
1199 + >> '('
1200 + >> str_p("svg")[assign_a(bRefTransform,true)]
1201 + >> !(real_p[assign_a(fRefOffsetX)] >> (',' | eps_p) >>
1202 + real_p[assign_a(fRefOffsetY)])
1203 + >> ')')
1205 + // the transform-list form
1206 + (list_p(
1207 + (
1208 + // matrix(a,b,c,d,e,f)
1209 + (str_p("matrix")
1210 + >> '('
1211 + >> real_p[assign_a(aCurrTransform.m00)] >> (',' | eps_p)
1212 + >> real_p[assign_a(aCurrTransform.m10)] >> (',' | eps_p)
1213 + >> real_p[assign_a(aCurrTransform.m01)] >> (',' | eps_p)
1214 + >> real_p[assign_a(aCurrTransform.m11)] >> (',' | eps_p)
1215 + >> real_p[assign_a(aCurrTransform.m02)] >> (',' | eps_p)
1216 + >> real_p[assign_a(aCurrTransform.m12)]
1217 + >> ')')[push_back_a(aTransforms,aCurrTransform)]
1218 + |
1219 + // translate(x,[y])
1220 + (str_p("translate")
1221 + >> '('
1222 + >> real_p[boost::bind(&assign_twice,
1223 + boost::ref(aCurrTransform.m02),
1224 + boost::ref(aCurrTransform.m12),_1)]
1225 + >> !((',' | eps_p) >> real_p[assign_a(aCurrTransform.m12)])
1226 + >> ')')[push_back_a(aTransforms,aCurrTransform)]
1227 + |
1228 + // scale(x,[y])
1229 + (str_p("scale")
1230 + >> '('
1231 + >> real_p[boost::bind(&assign_twice,
1232 + boost::ref(aCurrTransform.m00),
1233 + boost::ref(aCurrTransform.m11),_1)]
1234 + >> !((',' | eps_p) >> real_p[assign_a(aCurrTransform.m11)])
1235 + >> ')')[push_back_a(aTransforms,aCurrTransform)]
1236 + |
1237 + // rotate(phi,[cx, cy])
1238 + (str_p("rotate")
1239 + >> '('
1240 + >> real_p[assign_a(fRotationAngle)]
1241 + >> !((',' | eps_p) >> real_p[assign_a(aCurrTransform.m02)]
1242 + >> real_p[assign_a(aCurrTransform.m12)])
1243 + >> ')')[boost::bind(&calcRotation,
1244 + boost::ref(aTransforms),
1245 + boost::ref(aCurrTransform),
1246 + boost::cref(fRotationAngle))]
1247 + |
1248 + // skewX(phi)
1249 + (str_p("skewX")
1250 + >> '('
1251 + >> real_p[assign_a(fSkewAngle)]
1252 + >> ')')[boost::bind(&calcSkewX,
1253 + boost::ref(aTransforms),
1254 + boost::cref(fSkewAngle))]
1255 + |
1256 + // skewY(phi)
1257 + (str_p("skewY")
1258 + >> '('
1259 + >> real_p[assign_a(fSkewAngle)]
1260 + >> ')')[boost::bind(&calcSkewY,
1261 + boost::ref(aTransforms),
1262 + boost::cref(fSkewAngle))]
1263 + // reset current transform after every push
1264 + )[assign_a(aCurrTransform,aIdentityTransform)],
1265 + // list delimiter is either ',' or space
1266 + ',' | eps_p ))
1267 + ) >> end_p,
1268 + // End grammar
1269 + space_p).full;
1271 + if( !bRes )
1272 + return false;
1274 + // fold all transformations into one
1275 + const geometry::AffineMatrix2D aTotalTransform(
1276 + std::accumulate(aTransforms.begin(),
1277 + aTransforms.end(),
1278 + aIdentityTransform,
1279 + &multiplyMatrix));
1281 + basegfx::unotools::homMatrixFromAffineMatrix(
1282 + rTransform,
1283 + aTotalTransform);
1285 + // TODO(F1): handle the ref case
1286 + return bRes;
1289 +//////////////////////////////////////////////////////////////
1291 +bool parseViewBox( const char* sViewbox, basegfx::B2DRange& rRect )
1293 + using namespace ::boost::spirit;
1295 + double x=0.0,y=0.0,w=0.0,h=0.0;
1297 + const bool bRes = parse(sViewbox,
1298 + // Begin grammar
1300 + // either comma- or space-delimited list of four doubles
1301 + real_p[assign_a(x)] >> (',' | eps_p) >>
1302 + real_p[assign_a(y)] >> (',' | eps_p) >>
1303 + real_p[assign_a(w)] >> (',' | eps_p) >>
1304 + real_p[assign_a(h)] >> end_p
1305 + ),
1306 + // End grammar
1307 + space_p).full;
1309 + if( !bRes )
1310 + return false;
1312 + rRect = basegfx::B2DRange(x,y,x+w,y+h);
1314 + return true;
1317 +//////////////////////////////////////////////////////////////
1319 +bool parseDashArray( const char* sDashArray, std::vector<double>& rOutputVector )
1321 + using namespace ::boost::spirit;
1323 + rOutputVector.clear();
1324 + return parse(sDashArray,
1325 + // Begin grammar
1327 + // parse comma-delimited list of doubles (have to use the
1328 + // 'direct' variant, as otherwise spirit refactors our
1329 + // parser to push both real num and comma to push_back_a)
1330 + list_p.direct
1332 + real_p[push_back_a(rOutputVector)],
1333 + ','
1335 + ) >> end_p,
1336 + // End grammar
1337 + space_p).full;
1340 +//////////////////////////////////////////////////////////////
1342 +namespace
1344 +void appendChar( std::string& str, char character)
1346 + str.append(1,character);
1350 +bool parseXlinkHref( const char* sXlinkHref, std::string& data )
1352 + using namespace ::boost::spirit;
1354 + data.erase(data.begin(),data.end());
1356 + std::string sLink(sXlinkHref);
1358 + if (!sLink.compare(0,5,"data:"))
1360 + // the inplace "data" uri
1361 + size_t position = sLink.rfind(',');
1362 + if (position > 0 && position < std::string::npos)
1364 + data = sLink.substr(position+1);
1365 + OSL_TRACE("%s", data.c_str());
1366 + return true;
1370 + return false;
1373 +} // namespace svgi
1374 diff --git filter/source/svg/parserfragments.hxx filter/source/svg/parserfragments.hxx
1375 new file mode 100644
1376 index 0000000..c76b44b
1377 --- /dev/null
1378 +++ filter/source/svg/parserfragments.hxx
1379 @@ -0,0 +1,50 @@
1380 +/*************************************************************************
1382 + * OpenOffice.org - a multi-platform office productivity suite
1384 + * Author:
1385 + * Fridrich Strba <fridrich.strba@bluewin.ch>
1386 + * Thorsten Behrens <tbehrens@novell.com>
1388 + * Copyright (C) 2008, Novell Inc.
1390 + * The Contents of this file are made available subject to
1391 + * the terms of GNU Lesser General Public License Version 2.1.
1393 + ************************************************************************/
1395 +#ifndef INCLUDED_PARSERFRAGMENTS_HXX
1396 +#define INCLUDED_PARSERFRAGMENTS_HXX
1398 +#include <sal/config.h>
1399 +#include <vector>
1400 +#include <string>
1402 +namespace basegfx
1404 + class B2DHomMatrix;
1405 + class B2DRange;
1407 +namespace svgi
1409 + struct ARGBColor;
1411 + /// Parse given string for one of the SVG color grammars
1412 + bool parseColor( const char* sColor, ARGBColor& rColor );
1413 + bool parseOpacity( const char* sOpacity, ARGBColor& rColor );
1415 + /// Parse given string for one of the SVG transformation grammars
1416 + bool parseTransform( const char* sTransform, basegfx::B2DHomMatrix& rTransform );
1418 + /// Parse given string for the viewBox attribute
1419 + bool parseViewBox( const char* sViewbox, basegfx::B2DRange& rRect );
1421 + /// Parse given string for a list of double values, comma-delimited
1422 + bool parseDashArray( const char* sDashArray, std::vector<double>& rOutputVector );
1424 + /// Parse given string for the xlink attribute
1425 + bool parseXlinkHref( const char* xlink, std::string& data );
1427 +} // namespace svgi
1429 +#endif
1430 diff --git filter/source/svg/spirit_supplements.hxx filter/source/svg/spirit_supplements.hxx
1431 new file mode 100644
1432 index 0000000..43db8e6
1433 --- /dev/null
1434 +++ filter/source/svg/spirit_supplements.hxx
1435 @@ -0,0 +1,115 @@
1436 +/*************************************************************************
1438 + * OpenOffice.org - a multi-platform office productivity suite
1440 + * Author:
1441 + * Fridrich Strba <fridrich.strba@bluewin.ch>
1442 + * Thorsten Behrens <tbehrens@novell.com>
1444 + * Copyright (C) 2008, Novell Inc.
1446 + * The Contents of this file are made available subject to
1447 + * the terms of GNU Lesser General Public License Version 2.1.
1449 + ************************************************************************/
1451 +#ifndef INCLUDED_SPIRIT_SUPPLEMENTS_HXX
1452 +#define INCLUDED_SPIRIT_SUPPLEMENTS_HXX
1454 +# ifndef USE_MODERN_SPIRIT
1455 +# include <boost/spirit.hpp>
1457 +namespace boost { namespace spirit
1459 + template <>
1460 + class assign_actor< std::pair<const char*,const char*> >
1462 + public:
1463 + explicit assign_actor(std::pair<const char*,const char*>& ref_)
1464 + : ref(ref_) {}
1466 + template <typename T2>
1467 + void operator()(T2 const& val) const
1468 + { ref = val; }
1470 + template <typename IteratorT>
1471 + void operator()(IteratorT const& f, IteratorT const& l) const
1472 + {
1473 + ref.first = f, ref.second = l;
1476 + private:
1477 + std::pair<const char*,const char*>& ref;
1478 + };
1480 + template<typename Target, typename Value> struct assigner
1482 + assigner( Target& rTarget, Value aValue ) :
1483 + mrTarget(rTarget), maValue(aValue)
1484 + {}
1486 + void assign() const { mrTarget=maValue; }
1488 + void operator()() const { assign(); }
1489 + template<typename T1> void operator()(T1) const { assign(); }
1490 + template<typename T1,typename T2> void operator()(T1,T2) const { assign(); }
1491 + template<typename T1,typename T2,typename T3> void operator()(T1,T2,T3) const { assign(); }
1493 + Target& mrTarget;
1494 + const Value maValue;
1495 + };
1497 + template<typename Target, typename Value> inline assigner<Target,Value>
1498 + assign_a( Target& rTarget, Value aValue )
1500 + return assigner<Target,Value>(rTarget,aValue);
1503 + template <typename Target> inline assign_actor<Target>
1504 + assign_a(Target& rTarget)
1506 + return assign_actor<Target>(rTarget);
1509 + template<typename Target, typename Value> struct back_pusher
1511 + back_pusher( Target& rTarget, const Value& rValue ) :
1512 + mrTarget(rTarget), mrValue(rValue)
1513 + {}
1515 + void push_back() const { mrTarget.push_back(mrValue); }
1517 + void operator()() const { push_back(); }
1518 + template<typename T1> void operator()(T1) const { push_back(); }
1519 + template<typename T1,typename T2> void operator()(T1,T2) const { push_back(); }
1520 + template<typename T1,typename T2,typename T3> void operator()(T1,T2,T3) const { push_back(); }
1522 + Target& mrTarget;
1523 + const Value& mrValue;
1524 + };
1526 + template<typename Target, typename Value> inline back_pusher<Target,Value>
1527 + push_back_a( Target& rTarget, const Value& rValue )
1529 + return back_pusher<Target,Value>(rTarget,rValue);
1532 + template<typename Target> struct value_back_pusher
1534 + explicit value_back_pusher( Target& rTarget ) :
1535 + mrTarget(rTarget)
1536 + {}
1537 + template<typename T1> void operator()(T1 val) const { mrTarget.push_back(val); }
1539 + Target& mrTarget;
1540 + };
1542 + template<typename Target> inline value_back_pusher<Target>
1543 + push_back_a( Target& rTarget )
1545 + return value_back_pusher<Target>(rTarget);
1547 +} }
1549 +# endif
1550 +#endif
1551 diff --git filter/source/svg/svgfilter.cxx filter/source/svg/svgfilter.cxx
1552 index bc194c0..5b3c985 100644
1553 --- filter/source/svg/svgfilter.cxx
1554 +++ filter/source/svg/svgfilter.cxx
1555 @@ -33,13 +33,16 @@
1557 #include <cstdio>
1559 -#include "svgfilter.hxx"
1560 +#include <comphelper/servicedecl.hxx>
1561 +#include <uno/environment.h>
1562 #include <com/sun/star/drawing/XDrawPage.hpp>
1563 #include <com/sun/star/drawing/XDrawView.hpp>
1564 #include <com/sun/star/frame/XDesktop.hdl>
1565 #include <com/sun/star/frame/XController.hdl>
1566 #include <vos/mutex.hxx>
1568 +#include "svgfilter.hxx"
1570 using ::rtl::OUString;
1571 using namespace ::com::sun::star;
1573 @@ -47,8 +50,9 @@ using namespace ::com::sun::star;
1574 // - SVGFilter -
1575 // -------------
1577 -SVGFilter::SVGFilter( const Reference< XMultiServiceFactory > &rxMSF ) :
1578 - mxMSF( rxMSF ),
1579 +SVGFilter::SVGFilter( const Reference< XComponentContext >& rxCtx ) :
1580 + mxMSF( rxCtx->getServiceManager(),
1581 + uno::UNO_QUERY_THROW ),
1582 mpSVGDoc( NULL ),
1583 mpSVGExport( NULL ),
1584 mpSVGFontExport( NULL ),
1585 @@ -83,11 +87,9 @@ sal_Bool SAL_CALL SVGFilter::filter( const Sequence< PropertyValue >& rDescripto
1586 if( pFocusWindow )
1587 pFocusWindow->EnterWait();
1589 -#ifdef SOLAR_JAVA
1590 if( mxDstDoc.is() )
1591 bRet = implImport( rDescriptor );
1592 else
1593 -#endif
1594 if( mxSrcDoc.is() )
1596 uno::Reference< frame::XDesktop > xDesktop( mxMSF->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ),
1597 @@ -156,77 +158,64 @@ void SAL_CALL SVGFilter::setSourceDocument( const Reference< XComponent >& xDoc
1599 // -----------------------------------------------------------------------------
1601 -#ifdef SOLAR_JAVA
1602 void SAL_CALL SVGFilter::setTargetDocument( const Reference< XComponent >& xDoc )
1603 throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException)
1605 mxDstDoc = xDoc;
1607 -#endif
1609 // -----------------------------------------------------------------------------
1611 -void SAL_CALL SVGFilter::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& /* aArguments */ )
1612 - throw (Exception, RuntimeException)
1613 +rtl::OUString SAL_CALL SVGFilter::detect( Sequence< PropertyValue >& io_rDescriptor ) throw (RuntimeException)
1615 + uno::Reference< io::XInputStream > xInput;
1616 + rtl::OUString aURL;
1618 + const beans::PropertyValue* pAttribs = io_rDescriptor.getConstArray();
1619 + const sal_Int32 nAttribs = io_rDescriptor.getLength();
1620 + for( sal_Int32 i = 0; i < nAttribs; i++ )
1622 + if( pAttribs[i].Name.equalsAscii( "InputStream" ) )
1623 + pAttribs[i].Value >>= xInput;
1626 + if( !xInput.is() )
1627 + return rtl::OUString();
1629 + uno::Reference< io::XSeekable > xSeek( xInput, uno::UNO_QUERY );
1630 + if( xSeek.is() )
1631 + xSeek->seek( 0 );
1633 + // read the first 1024 bytes & check a few magic string
1634 + // constants (heuristically)
1635 + const sal_Int32 nLookAhead = 1024;
1636 + uno::Sequence< sal_Int8 > aBuf( nLookAhead );
1637 + const sal_uInt64 nBytes=xInput->readBytes(aBuf, nLookAhead);
1638 + const sal_Int8* const pBuf=aBuf.getConstArray();
1640 + sal_Int8 aMagic1[] = {'<', 's', 'v', 'g'};
1641 + if( std::search(pBuf, pBuf+nBytes,
1642 + aMagic1, aMagic1+sizeof(aMagic1)/sizeof(*aMagic1)) != pBuf+nBytes )
1643 + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("svg_Scalable_Vector_Graphics") );
1645 + sal_Int8 aMagic2[] = {'D', 'O', 'C', 'T', 'Y', 'P', 'E', ' ', 's', 'v', 'g'};
1646 + if( std::search(pBuf, pBuf+nBytes,
1647 + aMagic2, aMagic2+sizeof(aMagic2)/sizeof(*aMagic2)) != pBuf+nBytes )
1648 + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("svg_Scalable_Vector_Graphics") );
1650 + return rtl::OUString();
1653 // -----------------------------------------------------------------------------
1655 -OUString SVGFilter_getImplementationName ()
1656 - throw (RuntimeException)
1658 - return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Draw.SVGFilter" ) );
1661 -// -----------------------------------------------------------------------------
1663 -#define SERVICE_NAME "com.sun.star.document.SVGFilter"
1665 -sal_Bool SAL_CALL SVGFilter_supportsService( const OUString& ServiceName )
1666 - throw (RuntimeException)
1668 - return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
1671 -// -----------------------------------------------------------------------------
1673 -Sequence< OUString > SAL_CALL SVGFilter_getSupportedServiceNames( ) throw (RuntimeException)
1675 - Sequence < OUString > aRet(1);
1676 - OUString* pArray = aRet.getArray();
1677 - pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
1678 - return aRet;
1681 -#undef SERVICE_NAME
1683 -// -----------------------------------------------------------------------------
1685 -Reference< XInterface > SAL_CALL SVGFilter_createInstance( const Reference< XMultiServiceFactory > & rSMgr) throw( Exception )
1687 - return (cppu::OWeakObject*) new SVGFilter( rSMgr );
1690 -// -----------------------------------------------------------------------------
1692 -OUString SAL_CALL SVGFilter::getImplementationName( )
1693 - throw (RuntimeException)
1695 - return SVGFilter_getImplementationName();
1698 -// -----------------------------------------------------------------------------
1700 -sal_Bool SAL_CALL SVGFilter::supportsService( const OUString& rServiceName )
1701 - throw (RuntimeException)
1703 - return SVGFilter_supportsService( rServiceName );
1706 -// -----------------------------------------------------------------------------
1708 -::com::sun::star::uno::Sequence< OUString > SAL_CALL SVGFilter::getSupportedServiceNames( ) throw (RuntimeException)
1710 - return SVGFilter_getSupportedServiceNames();
1712 +namespace sdecl = comphelper::service_decl;
1713 + sdecl::class_<SVGFilter> serviceImpl;
1714 + const sdecl::ServiceDecl svgFilter(
1715 + serviceImpl,
1716 + "com.sun.star.comp.Draw.SVGFilter",
1717 + "com.sun.star.document.ImportFilter;"
1718 + "com.sun.star.document.ExportFilter;"
1719 + "com.sun.star.document.ExtendedTypeDetection" );
1721 +// The C shared lib entry points
1722 +COMPHELPER_SERVICEDECL_EXPORTS1(svgFilter)
1723 diff --git filter/source/svg/svgfilter.hxx filter/source/svg/svgfilter.hxx
1724 index 43b73d3..b1123cc 100644
1725 --- filter/source/svg/svgfilter.hxx
1726 +++ filter/source/svg/svgfilter.hxx
1727 @@ -38,20 +38,14 @@
1728 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
1729 #include <com/sun/star/presentation/XPresentationSupplier.hpp>
1730 #include <com/sun/star/document/XFilter.hpp>
1731 -#ifdef SOLAR_JAVA
1732 #include <com/sun/star/document/XImporter.hpp>
1733 -#endif // SOLAR_JAVA
1734 #include <com/sun/star/document/XExporter.hpp>
1735 +#include <com/sun/star/document/XExtendedFilterDetection.hpp>
1736 #include <com/sun/star/lang/XInitialization.hpp>
1737 #include <com/sun/star/lang/XServiceInfo.hpp>
1738 #include <com/sun/star/beans/XPropertySet.hpp>
1739 #include <com/sun/star/lang/XComponent.hpp>
1740 -#include <cppuhelper/implbase1.hxx>
1741 -#ifdef SOLAR_JAVA
1742 -#include <cppuhelper/implbase5.hxx>
1743 -#else // !SOLAR_JAVA
1744 #include <cppuhelper/implbase4.hxx>
1745 -#endif
1746 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
1747 #include <com/sun/star/io/XActiveDataSource.hpp>
1748 #include <com/sun/star/presentation/AnimationEffect.hpp>
1749 @@ -178,18 +172,10 @@ class SVGFontExport;
1750 class SVGActionWriter;
1751 class EditFieldInfo;
1753 -#ifdef SOLAR_JAVA
1754 -class SVGFilter : public cppu::WeakImplHelper5 < XFilter,
1755 - XImporter,
1756 - XExporter,
1757 - XInitialization,
1758 - XServiceInfo >
1759 -#else // !SOLAR_JAVA
1760 class SVGFilter : public cppu::WeakImplHelper4 < XFilter,
1761 + XImporter,
1762 XExporter,
1763 - XInitialization,
1764 - XServiceInfo >
1765 -#endif
1766 + XExtendedFilterDetection >
1768 typedef ::std::hash_map< Reference< XInterface >, ObjectRepresentation, HashReferenceXInterface > ObjectMap;
1770 @@ -206,15 +192,11 @@ private:
1772 ObjectMap* mpObjects;
1773 Reference< XComponent > mxSrcDoc;
1774 -#ifdef SOLAR_JAVA
1775 Reference< XComponent > mxDstDoc;
1776 -#endif
1777 Reference< XDrawPage > mxDefaultPage;
1778 Link maOldFieldHdl;
1780 -#ifdef SOLAR_JAVA
1781 sal_Bool implImport( const Sequence< PropertyValue >& rDescriptor ) throw (RuntimeException);
1782 -#endif
1784 sal_Bool implExport( const Sequence< PropertyValue >& rDescriptor ) throw (RuntimeException);
1785 Reference< XDocumentHandler > implCreateExportDocumentHandler( const Reference< XOutputStream >& rxOStm );
1786 @@ -253,26 +235,19 @@ protected:
1787 virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& rDescriptor ) throw(RuntimeException);
1788 virtual void SAL_CALL cancel( ) throw (RuntimeException);
1790 -#ifdef SOLAR_JAVA
1791 // XImporter
1792 virtual void SAL_CALL setTargetDocument( const Reference< XComponent >& xDoc ) throw(IllegalArgumentException, RuntimeException);
1793 -#endif
1795 // XExporter
1796 virtual void SAL_CALL setSourceDocument( const Reference< XComponent >& xDoc ) throw(IllegalArgumentException, RuntimeException);
1798 - // XInitialization
1799 - virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException);
1801 - // XServiceInfo
1802 - virtual ::rtl::OUString SAL_CALL getImplementationName() throw(RuntimeException);
1803 - virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(RuntimeException);
1804 - virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(RuntimeException);
1805 + // XExtendedFilterDetection
1806 + virtual rtl::OUString SAL_CALL detect( Sequence< PropertyValue >& io_rDescriptor ) throw (RuntimeException);
1808 public:
1810 - SVGFilter( const Reference< XMultiServiceFactory > &rxMSF );
1811 - virtual ~SVGFilter();
1812 + explicit SVGFilter( const Reference< XComponentContext >& rxCtx );
1813 + virtual ~SVGFilter();
1816 // -----------------------------------------------------------------------------
1817 diff --git filter/source/svg/svgimport.cxx filter/source/svg/svgimport.cxx
1818 index be0329f..b8a079b 100644
1819 --- filter/source/svg/svgimport.cxx
1820 +++ filter/source/svg/svgimport.cxx
1821 @@ -32,160 +32,59 @@
1822 #include "precompiled_filter.hxx"
1824 #include "svgfilter.hxx"
1825 +#include "svgreader.hxx"
1827 #include "rtl/ref.hxx"
1828 -#include "jvmaccess/virtualmachine.hxx"
1829 -// -------------
1830 -// - SVGFilter -
1831 -// -------------
1833 +#include <com/sun/star/lang/XMultiServiceFactory.hpp>
1835 +#include <com/sun/star/lang/XComponent.hpp>
1837 +#include <com/sun/star/uno/Any.hxx>
1838 +#include <com/sun/star/uno/Type.hxx>
1840 +#include <com/sun/star/beans/PropertyValue.hpp>
1842 +#include <com/sun/star/xml/sax/XParser.hpp>
1843 +#include <com/sun/star/xml/sax/InputSource.hpp>
1844 +#include <com/sun/star/xml/XImportFilter.hpp>
1846 +#include <com/sun/star/io/XActiveDataSource.hpp>
1847 +#include <com/sun/star/task/XStatusIndicator.hpp>
1849 +using namespace ::com::sun::star;
1850 +using namespace ::svgi;
1852 sal_Bool SVGFilter::implImport( const Sequence< PropertyValue >& rDescriptor )
1853 throw (RuntimeException)
1855 - Reference< XMultiServiceFactory > xServiceFactory( ::comphelper::getProcessServiceFactory() ) ;
1856 - rtl::OUString aTmpFileName;
1857 - String aFileName;
1858 - sal_Int32 nLength = rDescriptor.getLength();
1859 - const PropertyValue* pValue = rDescriptor.getConstArray();
1860 - sal_Bool bRet = sal_False;
1862 - for( sal_Int32 i = 0 ; ( i < nLength ) && !aTmpFileName.getLength(); i++)
1863 - if( pValue[ i ].Name.equalsAscii( "FileName" ) )
1864 - pValue[ i ].Value >>= aTmpFileName;
1865 + rtl::OUString aURL;
1866 + uno::Reference< io::XInputStream > xInputStream;
1867 + uno::Reference< task::XStatusIndicator > xStatus;
1868 + const sal_Int32 nLength = rDescriptor.getLength();
1869 + const beans::PropertyValue* pAttribs = rDescriptor.getConstArray();
1870 + for ( sal_Int32 i=0 ; i<nLength; ++i, ++pAttribs )
1872 + if( pAttribs->Name.equalsAscii( "InputStream" ) )
1874 + pAttribs->Value >>= xInputStream;
1876 + else if( pAttribs->Name.equalsAscii( "StatusIndicator" ) )
1877 + pAttribs->Value >>= xStatus;
1880 - if( aTmpFileName.getLength() && xServiceFactory.is() )
1882 + OSL_ASSERT(xInputStream.is());
1883 + if(!xInputStream.is())
1884 + return sal_False;
1886 - Reference< XJavaVM > xJavaVM( xServiceFactory->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.java.JavaVirtualMachine") ) ), UNO_QUERY );
1887 - Sequence< sal_Int8 > aProcessID( 17 );
1888 - String aLocalFile;
1889 + rtl::OUString sXMLImportService ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Draw.XMLOasisImporter" ) );
1890 + Reference < XDocumentHandler > xInternalHandler( mxMSF->createInstance( sXMLImportService ), UNO_QUERY );
1892 - if( ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTmpFileName, aLocalFile ) && aLocalFile.Len() )
1894 - rtl_getGlobalProcessId( (sal_uInt8 *) aProcessID.getArray() );
1895 - aProcessID[16] = 0;
1897 - OSL_ENSURE(sizeof (sal_Int64)
1898 - >= sizeof (jvmaccess::VirtualMachine *),
1899 - "Pointer cannot be represented as sal_Int64");
1900 - sal_Int64 nPointer = reinterpret_cast< sal_Int64 >(
1901 - static_cast< jvmaccess::VirtualMachine * >(0));
1902 - xJavaVM->getJavaVM(aProcessID) >>= nPointer;
1903 - rtl::Reference<jvmaccess::VirtualMachine> _virtualMachine =
1904 - reinterpret_cast< jvmaccess::VirtualMachine * >(nPointer);
1905 - if (!_virtualMachine.is())
1906 - return bRet;
1908 - jobjectArray aArgs;
1909 - jclass aClass;
1910 - jmethodID aMId;
1911 - jstring aJStr;
1913 - try
1915 - jvmaccess::VirtualMachine::AttachGuard vmGuard(_virtualMachine);
1917 - JNIEnv * pEnv = vmGuard.getEnvironment();
1919 - aClass = pEnv->FindClass( "SOTranscoder" );
1921 - if( aClass )
1923 - aMId = pEnv->GetStaticMethodID( aClass, "main", "([Ljava/lang/String;)V" );
1924 - if ( aMId )
1926 + // The XImporter sets up an empty target document for XDocumentHandler to write to..
1927 + uno::Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY);
1928 + xImporter->setTargetDocument(mxDstDoc);
1930 - ::utl::TempFile aTempFile;
1931 - String aOutputURL( aTempFile.GetURL() );
1932 - String aOutputFile;
1934 - aTempFile.EnableKillingFile();
1936 - if( ::utl::LocalFileHelper::ConvertURLToPhysicalName( aOutputURL, aOutputFile ) && aOutputFile.Len() )
1938 - aJStr = pEnv->NewStringUTF( ByteString( aLocalFile.GetBuffer(), RTL_TEXTENCODING_UTF8 ).GetBuffer() );
1939 - aArgs = static_cast<jobjectArray>(pEnv->NewObjectArray( 2, pEnv->FindClass( "java/lang/String" ), aJStr ));
1940 - aJStr = pEnv->NewStringUTF( ByteString( aOutputFile.GetBuffer(), RTL_TEXTENCODING_UTF8 ).GetBuffer() );
1941 - pEnv->SetObjectArrayElement( aArgs, 1, aJStr );
1942 - pEnv->CallStaticVoidMethod( aClass, aMId, aArgs );
1944 - Graphic aGraphic;
1945 - SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aOutputURL, STREAM_READ );
1947 - if( pIStm )
1949 - GraphicConverter::Import( *pIStm, aGraphic );
1950 - delete pIStm;
1953 - Reference< XDrawPagesSupplier > xDrawPagesSupplier( mxDstDoc, UNO_QUERY );
1955 - if( xDrawPagesSupplier.is() && ( aGraphic.GetType() != GRAPHIC_NONE ) )
1957 - Reference< XDrawPages > xDrawPages( xDrawPagesSupplier->getDrawPages() );
1959 - if( xDrawPages.is() && xDrawPages->getCount() )
1961 - Reference< XDrawPage > xDrawPage;
1963 - if( xDrawPages->getByIndex( 0 ) >>= xDrawPage )
1965 - Reference< XShapes > xShapes( xDrawPage, UNO_QUERY );
1966 - Reference< XPropertySet> xPagePropSet( xDrawPage, UNO_QUERY );
1967 - Reference< XShape > xShape( Reference< XMultiServiceFactory >( mxDstDoc, UNO_QUERY )->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.GraphicObjectShape" ) ) ), UNO_QUERY );
1969 - if( xPagePropSet.is() && xShapes.is() && xShape.is() )
1971 - Reference< XPropertySet > xPropSet( xShape, UNO_QUERY );
1972 - sal_Int32 nPageWidth = 0, nPageHeight = 0;
1974 - xPagePropSet->getPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Width" ) ) ) >>= nPageWidth;
1975 - xPagePropSet->getPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Height" ) ) ) >>= nPageHeight;
1977 - if( xPropSet.is() && nPageWidth && nPageHeight )
1979 - xShapes->add( xShape );
1981 - ::com::sun::star::awt::Point aPos;
1982 - ::com::sun::star::awt::Size aSize;
1983 - GraphicObject aGraphObj( aGraphic );
1984 - String aGraphURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) );
1985 - Any aValue;
1986 - Size aGraphicSize;
1987 - const MapMode aTargetMapMode( MAP_100TH_MM );
1989 - if( aGraphObj.GetPrefMapMode().GetMapUnit() == MAP_PIXEL )
1990 - aGraphicSize = Application::GetDefaultDevice()->PixelToLogic( aGraphObj.GetPrefSize(), aTargetMapMode );
1991 - else
1992 - aGraphicSize = OutputDevice::LogicToLogic( aGraphObj.GetPrefSize(), aGraphObj.GetPrefMapMode(), aTargetMapMode );
1994 - aGraphURL += String( aGraphObj.GetUniqueID(), RTL_TEXTENCODING_ASCII_US );
1995 - aValue <<= rtl::OUString( aGraphURL );
1996 - xPropSet->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ), aValue );
1998 - aPos.X = ( nPageWidth - aGraphicSize.Width() ) >> 1;
1999 - aPos.Y = ( nPageHeight - aGraphicSize.Height() ) >> 1;
2001 - aSize.Width = aGraphicSize.Width();
2002 - aSize.Height = aGraphicSize.Height();
2004 - xShape->setPosition( aPos );
2005 - xShape->setSize( aSize );
2007 - bRet = sal_True;
2017 - catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &)
2020 - }
2022 - return bRet;
2023 + SVGReader aReader(mxMSF, xInputStream, xInternalHandler);
2024 + return aReader.parseAndConvert();
2027 diff --git filter/source/svg/svgreader.cxx filter/source/svg/svgreader.cxx
2028 new file mode 100644
2029 index 0000000..ce3bc85
2030 --- /dev/null
2031 +++ filter/source/svg/svgreader.cxx
2032 @@ -0,0 +1,1876 @@
2033 +/*************************************************************************
2035 + * OpenOffice.org - a multi-platform office productivity suite
2037 + * Author:
2038 + * Fridrich Strba <fridrich.strba@bluewin.ch>
2039 + * Thorsten Behrens <tbehrens@novell.com>
2041 + * Copyright (C) 2008, Novell Inc.
2043 + * The Contents of this file are made available subject to
2044 + * the terms of GNU Lesser General Public License Version 2.1.
2046 + ************************************************************************/
2048 +// MARKER(update_precomp.py): autogen include statement, do not remove
2049 +#include "precompiled_filter.hxx"
2051 +#include "svgreader.hxx"
2052 +#include <xmloff/attrlist.hxx>
2053 +#include "gfxtypes.hxx"
2054 +#include "units.hxx"
2055 +#include "parserfragments.hxx"
2056 +#include "tokenmap.hxx"
2057 +#include "b2dellipse.hxx"
2059 +#include <rtl/math.hxx>
2060 +#include <rtl/ref.hxx>
2061 +#include <rtl/ustring.hxx>
2062 +#include <rtl/ustrbuf.hxx>
2063 +#include <basegfx/vector/b2enums.hxx>
2064 +#include <basegfx/range/b2drange.hxx>
2065 +#include <basegfx/matrix/b2dhommatrix.hxx>
2066 +#include <basegfx/polygon/b2dpolypolygon.hxx>
2067 +#include <basegfx/polygon/b2dlinegeometry.hxx>
2068 +#include <basegfx/polygon/b2dpolygontools.hxx>
2069 +#include <basegfx/polygon/b2dpolypolygontools.hxx>
2070 +#include <basegfx/polygon/b2dlinegeometry.hxx>
2071 +#include <com/sun/star/io/XSeekable.hpp>
2072 +#include <com/sun/star/xml/sax/XParser.hpp>
2073 +#include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
2074 +#include <com/sun/star/xml/dom/NodeType.hpp>
2076 +#include <boost/bind.hpp>
2077 +#include <hash_set>
2078 +#include <map>
2079 +#include <string.h>
2081 +#define USTR(x) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
2082 +#define OASIS_STR "urn:oasis:names:tc:opendocument:xmlns:"
2084 +using namespace ::com::sun::star;
2086 +namespace svgi
2088 +namespace
2091 +/** visits all children of the specified type with the given functor
2092 + */
2093 +template<typename Func> void visitChildren(const Func& rFunc,
2094 + const uno::Reference<xml::dom::XElement> xElem,
2095 + xml::dom::NodeType eChildType )
2097 + uno::Reference<xml::dom::XNodeList> xChildren( xElem->getChildNodes() );
2098 + const sal_Int32 nNumNodes( xChildren->getLength() );
2099 + for( sal_Int32 i=0; i<nNumNodes; ++i )
2101 + if( xChildren->item(i)->getNodeType() == eChildType )
2102 + rFunc( *xChildren->item(i).get() );
2106 +/** Visit all elements of the given tree (in-order traversal)
2108 + Given functor is called for every element, and passed the
2109 + element's attributes, if any
2110 + */
2111 +template<typename Func> void visitElements(Func& rFunc,
2112 + const uno::Reference<xml::dom::XElement> xElem)
2114 + if( xElem->hasAttributes() )
2115 + rFunc(xElem,xElem->getAttributes());
2116 + else
2117 + rFunc(xElem);
2119 + // notify children processing
2120 + rFunc.push();
2122 + // recurse over children
2123 + uno::Reference<xml::dom::XNodeList> xChildren( xElem->getChildNodes() );
2124 + const sal_Int32 nNumNodes( xChildren->getLength() );
2125 + for( sal_Int32 i=0; i<nNumNodes; ++i )
2127 + if( xChildren->item(i)->getNodeType() == xml::dom::NodeType_ELEMENT_NODE )
2128 + visitElements( rFunc,
2129 + uno::Reference<xml::dom::XElement>(
2130 + xChildren->item(i),
2131 + uno::UNO_QUERY_THROW) );
2134 + // children processing done
2135 + rFunc.pop();
2138 +template<typename value_type> value_type square(value_type v)
2140 + return v*v;
2143 +double colorDiffSquared(const ARGBColor& rCol1, const ARGBColor& rCol2)
2145 + return
2146 + square(rCol1.a-rCol2.a)
2147 + + square(rCol1.r-rCol2.r)
2148 + + square(rCol1.g-rCol2.g)
2149 + + square(rCol1.b-rCol2.b);
2152 +typedef std::map<rtl::OUString,sal_Size> ElementRefMapType;
2154 +struct AnnotatingVisitor
2156 + AnnotatingVisitor(StatePool& rStatePool,
2157 + StateMap& rStateMap,
2158 + const State& rInitialState,
2159 + const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler) :
2160 + mnCurrStateId(0),
2161 + maCurrState(),
2162 + maParentStates(),
2163 + mrStates(rStatePool),
2164 + mrStateMap(rStateMap),
2165 + mxDocumentHandler(xDocumentHandler),
2166 + maGradientVector(),
2167 + maGradientStopVector()
2169 + maParentStates.push_back(rInitialState);
2172 + void operator()( const uno::Reference<xml::dom::XElement>& )
2173 + {}
2175 + void operator()( const uno::Reference<xml::dom::XElement>& xElem,
2176 + const uno::Reference<xml::dom::XNamedNodeMap>& xAttributes )
2178 + const sal_Int32 nTagId(getTokenId(xElem->getTagName()));
2179 + switch (nTagId)
2181 + case XML_LINEARGRADIENT:
2183 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
2184 + rtl::OUString sAttributeValue;
2185 + maGradientVector.push_back(Gradient(Gradient::LINEAR));
2187 + // do we have a reference to a parent gradient? parse
2188 + // that first, as it sets our defaults here (manually
2189 + // tracking default state on each Gradient variable is
2190 + // much more overhead)
2191 + uno::Reference<xml::dom::XNode> xNode(xAttributes->getNamedItem(USTR("href")));
2192 + if(xNode.is())
2194 + const rtl::OUString sValue(xNode->getNodeValue());
2195 + ElementRefMapType::iterator aFound=maGradientIdMap.end();
2196 + if (sValue.copy(0,1).equalsAscii("#"))
2197 + aFound = maGradientIdMap.find(sValue.copy(1));
2198 + else
2199 + aFound = maGradientIdMap.find(sValue);;
2201 + if( aFound != maGradientIdMap.end() )
2202 + maGradientVector.back() = maGradientVector[aFound->second];
2205 + // do that after dereferencing, to prevent hyperlinked
2206 + // gradient to clobber our Id again
2207 + maGradientVector.back().mnId = maGradientVector.size()-1;
2208 + maGradientVector.back().meType = Gradient::LINEAR; // has been clobbered as well
2210 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
2212 + parseLinearGradientData( maGradientVector.back(),
2213 + maGradientVector.size()-1,
2214 + getTokenId(xAttributes->item(i)->getNodeName()),
2215 + xAttributes->item(i)->getNodeValue() );
2217 + break;
2219 + case XML_RADIALGRADIENT:
2221 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
2222 + rtl::OUString sAttributeValue;
2223 + maGradientVector.push_back(Gradient(Gradient::RADIAL));
2225 + // do we have a reference to a parent gradient? parse
2226 + // that first, as it sets our defaults here (manually
2227 + // tracking default state on each Gradient variable is
2228 + // much more overhead)
2229 + uno::Reference<xml::dom::XNode> xNode(xAttributes->getNamedItem(USTR("href")));
2230 + if(xNode.is())
2232 + const rtl::OUString sValue(xNode->getNodeValue());
2233 + ElementRefMapType::iterator aFound=maGradientIdMap.end();
2234 + if (sValue.copy(0,1).equalsAscii("#"))
2235 + aFound = maGradientIdMap.find(sValue.copy(1));
2236 + else
2237 + aFound = maGradientIdMap.find(sValue);;
2239 + if( aFound != maGradientIdMap.end() )
2240 + maGradientVector.back() = maGradientVector[aFound->second];
2243 + // do that after dereferencing, to prevent hyperlinked
2244 + // gradient to clobber our Id again
2245 + maGradientVector.back().mnId = maGradientVector.size()-1;
2246 + maGradientVector.back().meType = Gradient::RADIAL; // has been clobbered as well
2248 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
2250 + parseRadialGradientData( maGradientVector.back(),
2251 + maGradientVector.size()-1,
2252 + getTokenId(xAttributes->item(i)->getNodeName()),
2253 + xAttributes->item(i)->getNodeValue() );
2255 + break;
2257 + case XML_STOP:
2259 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
2260 + rtl::OUString sAttributeValue;
2261 + maGradientStopVector.push_back(GradientStop());
2262 + maGradientVector.back().maStops.push_back(maGradientStopVector.size()-1);
2263 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
2265 + parseGradientStop( maGradientStopVector.back(),
2266 + maGradientStopVector.size()-1,
2267 + getTokenId(xAttributes->item(i)->getNodeName()),
2268 + xAttributes->item(i)->getNodeValue() );
2270 + break;
2272 + default:
2274 + // init state. inherit defaults from parent.
2275 + maCurrState = maParentStates.back();
2276 + maCurrState.maTransform.identity();
2278 + // scan for style info
2279 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
2280 + rtl::OUString sAttributeValue;
2281 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
2283 + sAttributeValue = xAttributes->item(i)->getNodeValue();
2284 + const sal_Int32 nTokenId(
2285 + getTokenId(xAttributes->item(i)->getNodeName()));
2286 + if( XML_STYLE == nTokenId )
2287 + parseStyle(sAttributeValue);
2288 + else
2289 + parseAttribute(nTokenId,
2290 + sAttributeValue);
2293 + // all attributes parsed, can calc total CTM now
2294 + basegfx::B2DHomMatrix aLocalTransform;
2295 + if( !maCurrState.maViewBox.isEmpty() &&
2296 + maCurrState.maViewBox.getWidth() != 0.0 &&
2297 + maCurrState.maViewBox.getHeight() != 0.0 )
2299 + // transform aViewBox into viewport, such that they
2300 + // coincide
2301 + aLocalTransform.translate(-maCurrState.maViewBox.getMinX(),
2302 + -maCurrState.maViewBox.getMinY());
2303 + aLocalTransform.scale(maCurrState.maViewport.getWidth()/maCurrState.maViewBox.getWidth(),
2304 + maCurrState.maViewport.getHeight()/maCurrState.maViewBox.getHeight());
2306 + maCurrState.maCTM = maCurrState.maCTM*maCurrState.maTransform*aLocalTransform;
2308 + OSL_TRACE("annotateStyle - CTM is: %f %f %f %f %f %f",
2309 + maCurrState.maCTM.get(0,0),
2310 + maCurrState.maCTM.get(0,1),
2311 + maCurrState.maCTM.get(0,2),
2312 + maCurrState.maCTM.get(1,0),
2313 + maCurrState.maCTM.get(1,1),
2314 + maCurrState.maCTM.get(1,2));
2316 + // if necessary, serialize to automatic-style section
2317 + writeStyle(xElem,nTagId);
2319 + }
2322 + rtl::OUString getStyleName( const char* sPrefix, sal_Int32 nId )
2324 + return rtl::OUString::createFromAscii(sPrefix)+rtl::OUString::valueOf(nId);
2327 + bool hasGradientOpacity( const Gradient& rGradient )
2329 + return
2330 + maGradientStopVector[
2331 + rGradient.maStops[0]].maStopColor.a != 1.0 ||
2332 + maGradientStopVector[
2333 + rGradient.maStops[1]].maStopColor.a != 1.0;
2336 + struct StopSorter
2338 + explicit StopSorter( const std::vector< GradientStop >& rStopVec ) :
2339 + mrStopVec(rStopVec)
2340 + {}
2342 + bool operator()( sal_Size rLHS, sal_Size rRHS )
2344 + return mrStopVec[rLHS].mnStopPosition < mrStopVec[rRHS].mnStopPosition;
2347 + const std::vector< GradientStop >& mrStopVec;
2348 + };
2350 + void optimizeGradientStops( Gradient& rGradient )
2352 + // sort for increasing stop position
2353 + std::sort(rGradient.maStops.begin(),rGradient.maStops.end(),
2354 + StopSorter(maGradientStopVector));
2356 + if( rGradient.maStops.size() < 3 )
2357 + return; //easy! :-)
2359 + // join similar colors
2360 + std::vector<sal_Size> aNewStops(1,rGradient.maStops.front());
2361 + for( sal_Size i=1; i<rGradient.maStops.size(); ++i )
2363 + if( maGradientStopVector[rGradient.maStops[i]].maStopColor !=
2364 + maGradientStopVector[aNewStops.back()].maStopColor )
2365 + aNewStops.push_back(rGradient.maStops[i]);
2368 + rGradient.maStops = aNewStops;
2370 + // axial gradient, maybe?
2371 + if( rGradient.meType == Gradient::LINEAR &&
2372 + rGradient.maStops.size() == 3 &&
2373 + maGradientStopVector[rGradient.maStops.front()].maStopColor ==
2374 + maGradientStopVector[rGradient.maStops.back()].maStopColor )
2376 + // yep - keep it at that
2377 + return;
2380 + // find out most significant color difference, and limit to
2381 + // those two stops around this border (metric is
2382 + // super-simplistic: take euclidean distance of colors, weigh
2383 + // with stop distance)
2384 + sal_Size nMaxIndex=0;
2385 + double fMaxDistance=0.0;
2386 + for( sal_Size i=1; i<rGradient.maStops.size(); ++i )
2388 + const double fCurrDistance(
2389 + colorDiffSquared(
2390 + maGradientStopVector[rGradient.maStops[i-1]].maStopColor,
2391 + maGradientStopVector[rGradient.maStops[i]].maStopColor) *
2392 + (square(maGradientStopVector[rGradient.maStops[i-1]].mnStopPosition) +
2393 + square(maGradientStopVector[rGradient.maStops[i]].mnStopPosition)) );
2395 + if( fCurrDistance > fMaxDistance )
2397 + nMaxIndex = i-1;
2398 + fMaxDistance = fCurrDistance;
2401 + rGradient.maStops[0] = rGradient.maStops[nMaxIndex];
2402 + rGradient.maStops[1] = rGradient.maStops[nMaxIndex+1];
2403 + rGradient.maStops.erase(rGradient.maStops.begin()+2,rGradient.maStops.end());
2406 + sal_Int8 toByteColor( double val )
2408 + // TODO(Q3): duplicated from vcl::unotools
2409 + return sal::static_int_cast<sal_Int8>(
2410 + basegfx::fround(val*255.0));
2413 + rtl::OUString getOdfColor( const ARGBColor& rColor )
2415 + // TODO(Q3): duplicated from pdfimport
2416 + rtl::OUStringBuffer aBuf( 7 );
2417 + const sal_uInt8 nRed ( toByteColor(rColor.r) );
2418 + const sal_uInt8 nGreen( toByteColor(rColor.g) );
2419 + const sal_uInt8 nBlue ( toByteColor(rColor.b) );
2420 + aBuf.append( sal_Unicode('#') );
2421 + if( nRed < 10 )
2422 + aBuf.append( sal_Unicode('0') );
2423 + aBuf.append( sal_Int32(nRed), 16 );
2424 + if( nGreen < 10 )
2425 + aBuf.append( sal_Unicode('0') );
2426 + aBuf.append( sal_Int32(nGreen), 16 );
2427 + if( nBlue < 10 )
2428 + aBuf.append( sal_Unicode('0') );
2429 + aBuf.append( sal_Int32(nBlue), 16 );
2431 + // TODO(F3): respect alpha transparency (polygons etc.)
2432 + OSL_ASSERT(rColor.a == 1.0);
2434 + return aBuf.makeStringAndClear();
2437 + bool writeStyle(State& rState, const sal_Int32 nTagId)
2439 + rtl::Reference<SvXMLAttributeList> xAttrs( new SvXMLAttributeList() );
2440 + uno::Reference<xml::sax::XAttributeList> xUnoAttrs( xAttrs.get() );
2442 + std::pair<StatePool::iterator,
2443 + bool> aRes = mrStates.insert(rState);
2444 + if( !aRes.second )
2445 + return false; // not written
2447 + ++mnCurrStateId;
2449 + // mnStyleId does not take part in hashing/comparison
2450 + const_cast<State&>(*aRes.first).mnStyleId = mnCurrStateId;
2451 + mrStateMap.insert(std::make_pair(
2452 + mnCurrStateId,
2453 + rState));
2455 + // find two representative stop colors (as odf only support
2456 + // start&end color)
2457 + optimizeGradientStops(rState.maFillGradient);
2459 + // do we have a gradient fill? then write out gradient as well
2460 + if( rState.meFillType == GRADIENT && rState.maFillGradient.maStops.size() > 1 )
2462 + // TODO(F3): ODF12 supposedly also groks svg:linear/radialGradient
2463 + xAttrs->AddAttribute( USTR( "draw:name" ), getStyleName("svggradient", rState.maFillGradient.mnId) );
2464 + if( rState.maFillGradient.meType == Gradient::LINEAR )
2466 + // should the optimizeGradientStops method decide that
2467 + // this is a three-color gradient, it prolly wanted us
2468 + // to take axial instead
2469 + xAttrs->AddAttribute( USTR( "draw:style" ),
2470 + rState.maFillGradient.maStops.size() == 3 ?
2471 + USTR("axial") :
2472 + USTR("linear") );
2474 + else
2476 + xAttrs->AddAttribute( USTR( "draw:style" ), USTR("ellipsoid") );
2477 + xAttrs->AddAttribute( USTR( "draw:cx" ), USTR("50%") );
2478 + xAttrs->AddAttribute( USTR( "draw:cy" ), USTR("50%") );
2481 + basegfx::B2DTuple rScale, rTranslate;
2482 + double rRotate, rShearX;
2483 + if( rState.maFillGradient.maTransform.decompose(rScale, rTranslate, rRotate, rShearX) )
2484 + xAttrs->AddAttribute( USTR( "draw:angle" ),
2485 + rtl::OUString::valueOf(rRotate*1800.0/M_PI ) );
2486 + xAttrs->AddAttribute( USTR( "draw:start-color" ),
2487 + getOdfColor(
2488 + maGradientStopVector[
2489 + rState.maFillGradient.maStops[0]].maStopColor) );
2490 + xAttrs->AddAttribute( USTR( "draw:end-color" ),
2491 + getOdfColor(
2492 + maGradientStopVector[
2493 + rState.maFillGradient.maStops[1]].maStopColor) );
2494 + xAttrs->AddAttribute( USTR( "draw:border" ), USTR("0%") );
2495 + mxDocumentHandler->startElement( USTR("draw:gradient"),
2496 + xUnoAttrs );
2497 + mxDocumentHandler->endElement( USTR("draw:gradient") );
2499 + if( hasGradientOpacity(rState.maFillGradient) )
2501 + // need to write out opacity style as well
2502 + xAttrs->Clear();
2503 + xAttrs->AddAttribute( USTR( "draw:name" ), getStyleName("svgopacity", rState.maFillGradient.mnId) );
2504 + if( rState.maFillGradient.meType == Gradient::LINEAR )
2506 + xAttrs->AddAttribute( USTR( "draw:style" ), USTR("linear") );
2508 + else
2510 + xAttrs->AddAttribute( USTR( "draw:style" ), USTR("ellipsoid") );
2511 + xAttrs->AddAttribute( USTR( "draw:cx" ), USTR("50%") );
2512 + xAttrs->AddAttribute( USTR( "draw:cy" ), USTR("50%") );
2515 + // modulate gradient opacity with overall fill opacity
2516 + xAttrs->AddAttribute( USTR( "draw:end" ),
2517 + rtl::OUString::valueOf(
2518 + maGradientStopVector[
2519 + rState.maFillGradient.maStops[0]].maStopColor.a*
2520 + maCurrState.mnFillOpacity*100.0)+USTR("%" ) );
2521 + xAttrs->AddAttribute( USTR( "draw:start" ),
2522 + rtl::OUString::valueOf(
2523 + maGradientStopVector[
2524 + rState.maFillGradient.maStops[1]].maStopColor.a*
2525 + maCurrState.mnFillOpacity*100.0)+USTR("%" ) );
2526 + xAttrs->AddAttribute( USTR( "draw:border" ), USTR("0%") );
2527 + mxDocumentHandler->startElement( USTR("draw:opacity"),
2528 + xUnoAttrs );
2529 + mxDocumentHandler->endElement( USTR("draw:opacity") );
2533 + // serialize to automatic-style section
2534 + xAttrs->Clear();
2535 + xAttrs->AddAttribute( USTR( "style:name" ), getStyleName("svggraphicstyle", mnCurrStateId) );
2536 + xAttrs->AddAttribute( USTR( "style:family" ), USTR("graphic") );
2537 + mxDocumentHandler->startElement( USTR("style:style"),
2538 + xUnoAttrs );
2540 + xAttrs->Clear();
2541 + // text or shape? if the former, no use in processing any
2542 + // graphic attributes except stroke color, ODF can do ~nothing
2543 + // with text shapes
2544 + if( nTagId == XML_TEXT )
2546 + //xAttrs->AddAttribute( USTR( "draw:auto-grow-height"), USTR("true"));
2547 + xAttrs->AddAttribute( USTR( "draw:auto-grow-width"), USTR("true"));
2548 + xAttrs->AddAttribute( USTR( "draw:textarea-horizontal-align"), USTR("left"));
2549 + //xAttrs->AddAttribute( USTR( "draw:textarea-vertical-align"), USTR("top"));
2550 + xAttrs->AddAttribute( USTR( "fo:min-height"), USTR("0cm"));
2552 + xAttrs->AddAttribute( USTR( "fo:padding-top"), USTR("0cm"));
2553 + xAttrs->AddAttribute( USTR( "fo:padding-left"), USTR("0cm"));
2554 + xAttrs->AddAttribute( USTR( "fo:padding-right"), USTR("0cm"));
2555 + xAttrs->AddAttribute( USTR( "fo:padding-bottom"), USTR("0cm"));
2557 + // disable any background shape
2558 + xAttrs->AddAttribute( USTR( "draw:stroke" ), USTR("none"));
2559 + xAttrs->AddAttribute( USTR( "draw:fill" ), USTR("none"));
2561 + else
2563 + if( rState.meFillType != NONE )
2565 + if( rState.meFillType == GRADIENT )
2567 + xAttrs->AddAttribute( USTR( "draw:fill" ), USTR("gradient"));
2568 + xAttrs->AddAttribute( USTR( "draw:fill-gradient-name" ),
2569 + getStyleName("svggradient", rState.maFillGradient.mnId) );
2570 + if( hasGradientOpacity(rState.maFillGradient) )
2572 + // needs transparency gradient as well
2573 + xAttrs->AddAttribute( USTR( "draw:opacity-name" ),
2574 + getStyleName("svgopacity", rState.maFillGradient.mnId) );
2576 + else if( maCurrState.mnFillOpacity != 1.0 )
2577 + xAttrs->AddAttribute( USTR( "draw:opacity" ),
2578 + rtl::OUString::valueOf(100.0*maCurrState.mnFillOpacity)+USTR("%") );
2580 + else
2582 + xAttrs->AddAttribute( USTR( "draw:fill" ), USTR("solid"));
2583 + xAttrs->AddAttribute( USTR( "draw:fill-color" ), getOdfColor(rState.maFillColor));
2584 + if( maCurrState.mnFillOpacity != 1.0 )
2585 + xAttrs->AddAttribute( USTR( "draw:opacity" ),
2586 + rtl::OUString::valueOf(100.0*maCurrState.mnFillOpacity)+USTR("%") );
2589 + else
2590 + xAttrs->AddAttribute( USTR( "draw:fill" ), USTR("none"));
2592 + if( rState.meStrokeType != NONE )
2594 + xAttrs->AddAttribute( USTR( "draw:stroke" ), USTR("solid"));
2595 + xAttrs->AddAttribute( USTR( "svg:stroke-color" ), getOdfColor(rState.maStrokeColor));
2597 + else
2598 + xAttrs->AddAttribute( USTR( "draw:stroke" ), USTR("none"));
2600 + if( maCurrState.mnStrokeWidth != 0.0 )
2602 + ::basegfx::B2DVector aVec(maCurrState.mnStrokeWidth,0);
2603 + aVec *= maCurrState.maCTM;
2604 + xAttrs->AddAttribute( USTR("svg:stroke-width"), rtl::OUString::valueOf( pt2mm(aVec.getLength()) )+USTR("mm"));
2606 + if( maCurrState.meLineJoin == basegfx::B2DLINEJOIN_MITER )
2607 + xAttrs->AddAttribute( USTR( "draw:stroke-linejoin"), USTR("miter"));
2608 + else if( maCurrState.meLineJoin == basegfx::B2DLINEJOIN_ROUND )
2609 + xAttrs->AddAttribute( USTR( "draw:stroke-linejoin"), USTR("round"));
2610 + else if( maCurrState.meLineJoin == basegfx::B2DLINEJOIN_BEVEL )
2611 + xAttrs->AddAttribute( USTR( "draw:stroke-linejoin"), USTR("bevel"));
2612 + if( maCurrState.mnStrokeOpacity != 1.0 )
2613 + xAttrs->AddAttribute( USTR("svg:stroke-opacity"),
2614 + rtl::OUString::valueOf(100.0*maCurrState.mnStrokeOpacity)+USTR("%"));
2617 + mxDocumentHandler->startElement( USTR("style:graphic-properties"),
2618 + xUnoAttrs );
2619 + mxDocumentHandler->endElement( USTR("style:graphic-properties") );
2620 + mxDocumentHandler->endElement( USTR("style:style") );
2622 + return true; // newly written
2625 + void writeStyle(const uno::Reference<xml::dom::XElement>& xElem, const sal_Int32 nTagId)
2627 + sal_Int32 nEmulatedStyleId=0;
2628 + if( maCurrState.maDashArray.size() &&
2629 + maCurrState.meStrokeType != NONE )
2631 + // ODF dashing is severly borked - generate filled shape
2632 + // instead (further down the road - here, we simply
2633 + // emulate a filled style with the next id)
2635 + // move all stroke attribs to fill, Clear stroking
2636 + State aEmulatedStrokeState( maCurrState );
2637 + aEmulatedStrokeState.meFillType = maCurrState.meStrokeType;
2638 + aEmulatedStrokeState.mnFillOpacity = maCurrState.mnStrokeOpacity;
2639 + aEmulatedStrokeState.maFillColor = maCurrState.maStrokeColor;
2640 + aEmulatedStrokeState.maFillGradient = maCurrState.maStrokeGradient;
2641 + aEmulatedStrokeState.meFillRule = EVEN_ODD;
2642 + aEmulatedStrokeState.meStrokeType = NONE;
2644 + if( writeStyle(aEmulatedStrokeState, nTagId) )
2645 + nEmulatedStyleId = mnCurrStateId;
2646 + else
2647 + nEmulatedStyleId = mrStates.find(aEmulatedStrokeState)->mnStyleId;
2650 + sal_Int32 nStyleId=0;
2651 + if( writeStyle(maCurrState, nTagId) )
2652 + nStyleId = mnCurrStateId;
2653 + else
2654 + nStyleId = mrStates.find(maCurrState)->mnStyleId;
2656 + xElem->setAttribute(USTR("internal-style-ref"),
2657 + rtl::OUString::valueOf(
2658 + nStyleId)
2659 + +USTR("$")
2660 + +rtl::OUString::valueOf(
2661 + nEmulatedStyleId));
2664 + void push()
2666 + maParentStates.push_back(maCurrState);
2669 + void pop()
2671 + maParentStates.pop_back();
2674 + void parseLinearGradientData( Gradient& io_rCurrGradient,
2675 + const sal_Int32 nGradientNumber,
2676 + const sal_Int32 nTokenId,
2677 + const rtl::OUString& sValue )
2679 + switch(nTokenId)
2681 + case XML_GRADIENTTRANSFORM:
2683 + rtl::OString aValueUtf8( sValue.getStr(),
2684 + sValue.getLength(),
2685 + RTL_TEXTENCODING_UTF8 );
2686 + parseTransform(aValueUtf8.getStr(),io_rCurrGradient.maTransform);
2687 + break;
2689 + case XML_X1:
2690 + io_rCurrGradient.maCoords.linear.mfX1 = convLength(sValue,maCurrState,'h');
2691 + break;
2692 + case XML_X2:
2693 + io_rCurrGradient.maCoords.linear.mfX2 = convLength(sValue,maCurrState,'h');
2694 + break;
2695 + case XML_Y1:
2696 + io_rCurrGradient.maCoords.linear.mfY1 = convLength(sValue,maCurrState,'v');
2697 + break;
2698 + case XML_Y2:
2699 + io_rCurrGradient.maCoords.linear.mfY2 = convLength(sValue,maCurrState,'v');
2700 + break;
2701 + case XML_ID:
2702 + maGradientIdMap.insert(std::make_pair(sValue,nGradientNumber));
2703 + break;
2704 + case XML_GRADIENTUNITS:
2705 + if (getTokenId(sValue) == XML_OBJECTBOUNDINGBOX)
2706 + io_rCurrGradient.mbBoundingBoxUnits = true;
2707 + else
2708 + io_rCurrGradient.mbBoundingBoxUnits = false;
2709 + break;
2710 + default:
2711 + break;
2715 + void parseRadialGradientData( Gradient& io_rCurrGradient,
2716 + const sal_Int32 nGradientNumber,
2717 + const sal_Int32 nTokenId,
2718 + const rtl::OUString& sValue )
2720 + switch(nTokenId)
2722 + case XML_GRADIENTTRANSFORM:
2724 + rtl::OString aValueUtf8( sValue.getStr(),
2725 + sValue.getLength(),
2726 + RTL_TEXTENCODING_UTF8 );
2727 + parseTransform(aValueUtf8.getStr(),io_rCurrGradient.maTransform);
2728 + break;
2730 + case XML_CX:
2731 + io_rCurrGradient.maCoords.radial.mfCX = convLength(sValue,maCurrState,'h');
2732 + break;
2733 + case XML_CY:
2734 + io_rCurrGradient.maCoords.radial.mfCY = convLength(sValue,maCurrState,'v');
2735 + break;
2736 + case XML_FX:
2737 + io_rCurrGradient.maCoords.radial.mfFX = convLength(sValue,maCurrState,'h');
2738 + break;
2739 + case XML_FY:
2740 + io_rCurrGradient.maCoords.radial.mfFY = convLength(sValue,maCurrState,'v');
2741 + break;
2742 + case XML_R:
2743 + io_rCurrGradient.maCoords.radial.mfR = convLength(sValue,maCurrState,'r');
2744 + break;
2745 + case XML_ID:
2746 + maGradientIdMap.insert(std::make_pair(sValue,nGradientNumber));
2747 + break;
2748 + case XML_GRADIENTUNITS:
2749 + if (getTokenId(sValue) == XML_OBJECTBOUNDINGBOX)
2750 + io_rCurrGradient.mbBoundingBoxUnits = true;
2751 + else
2752 + io_rCurrGradient.mbBoundingBoxUnits = false;
2753 + break;
2754 + default:
2755 + break;
2759 + void parseGradientStop( GradientStop& io_rGradientStop,
2760 + const sal_Int32 nStopNumber,
2761 + const sal_Int32 nTokenId,
2762 + const rtl::OUString& sValue )
2764 + switch(nTokenId)
2766 + case XML_HREF:
2768 + ElementRefMapType::iterator aFound=maStopIdMap.end();
2769 + if (sValue.copy(0,1).equalsAscii("#"))
2770 + aFound = maStopIdMap.find(sValue.copy(1));
2771 + else
2772 + aFound = maStopIdMap.find(sValue);;
2774 + if( aFound != maStopIdMap.end() )
2775 + io_rGradientStop = maGradientStopVector[aFound->second];
2776 + break;
2778 + case XML_ID:
2779 + maStopIdMap.insert(std::make_pair(sValue,nStopNumber));
2780 + break;
2781 + case XML_OFFSET:
2782 + io_rGradientStop.mnStopPosition = sValue.toDouble();
2783 + break;
2784 + case XML_STYLE:
2785 + parseStyle( sValue );
2786 + break;
2787 + default:
2788 + break;
2792 + void parseAttribute( const sal_Int32 nTokenId,
2793 + const rtl::OUString& sValue )
2795 + rtl::OString aValueUtf8( sValue.getStr(),
2796 + sValue.getLength(),
2797 + RTL_TEXTENCODING_UTF8 );
2798 + switch(nTokenId)
2800 + case XML_WIDTH:
2802 + const double fViewPortWidth(
2803 + convLength(sValue,maCurrState,'h'));
2805 + maCurrState.maViewport.expand(
2806 + basegfx::B2DTuple(fViewPortWidth,0.0));
2807 + break;
2809 + case XML_HEIGHT:
2811 + const double fViewPortHeight(
2812 + convLength(sValue,maCurrState,'v'));
2814 + maCurrState.maViewport.expand(
2815 + basegfx::B2DTuple(0.0,fViewPortHeight));
2816 + break;
2818 + case XML_VIEWBOX:
2820 + // TODO(F1): preserveAspectRatio
2821 + parseViewBox(
2822 + aValueUtf8,
2823 + maCurrState.maViewBox);
2824 + break;
2826 + case XML_FILL_RULE:
2828 + if( aValueUtf8 == "evenodd" )
2829 + maCurrState.meFillRule = EVEN_ODD;
2830 + else if( aValueUtf8 == "nonzero" )
2831 + maCurrState.meFillRule = NON_ZERO;
2832 + else if( aValueUtf8 == "inherit" )
2833 + maCurrState.meFillRule = maParentStates.back().meFillRule;
2834 + break;
2836 + case XML_FILL_OPACITY:
2837 + if( aValueUtf8 == "inherit" )
2838 + maCurrState.mnFillOpacity = maParentStates.back().mnFillOpacity;
2839 + else
2840 + maCurrState.mnFillOpacity = aValueUtf8.toDouble();
2841 + break;
2842 + case XML_STROKE_WIDTH:
2844 + if( aValueUtf8 == "inherit" )
2845 + maCurrState.mnStrokeWidth = maParentStates.back().mnStrokeWidth;
2846 + else
2847 + maCurrState.mnStrokeWidth = convLength(sValue,maCurrState,'r');
2848 + break;
2850 + case XML_STROKE_LINECAP:
2852 + if( aValueUtf8 == "butt" )
2853 + maCurrState.meLineCap = BUTT;
2854 + else if( aValueUtf8 == "round" )
2855 + maCurrState.meLineCap = ROUND;
2856 + else if( aValueUtf8 == "square" )
2857 + maCurrState.meLineCap = RECT;
2858 + else if( aValueUtf8 == "inherit" )
2859 + maCurrState.meLineCap = maParentStates.back().meLineCap;
2860 + break;
2862 + case XML_STROKE_LINEJOIN:
2864 + if( aValueUtf8 == "miter" )
2865 + maCurrState.meLineJoin = basegfx::B2DLINEJOIN_MITER;
2866 + else if( aValueUtf8 == "round" )
2867 + maCurrState.meLineJoin = basegfx::B2DLINEJOIN_ROUND;
2868 + else if( aValueUtf8 == "bevel" )
2869 + maCurrState.meLineJoin = basegfx::B2DLINEJOIN_BEVEL;
2870 + else if( aValueUtf8 == "inherit" )
2871 + maCurrState.meLineJoin = maParentStates.back().meLineJoin;
2872 + break;
2874 + case XML_STROKE_MITERLIMIT:
2876 + if( aValueUtf8 == "inherit" )
2877 + maCurrState.mnMiterLimit = maParentStates.back().mnMiterLimit;
2878 + else
2879 + maCurrState.mnMiterLimit = aValueUtf8.toDouble();
2880 + break;
2882 + case XML_STROKE_DASHOFFSET:
2884 + if( aValueUtf8 == "inherit" )
2885 + maCurrState.mnDashOffset = maParentStates.back().mnDashOffset;
2886 + else
2887 + maCurrState.mnDashOffset = convLength(sValue,maCurrState,'r');
2888 + break;
2890 + case XML_STROKE_DASHARRAY:
2892 + if( aValueUtf8 == "none" )
2893 + maCurrState.maDashArray.clear();
2894 + else if( aValueUtf8 == "inherit" )
2895 + maCurrState.maDashArray = maParentStates.back().maDashArray;
2896 + else
2897 + parseDashArray(aValueUtf8.getStr(),
2898 + maCurrState.maDashArray);
2899 + break;
2901 + case XML_STROKE_OPACITY:
2902 + if( aValueUtf8 == "inherit" )
2903 + maCurrState.mnStrokeOpacity = maParentStates.back().mnStrokeOpacity;
2904 + else
2905 + maCurrState.mnStrokeOpacity = aValueUtf8.toDouble();
2906 + break;
2907 + case XML_FILL:
2909 + const State& rParent( maParentStates.back() );
2910 + parsePaint( sValue,
2911 + aValueUtf8.getStr(),
2912 + maCurrState.meFillType,
2913 + maCurrState.maFillColor,
2914 + maCurrState.maFillGradient,
2915 + rParent.meFillType,
2916 + rParent.maFillColor,
2917 + rParent.maFillGradient );
2918 + break;
2920 + case XML_STROKE:
2922 + const State& rParent( maParentStates.back() );
2923 + parsePaint( sValue,
2924 + aValueUtf8.getStr(),
2925 + maCurrState.meStrokeType,
2926 + maCurrState.maStrokeColor,
2927 + maCurrState.maStrokeGradient,
2928 + rParent.meStrokeType,
2929 + rParent.maStrokeColor,
2930 + rParent.maStrokeGradient );
2931 + break;
2933 + case XML_TRANSFORM:
2935 + basegfx::B2DHomMatrix aTransform;
2936 + parseTransform(aValueUtf8.getStr(),aTransform);
2937 + maCurrState.maTransform = maCurrState.maTransform*aTransform;
2938 + break;
2940 + case XML_FONT_FAMILY:
2941 + maCurrState.maFontFamily=sValue;
2942 + break;
2943 + case XML_FONT_SIZE:
2944 + maCurrState.mnFontSize=convLength(sValue,maCurrState,'v');
2945 + break;
2946 + case XML_FONT_STYLE:
2947 + maCurrState.meFontStyle=STYLE_ITALIC; // TODO: sValue.toStyleId();
2948 + break;
2949 + case XML_FONT_WEIGHT:
2950 + maCurrState.mnFontWeight=sValue.toDouble();
2951 + break;
2952 + case XML_FONT_VARIANT:
2953 + maCurrState.meFontVariant=VARIANT_SMALLCAPS; // TODO: sValue.toDouble();
2954 + break;
2955 + case XML_STOP_COLOR:
2956 + if( maGradientVector.empty() ||
2957 + maGradientVector.back().maStops.empty() )
2958 + break;
2959 + parseColor( aValueUtf8,
2960 + maGradientStopVector[
2961 + maGradientVector.back().maStops.back()].maStopColor );
2962 + break;
2963 + case XML_STOP_OPACITY:
2964 + if( maGradientVector.empty() ||
2965 + maGradientVector.back().maStops.empty() )
2966 + break;
2967 + parseOpacity( aValueUtf8,
2968 + maGradientStopVector[
2969 + maGradientVector.back().maStops.back()].maStopColor );
2970 + break;
2971 + default:
2972 + OSL_TRACE("unhandled token %s", getTokenName(nTokenId));
2973 + break;
2977 + void parseStyle( const rtl::OUString& sValue )
2979 + // split individual style attributes
2980 + sal_Int32 nIndex=0, nDummyIndex=0;
2981 + rtl::OUString aCurrToken;
2982 + do
2984 + aCurrToken=sValue.getToken(0,';',nIndex);
2986 + if( aCurrToken.getLength() )
2988 + // split attrib & value
2989 + nDummyIndex=0;
2990 + rtl::OUString aCurrAttrib(
2991 + aCurrToken.getToken(0,':',nDummyIndex).trim());
2992 + OSL_ASSERT(nDummyIndex!=-1);
2993 + nDummyIndex=0;
2994 + rtl::OUString aCurrValue(
2995 + aCurrToken.getToken(1,':',nDummyIndex).trim());
2996 + OSL_ASSERT(nDummyIndex==-1);
2998 + // recurse into normal attribute parsing
2999 + parseAttribute( getTokenId(aCurrAttrib),
3000 + aCurrValue );
3003 + while( nIndex != -1 );
3006 + void parsePaint( const rtl::OUString& rValue,
3007 + const char* sValue,
3008 + PaintType& rType,
3009 + ARGBColor& rColor,
3010 + Gradient& rGradient,
3011 + const PaintType& rInheritType,
3012 + const ARGBColor& rInheritColor,
3013 + const Gradient& rInheritGradient )
3015 + if( strcmp(sValue,"none") == 0 )
3016 + rType = NONE;
3017 + else if( strcmp(sValue,"currentColor") == 0 )
3019 + rType = SOLID;
3020 + rColor = maCurrState.maCurrentColor;
3022 + else if( strcmp(sValue,"inherit") == 0)
3024 + rType = rInheritType;
3025 + rColor = rInheritColor;
3026 + rGradient = rInheritGradient;
3028 + else if( strncmp(sValue,"url(#",5) == 0 )
3030 + // assuming gradient. assumption does not hold generally
3031 + if( rValue.getLength() > 5 )
3033 + ElementRefMapType::iterator aRes;
3034 + if( (aRes=maGradientIdMap.find(rValue.copy(5,
3035 + rValue.getLength()-6))) != maGradientIdMap.end() )
3037 + rGradient = maGradientVector[aRes->second];
3038 + rType = GRADIENT;
3042 + else
3043 + {
3044 + rType = SOLID;
3045 + parseColor(sValue,rColor);
3049 + sal_Int32 mnCurrStateId;
3050 + State maCurrState;
3051 + std::vector<State> maParentStates;
3052 + StatePool& mrStates;
3053 + StateMap& mrStateMap;
3054 + uno::Reference<xml::sax::XDocumentHandler> mxDocumentHandler;
3055 + std::vector< Gradient > maGradientVector;
3056 + std::vector< GradientStop > maGradientStopVector;
3057 + ElementRefMapType maGradientIdMap;
3058 + ElementRefMapType maStopIdMap;
3061 +/// Annotate svg styles with unique references to state pool
3062 +static void annotateStyles( StatePool& rStatePool,
3063 + StateMap& rStateMap,
3064 + const State& rInitialState,
3065 + const uno::Reference<xml::dom::XElement> xElem,
3066 + const uno::Reference<xml::sax::XDocumentHandler>& xDocHdl )
3068 + AnnotatingVisitor aVisitor(rStatePool,rStateMap,rInitialState,xDocHdl);
3069 + visitElements(aVisitor, xElem);
3072 +struct ShapeWritingVisitor
3074 + ShapeWritingVisitor(StatePool& /*rStatePool*/,
3075 + StateMap& rStateMap,
3076 + const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler) :
3077 + mrStateMap(rStateMap),
3078 + mxDocumentHandler(xDocumentHandler),
3079 + mnShapeNum(0)
3080 + {}
3082 + void operator()( const uno::Reference<xml::dom::XElement>& )
3086 + void operator()( const uno::Reference<xml::dom::XElement>& xElem,
3087 + const uno::Reference<xml::dom::XNamedNodeMap>& xAttributes )
3089 + rtl::Reference<SvXMLAttributeList> xAttrs( new SvXMLAttributeList() );
3090 + uno::Reference<xml::sax::XAttributeList> xUnoAttrs( xAttrs.get() );
3092 + sal_Int32 nDummyIndex(0);
3093 + rtl::OUString sStyleId(
3094 + xElem->getAttribute(
3095 + USTR("internal-style-ref")).getToken(
3096 + 0,'$',nDummyIndex));
3097 + StateMap::iterator pOrigState=mrStateMap.find(
3098 + sStyleId.toInt32());
3100 + if( pOrigState == mrStateMap.end() )
3101 + return; // non-exportable element, e.g. linearGradient
3103 + maCurrState = pOrigState->second;
3105 + const sal_Int32 nTokenId(getTokenId(xElem->getNodeName()));
3106 + switch(nTokenId)
3108 + case XML_LINE:
3110 + // collect attributes
3111 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
3112 + rtl::OUString sAttributeValue;
3113 + double x1=0.0,y1=0.0,x2=0.0,y2=0.0;
3114 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
3116 + sAttributeValue = xAttributes->item(i)->getNodeValue();
3117 + const sal_Int32 nAttribId(
3118 + getTokenId(xAttributes->item(i)->getNodeName()));
3119 + switch(nAttribId)
3121 + case XML_X1:
3122 + x1= convLength(sAttributeValue,maCurrState,'h');
3123 + break;
3124 + case XML_X2:
3125 + x2 = convLength(sAttributeValue,maCurrState,'h');
3126 + break;
3127 + case XML_Y1:
3128 + y1 = convLength(sAttributeValue,maCurrState,'v');
3129 + break;
3130 + case XML_Y2:
3131 + y2 = convLength(sAttributeValue,maCurrState,'v');
3132 + break;
3133 + default:
3134 + // skip
3135 + break;
3139 + rtl::OUString sLinePath = USTR("M")+rtl::OUString::valueOf(x1)+USTR(",")
3140 + +rtl::OUString::valueOf(y1)+USTR("L")+rtl::OUString::valueOf(x2)+USTR(",")
3141 + +rtl::OUString::valueOf(y2);
3142 + basegfx::B2DPolyPolygon aPoly;
3143 + basegfx::tools::importFromSvgD(aPoly, sLinePath);
3145 + writePathShape(xAttrs,
3146 + xUnoAttrs,
3147 + xElem,
3148 + sStyleId,
3149 + basegfx::B2DPolyPolygon(aPoly));
3150 + break;
3152 + case XML_POLYGON:
3153 + case XML_POLYLINE:
3155 + rtl::OUString sPoints = xElem->hasAttribute(USTR("points")) ? xElem->getAttribute(USTR("points")) : USTR("");
3156 + basegfx::B2DPolygon aPoly;
3157 + basegfx::tools::importFromSvgPoints(aPoly, sPoints);
3158 + if( nTokenId == XML_POLYGON || maCurrState.meFillType != NONE )
3159 + aPoly.setClosed(true);
3161 + writePathShape(xAttrs,
3162 + xUnoAttrs,
3163 + xElem,
3164 + sStyleId,
3165 + basegfx::B2DPolyPolygon(aPoly));
3166 + break;
3168 + case XML_RECT:
3170 + // collect attributes
3171 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
3172 + rtl::OUString sAttributeValue;
3173 + bool bRxSeen=false, bRySeen=false;
3174 + double x=0.0,y=0.0,width=0.0,height=0.0,rx=0.0,ry=0.0;
3175 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
3177 + sAttributeValue = xAttributes->item(i)->getNodeValue();
3178 + const sal_Int32 nAttribId(
3179 + getTokenId(xAttributes->item(i)->getNodeName()));
3180 + switch(nAttribId)
3182 + case XML_X:
3183 + x = convLength(sAttributeValue,maCurrState,'h');
3184 + break;
3185 + case XML_Y:
3186 + y = convLength(sAttributeValue,maCurrState,'v');
3187 + break;
3188 + case XML_WIDTH:
3189 + width = convLength(sAttributeValue,maCurrState,'h');
3190 + break;
3191 + case XML_HEIGHT:
3192 + height = convLength(sAttributeValue,maCurrState,'v');
3193 + break;
3194 + case XML_RX:
3195 + rx = convLength(sAttributeValue,maCurrState,'h');
3196 + bRxSeen=true;
3197 + break;
3198 + case XML_RY:
3199 + ry = convLength(sAttributeValue,maCurrState,'v');
3200 + bRySeen=true;
3201 + break;
3202 + default:
3203 + // skip
3204 + break;
3208 + if( bRxSeen && !bRySeen )
3209 + ry = rx;
3210 + else if( bRySeen && !bRxSeen )
3211 + rx = ry;
3213 + basegfx::B2DPolygon aPoly;
3214 + aPoly = basegfx::tools::createPolygonFromRect(
3215 + basegfx::B2DRange(x,y,x+width,y+height),
3216 + rx/width, ry/height );
3218 + writePathShape(xAttrs,
3219 + xUnoAttrs,
3220 + xElem,
3221 + sStyleId,
3222 + basegfx::B2DPolyPolygon(aPoly));
3223 + break;
3225 + case XML_PATH:
3227 + rtl::OUString sPath = xElem->hasAttribute(USTR("d")) ? xElem->getAttribute(USTR("d")) : USTR("");
3228 + basegfx::B2DPolyPolygon aPoly;
3229 + basegfx::tools::importFromSvgD(aPoly, sPath);
3231 + writePathShape(xAttrs,
3232 + xUnoAttrs,
3233 + xElem,
3234 + sStyleId,
3235 + aPoly);
3236 + break;
3238 + case XML_CIRCLE:
3240 + // collect attributes
3241 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
3242 + rtl::OUString sAttributeValue;
3243 + double cx=0.0,cy=0.0,r=0.0;
3244 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
3246 + sAttributeValue = xAttributes->item(i)->getNodeValue();
3247 + const sal_Int32 nAttribId(
3248 + getTokenId(xAttributes->item(i)->getNodeName()));
3249 + switch(nAttribId)
3251 + case XML_CX:
3252 + cx = convLength(sAttributeValue,maCurrState,'h');
3253 + break;
3254 + case XML_CY:
3255 + cy = convLength(sAttributeValue,maCurrState,'v');
3256 + break;
3257 + case XML_R:
3258 + r = convLength(sAttributeValue,maCurrState,'r');
3259 + default:
3260 + // skip
3261 + break;
3265 + writeEllipseShape(xAttrs,
3266 + xUnoAttrs,
3267 + xElem,
3268 + sStyleId,
3269 + basegfx::B2DEllipse(basegfx::B2DPoint(cx, cy), basegfx::B2DTuple(r,r)));
3270 + break;
3272 + case XML_ELLIPSE:
3274 + // collect attributes
3275 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
3276 + rtl::OUString sAttributeValue;
3277 + double cx=0.0,cy=0.0,rx=0.0, ry=0.0;
3278 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
3280 + sAttributeValue = xAttributes->item(i)->getNodeValue();
3281 + const sal_Int32 nAttribId(
3282 + getTokenId(xAttributes->item(i)->getNodeName()));
3283 + switch(nAttribId)
3285 + case XML_CX:
3286 + cx = convLength(sAttributeValue,maCurrState,'h');
3287 + break;
3288 + case XML_CY:
3289 + cy = convLength(sAttributeValue,maCurrState,'v');
3290 + break;
3291 + case XML_RX:
3292 + rx = convLength(sAttributeValue,maCurrState,'h');
3293 + break;
3294 + case XML_RY:
3295 + ry = convLength(sAttributeValue,maCurrState,'v');
3296 + default:
3297 + // skip
3298 + break;
3302 + writeEllipseShape(xAttrs,
3303 + xUnoAttrs,
3304 + xElem,
3305 + sStyleId,
3306 + basegfx::B2DEllipse(basegfx::B2DPoint(cx, cy), basegfx::B2DTuple(rx,ry)));
3307 + break;
3309 + case XML_IMAGE:
3311 + // collect attributes
3312 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
3313 + rtl::OUString sAttributeValue;
3314 + double x=0.0,y=0.0,width=0.0,height=0.0;
3315 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
3317 + sAttributeValue = xAttributes->item(i)->getNodeValue();
3318 + const sal_Int32 nAttribId(
3319 + getTokenId(xAttributes->item(i)->getNodeName()));
3320 + switch(nAttribId)
3322 + case XML_X:
3323 + x = convLength(sAttributeValue,maCurrState,'h');
3324 + break;
3325 + case XML_Y:
3326 + y = convLength(sAttributeValue,maCurrState,'v');
3327 + break;
3328 + case XML_WIDTH:
3329 + width = convLength(sAttributeValue,maCurrState,'h');
3330 + break;
3331 + case XML_HEIGHT:
3332 + height = convLength(sAttributeValue,maCurrState,'v');
3333 + break;
3334 + default:
3335 + // skip
3336 + break;
3340 + rtl::OUString sValue = xElem->hasAttribute(USTR("href")) ? xElem->getAttribute(USTR("href")) : USTR("");
3341 + rtl::OString aValueUtf8( sValue.getStr(), sValue.getLength(), RTL_TEXTENCODING_UTF8 );
3342 + std::string sLinkValue;
3343 + parseXlinkHref(aValueUtf8.getStr(), sLinkValue);
3345 + if (!sLinkValue.empty())
3346 + writeBinaryData(xAttrs, xUnoAttrs, xElem, basegfx::B2DRange(x,y,x+width,y+height), sLinkValue);
3347 + break;
3349 + case XML_TEXT:
3351 + // collect text from all TEXT_NODE children into sText
3352 + rtl::OUStringBuffer sText;
3353 + visitChildren(boost::bind(
3354 + (rtl::OUStringBuffer& (rtl::OUStringBuffer::*)(const sal_Unicode* str))&rtl::OUStringBuffer::append,
3355 + boost::ref(sText),
3356 + boost::bind(&xml::dom::XNode::getNodeValue,
3357 + _1)),
3358 + xElem,
3359 + xml::dom::NodeType_TEXT_NODE);
3361 + // collect attributes
3362 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
3363 + rtl::OUString sAttributeValue;
3364 + double x=0.0,y=0.0,width=0.0,height=0.0;
3365 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
3367 + sAttributeValue = xAttributes->item(i)->getNodeValue();
3368 + const sal_Int32 nAttribId(
3369 + getTokenId(xAttributes->item(i)->getNodeName()));
3370 + switch(nAttribId)
3372 + case XML_X:
3373 + x = convLength(sAttributeValue,maCurrState,'h');
3374 + break;
3375 + case XML_Y:
3376 + y = convLength(sAttributeValue,maCurrState,'v');
3377 + break;
3378 + case XML_WIDTH:
3379 + width = convLength(sAttributeValue,maCurrState,'h');
3380 + break;
3381 + case XML_HEIGHT:
3382 + height = convLength(sAttributeValue,maCurrState,'v');
3383 + break;
3384 + default:
3385 + // skip
3386 + break;
3390 + // actually export text
3391 + xAttrs->Clear();
3393 + // extract basic transformations out of CTM
3394 + basegfx::B2DTuple aScale, aTranslate;
3395 + double fRotate, fShearX;
3396 + ::rtl::OUString sTransformValue;
3397 + if (maCurrState.maCTM.decompose(aScale, aTranslate, fRotate, fShearX))
3399 + rtl::OUString sTransform;
3400 + x += aTranslate.getX();
3401 + y += aTranslate.getY();
3403 + sTransform +=
3404 + USTR("scale(") +
3405 + rtl::OUString::valueOf(aScale.getX()) +
3406 + USTR(", ") +
3407 + rtl::OUString::valueOf(aScale.getX()) +
3408 + USTR(")");
3410 + if( fRotate )
3411 + sTransform += USTR(" rotate(") + rtl::OUString::valueOf(fRotate*180.0/M_PI) + USTR(")");
3413 + if( fShearX )
3414 + sTransform += USTR(" skewX(") + rtl::OUString::valueOf(fShearX*180.0/M_PI) + USTR(")");
3417 + xAttrs->AddAttribute( USTR( "svg:x" ), rtl::OUString::valueOf(pt2mm(x))+USTR("mm"));
3418 + xAttrs->AddAttribute( USTR( "svg:y" ), rtl::OUString::valueOf(pt2mm(y))+USTR("mm"));
3419 + xAttrs->AddAttribute( USTR( "draw:style-name" ), USTR("svggraphicstyle")+sStyleId );
3421 + mxDocumentHandler->startElement(USTR("draw:frame"),xUnoAttrs);
3423 + xAttrs->Clear();
3424 + mxDocumentHandler->startElement(USTR("draw:text-box"),xUnoAttrs);
3425 + // TODO: put text style in here
3426 + mxDocumentHandler->startElement(USTR("text:p"),xUnoAttrs);
3427 + mxDocumentHandler->characters(sText.makeStringAndClear());
3428 + mxDocumentHandler->endElement(USTR("text:p"));
3429 + mxDocumentHandler->endElement(USTR("draw:text-box"));
3430 + mxDocumentHandler->endElement(USTR("draw:frame"));
3431 + break;
3436 + void push()
3437 + {}
3439 + void pop()
3440 + {}
3442 + void writeBinaryData( rtl::Reference<SvXMLAttributeList>& xAttrs,
3443 + const uno::Reference<xml::sax::XAttributeList>& xUnoAttrs,
3444 + const uno::Reference<xml::dom::XElement>& /* xElem */,
3445 + const basegfx::B2DRange& rShapeBounds,
3446 + const std::string& data)
3448 + xAttrs->Clear();
3449 + xAttrs->AddAttribute( USTR( "svg:x" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getMinX()))+USTR("mm"));
3450 + xAttrs->AddAttribute( USTR( "svg:y" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getMinY()))+USTR("mm"));
3451 + xAttrs->AddAttribute( USTR( "svg:width" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getWidth()))+USTR("mm"));
3452 + xAttrs->AddAttribute( USTR( "svg:height" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getHeight()))+USTR("mm"));
3454 + mxDocumentHandler->startElement(USTR("draw:frame"),xUnoAttrs);
3456 + xAttrs->Clear();
3457 + mxDocumentHandler->startElement(USTR("draw:image"),xUnoAttrs);
3459 + mxDocumentHandler->startElement(USTR("office:binary-data"),xUnoAttrs);
3461 + mxDocumentHandler->characters(rtl::OUString::createFromAscii(data.c_str()));
3463 + mxDocumentHandler->endElement(USTR("office:binary-data"));
3465 + mxDocumentHandler->endElement(USTR("draw:image"));
3467 + mxDocumentHandler->endElement(USTR("draw:frame"));
3471 + void writeTransformAttribute(const basegfx::B2DHomMatrix rMatrix, rtl::Reference<SvXMLAttributeList>& xAttrs)
3473 + basegfx::B2DTuple rScale, rTranslate;
3474 + double rRotate, rShearX;
3475 + ::rtl::OUString sTransformValue;
3476 + if (!rMatrix.decompose(rScale, rTranslate, rRotate, rShearX))
3477 + return;
3478 + if (rScale.getX() != 1.0 || rScale.getY() != 1.0)
3479 + sTransformValue += USTR("scale(")+::rtl::OUString::valueOf(rScale.getX())+USTR(" ")
3480 + +::rtl::OUString::valueOf(rScale.getY())+USTR(") ");
3481 + if (rTranslate.getX() != 0.0f || rTranslate.getY() != 0.0f)
3482 + sTransformValue += USTR("translate(")+::rtl::OUString::valueOf(rTranslate.getX()/100.0f)+USTR("mm ")
3483 + +::rtl::OUString::valueOf(rTranslate.getY()/100.0f)+USTR("mm) ");
3484 + if (rRotate != 0.0f)
3485 + sTransformValue += USTR("rotate(")+::rtl::OUString::valueOf(rRotate)+USTR(") ");
3487 + if (rShearX != 0.0f)
3488 + sTransformValue += USTR("skewX(")+::rtl::OUString::valueOf(rShearX)+USTR(") ");
3489 + if (!sTransformValue.getLength())
3490 + return;
3491 + xAttrs->AddAttribute( USTR("draw:transform"), sTransformValue);
3494 + void writeEllipseShape( rtl::Reference<SvXMLAttributeList>& xAttrs,
3495 + const uno::Reference<xml::sax::XAttributeList>& xUnoAttrs,
3496 + const uno::Reference<xml::dom::XElement>& xElem,
3497 + const rtl::OUString& rStyleId,
3498 + const basegfx::B2DEllipse& rEllipse)
3500 + State aState = maCurrState;
3501 + rtl::OUString aStyleId(rStyleId);
3503 + xAttrs->Clear();
3505 + basegfx::B2DPolygon aPoly = basegfx::tools::createPolygonFromEllipse(rEllipse.getB2DEllipseCenter(),
3506 + rEllipse.getB2DEllipseRadius().getX(), rEllipse.getB2DEllipseRadius().getY());
3507 + writePathShape(xAttrs, xUnoAttrs, xElem, rStyleId, basegfx::B2DPolyPolygon(aPoly));
3511 + void writePathShape( rtl::Reference<SvXMLAttributeList>& xAttrs,
3512 + const uno::Reference<xml::sax::XAttributeList>& xUnoAttrs,
3513 + const uno::Reference<xml::dom::XElement>& xElem,
3514 + const rtl::OUString& rStyleId,
3515 + const basegfx::B2DPolyPolygon& rPoly )
3517 + // we might need to split up polypolygon into multiple path
3518 + // shapes (e.g. when emulating line stroking)
3519 + std::vector<basegfx::B2DPolyPolygon> aPolys(1,rPoly);
3520 + State aState = maCurrState;
3521 + rtl::OUString aStyleId(rStyleId);
3523 + xAttrs->Clear();
3525 + OSL_TRACE("writePath - the CTM is: %f %f %f %f %f %f",
3526 + maCurrState.maCTM.get(0,0),
3527 + maCurrState.maCTM.get(0,1),
3528 + maCurrState.maCTM.get(0,2),
3529 + maCurrState.maCTM.get(1,0),
3530 + maCurrState.maCTM.get(1,1),
3531 + maCurrState.maCTM.get(1,2));
3533 + if( aState.maDashArray.size() )
3535 + // ODF dashing is severly borked - generate filled polygon instead
3536 + aPolys.clear();
3537 + for( sal_uInt32 i=0; i<rPoly.count(); ++i )
3538 + {
3539 + aPolys.push_back(
3540 + basegfx::tools::createAreaGeometryForPolygon(
3541 + rPoly.getB2DPolygon(i),
3542 + aState.mnStrokeWidth/2.0,
3543 + aState.meLineJoin));
3544 + // TODO(F2): line ends
3547 + sal_Int32 nDummyIndex(0);
3548 + aStyleId = xElem->getAttribute(
3549 + USTR("internal-style-ref")).getToken(1,'$',nDummyIndex);
3550 + StateMap::iterator pAlternateState=mrStateMap.find(aStyleId.toInt32());
3551 + OSL_ASSERT(pAlternateState != mrStateMap.end());
3552 + aState = pAlternateState->second;
3553 + OSL_ENSURE( pAlternateState == mrStateMap.end(),
3554 + "Doh - where's my alternate style entry?!" );
3557 + // TODO(F2): separate out shear, rotate etc.
3558 + // apply transformation to polygon, to keep draw
3559 + // import in 100th mm
3560 + std::for_each(aPolys.begin(),aPolys.end(),
3561 + boost::bind(&basegfx::B2DPolyPolygon::transform,
3562 + _1,boost::cref(aState.maCTM)));
3564 + for( sal_uInt32 i=0; i<aPolys.size(); ++i )
3566 + const basegfx::B2DRange aBounds(
3567 + aPolys[i].areControlPointsUsed() ?
3568 + basegfx::tools::getRange(
3569 + basegfx::tools::adaptiveSubdivideByAngle(aPolys[i])) :
3570 + basegfx::tools::getRange(aPolys[i]));
3571 + fillShapeProperties(xAttrs,
3572 + xElem,
3573 + aBounds,
3574 + USTR("svggraphicstyle")+aStyleId);
3576 + // force path coordinates to 100th millimeter, after
3577 + // putting polygon data at origin (odf viewbox
3578 + // calculations largely untested codepaths, as OOo always
3579 + // writes "0 0 w h" viewboxes)
3580 + basegfx::B2DHomMatrix aNormalize;
3581 + aNormalize.translate(-aBounds.getMinX(),-aBounds.getMinY());
3582 + aNormalize.scale(2540.0/72.0,2540.0/72.0);
3583 + aPolys[i].transform(aNormalize);
3585 + xAttrs->AddAttribute( USTR( "svg:d" ), basegfx::tools::exportToSvgD(
3586 + aPolys[i],
3587 + false, // no relative coords. causes rounding errors
3588 + false )); // no quad bezier detection. crashes older versions.
3589 + mxDocumentHandler->startElement(USTR("draw:path"),
3590 + xUnoAttrs);
3591 + mxDocumentHandler->endElement(USTR("draw:path"));
3595 + void fillShapeProperties( rtl::Reference<SvXMLAttributeList>& xAttrs,
3596 + const uno::Reference<xml::dom::XElement>& /* xElem */,
3597 + const basegfx::B2DRange& rShapeBounds,
3598 + const rtl::OUString& rStyleName )
3600 + xAttrs->AddAttribute( USTR( "draw:z-index" ), rtl::OUString::valueOf( mnShapeNum++ ));
3601 + xAttrs->AddAttribute( USTR( "draw:style-name" ), rStyleName);
3602 + xAttrs->AddAttribute( USTR( "svg:width" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getWidth()))+USTR("mm"));
3603 + xAttrs->AddAttribute( USTR( "svg:height" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getHeight()))+USTR("mm"));
3605 + // OOo expects the viewbox to be in 100th of mm
3606 + xAttrs->AddAttribute( USTR( "svg:viewBox" ),
3607 + USTR("0 0 ")
3608 + + rtl::OUString::valueOf(
3609 + basegfx::fround(pt100thmm(rShapeBounds.getWidth())) )
3610 + + USTR(" ")
3611 + + rtl::OUString::valueOf(
3612 + basegfx::fround(pt100thmm(rShapeBounds.getHeight())) ));
3614 + // TODO(F1): decompose transformation in calling code, and use
3615 + // transform attribute here
3616 + // writeTranslate(maCurrState.maCTM, xAttrs);
3617 + xAttrs->AddAttribute( USTR( "svg:x" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getMinX()))+USTR("mm"));
3618 + xAttrs->AddAttribute( USTR( "svg:y" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getMinY()))+USTR("mm"));
3621 + State maCurrState;
3622 + StateMap& mrStateMap;
3623 + uno::Reference<xml::sax::XDocumentHandler> mxDocumentHandler;
3624 + sal_Int32 mnShapeNum;
3627 +/// Write out shapes from DOM tree
3628 +static void writeShapes( StatePool& rStatePool,
3629 + StateMap& rStateMap,
3630 + const uno::Reference<xml::dom::XElement> xElem,
3631 + const uno::Reference<xml::sax::XDocumentHandler>& xDocHdl )
3633 + ShapeWritingVisitor aVisitor(rStatePool,rStateMap,xDocHdl);
3634 + visitElements(aVisitor, xElem);
3637 +#ifdef VERBOSE
3638 +struct DumpingVisitor
3640 + void operator()( const uno::Reference<xml::dom::XElement>& xElem )
3642 + OSL_TRACE("name: %s",
3643 + rtl::OUStringToOString(
3644 + xElem->getTagName(),
3645 + RTL_TEXTENCODING_UTF8 ).getStr());
3648 + void operator()( const uno::Reference<xml::dom::XElement>& xElem,
3649 + const uno::Reference<xml::dom::XNamedNodeMap>& xAttributes )
3651 + OSL_TRACE("name: %s",
3652 + rtl::OUStringToOString(
3653 + xElem->getTagName(),
3654 + RTL_TEXTENCODING_UTF8 ).getStr());
3655 + const sal_Int32 nNumAttrs( xAttributes->getLength() );
3656 + for( sal_Int32 i=0; i<nNumAttrs; ++i )
3658 + OSL_TRACE(" %s=%s",
3659 + rtl::OUStringToOString(
3660 + xAttributes->item(i)->getNodeName(),
3661 + RTL_TEXTENCODING_UTF8 ).getStr(),
3662 + rtl::OUStringToOString(
3663 + xAttributes->item(i)->getNodeValue(),
3664 + RTL_TEXTENCODING_UTF8 ).getStr());
3668 + void push() {}
3669 + void pop() {}
3672 +static void dumpTree( const uno::Reference<xml::dom::XElement> xElem )
3674 + DumpingVisitor aVisitor;
3675 + visitElements(aVisitor, xElem);
3677 +#endif
3679 +} // namespace
3682 +SVGReader::SVGReader(const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory,
3683 + const uno::Reference<io::XInputStream>& xInputStream,
3684 + const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler) :
3685 + m_xServiceFactory( xServiceFactory ),
3686 + m_xInputStream( xInputStream ),
3687 + m_xDocumentHandler( xDocumentHandler )
3691 +sal_Bool SVGReader::parseAndConvert()
3693 + uno::Reference<xml::dom::XDocumentBuilder> xDomBuilder(
3694 + m_xServiceFactory->createInstance(
3695 + rtl::OUString::createFromAscii("com.sun.star.xml.dom.DocumentBuilder")), uno::UNO_QUERY );
3697 + uno::Reference<xml::dom::XDocument> xDom(
3698 + xDomBuilder->parse(m_xInputStream),
3699 + uno::UNO_QUERY_THROW );
3701 + uno::Reference<xml::dom::XElement> xDocElem( xDom->getDocumentElement(),
3702 + uno::UNO_QUERY_THROW );
3704 + // the root state for svg document
3705 + State aInitialState;
3707 + /////////////////////////////////////////////////////////////////
3708 + // doc boilerplate
3709 + /////////////////////////////////////////////////////////////////
3711 + m_xDocumentHandler->startDocument();
3713 + // get the document dimensions
3715 + // if the "width" and "height" attributes are missing, inkscape fakes
3716 + // A4 portrait for. Let's do the same.
3717 + if (!xDocElem->hasAttribute(USTR("width")))
3718 + xDocElem->setAttribute(USTR("width"), USTR("210mm"));
3719 + if (!xDocElem->hasAttribute(USTR("height")))
3720 + xDocElem->setAttribute(USTR("height"), USTR("297mm"));
3722 + double fViewPortWidth( pt2mm(convLength(xDocElem->getAttribute(USTR("width")),aInitialState,'h')) );
3723 + double fViewPortHeight( pt2mm(convLength(xDocElem->getAttribute(USTR("height")),aInitialState,'v')) );
3725 + // document prolog
3726 + rtl::Reference<SvXMLAttributeList> xAttrs( new SvXMLAttributeList() );
3727 + uno::Reference<xml::sax::XAttributeList> xUnoAttrs( xAttrs.get() );
3729 + xAttrs->AddAttribute( USTR( "xmlns:office" ), USTR( OASIS_STR "office:1.0" ));
3730 + xAttrs->AddAttribute( USTR( "xmlns:style" ), USTR( OASIS_STR "style:1.0" ));
3731 + xAttrs->AddAttribute( USTR( "xmlns:text" ), USTR( OASIS_STR "text:1.0" ));
3732 + xAttrs->AddAttribute( USTR( "xmlns:svg" ), USTR( OASIS_STR "svg-compatible:1.0" ));
3733 + xAttrs->AddAttribute( USTR( "xmlns:table" ), USTR( OASIS_STR "table:1.0" ));
3734 + xAttrs->AddAttribute( USTR( "xmlns:draw" ), USTR( OASIS_STR "drawing:1.0" ));
3735 + xAttrs->AddAttribute( USTR( "xmlns:fo" ), USTR( OASIS_STR "xsl-fo-compatible:1.0" ));
3736 + xAttrs->AddAttribute( USTR( "xmlns:xlink" ), USTR( "http://www.w3.org/1999/xlink" ));
3737 + xAttrs->AddAttribute( USTR( "xmlns:dc" ), USTR( "http://purl.org/dc/elements/1.1/" ));
3738 + xAttrs->AddAttribute( USTR( "xmlns:number" ), USTR( OASIS_STR "datastyle:1.0" ));
3739 + xAttrs->AddAttribute( USTR( "xmlns:presentation" ), USTR( OASIS_STR "presentation:1.0" ));
3740 + xAttrs->AddAttribute( USTR( "xmlns:math" ), USTR( "http://www.w3.org/1998/Math/MathML" ));
3741 + xAttrs->AddAttribute( USTR( "xmlns:form" ), USTR( OASIS_STR "form:1.0" ));
3742 + xAttrs->AddAttribute( USTR( "xmlns:script" ), USTR( OASIS_STR "script:1.0" ));
3743 + xAttrs->AddAttribute( USTR( "xmlns:dom" ), USTR( "http://www.w3.org/2001/xml-events" ));
3744 + xAttrs->AddAttribute( USTR( "xmlns:xforms" ), USTR( "http://www.w3.org/2002/xforms" ));
3745 + xAttrs->AddAttribute( USTR( "xmlns:xsd" ), USTR( "http://www.w3.org/2001/XMLSchema" ));
3746 + xAttrs->AddAttribute( USTR( "xmlns:xsi" ), USTR( "http://www.w3.org/2001/XMLSchema-instance" ));
3747 + xAttrs->AddAttribute( USTR( "office:version" ), USTR( "1.0" ));
3748 + xAttrs->AddAttribute( USTR( "office:mimetype" ), USTR( "application/vnd.oasis.opendocument.graphics" ));
3750 + m_xDocumentHandler->startElement( USTR("office:document"), xUnoAttrs );
3752 + xAttrs->Clear();
3754 + m_xDocumentHandler->startElement( USTR("office:settings"), xUnoAttrs);
3756 + xAttrs->AddAttribute( USTR( "config:name" ), USTR( "ooo:view-settings" ));
3757 + m_xDocumentHandler->startElement( USTR("config:config-item-set"), xUnoAttrs);
3759 + xAttrs->Clear();
3761 + xAttrs->AddAttribute( USTR( "config:name" ), USTR( "VisibleAreaTop" ));
3762 + xAttrs->AddAttribute( USTR( "config:type" ), USTR( "int" ));
3763 + m_xDocumentHandler->startElement( USTR( "config:config-item" ), xUnoAttrs);
3765 + m_xDocumentHandler->characters( USTR( "0" ));
3767 + m_xDocumentHandler->endElement( USTR( "config:config-item" ));
3769 + xAttrs->Clear();
3771 + xAttrs->AddAttribute( USTR( "config:name" ), USTR( "VisibleAreaLeft" ));
3772 + xAttrs->AddAttribute( USTR( "config:type" ), USTR( "int" ));
3773 + m_xDocumentHandler->startElement( USTR( "config:config-item" ), xUnoAttrs);
3775 + m_xDocumentHandler->characters( USTR( "0" ));
3777 + m_xDocumentHandler->endElement( USTR( "config:config-item" ));
3779 + xAttrs->Clear();
3781 + xAttrs->AddAttribute( USTR( "config:name" ), USTR( "VisibleAreaWidth" ));
3782 + xAttrs->AddAttribute( USTR( "config:type" ), USTR( "int" ));
3783 + m_xDocumentHandler->startElement( USTR( "config:config-item" ), xUnoAttrs);
3785 + sal_Int64 iWidth = sal_Int64(fViewPortWidth);
3786 + m_xDocumentHandler->characters( ::rtl::OUString::valueOf(iWidth) );
3788 + m_xDocumentHandler->endElement( USTR( "config:config-item" ));
3790 + xAttrs->Clear();
3792 + xAttrs->AddAttribute( USTR( "config:name" ), USTR( "VisibleAreaHeight" ));
3793 + xAttrs->AddAttribute( USTR( "config:type" ), USTR( "int" ));
3794 + m_xDocumentHandler->startElement( USTR( "config:config-item" ), xUnoAttrs);
3796 + sal_Int64 iHeight = sal_Int64(fViewPortHeight);
3797 + m_xDocumentHandler->characters( ::rtl::OUString::valueOf(iHeight) );
3799 + m_xDocumentHandler->endElement( USTR( "config:config-item" ));
3801 + m_xDocumentHandler->endElement( USTR( "config:config-item-set" ));
3803 + m_xDocumentHandler->endElement( USTR( "office:settings" ));
3805 + xAttrs->Clear();
3807 + m_xDocumentHandler->startElement( USTR("office:automatic-styles"),
3808 + xUnoAttrs );
3810 + xAttrs->AddAttribute( USTR( "style:name" ), USTR("pagelayout1"));
3811 + m_xDocumentHandler->startElement( USTR("style:page-layout"),
3812 + xUnoAttrs );
3813 + // TODO(Q3): this is super-ugly. In-place container come to mind.
3814 + xAttrs->Clear();
3816 + // make page viewport-width times viewport-height mm large - add
3817 + // 5% border at every side
3818 + xAttrs->AddAttribute( USTR( "fo:margin-top" ), USTR("0mm"));
3819 + xAttrs->AddAttribute( USTR( "fo:margin-bottom" ), USTR("0mm"));
3820 + xAttrs->AddAttribute( USTR( "fo:margin-left" ), USTR("0mm"));
3821 + xAttrs->AddAttribute( USTR( "fo:margin-right" ), USTR("0mm"));
3822 + xAttrs->AddAttribute( USTR( "fo:page-width" ), rtl::OUString::valueOf(fViewPortWidth)+USTR("mm"));
3823 + xAttrs->AddAttribute( USTR( "fo:page-height" ), rtl::OUString::valueOf(fViewPortHeight)+USTR("mm"));
3824 + xAttrs->AddAttribute( USTR( "style:print-orientation" ),
3825 + fViewPortWidth > fViewPortHeight ?
3826 + USTR("landscape") :
3827 + USTR("portrait"));
3828 + m_xDocumentHandler->startElement( USTR("style:page-layout-properties"),
3829 + xUnoAttrs );
3830 + m_xDocumentHandler->endElement( USTR("style:page-layout-properties") );
3831 + m_xDocumentHandler->endElement( USTR("style:page-layout") );
3833 + xAttrs->Clear();
3834 + xAttrs->AddAttribute( USTR( "style:name" ), USTR("pagestyle1"));
3835 + xAttrs->AddAttribute( USTR( "style:family" ), USTR("drawing-page"));
3836 + m_xDocumentHandler->startElement( USTR("style:style"),
3837 + xUnoAttrs );
3839 + xAttrs->Clear();
3840 + xAttrs->AddAttribute( USTR( "draw:background-size" ), USTR("border"));
3841 + xAttrs->AddAttribute( USTR( "draw:fill" ), USTR("none"));
3842 + m_xDocumentHandler->startElement( USTR("style:drawing-page-properties"),
3843 + xUnoAttrs );
3844 + m_xDocumentHandler->endElement( USTR("style:drawing-page-properties") );
3845 + m_xDocumentHandler->endElement( USTR("style:style") );
3847 + StatePool aStatePool;
3848 + StateMap aStateMap;
3849 + annotateStyles(aStatePool,aStateMap,aInitialState,
3850 + xDocElem,m_xDocumentHandler);
3852 +#ifdef VERBOSE
3853 + dumpTree(xDocElem);
3854 +#endif
3856 + m_xDocumentHandler->endElement( USTR("office:automatic-styles") );
3858 + ////////////////////////////////////////////////////////////////////
3860 + xAttrs->Clear();
3861 + m_xDocumentHandler->startElement( USTR("office:styles"),
3862 + xUnoAttrs);
3863 + m_xDocumentHandler->endElement( USTR("office:styles") );
3865 + ////////////////////////////////////////////////////////////////////
3867 + m_xDocumentHandler->startElement( USTR("office:master-styles"),
3868 + xUnoAttrs );
3869 + xAttrs->Clear();
3870 + xAttrs->AddAttribute( USTR( "style:name" ), USTR("Default"));
3871 + xAttrs->AddAttribute( USTR( "style:page-layout-name" ), USTR("pagelayout1"));
3872 + xAttrs->AddAttribute( USTR( "draw:style-name" ), USTR("pagestyle1"));
3873 + m_xDocumentHandler->startElement( USTR("style:master-page"),
3874 + xUnoAttrs );
3875 + m_xDocumentHandler->endElement( USTR("style:master-page") );
3877 + m_xDocumentHandler->endElement( USTR("office:master-styles") );
3879 + ////////////////////////////////////////////////////////////////////
3881 + xAttrs->Clear();
3882 + m_xDocumentHandler->startElement( USTR("office:body"),
3883 + xUnoAttrs );
3884 + m_xDocumentHandler->startElement( USTR("office:drawing"),
3885 + xUnoAttrs );
3887 + xAttrs->Clear();
3888 + xAttrs->AddAttribute( USTR( "draw:master-page-name" ), USTR("Default"));
3889 + xAttrs->AddAttribute( USTR( "draw:style-name" ), USTR("pagestyle1"));
3890 + m_xDocumentHandler->startElement(USTR("draw:page"),
3891 + xUnoAttrs);
3893 + // write out all shapes
3894 + writeShapes(aStatePool,
3895 + aStateMap,
3896 + xDocElem,
3897 + m_xDocumentHandler);
3899 + m_xDocumentHandler->endElement( USTR("draw:page") );
3900 + m_xDocumentHandler->endElement( USTR("office:drawing") );
3901 + m_xDocumentHandler->endElement( USTR("office:body") );
3902 + m_xDocumentHandler->endElement( USTR("office:document") );
3903 + m_xDocumentHandler->endDocument();
3905 + return sal_True;
3908 +} // namespace svgi
3909 diff --git filter/source/svg/svgreader.hxx filter/source/svg/svgreader.hxx
3910 new file mode 100644
3911 index 0000000..420d326
3912 --- /dev/null
3913 +++ filter/source/svg/svgreader.hxx
3914 @@ -0,0 +1,43 @@
3915 +/*************************************************************************
3917 + * OpenOffice.org - a multi-platform office productivity suite
3919 + * Author:
3920 + * Fridrich Strba <fridrich.strba@bluewin.ch>
3921 + * Thorsten Behrens <tbehrens@novell.com>
3923 + * Copyright (C) 2008, Novell Inc.
3925 + * The Contents of this file are made available subject to
3926 + * the terms of GNU Lesser General Public License Version 2.1.
3928 + ************************************************************************/
3930 +#ifndef INCLUDED_SVGREADER_HXX
3931 +#define INCLUDED_SVGREADER_HXX
3933 +#include <com/sun/star/uno/XComponentContext.hpp>
3934 +#include <com/sun/star/lang/XMultiServiceFactory.hpp>
3935 +#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
3936 +#include <com/sun/star/io/XInputStream.hpp>
3938 +namespace svgi
3941 +class SVGReader
3943 + const ::com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > m_xServiceFactory;
3944 + const ::com::sun::star::uno::Reference< com::sun::star::io::XInputStream > m_xInputStream;
3945 + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler > m_xDocumentHandler;
3947 +public:
3948 + SVGReader( const com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory>& xServiceFactory,
3949 + const com::sun::star::uno::Reference< com::sun::star::io::XInputStream >& xInputStream,
3950 + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler >& xDocumentHandler );
3952 + sal_Bool parseAndConvert();
3955 +} // namespace svgi
3957 +#endif
3958 diff --git filter/source/svg/test/makefile.mk filter/source/svg/test/makefile.mk
3959 new file mode 100644
3960 index 0000000..3f14c88
3961 --- /dev/null
3962 +++ filter/source/svg/test/makefile.mk
3963 @@ -0,0 +1,114 @@
3964 +#*************************************************************************
3966 +# OpenOffice.org - a multi-platform office productivity suite
3968 +# Author:
3969 +# Fridrich Strba <fridrich.strba@bluewin.ch>
3970 +# Thorsten Behrens <tbehrens@novell.com>
3972 +# Copyright (C) 2008, Novell Inc.
3973 +# Parts copyright 2005 by Sun Microsystems, Inc.
3975 +# The Contents of this file are made available subject to
3976 +# the terms of GNU Lesser General Public License Version 2.1.
3978 +#*************************************************************************
3980 +PRJ=..$/..$/..
3981 +PRJNAME=filter
3982 +TARGET=tests
3983 +TARGETTYPE=CUI
3984 +ENABLE_EXCEPTIONS=TRUE
3986 +# --- Settings -----------------------------------------------------
3988 +.INCLUDE: settings.mk
3990 +# --- unit tests ---------------------------------------------------
3992 +SHL1OBJS= \
3993 + $(SLO)$/parsertest.obj
3995 +SHL1TARGET= tests
3996 +SHL1LIBS= $(SLB)$/svgfilter.lib
3997 +SHL1STDLIBS= \
3998 + $(BASEGFXLIB) \
3999 + $(SVXLIB) \
4000 + $(SVTOOLLIB) \
4001 + $(XMLOFFLIB) \
4002 + $(BASEGFXLIB) \
4003 + $(VCLLIB) \
4004 + $(UNOTOOLSLIB) \
4005 + $(TOOLSLIB) \
4006 + $(COMPHELPERLIB) \
4007 + $(CPPUHELPERLIB) \
4008 + $(CPPULIB) \
4009 + $(SALLIB) \
4010 + $(LIBXML) \
4011 + $(CPPUNITLIB)
4013 +# --- svg2xml binary ------------------------------------------------------
4015 +TARGET2=svg2odf
4017 +APP1TARGET=$(TARGET2)
4018 +APP1LIBSALCPPRT=
4019 +APP1OBJS= \
4020 + $(SLO)$/odfserializer.obj \
4021 + $(SLO)$/svg2odf.obj
4023 +APP1LIBS=\
4024 + $(SLB)$/svgfilter.lib
4026 +APP1STDLIBS=\
4027 + $(BASEGFXLIB) \
4028 + $(SVXLIB) \
4029 + $(XMLOFFLIB) \
4030 + $(BASEGFXLIB) \
4031 + $(VCLLIB) \
4032 + $(UNOTOOLSLIB) \
4033 + $(TOOLSLIB) \
4034 + $(COMPHELPERLIB) \
4035 + $(CPPUHELPERLIB) \
4036 + $(CPPULIB) \
4037 + $(SALLIB) \
4038 + $(LIBXML)
4040 +# --- Targets ------------------------------------------------------
4042 +.INCLUDE : target.mk
4043 +.INCLUDE : _cppunit.mk
4045 +# --- Special ------------------------------------------------------
4047 +TESTFILES=\
4048 + anarchist.svg \
4049 + anarchist2.svg \
4050 + Nested.svg
4052 +$(MISC)$/%_svgi_unittest_succeeded : $(BIN)$/svg2odf
4053 + rm -f $(MISC)$/$(@:s/_succeeded/.xml/:f)
4054 + $(BIN)$/svg2odf $(@:s/_svgi_unittest_succeeded/.svg/:f) $(MISC)$/$(@:s/_succeeded/.xml/:f) $(BIN)$/svgi_unittest_test.ini
4055 + $(TOUCH) $@
4057 +.IF "$(GUI)" == "WNT"
4058 +SAXPARSERLIB=$(SOLARBINDIR)$/sax.uno$(DLLPOST)
4059 +UNOXMLLIB=$(SOLARBINDIR)$/$(DLLPRE)unoxml$(OFFICEUPD)$(DLLPOSTFIX)$(DLLPOST)
4060 +.ELSE
4061 +SAXPARSERLIB=$(SOLARLIBDIR)$/sax.uno$(DLLPOST)
4062 +UNOXMLLIB=$(SOLARLIBDIR)$/$(DLLPRE)unoxml$(OFFICEUPD)$(DLLPOSTFIX)$(DLLPOST)
4063 +.ENDIF
4065 +$(BIN)$/unittestservices.rdb : makefile.mk $(SAXPARSERLIB) $(UNOXMLLIB)
4066 + rm -f $@
4067 + $(REGCOMP) -register -r $@ -c $(SAXPARSERLIB)
4068 + $(REGCOMP) -register -r $@ -c $(UNOXMLLIB)
4070 +$(BIN)$/svgi_unittest_test.ini : makefile.mk
4071 + rm -f $@
4072 + @echo UNO_SERVICES=$(BIN)$/unittestservices.rdb > $@
4073 + @echo UNO_TYPES=$(UNOUCRRDB:s/\/\\/) >> $@
4075 +ALLTAR : $(BIN)$/svgi_unittest_test.ini \
4076 + $(BIN)$/unittestservices.rdb \
4077 + $(foreach,i,$(TESTFILES:s/.svg/_svgi_unittest_succeeded/:f) $(MISC)$/$i)
4078 diff --git filter/source/svg/test/odfserializer.cxx filter/source/svg/test/odfserializer.cxx
4079 new file mode 100644
4080 index 0000000..7686223
4081 --- /dev/null
4082 +++ filter/source/svg/test/odfserializer.cxx
4083 @@ -0,0 +1,140 @@
4084 +/*************************************************************************
4086 + * OpenOffice.org - a multi-platform office productivity suite
4088 + * Author:
4089 + * Fridrich Strba <fridrich.strba@bluewin.ch>
4090 + * Thorsten Behrens <tbehrens@novell.com>
4092 + * Copyright (C) 2008, Novell Inc.
4093 + * Parts copyright 2005 by Sun Microsystems, Inc.
4095 + * The Contents of this file are made available subject to
4096 + * the terms of GNU Lesser General Public License Version 2.1.
4098 + ************************************************************************/
4100 +// MARKER(update_precomp.py): autogen include statement, do not remove
4101 +#include "precompiled_filter.hxx"
4103 +#include "odfserializer.hxx"
4104 +#include <osl/diagnose.h>
4105 +#include <rtl/ustrbuf.hxx>
4106 +#include <cppuhelper/compbase1.hxx>
4107 +#include <cppuhelper/basemutex.hxx>
4108 +#include <com/sun/star/uno/Sequence.hxx>
4109 +#include <boost/noncopyable.hpp>
4111 +using namespace ::com::sun::star;
4113 +namespace svgi
4116 +typedef ::cppu::WeakComponentImplHelper1<
4117 + com::sun::star::xml::sax::XDocumentHandler> ODFSerializerBase;
4119 +class ODFSerializer : private cppu::BaseMutex,
4120 + public ODFSerializerBase,
4121 + boost::noncopyable
4123 +public:
4124 + explicit ODFSerializer(const uno::Reference<io::XOutputStream>& xOut) :
4125 + ODFSerializerBase(m_aMutex),
4126 + m_xOutStream(xOut),
4127 + m_aLineFeed(1),
4128 + m_aBuf()
4130 + m_aLineFeed[0] = '\n';
4133 + virtual void SAL_CALL startDocument( ) throw (xml::sax::SAXException, uno::RuntimeException);
4134 + virtual void SAL_CALL endDocument( ) throw (xml::sax::SAXException, uno::RuntimeException);
4135 + virtual void SAL_CALL startElement( const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) throw (xml::sax::SAXException, uno::RuntimeException);
4136 + virtual void SAL_CALL endElement( const ::rtl::OUString& aName ) throw (xml::sax::SAXException, uno::RuntimeException);
4137 + virtual void SAL_CALL characters( const ::rtl::OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException);
4138 + virtual void SAL_CALL ignorableWhitespace( const ::rtl::OUString& aWhitespaces ) throw (xml::sax::SAXException, uno::RuntimeException);
4139 + virtual void SAL_CALL processingInstruction( const ::rtl::OUString& aTarget, const ::rtl::OUString& aData ) throw (xml::sax::SAXException, uno::RuntimeException);
4140 + virtual void SAL_CALL setDocumentLocator( const uno::Reference< xml::sax::XLocator >& xLocator ) throw (xml::sax::SAXException, uno::RuntimeException);
4142 +private:
4143 + uno::Reference<io::XOutputStream> m_xOutStream;
4144 + uno::Sequence<sal_Int8> m_aLineFeed;
4145 + uno::Sequence<sal_Int8> m_aBuf;
4148 +void SAL_CALL ODFSerializer::startDocument( ) throw (xml::sax::SAXException, uno::RuntimeException)
4150 + OSL_PRECOND(m_xOutStream.is(), "ODFSerializer(): invalid output stream");
4152 + rtl::OUStringBuffer aElement;
4153 + aElement.appendAscii("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
4154 + characters(aElement.makeStringAndClear());
4157 +void SAL_CALL ODFSerializer::endDocument() throw (xml::sax::SAXException, uno::RuntimeException)
4160 +void SAL_CALL ODFSerializer::startElement( const ::rtl::OUString& aName,
4161 + const uno::Reference< xml::sax::XAttributeList >& xAttribs ) throw (xml::sax::SAXException, uno::RuntimeException)
4163 + rtl::OUStringBuffer aElement;
4164 + aElement.appendAscii("<");
4165 + aElement.append(aName);
4166 + aElement.appendAscii(" ");
4168 + const sal_Int16 nLen=xAttribs->getLength();
4169 + for( sal_Int16 i=0; i<nLen; ++i )
4171 + rtl::OUStringBuffer aAttribute;
4172 + aElement.append(xAttribs->getNameByIndex(i));
4173 + aElement.appendAscii("=\"");
4174 + aElement.append(xAttribs->getValueByIndex(i));
4175 + aElement.appendAscii("\" ");
4178 + aElement.appendAscii(">");
4179 + characters(aElement.makeStringAndClear());
4182 +void SAL_CALL ODFSerializer::endElement( const ::rtl::OUString& aName ) throw (xml::sax::SAXException, uno::RuntimeException)
4184 + rtl::OUStringBuffer aElement;
4185 + aElement.appendAscii("</");
4186 + aElement.append(aName);
4187 + aElement.appendAscii(">");
4188 + characters(aElement.makeStringAndClear());
4191 +void SAL_CALL ODFSerializer::characters( const ::rtl::OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException)
4193 + const rtl::OString aStr = rtl::OUStringToOString(aChars,
4194 + RTL_TEXTENCODING_UTF8);
4195 + const sal_Int32 nLen( aStr.getLength() );
4196 + m_aBuf.realloc( nLen );
4197 + const sal_Char* pStr = aStr.getStr();
4198 + std::copy(pStr,pStr+nLen,m_aBuf.getArray());
4200 + m_xOutStream->writeBytes(m_aBuf);
4201 + // TODO(F1): Make pretty printing configurable
4202 + m_xOutStream->writeBytes(m_aLineFeed);
4205 +void SAL_CALL ODFSerializer::ignorableWhitespace( const ::rtl::OUString& aWhitespaces ) throw (xml::sax::SAXException, uno::RuntimeException)
4207 + // TODO(F1): Make pretty printing configurable
4208 + characters(aWhitespaces);
4211 +void SAL_CALL ODFSerializer::processingInstruction( const ::rtl::OUString&,
4212 + const ::rtl::OUString& ) throw (xml::sax::SAXException, uno::RuntimeException)
4215 +void SAL_CALL ODFSerializer::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& ) throw (xml::sax::SAXException, uno::RuntimeException)
4218 +uno::Reference< xml::sax::XDocumentHandler> createSerializer(const uno::Reference<io::XOutputStream>& xOut )
4220 + return uno::Reference<xml::sax::XDocumentHandler>(new ODFSerializer(xOut));
4224 diff --git filter/source/svg/test/odfserializer.hxx filter/source/svg/test/odfserializer.hxx
4225 new file mode 100644
4226 index 0000000..f2ab4a3
4227 --- /dev/null
4228 +++ filter/source/svg/test/odfserializer.hxx
4229 @@ -0,0 +1,31 @@
4230 +/*************************************************************************
4232 + * OpenOffice.org - a multi-platform office productivity suite
4234 + * Author:
4235 + * Fridrich Strba <fridrich.strba@bluewin.ch>
4236 + * Thorsten Behrens <tbehrens@novell.com>
4238 + * Copyright (C) 2008, Novell Inc.
4239 + * Parts copyright 2005 by Sun Microsystems, Inc.
4241 + * The Contents of this file are made available subject to
4242 + * the terms of GNU Lesser General Public License Version 2.1.
4244 + ************************************************************************/
4246 +#ifndef INCLUDED_SVG_ODFSERIALIZER_HXX
4247 +#define INCLUDED_SVG_ODFSERIALIZER_HXX
4249 +#include <com/sun/star/uno/Reference.hxx>
4250 +#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
4251 +#include <com/sun/star/io/XOutputStream.hpp>
4253 +namespace svgi
4255 + /// Creates a XDocumentHandler that serializes directly to an XOutputStream
4256 + ::com::sun::star::uno::Reference< com::sun::star::xml::sax::XDocumentHandler>
4257 + createSerializer(const ::com::sun::star::uno::Reference<com::sun::star::io::XOutputStream>& );
4260 +#endif // _COM_SUN_STAR_XML_SAX_XDOCUMENTHANDLER_HDL_
4261 diff --git filter/source/svg/test/parsertest.cxx filter/source/svg/test/parsertest.cxx
4262 new file mode 100644
4263 index 0000000..c8db101
4264 --- /dev/null
4265 +++ filter/source/svg/test/parsertest.cxx
4266 @@ -0,0 +1,210 @@
4267 +/*************************************************************************
4269 + * OpenOffice.org - a multi-platform office productivity suite
4271 + * Author:
4272 + * Fridrich Strba <fridrich.strba@bluewin.ch>
4273 + * Thorsten Behrens <tbehrens@novell.com>
4275 + * Copyright (C) 2008, Novell Inc.
4277 + * The Contents of this file are made available subject to
4278 + * the terms of GNU Lesser General Public License Version 2.1.
4280 + ************************************************************************/
4282 +// MARKER(update_precomp.py): autogen include statement, do not remove
4283 +#include "precompiled_filter.hxx"
4285 +#include <cppunit/simpleheader.hxx>
4287 +#include "../gfxtypes.hxx"
4288 +#include "../parserfragments.hxx"
4290 +using namespace svgi;
4292 +class TestParser : public CppUnit::TestFixture
4294 +public:
4295 + void setUp()
4296 + {}
4298 + void tearDown()
4299 + {}
4301 + void testParseColor()
4303 + ARGBColor aTmp;
4305 + const char* sIn="#102030 ";
4306 + ARGBColor aOut(16, 32, 48);
4307 + CPPUNIT_ASSERT_MESSAGE( "Consuming color #112233",
4308 + parseColor( sIn, aTmp ) );
4309 + OSL_TRACE("color is: a:%f r:%f g:%f b:%f", aTmp.a, aTmp.r, aTmp.g, aTmp.b);
4310 + CPPUNIT_ASSERT_MESSAGE( "Parsing color #112233",
4311 + aOut==aTmp );
4313 + sIn=" #321";
4314 + aOut=ARGBColor(51, 34, 17);
4315 + CPPUNIT_ASSERT_MESSAGE( "Consuming color #321",
4316 + parseColor( sIn, aTmp ) );
4317 + OSL_TRACE("color is: a:%f r:%f g:%f b:%f", aTmp.a, aTmp.r, aTmp.g, aTmp.b);
4318 + CPPUNIT_ASSERT_MESSAGE( "Parsing color #321",
4319 + aOut==aTmp );
4321 + sIn="rgb(100,200,\t 50)";
4322 + aOut=ARGBColor(100, 200, 50);
4323 + CPPUNIT_ASSERT_MESSAGE( "Consuming color rgb(100,200,50)",
4324 + parseColor( sIn, aTmp ) );
4325 + OSL_TRACE("color is: a:%f r:%f g:%f b:%f", aTmp.a, aTmp.r, aTmp.g, aTmp.b);
4326 + CPPUNIT_ASSERT_MESSAGE( "Parsing color rgb(100,200,50)",
4327 + aOut==aTmp );
4329 + sIn="rgb(0.1, \t0.2,0.9)";
4330 + aOut=ARGBColor(0.1, 0.2, 0.9);
4331 + CPPUNIT_ASSERT_MESSAGE( "Consuming color rgb(0.1,0.2,0.9)",
4332 + parseColor( sIn, aTmp ) );
4333 + OSL_TRACE("color is: a:%f r:%f g:%f b:%f", aTmp.a, aTmp.r, aTmp.g, aTmp.b);
4334 + CPPUNIT_ASSERT_MESSAGE( "Parsing color rgb(0.1,0.2,0.9)",
4335 + aOut==aTmp );
4337 + sIn=" burlywood ";
4338 + aOut=ARGBColor(222,184,135);
4339 + CPPUNIT_ASSERT_MESSAGE( "Consuming color burlywood",
4340 + parseColor( sIn, aTmp ) );
4341 + OSL_TRACE("color is: a:%f r:%f g:%f b:%f", aTmp.a, aTmp.r, aTmp.g, aTmp.b);
4342 + CPPUNIT_ASSERT_MESSAGE( "Parsing color burlywood",
4343 + aOut==aTmp );
4346 + void testParseOpacity()
4348 + ARGBColor aTmp;
4350 + const char* sIn=" 0.123 ";
4351 + ARGBColor aOut(0.123, 0.0, 0.0, 0.0);
4352 + CPPUNIT_ASSERT_MESSAGE( "Consuming opacity 0.123",
4353 + parseOpacity( sIn, aTmp ) );
4354 + OSL_TRACE("color is: a:%f r:%f g:%f b:%f", aTmp.a, aTmp.r, aTmp.g, aTmp.b);
4355 + CPPUNIT_ASSERT_MESSAGE( "Parsing opacity 0.123",
4356 + aOut==aTmp );
4359 + void testParseTransform()
4361 + basegfx::B2DHomMatrix aOut;
4363 + const char* sIn=" none ";
4364 + basegfx::B2DHomMatrix aTmp;
4365 + CPPUNIT_ASSERT_MESSAGE( "Consuming transformation none",
4366 + parseTransform( sIn, aTmp ) );
4367 + OSL_TRACE("transformation is: m00:%f m01:%f m02:%f m10:%f m11:%f m12:%f",
4368 + aTmp.get(0,0), aTmp.get(0,1), aTmp.get(0,2), aTmp.get(1,0), aTmp.get(1,1), aTmp.get(1,2) );
4369 + CPPUNIT_ASSERT_MESSAGE( "Parsing transformation none",
4370 + aOut==aTmp );
4372 + sIn=" scale( 10 ) ";
4373 + aOut.identity();
4374 + aOut.scale(10.0,10.0);
4375 + CPPUNIT_ASSERT_MESSAGE( "Consuming transformation scale(10)",
4376 + parseTransform( sIn, aTmp ) );
4377 + OSL_TRACE("transformation is: m00:%f m01:%f m02:%f m10:%f m11:%f m12:%f",
4378 + aTmp.get(0,0), aTmp.get(0,1), aTmp.get(0,2), aTmp.get(1,0), aTmp.get(1,1), aTmp.get(1,2) );
4379 + CPPUNIT_ASSERT_MESSAGE( "Parsing transformation scale(10)",
4380 + aOut==aTmp );
4382 + sIn=" scale( 10 20.12 ) ";
4383 + aOut.identity();
4384 + aOut.scale(10.0,20.12);
4385 + CPPUNIT_ASSERT_MESSAGE( "Consuming transformation scale(10 20.12)",
4386 + parseTransform( sIn, aTmp ) );
4387 + OSL_TRACE("transformation is: m00:%f m01:%f m02:%f m10:%f m11:%f m12:%f",
4388 + aTmp.get(0,0), aTmp.get(0,1), aTmp.get(0,2), aTmp.get(1,0), aTmp.get(1,1), aTmp.get(1,2) );
4389 + CPPUNIT_ASSERT_MESSAGE( "Parsing transformation scale(10 20.12)",
4390 + aOut==aTmp );
4392 + sIn="matrix( 1,2 3,4,5 6 )";
4393 + aOut.identity();
4394 + aOut.set(0,0,1.0); aOut.set(1,0,2.0); aOut.set(0,1,3.0); aOut.set(1,1,4.0); aOut.set(0,2,5.0); aOut.set(1,2,6.0);
4395 + CPPUNIT_ASSERT_MESSAGE( "Consuming transformation matrix(1,2,3,4,5,6)",
4396 + parseTransform( sIn, aTmp ) );
4397 + OSL_TRACE("transformation is: m00:%f m01:%f m02:%f m10:%f m11:%f m12:%f",
4398 + aTmp.get(0,0), aTmp.get(0,1), aTmp.get(0,2), aTmp.get(1,0), aTmp.get(1,1), aTmp.get(1,2) );
4399 + CPPUNIT_ASSERT_MESSAGE( "Parsing transformation matrix(1,2,3,4,5,6)",
4400 + aOut==aTmp );
4402 + sIn="matrix( 1 0 0 1 -10 -10 ) translate(10) scale(10), rotate(90)";
4403 + aOut.identity();
4404 + aOut.set(0,0,0.0); aOut.set(1,0,10.0); aOut.set(0,1,-10.0); aOut.set(1,1,0.0); aOut.set(0,2,0.0); aOut.set(1,2,0.0);
4405 + CPPUNIT_ASSERT_MESSAGE( "Consuming transformation matrix(1,2,3,4,5,6)",
4406 + parseTransform( sIn, aTmp ) );
4407 + OSL_TRACE("transformation is: m00:%f m01:%f m02:%f m10:%f m11:%f m12:%f",
4408 + aTmp.get(0,0), aTmp.get(0,1), aTmp.get(0,2), aTmp.get(1,0), aTmp.get(1,1), aTmp.get(1,2) );
4409 + CPPUNIT_ASSERT_MESSAGE( "Parsing transformation matrix(1,2,3,4,5,6)",
4410 + aOut==aTmp );
4412 + sIn="skewX(45)";
4413 + aOut.identity();
4414 + aOut.set(0,0,1.0); aOut.set(1,0,1.0); aOut.set(0,1,0.0); aOut.set(1,1,1.0); aOut.set(0,2,0.0); aOut.set(1,2,0.0);
4415 + CPPUNIT_ASSERT_MESSAGE( "Consuming transformation skewX(45)",
4416 + parseTransform( sIn, aTmp ) );
4417 + OSL_TRACE("transformation is: m00:%f m01:%f m02:%f m10:%f m11:%f m12:%f",
4418 + aTmp.get(0,0), aTmp.get(0,1), aTmp.get(0,2), aTmp.get(1,0), aTmp.get(1,1), aTmp.get(1,2) );
4419 + CPPUNIT_ASSERT_MESSAGE( "Parsing transformation skewX(45)",
4420 + aOut==aTmp );
4422 + sIn="skewY(45)";
4423 + aOut.identity();
4424 + aOut.set(0,0,1.0); aOut.set(1,0,0.0); aOut.set(0,1,1.0); aOut.set(1,1,1.0); aOut.set(0,2,0.0); aOut.set(1,2,0.0);
4425 + CPPUNIT_ASSERT_MESSAGE( "Consuming transformation skewY(45)",
4426 + parseTransform( sIn, aTmp ) );
4427 + OSL_TRACE("transformation is: m00:%f m01:%f m02:%f m10:%f m11:%f m12:%f",
4428 + aTmp.get(0,0), aTmp.get(0,1), aTmp.get(0,2), aTmp.get(1,0), aTmp.get(1,1), aTmp.get(1,2) );
4429 + CPPUNIT_ASSERT_MESSAGE( "Parsing transformation skewY(45)",
4430 + aOut==aTmp );
4433 + void testParseViewBox()
4435 + basegfx::B2DRange aTmp;
4437 + const char* sIn=" 10 20, 30.5,5 ";
4438 + basegfx::B2DRange aOut(10,20,40.5,25);
4439 + CPPUNIT_ASSERT_MESSAGE( "Consuming 10,20,30.5,5",
4440 + parseViewBox( sIn, aTmp ) );
4441 + OSL_TRACE("viewbox is: x1:%f y1:%f x2:%f y2:%f", aTmp.getMinX(), aTmp.getMinY(), aTmp.getMaxX(), aTmp.getMaxY());
4442 + CPPUNIT_ASSERT_MESSAGE( "Parsing 10,20,30.5,5",
4443 + aOut==aTmp );
4446 + void testParseDashArray()
4448 + std::vector<double> aTmp;
4450 + const char* sIn=" 10,20, -10.00 ";
4451 + std::vector<double> aOut; aOut.push_back(10.0); aOut.push_back(20.0); aOut.push_back(-10.0);
4452 + CPPUNIT_ASSERT_MESSAGE( "Consuming 10,20,-10.00",
4453 + parseDashArray( sIn, aTmp ) );
4454 + OSL_TRACE("dash array is: len %d, %f %f %f", aTmp.size(), aTmp[0], aTmp[1], aTmp[2] );
4455 + CPPUNIT_ASSERT_MESSAGE( "Parsing 10,20,-10.00",
4456 + aOut==aTmp );
4459 + CPPUNIT_TEST_SUITE(TestParser);
4460 + CPPUNIT_TEST(testParseColor);
4461 + CPPUNIT_TEST(testParseOpacity);
4462 + CPPUNIT_TEST(testParseTransform);
4463 + CPPUNIT_TEST(testParseViewBox);
4464 + CPPUNIT_TEST(testParseDashArray);
4465 + // TODO: CPPUNIT_TEST(testParseXlinkHref);
4466 + CPPUNIT_TEST_SUITE_END();
4469 +// -----------------------------------------------------------------------------
4471 +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(TestParser, "test svg parser fragments");
4473 +// this macro creates an empty function, which will called by the RegisterAllFunctions()
4474 +// to let the user the possibility to also register some functions by hand.
4475 +NOADDITIONAL;
4477 diff --git filter/source/svg/test/svg2odf.cxx filter/source/svg/test/svg2odf.cxx
4478 new file mode 100644
4479 index 0000000..a271ce0
4480 --- /dev/null
4481 +++ filter/source/svg/test/svg2odf.cxx
4482 @@ -0,0 +1,124 @@
4483 +/*************************************************************************
4485 + * OpenOffice.org - a multi-platform office productivity suite
4487 + * Author:
4488 + * Fridrich Strba <fridrich.strba@bluewin.ch>
4489 + * Thorsten Behrens <tbehrens@novell.com>
4491 + * Copyright (C) 2008, Novell Inc.
4492 + * Parts copyright 2005 by Sun Microsystems, Inc.
4494 + * The Contents of this file are made available subject to
4495 + * the terms of GNU Lesser General Public License Version 2.1.
4497 + ************************************************************************/
4499 +// MARKER(update_precomp.py): autogen include statement, do not remove
4500 +#include "precompiled_filter.hxx"
4502 +#include "../svgreader.hxx"
4503 +#include "odfserializer.hxx"
4505 +#include <sal/main.h>
4506 +#include <osl/file.hxx>
4507 +#include <osl/process.h>
4508 +#include <rtl/bootstrap.hxx>
4510 +#include <cppuhelper/implbase1.hxx>
4511 +#include <cppuhelper/bootstrap.hxx>
4512 +#include <cppuhelper/servicefactory.hxx>
4513 +#include <comphelper/processfactory.hxx>
4514 +#include <comphelper/oslfile2streamwrap.hxx>
4516 +using namespace ::com::sun::star;
4518 +namespace
4520 + class OutputWrap : public cppu::WeakImplHelper1<
4521 + io::XOutputStream>
4523 + osl::File maFile;
4525 + public:
4527 + explicit OutputWrap( const rtl::OUString& rURL ) : maFile(rURL)
4529 + maFile.open(osl_File_OpenFlag_Create|OpenFlag_Write);
4532 + virtual void SAL_CALL writeBytes( const com::sun::star::uno::Sequence< ::sal_Int8 >& aData ) throw (com::sun::star::io::NotConnectedException,com::sun::star::io::BufferSizeExceededException, com::sun::star::io::IOException, com::sun::star::uno::RuntimeException)
4535 + sal_uInt64 nBytesWritten(0);
4536 + maFile.write(aData.getConstArray(),aData.getLength(),nBytesWritten);
4539 + virtual void SAL_CALL flush() throw (com::sun::star::io::NotConnectedException, com::sun::star::io::BufferSizeExceededException, com::sun::star::io::IOException, com::sun::star::uno::RuntimeException)
4543 + virtual void SAL_CALL closeOutput() throw (com::sun::star::io::NotConnectedException, com::sun::star::io::BufferSizeExceededException, com::sun::star::io::IOException, com::sun::star::uno::RuntimeException)
4545 + maFile.close();
4547 + };
4550 +SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
4552 + if( argc != 4 )
4554 + OSL_TRACE( "Invocation: svg2odf <base_url> <dst_url> <ini_file>. Exiting" );
4555 + return 1;
4558 + ::rtl::OUString aBaseURL, aTmpURL, aSrcURL, aDstURL, aIniUrl;
4560 + osl_getProcessWorkingDir(&aBaseURL.pData);
4561 + osl_getFileURLFromSystemPath( rtl::OUString::createFromAscii(argv[1]).pData,
4562 + &aTmpURL.pData );
4563 + osl_getAbsoluteFileURL(aBaseURL.pData,aTmpURL.pData,&aSrcURL.pData);
4565 + osl_getFileURLFromSystemPath( rtl::OUString::createFromAscii(argv[2]).pData,
4566 + &aTmpURL.pData );
4567 + osl_getAbsoluteFileURL(aBaseURL.pData,aTmpURL.pData,&aDstURL.pData);
4569 + osl_getFileURLFromSystemPath( rtl::OUString::createFromAscii(argv[3]).pData,
4570 + &aTmpURL.pData );
4571 + osl_getAbsoluteFileURL(aBaseURL.pData,aTmpURL.pData,&aIniUrl.pData);
4573 + // bootstrap UNO
4574 + uno::Reference< lang::XMultiServiceFactory > xFactory;
4575 + uno::Reference< uno::XComponentContext > xCtx;
4576 + try
4578 + xCtx = ::cppu::defaultBootstrap_InitialComponentContext(aIniUrl);
4579 + xFactory = uno::Reference< lang::XMultiServiceFactory >(xCtx->getServiceManager(),
4580 + uno::UNO_QUERY);
4581 + if( xFactory.is() )
4582 + ::comphelper::setProcessServiceFactory( xFactory );
4584 + catch( uno::Exception& )
4588 + if( !xFactory.is() )
4590 + OSL_TRACE( "Could not bootstrap UNO, installation must be in disorder. Exiting." );
4591 + return 1;
4594 + osl::File aInputFile(aSrcURL);
4595 + if( osl::FileBase::E_None!=aInputFile.open(OpenFlag_Read) )
4597 + OSL_TRACE( "Cannot open input file" );
4598 + return 1;
4601 + svgi::SVGReader aReader(xFactory,
4602 + uno::Reference<io::XInputStream>(
4603 + new comphelper::OSLInputStreamWrapper(aInputFile)),
4604 + svgi::createSerializer(new OutputWrap(aDstURL)));
4605 + return aReader.parseAndConvert() ? 0 : 1;
4607 diff --git filter/source/svg/tokenmap.cxx filter/source/svg/tokenmap.cxx
4608 new file mode 100644
4609 index 0000000..d9fb57a
4610 --- /dev/null
4611 +++ filter/source/svg/tokenmap.cxx
4612 @@ -0,0 +1,62 @@
4613 +/*************************************************************************
4615 + * OpenOffice.org - a multi-platform office productivity suite
4617 + * Author:
4618 + * Fridrich Strba <fridrich.strba@bluewin.ch>
4619 + * Thorsten Behrens <tbehrens@novell.com>
4621 + * Copyright (C) 2008, Novell Inc.
4622 + * Parts copyright 2005 by Sun Microsystems, Inc.
4624 + * The Contents of this file are made available subject to
4625 + * the terms of GNU Lesser General Public License Version 2.1.
4627 + ************************************************************************/
4629 +// MARKER(update_precomp.py): autogen include statement, do not remove
4630 +#include "precompiled_filter.hxx"
4632 +#include "tokenmap.hxx"
4633 +#include <string.h>
4635 +namespace svgi
4638 +#include "tokens.cxx"
4640 +sal_Int32 getTokenId( const char* sIdent, sal_Int32 nLen )
4642 + const struct xmltoken* t = Perfect_Hash::in_word_set( sIdent, nLen );
4643 + if( t )
4644 + return t->nToken;
4645 + else
4646 + return XML_TOKEN_INVALID;
4649 +sal_Int32 getTokenId( const rtl::OUString& sIdent )
4651 + rtl::OString aUTF8( sIdent.getStr(),
4652 + sIdent.getLength(),
4653 + RTL_TEXTENCODING_UTF8 );
4654 + return getTokenId( aUTF8.getStr(), aUTF8.getLength() );
4657 +const char* getTokenName( sal_Int32 nTokenId )
4659 + if( nTokenId >= XML_TOKEN_COUNT )
4660 + return NULL;
4662 + const xmltoken* pCurr=wordlist;
4663 + const xmltoken* pEnd=wordlist+sizeof(wordlist)/sizeof(*wordlist);
4664 + while( pCurr != pEnd )
4666 + if(pCurr->nToken == nTokenId)
4667 + return pCurr->name;
4668 + ++pCurr;
4671 + return NULL;
4674 +} // namespace svgi
4675 diff --git filter/source/svg/tokenmap.hxx filter/source/svg/tokenmap.hxx
4676 new file mode 100644
4677 index 0000000..c77def6
4678 --- /dev/null
4679 +++ filter/source/svg/tokenmap.hxx
4680 @@ -0,0 +1,32 @@
4681 +/*************************************************************************
4683 + * OpenOffice.org - a multi-platform office productivity suite
4685 + * Author:
4686 + * Fridrich Strba <fridrich.strba@bluewin.ch>
4687 + * Thorsten Behrens <tbehrens@novell.com>
4689 + * Copyright (C) 2008, Novell Inc.
4691 + * The Contents of this file are made available subject to
4692 + * the terms of GNU Lesser General Public License Version 2.1.
4694 + ************************************************************************/
4696 +#ifndef INCLUDED_TOKENMAP_HXX
4697 +#define INCLUDED_TOKENMAP_HXX
4699 +#include "tokens.hxx"
4701 +#include <rtl/string.hxx>
4702 +#include <rtl/ustring.hxx>
4704 +namespace svgi
4706 + sal_Int32 getTokenId( const char* sIdent, sal_Int32 nLen );
4707 + sal_Int32 getTokenId( const rtl::OUString& sIdent );
4708 + const char* getTokenName( sal_Int32 nTokenId );
4710 +} // namespace svgi
4712 +#endif
4713 diff --git filter/source/svg/tokens.txt filter/source/svg/tokens.txt
4714 new file mode 100644
4715 index 0000000..1211e69
4716 --- /dev/null
4717 +++ filter/source/svg/tokens.txt
4718 @@ -0,0 +1,403 @@
4719 +#######################################
4721 +# elements (SVG Tiny 1.2)
4723 +#######################################
4725 +animate
4726 +animateColor
4727 +animateMotion
4728 +animateTransform
4729 +animation
4730 +audio
4731 +circle
4732 +defs
4733 +desc
4734 +discard
4735 +ellipse
4736 +font
4737 +font-face
4738 +font-face-src
4739 +font-face-uri
4740 +foreignObject
4742 +glyph
4743 +handler
4744 +hkern
4745 +image
4746 +line
4747 +linearGradient
4748 +listener
4749 +metadata
4750 +missing-glyph
4751 +mpath
4752 +path
4753 +polygon
4754 +polyline
4755 +prefetch
4756 +radialGradient
4757 +rect
4758 +script
4759 +set
4760 +solidColor
4761 +stop
4762 +svg
4763 +switch
4764 +tbreak
4765 +text
4766 +textArea
4767 +title
4768 +tspan
4769 +use
4770 +video
4771 +#######################################
4773 +# properties (SVG Tiny 1.2)
4775 +#######################################
4776 +audio-level
4777 +color
4778 +color-rendering
4779 +display
4780 +display-align
4781 +fill
4782 +fill-opacity
4783 +fill-rule
4784 +font-family
4785 +font-size
4786 +font-style
4787 +font-variant
4788 +font-weight
4789 +image-rendering
4790 +line-increment
4791 +opacity
4792 +pointer-events
4793 +shape-rendering
4794 +solid-color
4795 +solid-opacity
4796 +stop-color
4797 +stop-opacity
4798 +stroke
4799 +stroke-dasharray
4800 +stroke-dashoffset
4801 +stroke-linecap
4802 +stroke-linejoin
4803 +stroke-miterlimit
4804 +stroke-opacity
4805 +stroke-width
4806 +text-align
4807 +text-anchor
4808 +text-rendering
4809 +vector-effect
4810 +viewport-fill
4811 +viewport-fill-opacity
4812 +visibility
4813 +#######################################
4815 +# attributes (SVG Tiny 1.2)
4817 +#######################################
4818 +accent-height
4819 +accumulate
4820 +additive
4821 +alphabetic
4822 +arabic-form
4823 +ascent
4824 +attributeName
4825 +attributeType
4826 +bandwidth
4827 +baseProfile
4828 +bbox
4829 +begin
4831 +calcMode
4832 +cap-height
4833 +class
4834 +contentScriptType
4838 +defaultAction
4839 +descent
4840 +dur
4841 +editable
4842 +end
4843 +event
4844 +externalResourcesRequired
4845 +fill
4846 +focusHighlight
4847 +focusable
4848 +font-family
4849 +font-stretch
4850 +font-style
4851 +font-variant
4852 +font-weight
4853 +from
4858 +glyph-name
4859 +gradientTransform
4860 +gradientUnits
4861 +handler
4862 +hanging
4863 +height
4864 +height
4865 +horiz-adv-x
4866 +horiz-origin-x
4868 +ideographic
4869 +initialVisibility
4871 +keyPoints
4872 +keySplines
4873 +keyTimes
4874 +lang
4875 +mathematical
4876 +max
4877 +mediaCharacterEncoding
4878 +mediaContentEncodings
4879 +mediaSize
4880 +mediaTime
4881 +min
4882 +nav-down
4883 +nav-down-left
4884 +nav-down-right
4885 +nav-left
4886 +nav-next
4887 +nav-prev
4888 +nav-right
4889 +nav-up
4890 +nav-up-left
4891 +nav-up-right
4892 +observer
4893 +offset
4894 +origin
4895 +overlay
4896 +overline-position
4897 +overline-thickness
4898 +panose-1
4899 +path
4900 +pathLength
4901 +phase
4902 +playbackOrder
4903 +points
4904 +preserveAspectRatio
4905 +propagate
4907 +repeatCount
4908 +repeatDur
4909 +requiredExtensions
4910 +requiredFeatures
4911 +requiredFonts
4912 +requiredFormats
4913 +restart
4914 +rotate
4917 +slope
4918 +snapshotTime
4919 +stemh
4920 +stemv
4921 +strikethrough-position
4922 +strikethrough-thickness
4923 +style
4924 +syncBehavior
4925 +syncBehaviorDefault
4926 +syncMaster
4927 +syncTolerance
4928 +syncToleranceDefault
4929 +systemLanguage
4930 +target
4931 +timelineBegin
4933 +transform
4934 +transformBehavior
4935 +type
4938 +underline-position
4939 +underline-thickness
4940 +unicode
4941 +unicode-range
4942 +units-per-em
4943 +values
4944 +version
4945 +viewBox
4946 +width
4947 +widths
4949 +x-height
4952 +actuate
4953 +arcrole
4954 +href
4955 +role
4956 +show
4957 +base
4958 +space
4962 +zoomAndPan
4963 +#######################################
4965 +# colour values
4967 +#######################################
4968 +aliceblue
4969 +antiquewhite
4970 +aqua
4971 +aquamarine
4972 +azure
4973 +beige
4974 +bisque
4975 +black
4976 +blanchedalmond
4977 +blue
4978 +blueviolet
4979 +brown
4980 +burlywood
4981 +cadetblue
4982 +chartreuse
4983 +chocolate
4984 +coral
4985 +cornflowerblue
4986 +cornsilk
4987 +crimson
4988 +cyan
4989 +darkblue
4990 +darkcyan
4991 +darkgoldenrod
4992 +darkgray
4993 +darkgreen
4994 +darkgrey
4995 +darkkhaki
4996 +darkmagenta
4997 +darkolivegreen
4998 +darkorange
4999 +darkorchid
5000 +darkred
5001 +darksalmon
5002 +darkseagreen
5003 +darkslateblue
5004 +darkslategray
5005 +darkslategrey
5006 +darkturquoise
5007 +darkviolet
5008 +deeppink
5009 +deepskyblue
5010 +dimgray
5011 +dimgrey
5012 +dodgerblue
5013 +firebrick
5014 +floralwhite
5015 +forestgreen
5016 +fuchsia
5017 +gainsboro
5018 +ghostwhite
5019 +gold
5020 +goldenrod
5021 +gray
5022 +grey
5023 +green
5024 +greenyellow
5025 +honeydew
5026 +hotpink
5027 +indianred
5028 +indigo
5029 +ivory
5030 +khaki
5031 +lavender
5032 +lavenderblush
5033 +lawngreen
5034 +lemonchiffon
5035 +lightblue
5036 +lightcoral
5037 +lightcyan
5038 +lightgoldenrodyellow
5039 +lightgray
5040 +lightgreen
5041 +lightgrey
5042 +lightpink
5043 +lightsalmon
5044 +lightseagreen
5045 +lightskyblue
5046 +lightslategray
5047 +lightslategrey
5048 +lightsteelblue
5049 +lightyellow
5050 +lime
5051 +limegreen
5052 +linen
5053 +magenta
5054 +maroon
5055 +mediumaquamarine
5056 +mediumblue
5057 +mediumorchid
5058 +mediumpurple
5059 +mediumseagreen
5060 +mediumslateblue
5061 +mediumspringgreen
5062 +mediumturquoise
5063 +mediumvioletred
5064 +midnightblue
5065 +mintcream
5066 +mistyrose
5067 +moccasin
5068 +navajowhite
5069 +navy
5070 +oldlace
5071 +olive
5072 +olivedrab
5073 +orange
5074 +orangered
5075 +orchid
5076 +palegoldenrod
5077 +palegreen
5078 +paleturquoise
5079 +palevioletred
5080 +papayawhip
5081 +peachpuff
5082 +peru
5083 +pink
5084 +plum
5085 +powderblue
5086 +purple
5087 +red
5088 +rosybrown
5089 +royalblue
5090 +saddlebrown
5091 +salmon
5092 +sandybrown
5093 +seagreen
5094 +seashell
5095 +sienna
5096 +silver
5097 +skyblue
5098 +slateblue
5099 +slategray
5100 +slategrey
5101 +snow
5102 +springgreen
5103 +steelblue
5104 +tan
5105 +teal
5106 +thistle
5107 +tomato
5108 +turquoise
5109 +violet
5110 +wheat
5111 +white
5112 +whitesmoke
5113 +yellow
5114 +yellowgreen
5115 +#######################################
5117 +# Gradient units values
5119 +#######################################
5120 +userSpaceOnUse
5121 +objectBoundingBox
5122 diff --git filter/source/svg/units.cxx filter/source/svg/units.cxx
5123 new file mode 100644
5124 index 0000000..b4f9d94
5125 --- /dev/null
5126 +++ filter/source/svg/units.cxx
5127 @@ -0,0 +1,99 @@
5128 +/*************************************************************************
5130 + * OpenOffice.org - a multi-platform office productivity suite
5132 + * Author:
5133 + * Jan Holesovsky <kendy@suse.cz>
5134 + * Fridrich Strba <fridrich.strba@bluewin.ch>
5135 + * Thorsten Behrens <tbehrens@novell.com>
5137 + * Copyright (C) 2008, Novell Inc.
5139 + * The Contents of this file are made available subject to
5140 + * the terms of GNU Lesser General Public License Version 2.1.
5142 + ************************************************************************/
5144 +// MARKER(update_precomp.py): autogen include statement, do not remove
5145 +#include "precompiled_filter.hxx"
5147 +#include "units.hxx"
5148 +#include "gfxtypes.hxx"
5149 +#include "spirit_supplements.hxx"
5151 +#include <string.h>
5152 +#include <rtl/ustring.hxx>
5154 +#include <boost/bind.hpp>
5155 +// workaround. spirit uses INT_MAX.
5156 +#include <limits.h>
5157 +#include <boost/spirit.hpp>
5160 +namespace svgi
5163 +double convLength( double value, SvgUnit unit, const State& rState, char dir )
5165 + const double fBoxLen( dir=='h' ? rState.maViewBox.getWidth() :
5166 + (dir=='v' ? rState.maViewBox.getHeight() :
5167 + rState.maViewBox.getRange().getLength()));
5169 + // convert svg unit to internal coordinates ("pixel"). Since the
5170 + // OOo drawing layer is still largely integer-based, the initial
5171 + // viewport transformation includes a certain scale factor
5172 + double fRet(value);
5173 + switch ( unit )
5175 + case SVG_LENGTH_UNIT_CM: fRet *= 72.0/2.54; break;
5176 + case SVG_LENGTH_UNIT_IN: fRet *= 72.0; break;
5177 + case SVG_LENGTH_UNIT_MM: fRet *= 72.0/25.4; break;
5178 + case SVG_LENGTH_UNIT_PC: fRet *= 72.0/6.0; break;
5179 + case SVG_LENGTH_UNIT_USER:
5180 + case SVG_LENGTH_UNIT_PX: // no unit defaults to PX in svg,
5181 + // assume display to have 72DPI
5182 + case SVG_LENGTH_UNIT_PT: break;
5183 + case SVG_LENGTH_UNIT_EM: fRet *= rState.mnFontSize; break;
5184 + case SVG_LENGTH_UNIT_EX: fRet *= rState.mnFontSize / 2.0; break;
5185 + case SVG_LENGTH_UNIT_PERCENTAGE: fRet *= fBoxLen; break;
5186 + default: OSL_TRACE( "Unknown length type" ); break;
5189 + return fRet;
5192 +double convLength( const rtl::OUString& sValue, const State& rState, char dir )
5194 + using namespace ::boost::spirit;
5196 + rtl::OString aUTF8 = rtl::OUStringToOString( sValue,
5197 + RTL_TEXTENCODING_UTF8 );
5199 + double nVal=0.0;
5200 + SvgUnit eUnit=SVG_LENGTH_UNIT_PX;
5201 + const bool bRes = parse(aUTF8.getStr(),
5202 + // Begin grammar
5204 + real_p[assign_a(nVal)]
5205 + >> ( str_p("cm") [assign_a(eUnit,SVG_LENGTH_UNIT_CM)]
5206 + | str_p("em") [assign_a(eUnit,SVG_LENGTH_UNIT_EM)]
5207 + | str_p("ex") [assign_a(eUnit,SVG_LENGTH_UNIT_EX)]
5208 + | str_p("in") [assign_a(eUnit,SVG_LENGTH_UNIT_IN)]
5209 + | str_p("mm") [assign_a(eUnit,SVG_LENGTH_UNIT_MM)]
5210 + | str_p("pc") [assign_a(eUnit,SVG_LENGTH_UNIT_PC)]
5211 + | str_p("pt") [assign_a(eUnit,SVG_LENGTH_UNIT_PT)]
5212 + | str_p("px") [assign_a(eUnit,SVG_LENGTH_UNIT_PX)]
5213 + | str_p("%") [assign_a(eUnit,SVG_LENGTH_UNIT_PERCENTAGE)]
5214 + | str_p("") [assign_a(eUnit,SVG_LENGTH_UNIT_USER)]
5215 + | end_p)
5216 + ),
5217 + // End grammar
5218 + space_p).full;
5220 + if( !bRes )
5221 + return 0.0;
5223 + return convLength(nVal,eUnit,rState,dir);
5226 +} // namespace svgi
5227 diff --git filter/source/svg/units.hxx filter/source/svg/units.hxx
5228 new file mode 100644
5229 index 0000000..e48b5d5
5230 --- /dev/null
5231 +++ filter/source/svg/units.hxx
5232 @@ -0,0 +1,60 @@
5233 +/*************************************************************************
5235 + * OpenOffice.org - a multi-platform office productivity suite
5237 + * Author:
5238 + * Jan Holesovsky <kendy@suse.cz>
5239 + * Fridrich Strba <fridrich.strba@bluewin.ch>
5240 + * Thorsten Behrens <tbehrens@novell.com>
5242 + * Copyright (C) 2008, Novell Inc.
5244 + * The Contents of this file are made available subject to
5245 + * the terms of GNU Lesser General Public License Version 2.1.
5247 + ************************************************************************/
5249 +#ifndef INCLUDED_UNITS_HXX
5250 +#define INCLUDED_UNITS_HXX
5252 +#include <sal/config.h>
5254 +namespace rtl{ class OUString; }
5255 +namespace svgi
5257 + struct State;
5258 + enum SvgUnit
5260 + SVG_LENGTH_UNIT_CM,
5261 + SVG_LENGTH_UNIT_EM,
5262 + SVG_LENGTH_UNIT_EX,
5263 + SVG_LENGTH_UNIT_IN,
5264 + SVG_LENGTH_UNIT_MM,
5265 + SVG_LENGTH_UNIT_PC,
5266 + SVG_LENGTH_UNIT_PT,
5267 + SVG_LENGTH_UNIT_PX,
5268 + SVG_LENGTH_UNIT_PERCENTAGE,
5269 + SVG_LENGTH_UNIT_USER
5270 + };
5272 + /** return svg_length_t in 100th's of mm
5273 + @param fVal value to convert
5274 + @param unit unit the value is in
5275 + @param rState current state (needed for viewport dimensions etc.)
5276 + @param dir direction - either 'h' or 'v' for horizonal or vertical, resp.
5277 + */
5278 + double convLength( double fVal, SvgUnit unit, const State& rState, char dir );
5280 + /** return svg_length_t in 100th's of mm
5281 + @param sValue value to convert
5282 + @param rState current state (needed for viewport dimensions etc.)
5283 + @param dir direction - either 'h' or 'v' for horizonal or vertical, resp.
5284 + */
5285 + double convLength( const rtl::OUString& sValue, const State& rState, char dir );
5287 + inline double pt2mm(double fVal) { return fVal*25.4/72.0; }
5288 + inline double pt100thmm(double fVal) { return fVal*2540.0/72.0; }
5290 +} // namespace svgi
5292 +#endif