xref: /trunk/main/svgio/source/svgreader/svgdocumenthandler.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
1ddde725dSArmin Le Grand /**************************************************************
2ddde725dSArmin Le Grand  *
3ddde725dSArmin Le Grand  * Licensed to the Apache Software Foundation (ASF) under one
4ddde725dSArmin Le Grand  * or more contributor license agreements.  See the NOTICE file
5ddde725dSArmin Le Grand  * distributed with this work for additional information
6ddde725dSArmin Le Grand  * regarding copyright ownership.  The ASF licenses this file
7ddde725dSArmin Le Grand  * to you under the Apache License, Version 2.0 (the
8ddde725dSArmin Le Grand  * "License"); you may not use this file except in compliance
9ddde725dSArmin Le Grand  * with the License.  You may obtain a copy of the License at
10ddde725dSArmin Le Grand  *
11ddde725dSArmin Le Grand  *   http://www.apache.org/licenses/LICENSE-2.0
12ddde725dSArmin Le Grand  *
13ddde725dSArmin Le Grand  * Unless required by applicable law or agreed to in writing,
14ddde725dSArmin Le Grand  * software distributed under the License is distributed on an
15ddde725dSArmin Le Grand  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16ddde725dSArmin Le Grand  * KIND, either express or implied.  See the License for the
17ddde725dSArmin Le Grand  * specific language governing permissions and limitations
18ddde725dSArmin Le Grand  * under the License.
19ddde725dSArmin Le Grand  *
20ddde725dSArmin Le Grand  *************************************************************/
21ddde725dSArmin Le Grand 
22ddde725dSArmin Le Grand // MARKER(update_precomp.py): autogen include statement, do not remove
23ddde725dSArmin Le Grand #include "precompiled_svgio.hxx"
24ddde725dSArmin Le Grand 
25ddde725dSArmin Le Grand #include <svgio/svgreader/svgdocumenthandler.hxx>
26ddde725dSArmin Le Grand #include <svgio/svgreader/svgtoken.hxx>
27ddde725dSArmin Le Grand #include <svgio/svgreader/svgsvgnode.hxx>
28ddde725dSArmin Le Grand #include <svgio/svgreader/svggnode.hxx>
29ddde725dSArmin Le Grand #include <svgio/svgreader/svgnode.hxx>
30ddde725dSArmin Le Grand #include <svgio/svgreader/svgpathnode.hxx>
31ddde725dSArmin Le Grand #include <svgio/svgreader/svgrectnode.hxx>
32ddde725dSArmin Le Grand #include <svgio/svgreader/svggradientnode.hxx>
33ddde725dSArmin Le Grand #include <svgio/svgreader/svggradientstopnode.hxx>
34ddde725dSArmin Le Grand #include <svgio/svgreader/svgsymbolnode.hxx>
35ddde725dSArmin Le Grand #include <svgio/svgreader/svgusenode.hxx>
36ddde725dSArmin Le Grand #include <svgio/svgreader/svgcirclenode.hxx>
37ddde725dSArmin Le Grand #include <svgio/svgreader/svgellipsenode.hxx>
38ddde725dSArmin Le Grand #include <svgio/svgreader/svglinenode.hxx>
39ddde725dSArmin Le Grand #include <svgio/svgreader/svgpolynode.hxx>
40ddde725dSArmin Le Grand #include <svgio/svgreader/svgsymbolnode.hxx>
41ddde725dSArmin Le Grand #include <svgio/svgreader/svgtextnode.hxx>
42ddde725dSArmin Le Grand #include <svgio/svgreader/svgcharacternode.hxx>
43ddde725dSArmin Le Grand #include <svgio/svgreader/svgtspannode.hxx>
44ddde725dSArmin Le Grand #include <svgio/svgreader/svgtrefnode.hxx>
45ddde725dSArmin Le Grand #include <svgio/svgreader/svgtextpathnode.hxx>
46ddde725dSArmin Le Grand #include <svgio/svgreader/svgstylenode.hxx>
47ddde725dSArmin Le Grand #include <svgio/svgreader/svgimagenode.hxx>
48ddde725dSArmin Le Grand #include <svgio/svgreader/svgclippathnode.hxx>
49ddde725dSArmin Le Grand #include <svgio/svgreader/svgmasknode.hxx>
50ddde725dSArmin Le Grand #include <svgio/svgreader/svgmarkernode.hxx>
51ddde725dSArmin Le Grand #include <svgio/svgreader/svgpatternnode.hxx>
52025b0597SArmin Le Grand #include <svgio/svgreader/svgtitledescnode.hxx>
53ddde725dSArmin Le Grand 
54ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
55ddde725dSArmin Le Grand 
56ddde725dSArmin Le Grand using namespace com::sun::star;
57ddde725dSArmin Le Grand 
58ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
59ddde725dSArmin Le Grand 
60ddde725dSArmin Le Grand namespace
61ddde725dSArmin Le Grand {
whiteSpaceHandling(svgio::svgreader::SvgNode * pNode,svgio::svgreader::SvgCharacterNode * pLast)62ddde725dSArmin Le Grand     svgio::svgreader::SvgCharacterNode* whiteSpaceHandling(svgio::svgreader::SvgNode* pNode, svgio::svgreader::SvgCharacterNode* pLast)
63ddde725dSArmin Le Grand     {
64ddde725dSArmin Le Grand         if(pNode)
65ddde725dSArmin Le Grand         {
66ddde725dSArmin Le Grand             const svgio::svgreader::SvgNodeVector& rChilds = pNode->getChildren();
67ddde725dSArmin Le Grand             const sal_uInt32 nCount(rChilds.size());
68ddde725dSArmin Le Grand 
69ddde725dSArmin Le Grand             for(sal_uInt32 a(0); a < nCount; a++)
70ddde725dSArmin Le Grand             {
71ddde725dSArmin Le Grand                 svgio::svgreader::SvgNode* pCandidate = rChilds[a];
72ddde725dSArmin Le Grand 
73ddde725dSArmin Le Grand                 if(pCandidate)
74ddde725dSArmin Le Grand                 {
75ddde725dSArmin Le Grand                     switch(pCandidate->getType())
76ddde725dSArmin Le Grand                     {
77ddde725dSArmin Le Grand                         case svgio::svgreader::SVGTokenCharacter:
78ddde725dSArmin Le Grand                         {
79ddde725dSArmin Le Grand                             // clean whitespace in text span
80ddde725dSArmin Le Grand                             svgio::svgreader::SvgCharacterNode* pCharNode = static_cast< svgio::svgreader::SvgCharacterNode* >(pCandidate);
81ddde725dSArmin Le Grand                             pCharNode->whiteSpaceHandling();
82ddde725dSArmin Le Grand 
83ddde725dSArmin Le Grand                             // pCharNode may have lost all text. If that's the case, ignore
84ddde725dSArmin Le Grand                             // as invalid character node
85ddde725dSArmin Le Grand                             if(pCharNode->getText().getLength())
86ddde725dSArmin Le Grand                             {
87ddde725dSArmin Le Grand                                 if(pLast)
88ddde725dSArmin Le Grand                                 {
8986d02030SArmin Le Grand                                     bool bAddGap(true);
9086d02030SArmin Le Grand                                     static bool bNoGapsForBaselineShift(true);
9186d02030SArmin Le Grand 
9286d02030SArmin Le Grand                                     if(bNoGapsForBaselineShift)
9386d02030SArmin Le Grand                                     {
9486d02030SArmin Le Grand                                         // With this option a baseline shift between two char parts ('words')
9586d02030SArmin Le Grand                                         // will not add a space 'gap' to the end of the (non-last) word. This
9686d02030SArmin Le Grand                                         // seems to be the standard behaviour, see last bugdoc attached #122524#
9786d02030SArmin Le Grand                                         const svgio::svgreader::SvgStyleAttributes* pStyleLast = pLast->getSvgStyleAttributes();
9886d02030SArmin Le Grand                                         const svgio::svgreader::SvgStyleAttributes* pStyleCurrent = pCandidate->getSvgStyleAttributes();
9986d02030SArmin Le Grand 
10086d02030SArmin Le Grand                                         if(pStyleLast && pStyleCurrent && pStyleLast->getBaselineShift() != pStyleCurrent->getBaselineShift())
10186d02030SArmin Le Grand                                         {
10286d02030SArmin Le Grand                                             bAddGap = false;
10386d02030SArmin Le Grand                                         }
10486d02030SArmin Le Grand                                     }
10586d02030SArmin Le Grand 
106ddde725dSArmin Le Grand                                     // add in-between whitespace (single space) to last
107ddde725dSArmin Le Grand                                     // known character node
10886d02030SArmin Le Grand                                     if(bAddGap)
10986d02030SArmin Le Grand                                     {
110ddde725dSArmin Le Grand                                         pLast->addGap();
111ddde725dSArmin Le Grand                                     }
11286d02030SArmin Le Grand                                 }
113ddde725dSArmin Le Grand 
114*dcaf07f7SJohn Bampton                                 // remember new last corrected character node
115ddde725dSArmin Le Grand                                 pLast = pCharNode;
116ddde725dSArmin Le Grand                             }
117ddde725dSArmin Le Grand                             break;
118ddde725dSArmin Le Grand                         }
119ddde725dSArmin Le Grand                         case svgio::svgreader::SVGTokenTspan:
120ddde725dSArmin Le Grand                         case svgio::svgreader::SVGTokenTextPath:
121ddde725dSArmin Le Grand                         case svgio::svgreader::SVGTokenTref:
122ddde725dSArmin Le Grand                         {
123ddde725dSArmin Le Grand                             // recursively clean whitespaces in subhierarchy
124ddde725dSArmin Le Grand                             pLast = whiteSpaceHandling(pCandidate, pLast);
125ddde725dSArmin Le Grand                             break;
126ddde725dSArmin Le Grand                         }
127ddde725dSArmin Le Grand                         default:
128ddde725dSArmin Le Grand                         {
129ddde725dSArmin Le Grand                             OSL_ENSURE(false, "Unexpected token inside SVGTokenText (!)");
130ddde725dSArmin Le Grand                             break;
131ddde725dSArmin Le Grand                         }
132ddde725dSArmin Le Grand                     }
133ddde725dSArmin Le Grand                 }
134ddde725dSArmin Le Grand             }
135ddde725dSArmin Le Grand         }
136ddde725dSArmin Le Grand 
137ddde725dSArmin Le Grand         return pLast;
138ddde725dSArmin Le Grand     }
139ddde725dSArmin Le Grand }
140ddde725dSArmin Le Grand 
141ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
142ddde725dSArmin Le Grand 
143ddde725dSArmin Le Grand namespace svgio
144ddde725dSArmin Le Grand {
145ddde725dSArmin Le Grand     namespace svgreader
146ddde725dSArmin Le Grand     {
SvgDocHdl(const rtl::OUString & aAbsolutePath)147ddde725dSArmin Le Grand         SvgDocHdl::SvgDocHdl(const rtl::OUString& aAbsolutePath)
148ddde725dSArmin Le Grand         :   maDocument(aAbsolutePath),
1493aaca8a3SArmin Le Grand             mpTarget(0),
1503aaca8a3SArmin Le Grand             maCssContents()
151ddde725dSArmin Le Grand         {
152ddde725dSArmin Le Grand         }
153ddde725dSArmin Le Grand 
~SvgDocHdl()154ddde725dSArmin Le Grand         SvgDocHdl::~SvgDocHdl()
155ddde725dSArmin Le Grand         {
156ddde725dSArmin Le Grand #ifdef DBG_UTIL
157ddde725dSArmin Le Grand             if(mpTarget)
158ddde725dSArmin Le Grand             {
159ddde725dSArmin Le Grand                 OSL_ENSURE(false, "SvgDocHdl destructed with active target (!)");
160ddde725dSArmin Le Grand                 delete mpTarget;
161ddde725dSArmin Le Grand             }
1623aaca8a3SArmin Le Grand             OSL_ENSURE(!maCssContents.size(), "SvgDocHdl destructed with active css style stack entry (!)");
163ddde725dSArmin Le Grand #endif
164ddde725dSArmin Le Grand         }
165ddde725dSArmin Le Grand 
startDocument()166ddde725dSArmin Le Grand         void SvgDocHdl::startDocument(  ) throw (xml::sax::SAXException, uno::RuntimeException)
167ddde725dSArmin Le Grand         {
168ddde725dSArmin Le Grand             OSL_ENSURE(!mpTarget, "Already a target at document start (!)");
1693aaca8a3SArmin Le Grand             OSL_ENSURE(!maCssContents.size(), "SvgDocHdl startDocument with active css style stack entry (!)");
170ddde725dSArmin Le Grand         }
171ddde725dSArmin Le Grand 
endDocument()172ddde725dSArmin Le Grand         void SvgDocHdl::endDocument(  ) throw (xml::sax::SAXException, uno::RuntimeException)
173ddde725dSArmin Le Grand         {
174ddde725dSArmin Le Grand             OSL_ENSURE(!mpTarget, "Still a target at document end (!)");
1753aaca8a3SArmin Le Grand             OSL_ENSURE(!maCssContents.size(), "SvgDocHdl endDocument with active css style stack entry (!)");
176ddde725dSArmin Le Grand         }
177ddde725dSArmin Le Grand 
startElement(const::rtl::OUString & aName,const uno::Reference<xml::sax::XAttributeList> & xAttribs)178ddde725dSArmin Le Grand         void SvgDocHdl::startElement( const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) throw (xml::sax::SAXException, uno::RuntimeException)
179ddde725dSArmin Le Grand         {
180ddde725dSArmin Le Grand             if(aName.getLength())
181ddde725dSArmin Le Grand             {
18252cb04b8SArmin Le Grand                 const SVGToken aSVGToken(StrToSVGToken(aName, false));
183ddde725dSArmin Le Grand 
184ddde725dSArmin Le Grand                 switch(aSVGToken)
185ddde725dSArmin Le Grand                 {
186ddde725dSArmin Le Grand                     /// structural elements
187ddde725dSArmin Le Grand                     case SVGTokenSymbol:
188ddde725dSArmin Le Grand                     {
189ddde725dSArmin Le Grand                         /// new basic node for Symbol. Content gets scanned, but
190ddde725dSArmin Le Grand                         /// will not be decomposed (see SvgNode::decomposeSvgNode and bReferenced)
191ddde725dSArmin Le Grand                         mpTarget = new SvgSymbolNode(maDocument, mpTarget);
192ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
193ddde725dSArmin Le Grand                         break;
194ddde725dSArmin Le Grand                     }
195ddde725dSArmin Le Grand                     case SVGTokenDefs:
196ddde725dSArmin Le Grand                     case SVGTokenG:
197ddde725dSArmin Le Grand                     {
198ddde725dSArmin Le Grand                         /// new node for Defs/G
199ddde725dSArmin Le Grand                         mpTarget = new SvgGNode(aSVGToken, maDocument, mpTarget);
200ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
201ddde725dSArmin Le Grand                         break;
202ddde725dSArmin Le Grand                     }
203ddde725dSArmin Le Grand                     case SVGTokenSvg:
204ddde725dSArmin Le Grand                     {
205ddde725dSArmin Le Grand                         /// new node for Svg
206ddde725dSArmin Le Grand                         mpTarget = new SvgSvgNode(maDocument, mpTarget);
207ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
208ddde725dSArmin Le Grand                         break;
209ddde725dSArmin Le Grand                     }
210ddde725dSArmin Le Grand                     case SVGTokenUse:
211ddde725dSArmin Le Grand                     {
212ddde725dSArmin Le Grand                         /// new node for Use
213ddde725dSArmin Le Grand                         mpTarget = new SvgUseNode(maDocument, mpTarget);
214ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
215ddde725dSArmin Le Grand                         break;
216ddde725dSArmin Le Grand                     }
217ddde725dSArmin Le Grand 
218ddde725dSArmin Le Grand                     /// shape elements
219ddde725dSArmin Le Grand                     case SVGTokenCircle:
220ddde725dSArmin Le Grand                     {
221ddde725dSArmin Le Grand                         /// new node for Circle
222ddde725dSArmin Le Grand                         mpTarget = new SvgCircleNode(maDocument, mpTarget);
223ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
224ddde725dSArmin Le Grand                         break;
225ddde725dSArmin Le Grand                     }
226ddde725dSArmin Le Grand                     case SVGTokenEllipse:
227ddde725dSArmin Le Grand                     {
228ddde725dSArmin Le Grand                         /// new node for Ellipse
229ddde725dSArmin Le Grand                         mpTarget = new SvgEllipseNode(maDocument, mpTarget);
230ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
231ddde725dSArmin Le Grand                         break;
232ddde725dSArmin Le Grand                     }
233ddde725dSArmin Le Grand                     case SVGTokenLine:
234ddde725dSArmin Le Grand                     {
235ddde725dSArmin Le Grand                         /// new node for Line
236ddde725dSArmin Le Grand                         mpTarget = new SvgLineNode(maDocument, mpTarget);
237ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
238ddde725dSArmin Le Grand                         break;
239ddde725dSArmin Le Grand                     }
240ddde725dSArmin Le Grand                     case SVGTokenPath:
241ddde725dSArmin Le Grand                     {
242ddde725dSArmin Le Grand                         /// new node for Path
243ddde725dSArmin Le Grand                         mpTarget = new SvgPathNode(maDocument, mpTarget);
244ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
245ddde725dSArmin Le Grand                         break;
246ddde725dSArmin Le Grand                     }
247ddde725dSArmin Le Grand                     case SVGTokenPolygon:
248ddde725dSArmin Le Grand                     {
249ddde725dSArmin Le Grand                         /// new node for Polygon
250ddde725dSArmin Le Grand                         mpTarget = new SvgPolyNode(maDocument, mpTarget, false);
251ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
252ddde725dSArmin Le Grand                         break;
253ddde725dSArmin Le Grand                     }
254ddde725dSArmin Le Grand                     case SVGTokenPolyline:
255ddde725dSArmin Le Grand                     {
256ddde725dSArmin Le Grand                         /// new node for Polyline
257ddde725dSArmin Le Grand                         mpTarget = new SvgPolyNode(maDocument, mpTarget, true);
258ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
259ddde725dSArmin Le Grand                         break;
260ddde725dSArmin Le Grand                     }
261ddde725dSArmin Le Grand                     case SVGTokenRect:
262ddde725dSArmin Le Grand                     {
263ddde725dSArmin Le Grand                         /// new node for Rect
264ddde725dSArmin Le Grand                         mpTarget = new SvgRectNode(maDocument, mpTarget);
265ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
266ddde725dSArmin Le Grand                         break;
267ddde725dSArmin Le Grand                     }
268ddde725dSArmin Le Grand                     case SVGTokenImage:
269ddde725dSArmin Le Grand                     {
270ddde725dSArmin Le Grand                         /// new node for Image
271ddde725dSArmin Le Grand                         mpTarget = new SvgImageNode(maDocument, mpTarget);
272ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
273ddde725dSArmin Le Grand                         break;
274ddde725dSArmin Le Grand                     }
275ddde725dSArmin Le Grand 
276025b0597SArmin Le Grand                     /// title and description
277025b0597SArmin Le Grand                     case SVGTokenTitle:
278025b0597SArmin Le Grand                     case SVGTokenDesc:
279025b0597SArmin Le Grand                     {
280025b0597SArmin Le Grand                         /// new node for Title and/or Desc
281025b0597SArmin Le Grand                         mpTarget = new SvgTitleDescNode(aSVGToken, maDocument, mpTarget);
282025b0597SArmin Le Grand                         break;
283025b0597SArmin Le Grand                     }
284025b0597SArmin Le Grand 
285ddde725dSArmin Le Grand                     /// gradients
286ddde725dSArmin Le Grand                     case SVGTokenLinearGradient:
287ddde725dSArmin Le Grand                     case SVGTokenRadialGradient:
288ddde725dSArmin Le Grand                     {
289ddde725dSArmin Le Grand                         mpTarget = new SvgGradientNode(aSVGToken, maDocument, mpTarget);
290ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
291ddde725dSArmin Le Grand                         break;
292ddde725dSArmin Le Grand                     }
293ddde725dSArmin Le Grand 
294ddde725dSArmin Le Grand                     /// gradient stops
295ddde725dSArmin Le Grand                     case SVGTokenStop:
296ddde725dSArmin Le Grand                     {
297ddde725dSArmin Le Grand                         mpTarget = new SvgGradientStopNode(maDocument, mpTarget);
298ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
299ddde725dSArmin Le Grand                         break;
300ddde725dSArmin Le Grand                     }
301ddde725dSArmin Le Grand 
302ddde725dSArmin Le Grand                     /// text
303ddde725dSArmin Le Grand                     case SVGTokenText:
304ddde725dSArmin Le Grand                     {
305ddde725dSArmin Le Grand                         mpTarget = new SvgTextNode(maDocument, mpTarget);
306ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
307ddde725dSArmin Le Grand                         break;
308ddde725dSArmin Le Grand                     }
309ddde725dSArmin Le Grand                     case SVGTokenTspan:
310ddde725dSArmin Le Grand                     {
311ddde725dSArmin Le Grand                         mpTarget = new SvgTspanNode(maDocument, mpTarget);
312ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
313ddde725dSArmin Le Grand                         break;
314ddde725dSArmin Le Grand                     }
315ddde725dSArmin Le Grand                     case SVGTokenTref:
316ddde725dSArmin Le Grand                     {
317ddde725dSArmin Le Grand                         mpTarget = new SvgTrefNode(maDocument, mpTarget);
318ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
319ddde725dSArmin Le Grand                         break;
320ddde725dSArmin Le Grand                     }
321ddde725dSArmin Le Grand                     case SVGTokenTextPath:
322ddde725dSArmin Le Grand                     {
323ddde725dSArmin Le Grand                         mpTarget = new SvgTextPathNode(maDocument, mpTarget);
324ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
325ddde725dSArmin Le Grand                         break;
326ddde725dSArmin Le Grand                     }
327ddde725dSArmin Le Grand 
328ddde725dSArmin Le Grand                     /// styles (as stylesheets)
329ddde725dSArmin Le Grand                     case SVGTokenStyle:
330ddde725dSArmin Le Grand                     {
3313aaca8a3SArmin Le Grand                         SvgStyleNode* pNew = new SvgStyleNode(maDocument, mpTarget);
3323aaca8a3SArmin Le Grand                         mpTarget = pNew;
33366c4a92eSArmin Le Grand                         const sal_uInt32 nAttributes(xAttribs->getLength());
33466c4a92eSArmin Le Grand 
33566c4a92eSArmin Le Grand                         if(0 == nAttributes)
33666c4a92eSArmin Le Grand                         {
33766c4a92eSArmin Le Grand                             // #125326# no attributes, thus also no type="text/css". This is allowed to be missing,
33866c4a92eSArmin Le Grand                             // thus do mark this style as CssStyle. This is required to read the contained
33966c4a92eSArmin Le Grand                             // text (which defines the css style)
34066c4a92eSArmin Le Grand                             pNew->setTextCss(true);
34166c4a92eSArmin Le Grand                         }
34266c4a92eSArmin Le Grand                         else
34366c4a92eSArmin Le Grand                         {
34466c4a92eSArmin Le Grand                             // #125326# there are attributes, read them. This will set isTextCss to true if
34566c4a92eSArmin Le Grand                             // a type="text/css" is contained as exact match, else not
346ddde725dSArmin Le Grand                             mpTarget->parseAttributes(xAttribs);
34766c4a92eSArmin Le Grand                         }
3483aaca8a3SArmin Le Grand 
3493aaca8a3SArmin Le Grand                         if(pNew->isTextCss())
3503aaca8a3SArmin Le Grand                         {
35166c4a92eSArmin Le Grand                             // if it is a Css style, allow reading text between the start and end tag (see
35266c4a92eSArmin Le Grand                             // SvgDocHdl::characters for details)
3533aaca8a3SArmin Le Grand                             maCssContents.push_back(rtl::OUString());
3543aaca8a3SArmin Le Grand                         }
355ddde725dSArmin Le Grand                         break;
356ddde725dSArmin Le Grand                     }
357ddde725dSArmin Le Grand 
358ddde725dSArmin Le Grand                     /// structural elements clip-path and mask. Content gets scanned, but
359ddde725dSArmin Le Grand                     /// will not be decomposed (see SvgNode::decomposeSvgNode and bReferenced)
360ddde725dSArmin Le Grand                     case SVGTokenClipPathNode:
361ddde725dSArmin Le Grand                     {
362ddde725dSArmin Le Grand                         /// new node for ClipPath
363ddde725dSArmin Le Grand                         mpTarget = new SvgClipPathNode(maDocument, mpTarget);
364ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
365ddde725dSArmin Le Grand                         break;
366ddde725dSArmin Le Grand                     }
367ddde725dSArmin Le Grand                     case SVGTokenMask:
368ddde725dSArmin Le Grand                     {
369ddde725dSArmin Le Grand                         /// new node for Mask
370ddde725dSArmin Le Grand                         mpTarget = new SvgMaskNode(maDocument, mpTarget);
371ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
372ddde725dSArmin Le Grand                         break;
373ddde725dSArmin Le Grand                     }
374ddde725dSArmin Le Grand 
375ddde725dSArmin Le Grand                     /// structural element marker
376ddde725dSArmin Le Grand                     case SVGTokenMarker:
377ddde725dSArmin Le Grand                     {
378ddde725dSArmin Le Grand                         /// new node for marker
379ddde725dSArmin Le Grand                         mpTarget = new SvgMarkerNode(maDocument, mpTarget);
380ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
381ddde725dSArmin Le Grand                         break;
382ddde725dSArmin Le Grand                     }
383ddde725dSArmin Le Grand 
384ddde725dSArmin Le Grand                     /// structural element pattern
385ddde725dSArmin Le Grand                     case SVGTokenPattern:
386ddde725dSArmin Le Grand                     {
387ddde725dSArmin Le Grand                         /// new node for pattern
388ddde725dSArmin Le Grand                         mpTarget = new SvgPatternNode(maDocument, mpTarget);
389ddde725dSArmin Le Grand                         mpTarget->parseAttributes(xAttribs);
390ddde725dSArmin Le Grand                         break;
391ddde725dSArmin Le Grand                     }
392ddde725dSArmin Le Grand 
393ddde725dSArmin Le Grand                     default:
394ddde725dSArmin Le Grand                     {
395ddde725dSArmin Le Grand                         /// invalid token, ignore
396ddde725dSArmin Le Grand #ifdef DBG_UTIL
397ddde725dSArmin Le Grand                         myAssert(
398ddde725dSArmin Le Grand                             rtl::OUString::createFromAscii("Unknown Base SvgToken <") +
399ddde725dSArmin Le Grand                             aName +
400ddde725dSArmin Le Grand                             rtl::OUString::createFromAscii("> (!)"));
401ddde725dSArmin Le Grand #endif
402ddde725dSArmin Le Grand                         break;
403ddde725dSArmin Le Grand                     }
404ddde725dSArmin Le Grand                 }
405ddde725dSArmin Le Grand             }
406ddde725dSArmin Le Grand         }
407ddde725dSArmin Le Grand 
endElement(const::rtl::OUString & aName)408ddde725dSArmin Le Grand         void SvgDocHdl::endElement( const ::rtl::OUString& aName ) throw (xml::sax::SAXException, uno::RuntimeException)
409ddde725dSArmin Le Grand         {
410ddde725dSArmin Le Grand             if(aName.getLength())
411ddde725dSArmin Le Grand             {
41252cb04b8SArmin Le Grand                 const SVGToken aSVGToken(StrToSVGToken(aName, false));
413ddde725dSArmin Le Grand                 SvgNode* pWhitespaceCheck(SVGTokenText == aSVGToken ? mpTarget : 0);
4143aaca8a3SArmin Le Grand                 SvgStyleNode* pCssStyle(SVGTokenStyle == aSVGToken ? static_cast< SvgStyleNode* >(mpTarget) : 0);
415025b0597SArmin Le Grand                 SvgTitleDescNode* pSvgTitleDescNode(SVGTokenTitle == aSVGToken || SVGTokenDesc == aSVGToken ? static_cast< SvgTitleDescNode* >(mpTarget) : 0);
416ddde725dSArmin Le Grand 
417ddde725dSArmin Le Grand                 switch(aSVGToken)
418ddde725dSArmin Le Grand                 {
419ddde725dSArmin Le Grand                     /// valid tokens for which a new one was created
420ddde725dSArmin Le Grand 
421ddde725dSArmin Le Grand                     /// structural elements
422ddde725dSArmin Le Grand                     case SVGTokenDefs:
423ddde725dSArmin Le Grand                     case SVGTokenG:
424ddde725dSArmin Le Grand                     case SVGTokenSvg:
425ddde725dSArmin Le Grand                     case SVGTokenSymbol:
426ddde725dSArmin Le Grand                     case SVGTokenUse:
427ddde725dSArmin Le Grand 
428ddde725dSArmin Le Grand                     /// shape elements
429ddde725dSArmin Le Grand                     case SVGTokenCircle:
430ddde725dSArmin Le Grand                     case SVGTokenEllipse:
431ddde725dSArmin Le Grand                     case SVGTokenLine:
432ddde725dSArmin Le Grand                     case SVGTokenPath:
433ddde725dSArmin Le Grand                     case SVGTokenPolygon:
434ddde725dSArmin Le Grand                     case SVGTokenPolyline:
435ddde725dSArmin Le Grand                     case SVGTokenRect:
436ddde725dSArmin Le Grand                     case SVGTokenImage:
437ddde725dSArmin Le Grand 
438025b0597SArmin Le Grand                     /// title and description
439025b0597SArmin Le Grand                     case SVGTokenTitle:
440025b0597SArmin Le Grand                     case SVGTokenDesc:
441025b0597SArmin Le Grand 
442ddde725dSArmin Le Grand                     /// gradients
443ddde725dSArmin Le Grand                     case SVGTokenLinearGradient:
444ddde725dSArmin Le Grand                     case SVGTokenRadialGradient:
445ddde725dSArmin Le Grand 
446ddde725dSArmin Le Grand                     /// gradient stops
447ddde725dSArmin Le Grand                     case SVGTokenStop:
448ddde725dSArmin Le Grand 
449ddde725dSArmin Le Grand                     /// text
450ddde725dSArmin Le Grand                     case SVGTokenText:
451ddde725dSArmin Le Grand                     case SVGTokenTspan:
452ddde725dSArmin Le Grand                     case SVGTokenTextPath:
453ddde725dSArmin Le Grand                     case SVGTokenTref:
454ddde725dSArmin Le Grand 
455ddde725dSArmin Le Grand                     /// styles (as stylesheets)
456ddde725dSArmin Le Grand                     case SVGTokenStyle:
457ddde725dSArmin Le Grand 
458ddde725dSArmin Le Grand                     /// structural elements clip-path and mask
459ddde725dSArmin Le Grand                     case SVGTokenClipPathNode:
460ddde725dSArmin Le Grand                     case SVGTokenMask:
461ddde725dSArmin Le Grand 
462ddde725dSArmin Le Grand                     /// structural element marker
463ddde725dSArmin Le Grand                     case SVGTokenMarker:
464ddde725dSArmin Le Grand 
465ddde725dSArmin Le Grand                     /// structural element pattern
466ddde725dSArmin Le Grand                     case SVGTokenPattern:
467ddde725dSArmin Le Grand 
468ddde725dSArmin Le Grand                     /// content handling after parsing
469ddde725dSArmin Le Grand                     {
470ddde725dSArmin Le Grand                         if(mpTarget)
471ddde725dSArmin Le Grand                         {
472ddde725dSArmin Le Grand                             if(!mpTarget->getParent())
473ddde725dSArmin Le Grand                             {
474ddde725dSArmin Le Grand                                 // last element closing, save this tree
475ddde725dSArmin Le Grand                                 maDocument.appendNode(mpTarget);
476ddde725dSArmin Le Grand                             }
477ddde725dSArmin Le Grand 
478ddde725dSArmin Le Grand                             mpTarget = const_cast< SvgNode* >(mpTarget->getParent());
479ddde725dSArmin Le Grand                         }
480ddde725dSArmin Le Grand                         else
481ddde725dSArmin Le Grand                         {
482ddde725dSArmin Le Grand                             OSL_ENSURE(false, "Closing token, but no context (!)");
483ddde725dSArmin Le Grand                         }
484ddde725dSArmin Le Grand                         break;
485ddde725dSArmin Le Grand                     }
486ddde725dSArmin Le Grand                     default:
487ddde725dSArmin Le Grand                     {
488ddde725dSArmin Le Grand                         /// invalid token, ignore
489ddde725dSArmin Le Grand                     }
490ddde725dSArmin Le Grand                 }
491ddde725dSArmin Le Grand 
492025b0597SArmin Le Grand                 if(pSvgTitleDescNode && mpTarget)
493025b0597SArmin Le Grand                 {
494025b0597SArmin Le Grand                     const rtl::OUString aText(pSvgTitleDescNode->getText());
495025b0597SArmin Le Grand 
496025b0597SArmin Le Grand                     if(aText.getLength())
497025b0597SArmin Le Grand                     {
498025b0597SArmin Le Grand                         if(SVGTokenTitle == aSVGToken)
499025b0597SArmin Le Grand                         {
500025b0597SArmin Le Grand                             mpTarget->parseAttribute(getStrTitle(), aSVGToken, aText);
501025b0597SArmin Le Grand                         }
502025b0597SArmin Le Grand                         else // if(SVGTokenDesc == aSVGToken)
503025b0597SArmin Le Grand                         {
504025b0597SArmin Le Grand                             mpTarget->parseAttribute(getStrDesc(), aSVGToken, aText);
505025b0597SArmin Le Grand                         }
506025b0597SArmin Le Grand                     }
507025b0597SArmin Le Grand                 }
508025b0597SArmin Le Grand 
5093aaca8a3SArmin Le Grand                 if(pCssStyle && pCssStyle->isTextCss())
5103aaca8a3SArmin Le Grand                 {
5113aaca8a3SArmin Le Grand                     // css style parsing
5123aaca8a3SArmin Le Grand                     if(maCssContents.size())
5133aaca8a3SArmin Le Grand                     {
5143aaca8a3SArmin Le Grand                         // need to interpret css styles and remember them as StyleSheets
51506420f18SArmin Le Grand                         // #125325# Caution! the Css content may contain block comments
51606420f18SArmin Le Grand                         // (see http://www.w3.org/wiki/CSS_basics#CSS_comments). These need
51706420f18SArmin Le Grand                         // to be removed first
51806420f18SArmin Le Grand                         const rtl::OUString aCommentFreeSource(removeBlockComments(*(maCssContents.end() - 1)));
51906420f18SArmin Le Grand 
52006420f18SArmin Le Grand                         if(aCommentFreeSource.getLength())
52106420f18SArmin Le Grand                         {
52206420f18SArmin Le Grand                             pCssStyle->addCssStyleSheet(aCommentFreeSource);
52306420f18SArmin Le Grand                         }
52406420f18SArmin Le Grand 
5253aaca8a3SArmin Le Grand                         maCssContents.pop_back();
5263aaca8a3SArmin Le Grand                     }
5273aaca8a3SArmin Le Grand                     else
5283aaca8a3SArmin Le Grand                     {
5293aaca8a3SArmin Le Grand                         OSL_ENSURE(false, "Closing CssStyle, but no collector string on stack (!)");
5303aaca8a3SArmin Le Grand                     }
5313aaca8a3SArmin Le Grand                 }
5323aaca8a3SArmin Le Grand 
533ddde725dSArmin Le Grand                 if(pWhitespaceCheck)
534ddde725dSArmin Le Grand                 {
535ddde725dSArmin Le Grand                     // cleanup read strings
536ddde725dSArmin Le Grand                     whiteSpaceHandling(pWhitespaceCheck, 0);
537ddde725dSArmin Le Grand                 }
538ddde725dSArmin Le Grand             }
539ddde725dSArmin Le Grand         }
540ddde725dSArmin Le Grand 
characters(const::rtl::OUString & aChars)541ddde725dSArmin Le Grand         void SvgDocHdl::characters( const ::rtl::OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException)
542ddde725dSArmin Le Grand         {
543ddde725dSArmin Le Grand             const sal_uInt32 nLength(aChars.getLength());
544ddde725dSArmin Le Grand 
545025b0597SArmin Le Grand             if(mpTarget && nLength)
546ddde725dSArmin Le Grand             {
547ddde725dSArmin Le Grand                 switch(mpTarget->getType())
548ddde725dSArmin Le Grand                 {
549ddde725dSArmin Le Grand                     case SVGTokenText:
550ddde725dSArmin Le Grand                     case SVGTokenTspan:
551ddde725dSArmin Le Grand                     case SVGTokenTextPath:
552ddde725dSArmin Le Grand                     {
553ddde725dSArmin Le Grand                         const SvgNodeVector& rChilds = mpTarget->getChildren();
554ddde725dSArmin Le Grand                         SvgCharacterNode* pTarget = 0;
555ddde725dSArmin Le Grand 
556ddde725dSArmin Le Grand                         if(rChilds.size())
557ddde725dSArmin Le Grand                         {
558ddde725dSArmin Le Grand                             pTarget = dynamic_cast< SvgCharacterNode* >(rChilds[rChilds.size() - 1]);
559ddde725dSArmin Le Grand                         }
560ddde725dSArmin Le Grand 
561ddde725dSArmin Le Grand                         if(pTarget)
562ddde725dSArmin Le Grand                         {
563ddde725dSArmin Le Grand                             // concatenate to current character span
564ddde725dSArmin Le Grand                             pTarget->concatenate(aChars);
565ddde725dSArmin Le Grand                         }
566ddde725dSArmin Le Grand                         else
567ddde725dSArmin Le Grand                         {
568ddde725dSArmin Le Grand                             // add character span as simplified tspan (no arguments)
569ddde725dSArmin Le Grand                             // as direct child of SvgTextNode/SvgTspanNode/SvgTextPathNode
570ddde725dSArmin Le Grand                             new SvgCharacterNode(maDocument, mpTarget, aChars);
571ddde725dSArmin Le Grand                         }
572ddde725dSArmin Le Grand                         break;
573ddde725dSArmin Le Grand                     }
574ddde725dSArmin Le Grand                     case SVGTokenStyle:
575ddde725dSArmin Le Grand                     {
576ddde725dSArmin Le Grand                         SvgStyleNode& rSvgStyleNode = static_cast< SvgStyleNode& >(*mpTarget);
577ddde725dSArmin Le Grand 
578ddde725dSArmin Le Grand                         if(rSvgStyleNode.isTextCss())
579ddde725dSArmin Le Grand                         {
5803aaca8a3SArmin Le Grand                             // collect characters for css style
5813aaca8a3SArmin Le Grand                             if(maCssContents.size())
5823aaca8a3SArmin Le Grand                             {
583ddde725dSArmin Le Grand                                 const ::rtl::OUString aTrimmedChars(aChars.trim());
584ddde725dSArmin Le Grand 
585ddde725dSArmin Le Grand                                 if(aTrimmedChars.getLength())
586ddde725dSArmin Le Grand                                 {
5873aaca8a3SArmin Le Grand                                     std::vector< rtl::OUString >::iterator aString(maCssContents.end() - 1);
5883aaca8a3SArmin Le Grand                                     (*aString) += aTrimmedChars;
5893aaca8a3SArmin Le Grand                                 }
5903aaca8a3SArmin Le Grand                             }
5913aaca8a3SArmin Le Grand                             else
5923aaca8a3SArmin Le Grand                             {
5933aaca8a3SArmin Le Grand                                 OSL_ENSURE(false, "Closing CssStyle, but no collector string on stack (!)");
594ddde725dSArmin Le Grand                             }
595ddde725dSArmin Le Grand                         }
596ddde725dSArmin Le Grand                         break;
597ddde725dSArmin Le Grand                     }
598025b0597SArmin Le Grand                     case SVGTokenTitle:
599025b0597SArmin Le Grand                     case SVGTokenDesc:
600025b0597SArmin Le Grand                     {
601025b0597SArmin Le Grand                         SvgTitleDescNode& rSvgTitleDescNode = static_cast< SvgTitleDescNode& >(*mpTarget);
602025b0597SArmin Le Grand 
603025b0597SArmin Le Grand                         // add text directly to SvgTitleDescNode
604025b0597SArmin Le Grand                         rSvgTitleDescNode.concatenate(aChars);
605025b0597SArmin Le Grand                         break;
606025b0597SArmin Le Grand                     }
607ddde725dSArmin Le Grand                     default:
608ddde725dSArmin Le Grand                     {
609ddde725dSArmin Le Grand                         // characters not used by a known node
610ddde725dSArmin Le Grand                         break;
611ddde725dSArmin Le Grand                     }
612ddde725dSArmin Le Grand                 }
613ddde725dSArmin Le Grand             }
614ddde725dSArmin Le Grand         }
615ddde725dSArmin Le Grand 
ignorableWhitespace(const::rtl::OUString &)616e2bf1e9dSArmin Le Grand         void SvgDocHdl::ignorableWhitespace(const ::rtl::OUString& /*aWhitespaces*/) throw (xml::sax::SAXException, uno::RuntimeException)
617ddde725dSArmin Le Grand         {
618ddde725dSArmin Le Grand         }
619ddde725dSArmin Le Grand 
processingInstruction(const::rtl::OUString &,const::rtl::OUString &)620e2bf1e9dSArmin Le Grand         void SvgDocHdl::processingInstruction(const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/) throw (xml::sax::SAXException, uno::RuntimeException)
621ddde725dSArmin Le Grand         {
622ddde725dSArmin Le Grand         }
623ddde725dSArmin Le Grand 
setDocumentLocator(const uno::Reference<xml::sax::XLocator> &)624e2bf1e9dSArmin Le Grand         void SvgDocHdl::setDocumentLocator(const uno::Reference< xml::sax::XLocator >& /*xLocator*/) throw (xml::sax::SAXException, uno::RuntimeException)
625ddde725dSArmin Le Grand         {
626ddde725dSArmin Le Grand         }
627ddde725dSArmin Le Grand     } // end of namespace svgreader
628ddde725dSArmin Le Grand } // end of namespace svgio
629ddde725dSArmin Le Grand 
630ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
631ddde725dSArmin Le Grand // eof
632